海天一色001 发表于 2019-7-12 07:38

160个Crackme之029学习笔记

第29个CM程序,和第28个界面差不多,输入name/serial=“52pojie/1234567890”,程序这次没将小写字母转换成大写形式,点击“CHECK”按钮,弹出错误提示框:

第一步、查壳:

无壳,仍是VC++6.0编程:
第二步、爆破
用OD载入CoSH.3.exe,智能搜索字符串:

在004015C5错误标题这一行双击进入CPU窗口:

在错误提示上面的004015C3处是由3个地方跳转来的,来到错误:

再向上一行的004015C1处是跳过错误,来到成功的跳,所以将直接将004015C3处命令改成jmp 004015C1让它跳到正确提示,

保存成可执行文件CoSH.3.jmp.exe,运行一下,不输入任何东西,点击“CHECK”按钮,弹出正确提示,爆破成功。

第三步、追码:
将004015 C3处的跳转指令撤消修改,观察代码,这一次要复杂得多了:
具体分析过程如下,大致分为4部分:(每一部分起止可能不很准确)
1、先判断name和serial的长度,均不能小于5位:
004014F5|.E8 AA030000   call <jmp.&MFC42.#CWnd::GetWindowTextLengthA_3876>       ;得到name长度
004014FA|.8945 EC       mov ,eax
004014FD|.837D EC 05    cmp ,0x5                                        ;name长度不小于5位,否则失败
00401501|.7F 05         jg short cosh_3.00401508                                 ;下步取假码
00401503|.E9 BB000000   jmp cosh_3.004015C3                                    ;失败
00401508|>8B4D E0       mov ecx,
0040150B|.83C1 60       add ecx,0x60
0040150E|.E8 91030000   call <jmp.&MFC42.#CWnd::GetWindowTextLengthA_3876>       ;==len(serial) 得到假码长度
00401513|.8945 E8       mov ,eax
00401516|.837D E8 05    cmp ,0x5                                        ;serial长度不小于5位
0040151A|.7F 05         jg short cosh_3.00401521
0040151C|.E9 A2000000   jmp cosh_3.004015C3
00401521|>8B45 E0       mov eax,
2、用i=1 to len(name)分别与name的第i位字符的ASC值异或,再转换成相对应的字符,组成一个新的字符串;
00401570|.33C0          xor eax,eax
00401572|.33DB          xor ebx,ebx
00401574|.33C9          xor ecx,ecx
00401576|.B9 01000000   mov ecx,0x1
0040157B|.33D2          xor edx,edx
0040157D|.8B45 E4       mov eax,                                        ;=name.text
00401580|>8A18          /mov bl,byte ptr ds:                              ;=asc(name(i))
00401582|.32D9          |xor bl,cl                                             ;= xor 1
00401584|.8818          |mov byte ptr ds:,bl                              ;ds:=
00401586|.41            |inc ecx                                                 ;=+1
00401587|.40            |inc eax                                                 ;=+1
00401588|.8038 00       |cmp byte ptr ds:,0x0                               ;cmp asc(name(i+1),0
0040158B|.^ 75 F3         \jnz short cosh_3.00401580

3、用i=10 to len(name)+10分别与serial的第i位字符的ASC值异或,再转换成相对应的字符,组成一个新的字符串;
0040158D|.33C0          xor eax,eax
0040158F|.33DB          xor ebx,ebx
00401591|.33C9          xor ecx,ecx
00401593|.B9 0A000000   mov ecx,0xA                                              ;=0xA
00401598|.33D2          xor edx,edx
0040159A|.8B45 F0       mov eax,                                        ;=serial.text
0040159D|>8A18          /mov bl,byte ptr ds:                              ;=asc(serial(i))
0040159F|.32D9          |xor bl,cl                                             ;= xor 0xA
004015A1|.8818          |mov byte ptr ds:,bl                              ;ds:=
004015A3|.41            |inc ecx                                                 ;=+1
004015A4|.40            |inc eax                                                 ;=+1
004015A5|.8038 00       |cmp byte ptr ds:,0x0
004015A8|.^ 75 F3         \jnz short cosh_3.0040159D
4、检查第2部分和第3部分生成的两个新的字符串每一位是否相等:
004015AA|.8B45 E4       mov eax,                                        ;name得到的字串
004015AD|.8B55 F0       mov edx,                                        ;serial得到的字串
004015B0|>33C9          /xor ecx,ecx
004015B2|.8A18          |mov bl,byte ptr ds:
004015B4|.8A0A          |mov cl,byte ptr ds:
004015B6|.3AD9          |cmp bl,cl                                             ;每一位进行比较,有一位不等就跳到错误
004015B8|.75 09         |jnz short cosh_3.004015C3
004015BA|.40            |inc eax
004015BB|.42            |inc edx
004015BC|.8038 00       |cmp byte ptr ds:,0x0
004015BF|.^ 75 EF         \jnz short cosh_3.004015B0
004015C1|.EB 16         jmp short cosh_3.004015D9
004015C3      6A 00         push 0x0
004015C5|.68 6C304000   push cosh_3.0040306C                                     ;ERROR
004015CA|.68 40304000   push cosh_3.00403040                                     ;One of the Details you entered was wrong
那么注册算法就很清楚了:
首先serial的长度必须和name的长度相等,且大于4;
其次asc(serial(i)) xor (i+9) = asc(name(i)) xor i。
因为xor的可逆性,所以asc(serial(i)) = asc(name(i)) xor i xor (i+9)
Serial(i)=chr(asc(name(i)) xor i xor (i+9))
最后按序连接每一个字符就得到真码了。具体代码见注册机。
附件,含CM原程序、爆破后的程序、注册机、OD的调试文件等。百度链接是:http://pan.baidu.com/s/1skMkJY9,密码: 86pm,160个CM、我已练习过的前29个crackme程序(不含012)都在里面。

wangqiuguo 发表于 2019-7-12 08:08

这个厉害,学习成长的路段

daymissed 发表于 2019-7-12 08:32

这个可以有的,收藏

血羽苍龙 发表于 2019-7-12 08:36

这个厉害,学习成长的路段

wapj152321 发表于 2019-7-12 08:43

谢谢分享

shelly1314 发表于 2019-7-12 08:57

感谢楼主分享

jizigo 发表于 2019-7-12 15:42

顶一个,终于有一个适合新手的教程了

30900 发表于 2019-7-12 21:24

我是菜鸟,感谢大神分享!学习啦!

吾乃齐天大圣 发表于 2019-7-13 09:59

感谢楼主!

益达婷宝 发表于 2019-7-13 23:38

是真的厉害的我
页: [1]
查看完整版本: 160个Crackme之029学习笔记