吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13762|回复: 31
收起左侧

[原创] 初练160个CrakeMe程序之007

  [复制链接]
海天一色001 发表于 2017-6-3 13:44
本帖最后由 海天一色001 于 2017-6-3 13:53 编辑

7CM,还是先打开看看是什么情况:
01.png
仍然是用户名/注册码形式的,随意输入用户名和注册码,点Register键,没任何反应;再点Cancella键,注册码清零;继续点击Register键,出现信息框要求注册码大于0。再点About-Help,四个信息窗口出来了。大概意思是最好不爆破打补丁,要找出对应的用户名和注册码,隐藏下面的按钮。与上一个有些类似,肯定是更难了!老规矩,先查壳:
02.png
没壳,Delphi程序,还是先汉化一下吧,目的仍然是对各种软件工具的熟悉和掌握。具体过程和上一个基本一致,利用ResScopeOD基本上完成了,汉化程序另存为cm007.exe;给个界面: 03.png           06.png
点击注册按钮后见右上图,有点小问题:如果注册码输入非纯数字,如下图:
04_1.png
点击关于-帮助按钮后:
04.png

05.png
后面还有两条提示信息,和上一个CM中的提示一样,因为没什么有用信息,我没有对它们汉化,直接又练习了一次去掉弹出窗口:如下图将地址00442CDC至00442CEB处的代码全部nop掉,再保存到可执行文件后,就去除了后两个弹出信息窗口。
07.png
在保存到可执行文件时提示文件基址有变化,是否保存,我还是保存了,保存后发现文件中地址确实有了变化,但功能没有什么影响,对比图如下:
08.png

