kangroo 发表于 2007-6-5 10:17:05

DCG_2_2算法分析(第一次算法分析!)

【文章标题】: DCG_2_2算法分析
【文章作者】: kangroo
【作者邮箱】: [email protected]
【作者QQ号】: 87636423
【软件名称】: DCG_2_2
【软件大小】: 503KB
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 根据输入的用户名计算注册码
【编写语言】: Borland Delphi v6.0-v7.0
【使用工具】: ollydbg peid
【操作平台】: XP/2000
【软件介绍】: DCG官方出品的CRACKME
【作者声明】: 这是我的第一篇算法分析,网络上也有类似破文,事先申明绝对靠自己一步步分析出来,花了2天时间,写的不好,高手就别看了,要是看了还望多多指教.
--------------------------------------------------------------------------------
【详细过程】
字符串参考 找到单击注册按钮发生事件代码:
00466580 >/.55            PUSH EBP                                 ;TForm1@Button1Click
00466581|.8BEC          MOV EBP,ESP
00466583|.83C4 E8       ADD ESP,-18
00466586|.33C9          XOR ECX,ECX
00466588|.894D E8       MOV DWORD PTR SS:,ECX
0046658B|.894D EC       MOV DWORD PTR SS:,ECX
0046658E|.894D F4       MOV DWORD PTR SS:,ECX
00466591|.8955 F0       MOV DWORD PTR SS:,EDX
00466594|.8945 FC       MOV DWORD PTR SS:,EAX
00466597|.33C0          XOR EAX,EAX
00466599|.55            PUSH EBP
0046659A|.68 60664600   PUSH <DCG_2_2.System.@HandleFinally;>
0046659F|.64:FF30       PUSH DWORD PTR FS:
004665A2|.64:8920       MOV DWORD PTR FS:,ESP
004665A5|.68 BF580000   PUSH 58BF                              ; /Arg1 = 000058BF
004665AA|.66:B9 6DCE    MOV CX,0CE6D                           ; |
004665AE|.B2 01         MOV DL,1                                 ; |
004665B0|.A1 84614600   MOV EAX,DWORD PTR DS:            ; |将字符TSecurity指针存到EAX
004665B5|.E8 22FCFFFF   CALL DCG_2_2.004661DC                  ; \DCG_2_2.004661DC
004665BA|.8945 F8       MOV DWORD PTR SS:,EAX
004665BD|.33C0          XOR EAX,EAX
004665BF|.55            PUSH EBP
004665C0|.68 36664600   PUSH <DCG_2_2.System.@HandleFinally;>
004665C5|.64:FF30       PUSH DWORD PTR FS:
004665C8|.64:8920       MOV DWORD PTR FS:,ESP
004665CB|.8D45 F4       LEA EAX,DWORD PTR SS:
004665CE|.50            PUSH EAX
004665CF|.8D55 EC       LEA EDX,DWORD PTR SS:
004665D2|.8B45 FC       MOV EAX,DWORD PTR SS:
004665D5|.8B80 FC020000 MOV EAX,DWORD PTR DS:
004665DB >|.E8 08BBFCFF   CALL DCG_2_2.004320E8                  ;Controls.TControl.GetText(TControl):TCaption;
004665E0|.8B55 EC       MOV EDX,DWORD PTR SS:            ;指向用户名的指针保存EDX
004665E3|.66:B9 E14D    MOV CX,4DE1                              ;4DE1是下面关键CALL计算所需常数
004665E7|.8B45 F8       MOV EAX,DWORD PTR SS:             ;
004665EA|.E8 41FCFFFF   CALL DCG_2_2.00466230                  ;关键CALL
004665EF|.8D55 E8       LEA EDX,DWORD PTR SS:
004665F2|.8B45 FC       MOV EAX,DWORD PTR SS:
004665F5|.8B80 00030000 MOV EAX,DWORD PTR DS:
004665FB >|.E8 E8BAFCFF   CALL DCG_2_2.004320E8                  ;Controls.TControl.GetText(TControl):TCaption;
00466600|.8B45 E8       MOV EAX,DWORD PTR SS:            ; 将正确的注册码送入EAX
00466603|.8B55 F4       MOV EDX,DWORD PTR SS:             ; 将假码送入EDX
00466606 >|.E8 A1DDF9FF   CALL DCG_2_2.004043AC                  ;比较真正的注册码和假码
0046660B      75 13         JNZ SHORT DCG_2_2.00466620               ;关键跳转, 不相同就跳转
0046660D|.6A 00         PUSH 0                                 ; /Style = MB_OK|MB_APPLMODAL
0046660F|.68 6C664600   PUSH DCG_2_2.0046666C                  ; |Valid Key
00466614|.68 6C664600   PUSH DCG_2_2.0046666C                  ; |Valid Key
00466619|.6A 00         PUSH 0                                 ; |hOwner = NULL
0046661B >|.E8 D400FAFF   CALL <JMP.&user32.MessageBoxA>         ; \user32.MessageBoxA()

