长春真人 作西游记:OllyDBG破解入门实例(图)_04

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 15:18:42

看上图,我们可以把两条都设上断点。这个程序只需在第一条指令设断点就可以了。好,我们现在按前面提到的第一条方法,就是“在每个参考上设置断点”,这样上图中的两条指令都会设上断点。断点设好后我们转到我们调试的程序上来,现在我们在被我们调试的程序上点击那个“Check It”按钮,被 OllyDBG 断下:
00401323 |. E8 4C010000 CALL     ; GetWindowTextA
00401328 |. E8 A5000000 CALL CrackHea.004013D2        ; 关键,要按F7键跟进去
0040132D |. 3BC6    CMP EAX,ESI          ; 比较
0040132F |. 75 42    JNZ SHORT CrackHea.00401373    ; 不等则完蛋
00401331 |. EB 2C    JMP SHORT CrackHea.0040135F
00401333 |. 4E 6F 77 20 7> ASCII "Now write a keyg"
00401343 |. 65 6E 20 61 6> ASCII "en and tut and y"
00401353 |. 6F 75 27 72 6> ASCII "ou're done.",0
0040135F |> 6A 00    PUSH 0          ; Style = MB_OK|MB_APPLMODAL
00401361 |. 68 0F304000 PUSH CrackHea.0040300F        ; Title = "Crudd's Crack Head"
00401366 |. 68 33134000 PUSH CrackHea.00401333        ; Text = "Now write a keygen and tut and you're done."
0040136B |. FF75 08     PUSH DWORD PTR SS:[EBP+8]    ; hOwner
0040136E |. E8 19010000 CALL    ; MessageBoxA
从上面的代码,我们很容易看出 00401328 地址处的 CALL CrackHea.004013D2 是关键,必须仔细跟踪。而注册成功则会显示一个对话框,标题是“Crudd's Crack Head”,对话框显示的内容是“Now write a keygen and tut and you're done.”现在我按一下 F8,准备步进到 00401328 地址处的那条 CALL CrackHea.004013D2 指令后再按 F7 键跟进去。等等,怎么回事?怎么按一下 F8 键跑到这来了:
00401474 $- FF25 2C204000 JMP DWORD PTR DS:[   ; USER32.GetWindowTextA
0040147A $- FF25 30204000 JMP DWORD PTR DS:[]   ; USER32.LoadCursorA
00401480 $- FF25 1C204000 JMP DWORD PTR DS:[] ; USER32.LoadIconA
00401486 $- FF25 20204000 JMP DWORD PTR DS:[] ; USER32.LoadMenuA
0040148C $- FF25 24204000 JMP DWORD PTR DS:[]   ; USER32.MessageBoxA
原来是跳到另一个断点了。这个断点我们不需要,按一下 F2 键删掉它吧。删掉 00401474 地址处的断点后,我再按 F8 键,呵,完了,跑到 User32.dll 的领空了。看一下 OllyDBG 的标题栏:“[CPU - 主线程, 模块 - USER32],跑到系统领空了,OllyDBG 反汇编窗口中显示代码是这样:
77D3213C 6A 0C    PUSH 0C
77D3213E 68 A021D377 PUSH USER32.77D321A0
77D32143 E8 7864FEFF CALL USER32.77D185C0
怎么办?别急,我们按一下 ALT+F9 组合键,呵,回来了:
00401328 |. E8 A5000000 CALL CrackHea.004013D2        ; 关键,要按F7键跟进去
0040132D |. 3BC6    CMP EAX,ESI           ; 比较
0040132F |. 75 42     JNZ SHORT CrackHea.00401373    ; 不等则完蛋
光标停在 00401328 地址处的那条指令上。现在我们按 F7 键跟进:
004013D2 /$ 56    PUSH ESI          ; ESI入栈
004013D3 |. 33C0     XOR EAX,EAX          ; EAX清零
004013D5 |. 8D35 C4334000   LEA ESI,DWORD PTR DS:[4033C4]    ; 把注册码框中的数值送到ESI
004013DB |. 33C9     XOR ECX,ECX          ; ECX清零
004013DD |. 33D2     XOR EDX,EDX          ; EDX清零
004013DF |. 8A06     MOV AL,BYTE PTR DS:[ESI]    ; 把注册码中的每个字符送到AL
004013E1 |. 46    INC ESI          ; 指针加1,指向下一个字符
004013E2 |. 3C 2D     CMP AL,2D          ; 把取得的字符与16进制值为2D的字符(即“-”)比较,这里主要用于判断输入的是不是负数
004013E4 |. 75 08     JNZ SHORT CrackHea.004013EE    ; 不等则跳
004013E6 |. BA FFFFFFFF MOV EDX,-1          ; 如果输入的是负数,则把-1送到EDX,即16进制FFFFFFFF
004013EB |. 8A06     MOV AL,BYTE PTR DS:[ESI]    ; 取“-”号后的第一个字符
004013ED |. 46    INC ESI          ; 指针加1,指向再下一个字符
004013EE |> EB 0B     JMP SHORT CrackHea.004013FB
004013F0 |> 2C 30     SUB AL,30          ; 每位字符减16进制的30,因为这里都是数字,如1的ASCII码是“31H”,减30H后为1,即我们平时看到的数值
004013F2 |. 8D0C89     LEA ECX,DWORD PTR DS:[ECX+ECX*4]     ; 把前面运算后保存在ECX中的结果乘5再送到ECX
004013F5 |. 8D0C48     LEA ECX,DWORD PTR DS:[EAX+ECX*2]     ; 每位字符运算后的值与2倍上一位字符运算后值相加后送ECX
004013F8 |. 8A06     MOV AL,BYTE PTR DS:[ESI]    ; 取下一个字符
004013FA |. 46    INC ESI          ; 指针加1,指向再下一个字符
004013FB |> 0AC0     or AL,AL
004013FD |.^ 75 F1     JNZ SHORT CrackHea.004013F0    ; 上面一条和这一条指令主要是用来判断是否已把用户输入的注册码计算完
004013FF |. 8D040A     LEA EAX,DWORD PTR DS:[EDX+ECX]     ; 把EDX中的值与经过上面运算后的ECX中值相加送到EAX
00401402 |. 33C2     XOR EAX,EDX          ; 把EAX与EDX异或。如果我们输入的是负数,则此处功能就是把EAX中的值取反
00401404 |. 5E    POP ESI          ; ESI出栈。看到这条和下一条指令,我们要考虑一下这个ESI的值是哪里运算得出的呢?
00401405 |. 81F6 53757A79   XOR ESI,797A7553       ; 把ESI中的值与797A7553H异或
0040140B \. C3    RETN
这里留下了一个问题:那个 ESI 寄存器中的值是从哪运算出来的?先不管这里,我们接着按 F8 键往下走,来到 0040140B 地址处的那条 RETN 指令(这里可以通过在调试选项的“命令”标签中勾选“使用 RET 代替 RETN”来更改返回指令的显示方式),再按一下 F8,我们就走出 00401328 地址处的那个 CALL 了。现在我们回到了这里:
0040132D |. 3BC6     CMP EAX,ESI          ; 比较
0040132F |. 75 42     JNZ SHORT CrackHea.00401373    ; 不等则完蛋
光标停在了 0040132D 地址处的那条指令上。根据前面的分析,我们知道 EAX 中存放的是我们输入的注册码经过计算后的值。我们来看一下信息窗口:
ESI=E6B5F2F9
EAX=FF439EBE
左键选择信息窗口中的 ESI=E6B5F2F9,再按右键,在弹出菜单上选“修改寄存器”,我们会看到这样一个窗口:

可能你的显示跟我不一样,因为这个 crackme 中已经说了每个机器的序列号不一样。关掉上面的窗口,再对信息窗口中的 EAX=FF439EBE 做同样操作:

由上图我们知道了原来前面分析的对我们输入的注册码进行处理后的结果就是把字符格式转为数字格式。我们原来输入的是字串“12345666”,现在转换为了数字 12345666。这下就很清楚了,随便在上面那个修改 ESI 图中显示的有符号或无符号编辑框中复制一个,粘贴到我们调试的程序中的编辑框中试一下:
 
成功了。这个 crackme 是要求写出注册机的。我们先不要求写注册机,但注册的算法我们要搞清楚。还记得我在前面说到的那个 ESI 寄存器值的问题吗?现在看看我们上面的分析,其实对做注册机来说是没有多少帮助的。要搞清注册算法,必须知道上面那个 ESI 寄存器值是如何产生的,这弄清楚后才能真正清楚这个 crackme 算法。