09.png
上一张图是原程序的代码,先将字符串赋值给eax,再把eax作为call的参数,运行call来显示提示信息,下一张是修改汉化后的代码,可以看出是使用直接显示字符串的方法。经测试,修改后的程序能够正常运行,所以就这样保存下来了。好了,虽然程序要求找算法,但为了练习,我还是先爆破再追码:Delphi程序有IDA等软件进行反汇编,可以进行更有效的分析,可是我不会!哪位大神有中文版的使用教程啊?还是请出DeDe出场,看到了这些熟悉的过程:
10.png
AboutClick事件就不用跟踪了,其他三个事件都要进去分析。还是对照Dede中的注释在OD中去分析各个事件的代码:
11.png
第一次爆破:OD载入CM007.exeCtrl+E,粘贴入Dede中复制来的RAV(内存地址) 00442F28”,到达RegisterzClick事件段首,F2下断点:F9运行程序,输入用户名“52pojie.cn”,注册码“1111111111”,点击注册按钮,程序中断,F8单步向下:到达地址00442F60处,指令为cmp [local.1],0x0 ,下句是跳过失败的jz指令。此处的指令在Dede中反编译出来的是“cmp dword ptr [ebp-$04], +$00”,总算是知道了这个地址的由来!同时猜测[local.1]的值应该是决定按钮隐藏与否的值。
12.png
向下查看代码,有三个跳转指令跳过了隐藏注册按钮,显示Again按钮,走向失败,而本句的指令跳过了第一个走向失败的jmp指令,所以此处可以不动;此时关键call不再执行,所以要继续向下到达00442F9B地址处,因为怕上一个跳过本条指令的je指令失效,所以将这里nop掉!一直单步向下,同样将两个跳到失败的语句nop掉,一条在紧挨着第一个跳转到失败指令的00442F9F处,一条在00442FC0处。
13.png
这三个跳转失效,继续单步到段尾处,F9,程序果然将注册按钮隐藏了,不过又显出了一个“再次”的按钮!(见左下图)
14.png
其实到这里,根据上一个CM和这里的实际情况,再在00442FCF地址处将mov dl,0x1改成mov dl 0x0,就可以让再次按钮根本不显示!修改之后,将全部修改保存到可执行文件CM007_Register_nop.exe中!运行CM007_Register_nop.exe,果然点击注册按钮,自身隐藏起来了,“再次”按钮也没有出现!
15.png
第二次爆破:虽然爆破法很暴力,但在00442FCF地址处将mov dl,0x1改成mov dl 0x0也有点太粗暴了,毕竟程序还要显示出来一个“再次”按钮的,那么撤消此处的修改,继续爆破:004430BC处下断,点击再次按钮,程序断在了AgainClick事件段首。观察本段代码,与注册按钮事件很相似,那么先按照上一个思路,同样将三个跳转(0044312D处的jmp,00443134处的jle,00443159处的jenop掉。因为此时按钮已全部隐藏了,干脆将全部修改复制到可执行文件CM007_again_nop.exe中,打开CM007_again_nop.exe,如下左图:点击注册,如下中图:再点击再次,如下右图,爆破成功!有点不舒服的是隐藏再次按钮后程序标题有点小乱,其实是点击再次按钮后,标题栏要加上用户名,因为爆破不完全,使字符看起来不正确了。
16.png           17.png           18.png
这种爆破方法要修改好几个跳转语句,有点太过于直接,还是应该找到关键call和关键跳,直接修改关键call的返回值,使之符合关键跳成功的条件。这样分析起来可能要费劲些,但修改的地方就少了,可能修改一个地方或者两个地方就能爆破成功了。第三次爆破:重载程序,F9,输入用户名“52pojie.cn”,注册码“1234567890”,点击注册按钮,程序中断。F8向下,走到00442F59处,一时不注意F7跟入00402958这个call了。既然进来了,就单步看看是干什么的吧。仔细分析,发现这是对输入的注册码进行判断和处理的子程序,如果注册码字符不符合程序内含条件,则跳出失败的提示;如果首字符是“-+Xx$”等特殊值时进行新的计算,最后得到处理注册码后的数值存入eax中。再来到00442F60地址处,可以认为栈[local.1]中的值是判断注册码输入格式正确与否的,正确则跳走,不正确则跳出错误提示框
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
00442F4E  |.  E8 ED02FEFF   call CM007.00423240                     ;  controls.TControl.GetText(TControl):TCaption;得到假码和假码长度
00442F53  |.  8B45 F8       mov eax,[local.2]                       ;  mov eax, [ebp-$08],取假码
00442F56  |.  8D55 FC       lea edx,[local.1]                       ;  lea edx, [ebp-$04]
00442F59  |.  E8 FAF9FBFF   call CM007.00402958                     ;  * Reference to: system.@ValLong;判断假码第一个字符是不是空格、+、-、X、x、$等特殊字符,最后得到假码的16进制数值存入eax中
00442F5E  |.  8BF0          mov esi,eax                       ;  esi=假码的16进制数值
00442F60  |.  837D FC 00    cmp [local.1],0x0                       ;  cmp dword ptr [ebp-$04], +$00:第一个判断:此处的地址存入的值应该是判断注册码输入正误的值
00442F64      74 37         je short CM007.00442F9D                 ;  假码输入格式正确则跳,错误不跳,不用动
00442F66  |.  B8 38304400   mov eax,CM007.00443038                  ;  eax为在注册码编辑栏中输入一个有效数值的提示内容
00442F6B  |.  E8 00F6FFFF   call CM007.00442570                     ;  dialogs.ShowMessage(AnsiString);显示提示信息框
00442F70  |.  8D55 F8       lea edx,[local.2]                       ;  lea edx, [ebp-$08]
00442F73  |.  8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]        ;  * Reference to control Codice : TLabel
00442F79  |.  E8 C202FEFF   call CM007.00423240                     ;  controls.TControl.GetText(TControl):得到字符串及其长度
00442F7E  |.  8B45 F8       mov eax,[local.2]                       ;  mov eax, [ebp-$08]:eax=假码
00442F81  |.  E8 06FBFFFF   call CM007.00442A8C                     ;  * Reference to : TPrincipale._PROC_00442A8C()
00442F86  |.  A3 30584400   mov dword ptr ds:[0x445830],eax
00442F8B  |.  BA 90304400   mov edx,CM007.00443090                  ;  edx为注册码,上面判断出是错误的,所以用0代替它
00442F90  |.  8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]        ;  * Reference to control Codice : TLabel
00442F96  |.  E8 D502FEFF   call CM007.00423270                     ;  * Reference to: controls.TControl.SetText(TControl;TCaption);
00442F9B      EB 6F         jmp short CM007.0044300C                ;  跳过了隐藏注册按钮,显示Again按钮,走向失败
00442F9D  |>  85F6          test esi,esi                            ;  第二个判断处,看假码是否小于等于0
00442F9F      7E 5A         jle short CM007.00442FFB                ;  跳过了隐藏注册按钮,显示Again按钮,走向失败
00442FA1  |.  8D55 F8       lea edx,[local.2]                       ;  lea edx, [ebp-$08]
00442FA4  |.  8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]        ;  * Reference to control Nome : TLabel
00442FAA  |.  E8 9102FEFF   call CM007.00423240                     ;  * Reference to: controls.TControl.GetText(TControl):TCaption;
00442FAF  |.  8B4D F8       mov ecx,[local.2]                       ;  mov ecx, [ebp-$08],ecx=用户名
00442FB2  |.  8BD6          mov edx,esi
00442FB4  |.  A1 30584400   mov eax,dword ptr ds:[0x445830]
00442FB9  |.  E8 EAF9FFFF   call CM007.004429A8                     ;  关键Call,参数为eax=0?,edx=假码的16进制值,ecx=用户名
00442FBE  |.  84C0          test al,al                              ;  第三个判断
00442FC0      74 30         je short CM007.00442FF2                 ;  跳过了隐藏注册按钮,显示Again按钮,走向失败
00442FC2  |.  33D2          xor edx,edx
00442FC4  |.  8B83 CC020000 mov eax,dword ptr ds:[ebx+0x2CC]        ;  * Reference to control Registerz : TButton
00442FCA  |.  E8 6101FEFF   call CM007.00423130                     ;  * Reference to: controls.TControl.SetVisible(TControl;Boolean);
00442FCF      B2 01         mov dl,0x1
00442FD1  |.  8B83 E8020000 mov eax,dword ptr ds:[ebx+0x2E8]        ;  * Reference to control Again : TButton
00442FD7  |.  E8 5401FEFF   call CM007.00423130                     ;  * Reference to: controls.TControl.SetVisible(TControl;Boolean);
00442FDC  |.  33D2          xor edx,edx
00442FDE  |.  8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]        ;  * Reference to control Nome : TLabel
00442FE4  |.  8B08          mov ecx,dword ptr ds:[eax]
00442FE6  |.  FF51 60       call dword ptr ds:[ecx+0x60]
00442FE9  |.  33C0          xor eax,eax
00442FEB  |.  A3 30584400   mov dword ptr ds:[0x445830],eax
00442FF0  |.  EB 1A         jmp short CM007.0044300C
继续来到00442FB9处,对照Dede发现此处的call没有明确的注释,可能就是关键call了!仔细分析程序代码,第三个判断处下面是隐藏注册按钮,显示Again按钮的代码,下面是关键跳,在它上面的就是关键call了。F7跟入关键call中,004429A8处下断,F8向下:
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
004429A8  /$  55            push ebp                                ;  关键Call,计算与判断注册码
004429A9  |.  8BEC          mov ebp,esp
004429AB  |.  83C4 F4       add esp,-0xC
004429AE  |.  53            push ebx
004429AF  |.  56            push esi
004429B0  |.  57            push edi
004429B1  |.  894D F8       mov [local.2],ecx                       ;  用户名入栈
004429B4  |.  8955 FC       mov [local.1],edx
004429B7  |.  8BF8          mov edi,eax
004429B9  |.  8B45 F8       mov eax,[local.2]                       ;  取用户名
004429BC  |.  E8 2712FCFF   call CM007.00403BE8                     ;  结果是edx=2????
004429C1  |.  33C0          xor eax,eax
004429C3  |.  55            push ebp
004429C4  |.  68 7A2A4400   push CM007.00442A7A
004429C9  |.  64:FF30       push dword ptr fs:[eax]
004429CC  |.  64:8920       mov dword ptr fs:[eax],esp
004429CF  |.  8B45 F8       mov eax,[local.2]                       ;  取用户名
004429D2  |.  E8 5D10FCFF   call CM007.00403A34                     ;  取用户名长度,返回eax中
004429D7  |.  83F8 04       cmp eax,0x4                             ;  用户名长度不能小于4位
004429DA  |.  0F8E 82000000 jle CM007.00442A62                      ;  跳则死
004429E0  |.  33DB          xor ebx,ebx                             ;  ebx=0
004429E2  |.  8B45 F8       mov eax,[local.2]                       ;  取用户名
004429E5  |.  E8 4A10FCFF   call CM007.00403A34                     ;  取用户名长度
004429EA  |.  85C0          test eax,eax
004429EC  |.  7E 38         jle short CM007.00442A26
004429EE  |.  8945 F4       mov [local.3],eax                       ;  用户名长度入栈
004429F1  |.  BE 01000000   mov esi,0x1                             ;  esi=1,循环的起始序号
004429F6  |>  8B45 F8       /mov eax,[local.2]                      ;  取用户名
004429F9  |.  E8 3610FCFF   |call CM007.00403A34                    ;  取用户名长度
004429FE  |.  83F8 01       |cmp eax,0x1                            ;  eax>1
00442A01  |.  7C 1D         |jl short CM007.00442A20
00442A03  |>  8B55 F8       |/mov edx,[local.2]                     ;  edx=用户名
00442A06  |.  0FB65432 FF   ||movzx edx,byte ptr ds:[edx+esi-0x1]   ;  取每次循环后用户名的第一个字符的16进制ASCII值
00442A0B  |.  8B4D F8       ||mov ecx,[local.2]                     ;  ecx=用户名
00442A0E  |.  0FB64C01 FF   ||movzx ecx,byte ptr ds:[ecx+eax-0x1]   ;  取每次循环后用户名的最后一个字符的16进制ASCII值
00442A13  |.  0FAFD1        ||imul edx,ecx                          ;  edx=edx*ecx;第一位乘以最后一位
00442A16  |.  0FAFD7        ||imul edx,edi                          ;  edx=edx*edi   edi为0,得edx=0
00442A19  |.  03DA          ||add ebx,edx                           ;  ebx=ebx+edx;;可是ebx也是0,结果还是0
00442A1B  |.  48            ||dec eax                               ;  eax递减
00442A1C  |.  85C0          ||test eax,eax                          ;  检测eax是否为0
00442A1E  |.^ 75 E3         |\jnz short CM007.00442A03              ;  循环结果是eax=0,ecx=用户名第一位字符的16进制ASCII值,edx=0
00442A20  |>  46            |inc esi
00442A21  |.  FF4D F4       |dec [local.3]
00442A24  |.^ 75 D0         \jnz short CM007.004429F6               ;  循环结果是eax=0,ecx=用户名第一位字符的16进制ASCII值,esi=用户名长度+1
00442A26  |>  8BC3          mov eax,ebx
00442A28  |.  99            cdq
00442A29  |.  33C2          xor eax,edx
00442A2B  |.  2BC2          sub eax,edx
00442A2D  |.  B9 2A2C0A00   mov ecx,0xA2C2A
00442A32  |.  99            cdq
00442A33  |.  F7F9          idiv ecx                                ;  结果是eax=0!!!!!
00442A35  |.  8BDA          mov ebx,edx
00442A37  |.  8B45 FC       mov eax,[local.1]                       ;  【local.1】的值才是真正开始计算的值,是假码的16进制数值
00442A3A  |.  B9 59000000   mov ecx,0x59
00442A3F  |.  99            cdq
00442A40  |.  F7F9          idiv ecx                                ;  eax/0x59,商入eax,余数入edx
00442A42  |.  8BC8          mov ecx,eax                             ;  ecx=eax,即上面算式结果取整
00442A44  |.  8B45 FC       mov eax,[local.1]
00442A47  |.  BE 50000000   mov esi,0x50
00442A4C  |.  99            cdq
00442A4D  |.  F7FE          idiv esi                                ;  eax/esi,商入eax,余数入edx
00442A4F  |.  03CA          add ecx,edx                             ;  【local.1】/0x59取整后的数+【local.1】/0x50取余的数
00442A51  |.  41            inc ecx                                 ;  ecx=ecx+1
00442A52  |.  894D FC       mov [local.1],ecx                       ;  ecx就是最终的结果
00442A55  |.  3B5D FC       cmp ebx,[local.1]                       ;  ebx与注册码比较
00442A58     /75 04         jnz short CM007.00442A5E                ;  也可以在这里nop,其他地方就不用nop了
00442A5A  |.  B3 01         mov bl,0x1                              ;  bl=1,正确
00442A5C  |.  EB 06         jmp short CM007.00442A64
00442A5E  |>  33DB          xor ebx,ebx                             ;  bl=0,错误
00442A60  |.  EB 02         jmp short CM007.00442A64
00442A62  |>  33DB          xor ebx,ebx
00442A64  |>  33C0          xor eax,eax
00442A66  |.  5A            pop edx                                 ;  0012F6A4
00442A67  |.  59            pop ecx                                 ;  0012F6A4
00442A68  |.  59            pop ecx                                 ;  0012F6A4
00442A69  |.  64:8910       mov dword ptr fs:[eax],edx
00442A6C  |.  68 812A4400   push CM007.00442A81
00442A71  |>  8D45 F8       lea eax,[local.2]
00442A74  |.  E8 3F0DFCFF   call CM007.004037B8
00442A79  \.  C3            retn
00442A7A   .^ E9 F907FCFF   jmp CM007.00403278
00442A7F   .^ EB F0         jmp short CM007.00442A71
00442A81   .  8BC3          mov eax,ebx
00442A83   .  5F            pop edi                                 ;  0012F6A4
00442A84   .  5E            pop esi                                 ;  0012F6A4
00442A85   .  5B            pop ebx                                 ;  0012F6A4
00442A86   .  8BE5          mov esp,ebp
00442A88   .  5D            pop ebp                                 ;  0012F6A4
00442A89   .  C3            retn
从整个call运行的结果看,返回值是al=1或者0,而al=0则死,那么干脆在call的第一句就赋值:mov al,0x1,第二句就retn!运行程序,果然注册按钮隐藏起来,再次按钮显示了。点击再次按钮,程序中断到AgainClick事件段首,F8继续,运行到00443152处,出现了“call CM007.004429A8”这个指令,和RegisterzClick事件调用的同一个关键Call!那么就不用再单步走了,直接F9,再次按钮也隐藏了!将这个修改保存到CM007_call_retn.exe中,试运行一下,成功!这种爆破将关键call里的运算全部屏蔽掉了,而且修改的地方很少,此时程序可以不用输入用户名;还可以在关键call00442A58地址处将跳转语句nop掉,这时bl=1,继续运行后又将ebx的值传给了eax,同样使整个call的返回值变成al=0,这样的修改保存为CM007_call_nop.exe,这样爆破掉整个程序,必须输入用户名和注册码。在我们改好以上之后,可以看到注册按钮和再次按钮都消失了。不过对照上个CMCannellaClick事件中还有很重要的算法,也不能掉以轻心!OD中给CannellaClick事件段首下断,点击清零按钮,程序中断,F8向下分析,很快来到关键call和关键跳处:
[Asm] 纯文本查看 复制代码
1
2
3
4
5
00442BD2  |.  8B45 F4       mov eax,[local.3]
00442BD5  |.  5A            pop edx
00442BD6  |.  E8 55FFFFFF   call aLoNg3x_.00442B30                   ;关键call
00442BDB  |.  84C0          test al,al
00442BDD  |.  0F84 86000000 je aLoNg3x_.00442C69