关键CALL跟入分析:
00466230/$55            PUSH EBP
00466231|.8BEC          MOV EBP,ESP
00466233|.83C4 E4       ADD ESP,-1C
00466236|.53            PUSH EBX
00466237|.33DB          XOR EBX,EBX
00466239|.895D E4       MOV DWORD PTR SS:,EBX            ;堆栈存有用户名字符串个数被清零
0046623C|.66:894D F6    MOV WORD PTR SS:,CX               ;记数器存到0012F5E6
00466240|.8955 F8       MOV DWORD PTR SS:,EDX             ;将字符串指针存到12F5E8
00466243|.8945 FC       MOV DWORD PTR SS:,EAX             ;上面2句和本句保存数据为以后调用作准备,该句是保存字符串TSecurity指针
00466246|.33C0          XOR EAX,EAX
00466248|.55            PUSH EBP
00466249|.68 E9624600   PUSH DCG_2_2.004662E9                  ;4662e9入栈
0046624E|.64:FF30       PUSH DWORD PTR FS:                  ;0012f5fc入栈
00466251|.64:8920       MOV DWORD PTR FS:,ESP               ;将ESP指针012F5C4存入上面的地址FS中
00466254|.66:8B45 F6    MOV AX,WORD PTR SS:               ;常数4DE1-->AX
00466258|.66:8945 EE    MOV WORD PTR SS:,AX            ;4DE1存入12F5DE
0046625C|.8B45 08       MOV EAX,DWORD PTR SS:             ;将0012F620存入EAX
0046625F|.E8 3CDDF9FF   CALL DCG_2_2.00403FA0
00466264|.8B45 F8       MOV EAX,DWORD PTR SS:             ;EAX指针指向用户名地址
00466267|.E8 F4DFF9FF   CALL DCG_2_2.00404260                  ;取得用户名字符串长度并将其结果存入EAX
0046626C|.85C0          TEST EAX,EAX                           ;检测用户是否存在
0046626E|.7E 63         JLE SHORT DCG_2_2.004662D3               ;用户名小于0就退出
00466270|.8945 E8       MOV DWORD PTR SS:,EAX            ;eax中的字符串个数,存储用户名长度在地址12F5D8
00466273|.C745 F0 01000>MOV DWORD PTR SS:,1            ;在0012f5e0地址处存储 1
0046627A|>8B45 F8       /MOV EAX,DWORD PTR SS:            ;将12f5e8保存的用户名的指针存入EAX
0046627D|.8B55 F0       |MOV EDX,DWORD PTR SS:         ;获得本次循环取值的位置
00466280|.8A4410 FF   |MOV AL,BYTE PTR DS:          ;将用户名其中一个字母存在AL中,所取字母位置由EDX决定
00466284|.0FB755 EE   |MOVZX EDX,WORD PTR SS:          ;常数4DE1传送到EDX低16位地址,高地址清0
00466288|.C1EA 08       |SHR EDX,8                               ;EDX向右移出一个字节edx=N/100h
0046628B|.32C2          |XOR AL,DL                               ;第一个用户名字符的ASCII与4D发生异或运算
0046628D|.8845 F5       |MOV BYTE PTR SS:,AL            ;将计算结果26存储在12F5E5的指针地址处
00466290|.33C0          |XOR EAX,EAX                           ;eax清零
00466292|.8A45 F5       |MOV AL,BYTE PTR SS:            ;将计算结果送到AL中
00466295|.66:0345 EE    |ADD AX,WORD PTR SS:             ;内存中常数4DE1和计算结果26进行add运算,计算结果保存在AX
00466299|.8B55 FC       |MOV EDX,DWORD PTR SS:            ;将字符串TSecurity指针存入EDX,不知道该句是什么作用
0046629C|.66:F76A 04    |IMUL WORD PTR DS:                ;将计算结果和内存中的数CE6D进行乘运算,CE6D是常数
004662A0|.8B55 FC       |MOV EDX,DWORD PTR SS:            ;将字符串TSecurity指针移动到EDX
004662A3|.66:0342 06    |ADD AX,WORD PTR DS:            ;58bf和计算结果进行add运算
004662A7|.66:8945 EE    |MOV WORD PTR SS:,AX             ;将计算结果保存到12F5DE
004662AB|.8D4D E4       |LEA ECX,DWORD PTR SS:
004662AE|.33C0          |XOR EAX,EAX
004662B0|.8A45 F5       |MOV AL,BYTE PTR SS:            ;将46628B计算结果送入AL
004662B3|.BA 02000000   |MOV EDX,2
004662B8|.E8 831CFAFF   |CALL DCG_2_2.00407F40                   ;将计算结果转成十六进制字符串
004662BD|.8B55 E4       |MOV EDX,DWORD PTR SS:         ;该地址指向46625B计算的结果,就是异或运算结果的值
004662C0|.8B45 08       |MOV EAX,DWORD PTR SS:
004662C3|.E8 A0DFF9FF   |CALL DCG_2_2.00404268                   ;连接上面CALL所转换得到的字符串,最后得到正确注册码
004662C8|.8B45 08       |MOV EAX,DWORD PTR SS:
004662CB|.FF45 F0       |INC DWORD PTR SS:               ;堆栈中数值用来计算用户名的字符串个数的位置,将其值加一为下次循环做准备
004662CE|.FF4D E8       |DEC DWORD PTR SS:               ;计算用户名字符串个数减一,用EDX做为循环记数器为下次循环计算做好准备
004662D1|.^ 75 A7         \JNZ SHORT DCG_2_2.0046627A            ;判断用户名是否取完,没取完继续回跳计算
004662D3|>33C0          XOR EAX,EAX
004662D5|.5A            POP EDX
004662D6|.59            POP ECX
004662D7|.59            POP ECX
004662D8|.64:8910       MOV DWORD PTR FS:,EDX
004662DB|.68 F0624600   PUSH DCG_2_2.004662F0
004662E0|>8D45 E4       LEA EAX,DWORD PTR SS:
004662E3|.E8 B8DCF9FF   CALL DCG_2_2.00403FA0
004662E8\.C3            RETN
004662E9   .^ E9 62D5F9FF   JMP DCG_2_2.00403850
004662EE   .^ EB F0         JMP SHORT DCG_2_2.004662E0
004662F0   .5B            POP EBX
004662F1   .8BE5          MOV ESP,EBP
004662F3   .5D            POP EBP
004662F4   .C2 0400       RETN 4
最后分析结果:

2个常数 CE6D 和 58BF 和一个初始化值 4DE1
(用户名ASCII xor N/100H )=x其中 N 的初始化值为4DE1,而后有 N=M了
M={[(x add N)*CE6D]add 58BF}
将每一次生成的x转换成字符连接起来就是注册码了
编程刚开始学,所以也就没能力做注册机了,还望大家见谅!
给一个有效的KEY把
NAME:kangroo
serial:265247C28CA6F5
文中有什么 不对的地方还望高手指正! 谢谢!

--------------------------------------------------------------------------------
【版权声明】: 】本文纯属技术交流, 转载请注明作者信息并保持文章的完整, 谢谢!

                                                       2007年06月05日 10:09:20

[ 本帖最后由 kangroo 于 2007-6-5 14:03 编辑 ]

myselfsky 发表于 2007-6-5 11:18:04

呵呵,好人做到底,把那个DCG_2_2顺便也粘上来吧,反正也不大,方便大家学习!/:09

kangroo 发表于 2007-6-5 13:12:28

本来就是打算上传的,不好意思第一次啊 紧张 给忘了

yjz1409276 发表于 2007-6-5 17:19:15

好文哦~加油.我也正在研究算法~可惜还有好多地方看不懂~/:02

zsl01 发表于 2008-9-23 08:17:39

好文,学习了,多谢分享。
页: [1]
查看完整版本: DCG_2_2算法分析(第一次算法分析!)