ikki_CrackMe变形SHA和变形BlowFish逆向分析(…
首先祝大家新年快乐万事如意,很久没有写过一篇文章了,看到别人写出一篇篇精彩文章,手不禁有些庠庠的,实在没什么写的,近来在学习密码学算法,所以写下了这个学习笔记。
[目标程序]CrackMe N0 2 by ikki
[目 的]学习密码学算法。
[下载地址]附件:crackme.No.2.rar
[作 者]小虾(战神[DFCG])
[官方论坛]http://www.chinadfcg.com
首先要说明的是,这篇文章是我学习密码学算法的笔记之一,写得不好,如果你是高手就不必看了,否则就一定要捂紧大嘴,免得笑掉了大牙。这个CrackMe N0 2是ikki早前放出来的,已经有二、三个月了,但至今还没有结果(也可能是我没有看见到)。其次这个CrackMe一开始放出来时我就接触过了,开始跟踪后才发现这个CrackMe用了密码学算法,但那时学识浅,不认识。于是在看雪主页下载了一个密码学分析软件后发现这个算法使用了SHA1和BlowFish算法,于是我又兴冲冲地在网上找来这两个加密解密算法的工具,但很可惜,ikki可能对这个算法进行过变形处理,我的工具算出的值和CrackMe算出的值不相同。最后我的第一次Crack流产。
现经过这二、三个月的时间,学习了一些密码学算法,对SHA1和BlowFish算法有了一个大概的理解,于是为了实践自己的理解,这次再拿他出来研究研究。呵呵!
最后说明,我学习Crack才一年半有余,学习编程也就四、五个月左右(ASM、C、VB、Delphi(Pascal)),目前也只对Delphi(Pascal)比较熟悉一点点(只是熟悉一点点,嘿嘿,贪多的下场),所以我下面的注释和写注册机时,用了Delph(Pascal)语言,不过我学习编程也就四、五个月,所以代码写得不怎么样,还请大家见谅。
说到这里,我们还是转入正题,来看看这个CrackMe吧。这个算法没有反跟跟和反爆破,所以关键点很好定位,一般只要有一些Crack经验的人都能很快定位到关键点并爆破之(但采用破爆就没什么意思了)。不过这个CrackMe采取两种加密算法(还是变形的),而且是非明码比较,所以要得正确的注册码很不容易(SHA1算法代码超长,看到就头晕),因为我们必须对这个CrackMe的整个算法进行分析,最后还得写出BlowFish的解密算法。
因为分析文章会比较长,所以,我将这个CrackMe分成三次来分析,第一次是开幕篇,主要分析整体框架结构,第二次是分析SHA1的算法,第三次则分析BlowFish算法并写出解密算法。
呵呵,废话说得太多了,现在我们开始吧。用OD加载目标程序,F9运行。接着在程序的输入框中填入用户名、注册码一和注册码二。然后下断bpx GetDlgItemTextA(如果你的系统是Win2K以上也可以下API断点:bp GetDlgItemTextA)。
用户名:zhanshen[dfcg]
试炼码:78787878-12121212
接着按确定按钮,程序将中断在这里,GetDlgItemTextA这个函数不用我说了吧,作用是取得Edit1.Text的Name_Str。
00411D49 CALL DWORD PTR DS:[<&USER32.GetDlgItemTextA>] ; \GetDlgItemTextA
00411D4F CMP ESI,ESP
00411D51 CALL CRACKME_.004113FC
00411D56 LEA EAX,DWORD PTR SS:[EBP-EC]
00411D5C PUSH EAX
00411D5D CALL CRACKME_.00411221 ; 取得Name_Len
00411D62 ADD ESP,4
00411D65 MOV DWORD PTR SS:[EBP-F8],EAX ; 保存Name_Len
这里比较输入的用户名长度是否小于1和大于等于0x64,不等则OVER。
00411D6B CMP DWORD PTR SS:[EBP-F8],1
00411D72 JL SHORT CRACKME_.00411D7D ; if Name_Len < 1 then Exit;
00411D74 CMP DWORD PTR SS:[EBP-F8],64
00411D7B JLE SHORT CRACKME_.00411DA4 ; if not(Name_Len <= $64) then Exit;
00411D7D MOV ESI,ESP
Name_Len为空的出错提示。
00411D7F PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00411D81 LEA EAX,DWORD PTR SS:[EBP-24] ; |
00411D84 PUSH EAX ; |Title
00411D85 LEA ECX,DWORD PTR SS:[EBP-14] ; |
00411D88 PUSH ECX ; |Text
00411D89 MOV EDX,DWORD PTR SS:[EBP+8] ; |
00411D8C PUSH EDX ; |hOwner
00411D8D CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; \MessageBoxA
00411D93 CMP ESI,ESP
00411D95 CALL CRACKME_.004113FC
00411D9A MOV EAX,1
00411D9F JMP CRACKME_.00411EEA ; OVER;
这里开始进行SHA1的常规始初化常数。这个函数参考原型如下:
procedure SHA1_Init(var SHA1_Init:array of DWORD);
00411DA4 MOV DWORD PTR SS:[EBP-124],0 ; var Sn1:DWORD = 0;
00411DAE XOR EAX,EAX
00411DB0 MOV DWORD PTR SS:[EBP-120],EAX ; var Sn2:DWORD = 0;
00411DB6 LEA EAX,DWORD PTR SS:[EBP-114] ; var SHA1_Init[1..5] of DWORD;
00411DBC PUSH EAX
00411DBD CALL CRACKME_.0041117C ; CALL SHA1_Init;
00411DC2 ADD ESP,4
开始用Name_Str填充待加密的64位消息。这个函数包含了SHA1_En加密算法在内,现先不管他,待后再分析。填充64位消息函数参考原型如下:
procedure Name_Init_64(var SHA1_Init:array of DWORD; var Name_Str:String; var Name_Len:DWORD; tmp:DWORD = 0);
00411DC5 PUSH 0 ; var tmp:DWORD = 0;
00411DC7 MOV EAX,DWORD PTR SS:[EBP-F8]
00411DCD PUSH EAX ; var Name_Len
00411DCE LEA ECX,DWORD PTR SS:[EBP-EC]
00411DD4 PUSH ECX ; var Name_Str;
00411DD5 LEA EDX,DWORD PTR SS:[EBP-114]
00411DDB PUSH EDX ; var SHA1_Init:array[1..5] of DWORD;
00411DDC CALL CRACKME_.004110C8 ; CALL SHA1_Init;
00411DE1 ADD ESP,10
这里开始填充BlowFish的Key,密钥就是经过SHA1加密的Name_Str。这个函数参考原型如下:
procedure BlowFish_Init(var BlowFish_Init:array of DWORD; var SHA_Init_En:array of DWORD);
00411DE4 LEA EAX,DWORD PTR SS:[EBP-114]
00411DEA PUSH EAX ; var SHA1_Init_En[1..5] of DWORD;
00411DEB LEA ECX,DWORD PTR SS:[EBP-11AC]
00411DF1 PUSH ECX ; var BlowFish_Init:array[1..1024] of DWORD;
00411DF2 CALL CRACKME_.004112A8 ; CALL BlowFish_Init;
00411DF7 ADD ESP,8
00411DFA MOV ESI,ESP
这个函数也不用说了吧,这个函数就是将Edit2.Text的Sn1取出并转为整数(Hex)。在Delphi中就有StrToInt函数。不过我还是喜欢我自己编写一个这样的函数(Delphi的这个函数若遇上ABCD等字母会出常异常)。
00411DFC PUSH 0 ; /IsSigned = FALSE
00411DFE PUSH 0 ; |pSuccess = NULL
00411E00 PUSH 3ED ; |ControlID = 3ED (1005.)
00411E05 MOV EAX,DWORD PTR SS:[EBP+8] ; |
00411E08 PUSH EAX ; |hWnd
00411E09 CALL DWORD PTR DS:[<&USER32.GetDlgItemInt>] ; \GetDlgItemInt
00411E0F CMP ESI,ESP
00411E11 CALL CRACKME_.004113FC
保存Sn1
00411E16 MOV DWORD PTR SS:[EBP-124],EAX ; Sn1 := MyStrToHex(Edit2.Text);
00411E1C MOV ESI,ESP
和上面一样,将Edit3.Text取出并转为整数(Hex)。
00411E1E PUSH 0 ; /IsSigned = FALSE
00411E20 PUSH 0 ; |pSuccess = NULL
00411E22 PUSH 3F0 ; |ControlID = 3F0 (1008.)
00411E27 MOV EAX,DWORD PTR SS:[EBP+8] ; |
00411E2A PUSH EAX ; |hWnd
00411E2B CALL DWORD PTR DS:[<&USER32.GetDlgItemInt>] ; \GetDlgItemInt
00411E31 CMP ESI,ESP
00411E33 CALL CRACKME_.004113FC
保存Sn2
00411E38 MOV DWORD PTR SS:[EBP-120],EAX ; Sn2 := MyStrToHex(Edit3.Text);
这里开始对Sn1和Sn2进行BlowFish_En加密。参考函数原型如下:
procedure BlowFish_En(var BlowFish_Init_En:array of DWORD; var Sn1, Sn2:DWORD);
00411E3E LEA EAX,DWORD PTR SS:[EBP-120]
00411E44 PUSH EAX ; var Sn2:DWORD;
00411E45 LEA ECX,DWORD PTR SS:[EBP-124]
00411E4B PUSH ECX ; var Sn1:DWORD;
00411E4C LEA EDX,DWORD PTR SS:[EBP-11AC]
00411E52 PUSH EDX ; var BlowFish_Init_En:array[1..1024] of DWORD;
00411E53 CALL CRACKME_.004114D3 ; CALL BlowFish_En;
00411E58 ADD ESP,0C
这里开始进行用户名和注册码的比较,因为BlowFish算法是_64位的分组对称加密算法,所以要比较两次。
第一次:if (SHA1_Init_En[1] xor SHA1_Init_En[5]) <> Sn1_En then 就OVER了。
第二次:if (SHA1_Init_En[2] xor SHA1_Init_En[4]) <> Sn2_En then 就OVER了。
00411E5B MOV EAX,DWORD PTR SS:[EBP-114] ; SHA1_Init_En[1]
00411E61 XOR EAX,DWORD PTR SS:[EBP-104]
00411E67 CMP DWORD PTR SS:[EBP-124],EAX
第一次关键比较,如果要爆破的话将这里NOP掉。
00411E6D JNZ SHORT CRACKME_.00411EA5 ; if (SHA1_Init_En[1] xor SHA1_Init_En[5]) <> Sn1_En then Exit;
00411E6F MOV EAX,DWORD PTR SS:[EBP-110] ; SHA1_Init_En[2]
00411E75 XOR EAX,DWORD PTR SS:[EBP-108]
第二次关键比较,爆破的话这里也要NOP掉。
00411E7B CMP DWORD PTR SS:[EBP-120],EAX
00411E81 JNZ SHORT CRACKME_.00411EA5 ; if (SHA1_Init_En[2] xor SHA1_Init_En[4]) <> Sn2_En then Exit;
00411E83 MOV ESI,ESP
这个对话框是注册成功的对话框。
00411E85 PUSH 2040 ; /Style = MB_OK|MB_ICONASTERISK|MB_TASKMODAL
00411E8A LEA EAX,DWORD PTR SS:[EBP-50] ; |
00411E8D PUSH EAX ; |Title
00411E8E LEA ECX,DWORD PTR SS:[EBP-38] ; |
00411E91 PUSH ECX ; |Text
00411E92 MOV EDX,DWORD PTR SS:[EBP+8] ; |
00411E95 PUSH EDX ; |hOwner
00411E96 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; \MessageBoxA
00411E9C CMP ESI,ESP
00411E9E CALL CRACKME_.004113FC
00411EA3 JMP SHORT CRACKME_.00411EC5
00411EA5 MOV ESI,ESP
这个对话框是注册失败的对话框。至此,后面的没什么可说的了。
00411EA7 PUSH 2030 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL
00411EAC LEA EAX,DWORD PTR SS:[EBP-7C] ; |
00411EAF PUSH EAX ; |Title
00411EB0 LEA ECX,DWORD PTR SS:[EBP-6C] ; |
00411EB3 PUSH ECX ; |Text
00411EB4 MOV EDX,DWORD PTR SS:[EBP+8] ; |
00411EB7 PUSH EDX ; |hOwner
00411EB8 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; \MessageBoxA
00411EBE CMP ESI,ESP
00411EC0 CALL CRACKME_.004113FC
00411EC5 MOV EAX,1
00411ECA JMP SHORT CRACKME_.00411EEA
00411ECC MOV ESI,ESP
00411ECE PUSH 0 ; /Result = 0
00411ED0 MOV EAX,DWORD PTR SS:[EBP+8] ; |
00411ED3 PUSH EAX ; |hWnd
00411ED4 CALL DWORD PTR DS:[<&USER32.EndDialog>] ; \EndDialog
00411EDA CMP ESI,ESP
00411EDC CALL CRACKME_.004113FC
00411EE1 MOV EAX,1
00411EE6 JMP SHORT CRACKME_.00411EEA
00411EE8 XOR EAX,EAX
00411EEA PUSH EDX
00411EEB MOV ECX,EBP
00411EED PUSH EAX
00411EEE LEA EDX,DWORD PTR DS:[411F11]
00411EF4 CALL CRACKME_.004111D1
00411EF9 POP EAX
00411EFA POP EDX
00411EFB POP EDI
00411EFC POP ESI
00411EFD POP EBX
00411EFE ADD ESP,1274
00411F04 CMP EBP,ESP
00411F06 CALL CRACKME_.004113FC
00411F0B MOV ESP,EBP
00411F0D POP EBP
00411F0E RETN 10
至此,第一篇文章分析完毕,接着进行第二篇SHA1算法的分析(不过我是边分析边写破文的,SHA1算法还没完全写完(呵呵,看到一大段的代码我的头都有点晕了),所以,第二篇可能要明天或后天了)。未完待续。。。
----本文只能作为内部研究之用,如需转载请保持文章的完整性,谢谢!----小虾(战神[DFCG]),2005/2/10
下一篇:riijj Crackme (4)的详解 2 >>
相关文章:
- · WebSphereInformationIntegratorV8.2
- · 阐述 IBM LWWCM 的概念和特性
- · 如何在DB2上为AIX5L设置unixODBC
- · 配置 IBM DB2 通用数据库以构建 SQL 过程
- · 设置DB UDB版本8中的混合字…
- · DB2 V8 连通性快捷表
- · 从 Microsoft SQL Server 2000 移植
- · 升级到 Informix Dynamic Server 9.40FC1
- · 利用您的 Oracle 9i
- · 使用 IBM DB2 Migration To…
- · IBM DB2 Universal Database V8.1
- · 培养商业智能技能
- · DB2 认证 — 认证须知
- · 灵活有效的数据仓库解决方案: 第 1 部分
- · DB2 for z/OS: DB2 数据库设计
- · 初始调优和设计方面的考虑
- · 决策支持系统(DSS)应用程序处理
- · (Query Patroller)V7.2 规划资源需求
- · 工程实施及项目管理
- · DB2 UDB Stinger 与自主计算
- · SMART 程度更高的 DB2
- · 自动化的将来
- · 网格揭密
- · Susan Malaika 讨论 XML 标准和网格计算
- · 对 Enterprise Replication 使用主复制
- · 崩溃恢复的基石
- · CommonStore 和 SAP 归档接…
- · 管理 XPS 数据库服务器上的…
- · DB2 重定向恢复脚本
- · 为 DB2 编写基于 Web 的表编辑器 GUI
- · DB2 UDB Express 的 GUI 工具简介第 1 部分
- · DB2 命令行处理器(CLP)中…
- · 测试您的 DB2 数据库: 用 JMeter 测量性能
- · IBM DB2 Everyplace Sync Server V8.2
- · DB2 Everyplace Version 8.2 同步水平过滤
- · 构建基于 DB2 Everyplace 的 MIDP 应用程序
- · 同步服务器的三种典型管理方式
- · 为 Palm 设备创建移动应用程序