关键跳00442BD6处的call追入查看,得知仍是利用用户名和注册码计算后,然后返回al是否为0,不为0则完成破解,为0时则将注册码清零。所以在这里仍然可以将00442BDDnop掉,
26.png
或者进入00442B30call中,用retn大法或者nop00442B66处的跳,也可以将00442B6C处的指令改为“mov bl,0x1”,最终达到的效果是点击清零按钮,出现GREATLAMER两个信息框,完全爆破程序!此处爆破后我是nop00442B66处的跳,最终保存为CM007_end_nop.exe。其他几种请大家自行测试吧。在爆破过程中发现,第二个信息框的字符“LAMER”是利用“GREAT”变换而来的,大家也可以试着改改,不过用途不是很大。爆破成功,接下来是追码,尽量编写出注册机吧!重新载入CM007.exeF9运行,因为注册和再次按钮都调用了同一个关键call,所以先禁用其他断点,激活关键call的段首处断点,输入用户名和注册码,点注册按钮,程序中断到004429A8处。单步运行了好几次,一遍遍地分析代码,唯恐看错了哪里。但是不得不说,这段代码有点莫名其妙的! 00442A35地址以前的计算,看上去很热闹,循环处理用户名的每一个字符,又是乘法又是加法,结果是0!很怀疑是不是作者哪个地方弄错了。从00442A37地址开始才是有效的判断注册码正误的算法!只是利用了注册码然后就判断了吗?具体的算法是:先取假码的16进制值,除以0x59,商取整,再加上假码的16进制值除以0x50的余数,最后加上0x1,结果=0!!!!程序到00442A55处指令是“cmp ebx,[local.1]”,应该是ebx中的值与注册码算出的结果比较,问题是在004429E0“xor ebx,ebx”指令将ebx清零后下面的指令就没有给ebx赋值的语句了,所以ebx=0!我猜测可能是上面用户名算出的结果应该不为0,并存入ebx中,此时再与注册码计算出的结果比较才对呀。那么ebx清零之前又是多少?向上查看何处给ebx赋值:地址00442A35处是指令“mov ebx,edx”,再来找这个edx的值从何而来:在00442A29处和00442A2B处又有两条指令中有edx,但这不是赋值;
[Asm] 纯文本查看 复制代码
1
2
00442A29  |.  33C2          xor eax,edx
00442A2B  |.  2BC2          sub eax,edx
继续向上找,到00442A16处,这里是带符号数的乘法,“imul edx,edi”,在这一句的上一条指令中,edx的值是用户名第一个字符与最后一个字符的16进制ASCII值的积,已有了具体的值,但在这一句中因为edi=0所以edx结果始终为0
19.png
问题又转到了edi0从何而来了:继续向上查看:到地址004429B7处,“mov edi,eax”指令又将问题交给了eax!(反复查找了几次,此处注释为:“edi=ds:[0x445830]的值”!) 20.png
再向上看,就到了关键call的段首,还没有其他的给eax赋值语句,说明要回溯到关键call外面去找了!
21.png
在调用这个关键call的地方,请看后面的注释,eax=ds:[0x445830],再去找这个堆栈被赋值的地方!向上再向上,肯定在调用关键call前面有被赋值的地址,这次很快就找到了地方:00442F86处。但这是注册码输入错误格式后才能来到这里的啊!如果注册码格式正确,不可能来到这里。
22.png
不信邪地在程序中Ctrl+F查找“mov dword ptr ds:[0x445830],eax”这条指令,Ctrl+L下一个,每找到一处都进行注释:
23.png

24.png

25.png
总共找到了八处,前四处在RegisterzClick事件中,后四处在AgainClick事件中,而且代码位置十分相似,只分析RegisterzClick事件的代码就行了。看过来看过去,反复运行程序验证,终于得出了程序流程:程序共分三步,第一步先输入用户名和非标准格式(非纯数字形式)的注册码,点击注册按钮,程序弹出注册码错误提示信息后继续向下运行,此时经call CM007.00442A8C算出结果给ds:[0x445830]赋值,跳过隐藏注册按钮和显示再次按钮;第二步保持用户名不动,重新输入一个格式正确(纯数字形式的)的注册码,点击注册按钮,此时关键call中的eax-edi-edx-ebx-eax终于都不再为0了,可以计算出一个正确的结果使注册按钮隐藏,再次按钮出现;第三步,保持用户名不变,再输入第一步的非标准的注册码,点击再次按钮,程序又弹出错误信息,继续运行,再将第二步的注册码输入到注册码编辑框中,再点再次按钮,再次按钮消失!最后再看CannellaClick事件,关键call00442B30,里面的关键代码竟然是直接比较用户名和注册码,相等则弹出信息框,不等则清零!
27.png
但是不管CannellaClick事件也完全能够达到隐藏按钮的目的,不明白这个东东有什么用!
VB编出了一个注册机,取输入的用户名和第一次的注册码,通过穷举法得出第二个注册码来。由于初学,很多问题都是一知半解的,特别是关于数值溢出的问题,困住了将近一周的时间!即使最终生成了注册机,也还可能存在溢出或是数据类型不匹配的问题,希望得到大家的帮助,共同学习提高。
最后,强迫症发作,自认为完美的程序流程是:先输入用户名(只要不是纯数字的就行),再将这个用户名作为第一次的注册码输入到注册码编辑框中,点击“清零”按钮,出现两个弹出窗;点掉后,点击“注册按钮”,再点掉错误提示,输入注册机中算出的第二次的注册码,再点击“注册”按钮;然后将用户名重新输入到注册码编辑框中,点击“再次”按钮,再点掉错误提示,再次输入第二次的注册码,点击“再次”按钮,程序破解全部完成!
自己的007练习附件: 007-1.7z (587.62 KB, 下载次数: 71) 包括原程序、汉化后的程序及爆破后的程序、注册机及源码均在内。
百度链接是:http://pan.baidu.com/s/1skMkJY9 密码: 86pm160CM、个人学习过的前7crackme程序都在里面。

免费评分

参与人数 15威望 +2 吾爱币 +24 热心值 +14 收起 理由
小婊砸 + 1 + 1 我很赞同!
SomnusXZY + 1 + 1 谢谢@Thanks!
a5606495 + 1 + 1 谢谢@Thanks!
pk8900 + 1 + 1 我很赞同!
xiaozhou2017 + 1 + 1 热心回复!
thisis + 1 + 1 我很赞同!
Lbf + 1 + 1 谢谢@Thanks!
Sound + 2 + 9 + 1 已经处理,感谢您对吾爱破解论坛的支持!
lumou + 1 + 1 用心讨论,共获提升!
夏雨微凉 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
zhenyan + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
灰太狼大王 + 1 + 1 先收藏了
pwp + 1 用心讨论,共获提升!
WYWZ + 1 用心讨论,共获提升!
KaQqi + 3 + 1 涛个贴留个名

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

肥牛 发表于 2017-6-5 07:00
其实楼主在分析DeDe的时候就能看出来,有一个叫Again的按钮是隐藏状态:
[Delphi] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
object Registerz: TButton
  Left = 24
  Top = 16
  Width = 113
  Height = 41
  Caption = 'Register...'
  TabOrder = 0
  OnClick = RegisterzClick
end
object Again: TButton
  Left = 160
  Top = 16
  Width = 113
  Height = 41
  Caption = '...again !!! :p'
  TabOrder = 1
  Visible = False
  OnClick = AgainClick
end


再去分析Registerz中的代码,应该是先把隐藏按钮显示出来。再分析Registerz按钮和Again按钮,基本功能都是一样的。所以只需要分析一个按钮的功能就可以了。
[Asm] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
* Reference to control Codice : TLabel
|
00443105   8B83DC020000           mov     eax, [ebx+$02DC]
 
* Reference to: controls.TControl.GetText(TControl):TCaption;
|
0044310B   E83001FEFF             call    00423240
00443110   8B45F4                 mov     eax, [ebp-$0C]
 
* Reference to : TPrincipale._PROC_00442A8C()               //这是第一个关键点
|
00443113   E874F9FFFF             call    00442A8C
00443118   A330584400             mov     dword ptr [$00445830], eax
0044311D   BA9C324400             mov     edx, $0044329C
 
* Reference to control Codice : TLabel
|
00443122   8B83DC020000           mov     eax, [ebx+$02DC]
 
* Reference to: controls.TControl.SetText(TControl;TCaption);
|
00443128   E84301FEFF             call    00423270
0044312D   E9DD000000             jmp     0044320F
00443132   85F6                   test    esi, esi
00443134   0F8EC4000000           jle     004431FE
0044313A   8D55F4                 lea     edx, [ebp-$0C]
 
* Reference to control Nome : TLabel
|
0044313D   8B83D8020000           mov     eax, [ebx+$02D8]
 
* Reference to: controls.TControl.GetText(TControl):TCaption;
|
00443143   E8F800FEFF             call    00423240
00443148   8B4DF4                 mov     ecx, [ebp-$0C]
0044314B   8BD6                   mov     edx, esi
0044314D   A130584400             mov     eax, dword ptr [$00445830]
 
|
00443152   E851F8FFFF             call    004429A8          //这是第二个关键点
00443157   84C0                   test    al, al
00443159   7473                   jz      004431CE
0044315B   33D2                   xor     edx, edx
 
* Reference to control Again : TButton

很显然,第一个函数是判断有没有特殊字符的,也就是说要报错的。第二个函数是计算注册码的。
而且,从代码中可以看到,第一个函数与第二个函数是互斥的,执行第一个就不会执行第二个了,执行第二个就不会执行第一个。
但是,第一个函数的结果会影响到第二个函数的注册码的计算。
那么思路就是先输入一个带有特殊字符的注册码,让程序报错,然后再输入正确的注册码。
于是,按照这个思路写注册机就行了。
注意看,我输入的第一个注册码是带空格的,这个注册码不同,最终生成的真正的注册码也不同。
另外,再和楼主说一下,生成最终的注册码时,不需要用穷举法。
只需要把前面阶段生成的(EBX-1)*0x59,然后再去与0x50的余数找平就可以了。
[Delphi] 纯文本查看 复制代码
1
2
3
EAX := (EBX-1) * $59;
EDX := EAX mod $50;
EAX := EAX - EDX +1;


1.png
2.png
3.png
llto521 发表于 2017-6-3 14:04
pwp 发表于 2017-6-3 15:17
 楼主| 海天一色001 发表于 2017-6-3 15:42

谢谢你的评分和回复!不过我还只是初学者,目标是专家,现在还远远达不到标准呢!希望能在论坛中共同学习提高!!
pwp 发表于 2017-6-3 15:44
海天一色001 发表于 2017-6-3 15:42
谢谢你的评分和回复!不过我还只是初学者,目标是专家,现在还远远达不到标准呢!希望能在论坛中共同学习 ...

你学过汇编的对吧?看着你分析的好透彻
夏雨微凉 发表于 2017-6-3 15:50
多谢楼主分享教程
我爱小豆丁3.29 发表于 2017-6-3 17:21
我也想学,楼主能否加个联系方式把用到的工具发下。也想有个老司机带这学下
byh3025 发表于 2017-6-3 20:27
能把CM分析地这么透彻,将来必定是大牛,先膜拜下
肥牛 发表于 2017-6-3 20:58
明天我也研究一下这个007
渴望自来 发表于 2017-6-3 21:04
看到论坛里一个个厉害的程序员,真的好羡慕啊……
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-5-21 14:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表