好友
阅读权限20
听众
最后登录1970-1-1
|
封心锁爱
发表于 2013-12-16 14:09
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
本帖最后由 封心锁爱 于 2013-12-16 14:14 编辑
[文章标题]: 【吾爱2013CM大赛解答】-- 2013CM - Crack晓晓爆破&补丁
[作者信息]: 封心锁爱
[操作平台]: Win7 Sp1
[使用工具]: OD
[软件名称]: 2013CM - Crack晓晓
[下载地址]:http://www.52pojie.cn/thread-228708-1-1.html
这个程序是个Delphi程序,我们可以用Delphi的按钮事件特征码FF 93 20 01 00 00 5B C3 53来找到关键地方!(感谢前辈),首先,我们Ctrl+g到00401000处,然后搜索特征码,找到后下断
004343E6 |. 8B83 24010000 mov eax, dword ptr [ebx+0x124>
004343EC |. FF93 20010000 call dword ptr [ebx+0x120] >> 这里
004343F2 |> 5B pop ebx
004343F3 \. C3 retn
然后来运行程序,输入用户名和密码,点按钮后断下,然后F7,单步走一段,到下面这里
00468102 . 8B45 FC mov eax, dword ptr [ebp-0x4] ; eax = 用户名
00468105 . 8038 35 cmp byte ptr [eax], 0x35 ; 比较用户名第一位是否为'5'
00468108 . 0F85 EF000000 jnz 004681FD
0046810E . 33C0 xor eax, eax
00468110 . 55 push ebp
00468111 . 68 2C814600 push 0046812C ; SEH处理程序
00468116 . 64:FF30 push dword ptr fs:[eax]
00468119 . 64:8920 mov dword ptr fs:[eax], esp ; 构造SEH
0046811C . 3E:0000 add byte ptr [eax], al ; 触发异常,在0x0046812c下断
0046811F . 33C0 xor eax, eax
00468121 . 5A pop edx
00468122 . 59 pop ecx
00468123 . 59 pop ecx
00468124 . 64:8910 mov dword ptr fs:[eax], edx
00468127 . E9 D1000000 jmp 004681FD
0046812C .^ E9 A7B4F9FF jmp 004035D8 ; 跳向异常处理程序
00468131 . 8B45 FC mov eax, dword ptr [ebp-0x4] ; eax = 用户名
00468134 . 8078 02 50 cmp byte ptr [eax+0x2], 0x50 ; 比较第3位是否为'P'
00468138 . 0F85 BA000000 jnz 004681F8
0046813E . 33C0 xor eax, eax
00468140 . 55 push ebp
00468141 . 68 61814600 push 00468161
00468146 . 64:FF30 push dword ptr fs:[eax]
00468149 . 64:8920 mov dword ptr fs:[eax], esp ; 同样是构造SEH,在0x00468116下段
0046814C . 8B45 DC mov eax, dword ptr [ebp-0x24]
0046814F . E8 88FDF9FF call 00407EDC
00468154 . 33C0 xor eax, eax
00468156 . 5A pop edx
00468157 . 59 pop ecx
00468158 . 59 pop ecx
00468159 . 64:8910 mov dword ptr fs:[eax], edx
0046815C . E9 97000000 jmp 004681F8
00468161 .^ E9 72B4F9FF jmp 004035D8
00468166 . 8B45 F8 mov eax, dword ptr [ebp-0x8]
00468169 . 8078 01 32 cmp byte ptr [eax+0x1], 0x32 ; 比较用户名第2位是否为'2'
0046816D . 0F85 80000000 jnz 004681F3
00468173 . 33C0 xor eax, eax
00468175 . 55 push ebp
00468176 . 68 93814600 push 00468193
0046817B . 64:FF30 push dword ptr fs:[eax]
0046817E . 64:8920 mov dword ptr fs:[eax], esp ; seh
00468181 . 8B45 F8 mov eax, dword ptr [ebp-0x8]
00468184 . E8 53FDF9FF call 00407EDC
00468189 . 33C0 xor eax, eax
0046818B . 5A pop edx
0046818C . 59 pop ecx
0046818D . 59 pop ecx
0046818E . 64:8910 mov dword ptr fs:[eax], edx
00468191 . EB 60 jmp short 004681F3
00468193 .^ E9 40B4F9FF jmp 004035D8
00468198 . 8B45 F4 mov eax, dword ptr [ebp-0xC]
0046819B . 8078 04 4A cmp byte ptr [eax+0x4], 0x4A ; 第5位是否为'J'
0046819F . 75 4D jnz short 004681EE
004681A1 . 33C0 xor eax, eax
004681A3 . 55 push ebp
004681A4 . 68 C1814600 push 004681C1
004681A9 . 64:FF30 push dword ptr fs:[eax]
004681AC . 64:8920 mov dword ptr fs:[eax], esp ; seh
004681AF . 8B45 E4 mov eax, dword ptr [ebp-0x1C]
004681B2 . E8 25FDF9FF call 00407EDC
004681B7 . 33C0 xor eax, eax
004681B9 . 5A pop edx
004681BA . 59 pop ecx
004681BB . 59 pop ecx
004681BC . 64:8910 mov dword ptr fs:[eax], edx
004681BF . EB 2D jmp short 004681EE
004681C1 .^ E9 12B4F9FF jmp 004035D8
004681C6 . 8B45 F0 mov eax, dword ptr [ebp-0x10]
004681C9 . 8078 03 6F cmp byte ptr [eax+0x3], 0x6F ; 第4位是否为'o'
004681CD . 75 1A jnz short 004681E9
004681CF . 8B45 EC mov eax, dword ptr [ebp-0x14]
004681D2 . 8078 06 65 cmp byte ptr [eax+0x6], 0x65 ; 第7位是否为'e'
004681D6 . 75 11 jnz short 004681E9
004681D8 . 8B45 F4 mov eax, dword ptr [ebp-0xC]
004681DB . 8078 05 69 cmp byte ptr [eax+0x5], 0x69 ; 第8位是否为'i'
004681DF . 75 08 jnz short 004681E9
004681E1 . 8B45 DC mov eax, dword ptr [ebp-0x24] ; 至此我们可以知道用户名为52PoJie
004681E4 . E8 0BFCFFFF call 00467DF4 ; 这里F7
这个程序用了很多异常处理,如果不引发异常会走不到关键,下面这段代码就是构造一个SEH,跟踪时我们需要在SEH处理程序处下段,
也就是xxxxxxxx地址处,经过跟踪,这个程序的异常处理程序每次都返回到xxxxxxxx下面,大家也可以直接在xxxxxxxx下面下断
00468111 . 68 2C814600 push xxxxxxxx ; SEH处理程序
00468116 . 64:FF30 push dword ptr fs:[eax]
00468119 . 64:8920 mov dword ptr fs:[eax], esp ; 构造SEH
到下面是注意下,这个函数会引发异常,进行下一阶段,如果没引发异常的话就会跳过关键走了
0046814F . E8 88FDF9FF call 00407EDC ; >> f7进去瞅瞅
sub_00407EDC:
00407EE1 . 8BD8 mov ebx, eax
00407EE3 . 8BD4 mov edx, esp
00407EE5 . 8BC3 mov eax, ebx
00407EE7 . E8 88ACFFFF call 00402B74 ; 返回密码的10进制值
00407EEC 8BF0 mov esi, eax
00407EEE 833C24 00 cmp dword ptr [esp], 0x0
00407EF2 > 74 19 je short 00407F0D ; 这里不跳会引发异常
00407EF4 . 895C24 04 mov dword ptr [esp+0x4], ebx
可以看到,引不引发异常,je来控制,经过跟踪发现,在call 00402b74中会判断,如果密码中存在字符或密码根据下面式子
Sum = 0, Sum += Sum * 10 + Key一位的整数值, 当Sum > 0x0ccccccc时[esp]除才不为0,也就是会引发异常,现阶段我们需要引发异常才能继续执行下去,所我们先手改下,继续走下去
下面几个类似,就不说了,走到004681E4后F7进入,进入后会发现Jnz很奇怪,跳向了一条指令的第二个字节,刚开始我以为OD有问题,可是我用IDA看了下,并没有问题,而且机器码并不一样,然后我将程序重新载入,但不运行,发现这个地方是正常的,这说明在程序的运行时这里的指令被改了,下面我们来找出修改的地方
00467DF4 $ 55 push ebp
00467DF5 . 8BEC mov ebp, esp
00467DF7 . B9 09000000 mov ecx, 0x9
00467DFC > 6A 00 push 0x0
00467DFE . 6A 00 push 0x0
00467E00 . 49 dec ecx
00467E01 . 75 52 jnz short 00467E55
00467E03 . 0131 add dword ptr [ecx], esi
00467E05 . 40 inc eax
00467E06 . 0045 FC add byte ptr [ebp-0x4], al
我们右击Jnz处,选择数据窗口跟随--选择,在数据窗口中Jnz的第二个字节下硬件访问断点
然后重新载入,运行程序,断在这里
我们看到这个过程是在检查从467df4开始的0x64字节是否存在0xcc,也就是内存断点,如果有的话,就返回1,我们继续走出这个过程
走出后可以发现,如果存在内存断点就会修改指令了,我们在这个过程头部下端,重新载入运行看看,可以看到会检查两个地方,第一个是从4680cc开始的0x258字节,第二个是从467DF4开始的0x64字节,这里让两个跳转跳过改指令处就可以了,下面我们继续看call 00467df4,这下代码没有乱了,我们单步,走到467e33
跟踪可以发现是3个MD5函数,将密码3次MD5加密,继续走
00467E75 . 8A52 1D mov dl, byte ptr [edx+0x1D] ; 取3次加密后的MD50 x1d位
00467E78 . 8850 01 mov byte ptr [eax+0x1], dl
00467E7B . C600 01 mov byte ptr [eax], 0x1
00467E7E . 8D55 D8 lea edx, dword ptr [ebp-0x28]
00467E81 . 8D45 D4 lea eax, dword ptr [ebp-0x2C]
00467E84 . E8 AFABF9FF call 00402A38
00467E89 . 8D45 D0 lea eax, dword ptr [ebp-0x30]
00467E8C . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467E8F . 8A52 1E mov dl, byte ptr [edx+0x1E] ; 取MD5值 0x1e位
00467E92 . 8850 01 mov byte ptr [eax+0x1], dl
00467E95 . C600 01 mov byte ptr [eax], 0x1
00467E98 . 8D55 D0 lea edx, dword ptr [ebp-0x30]
00467E9B . 8D45 D4 lea eax, dword ptr [ebp-0x2C]
00467E9E . B1 02 mov cl, 0x2
00467EA0 . E8 63ABF9FF call 00402A08
00467EA5 . 8D55 D4 lea edx, dword ptr [ebp-0x2C]
00467EA8 . 8D45 CC lea eax, dword ptr [ebp-0x34]
00467EAB . E8 88ABF9FF call 00402A38
00467EB0 . 8D45 D0 lea eax, dword ptr [ebp-0x30]
00467EB3 . 8B55 F8 mov edx, dword ptr [ebp-0x8]
00467EB6 . 8A52 1F mov dl, byte ptr [edx+0x1F] ; 取MD5 0x1f位
00467EB9 . 8850 01 mov byte ptr [eax+0x1], dl
00467EBC . C600 01 mov byte ptr [eax], 0x1
00467EBF . 8D55 D0 lea edx, dword ptr [ebp-0x30]
00467EC2 . 8D45 CC lea eax, dword ptr [ebp-0x34]
00467EC5 . B1 03 mov cl, 0x3
00467EC7 . E8 3CABF9FF call 00402A08
00467ECC . 8D55 CC lea edx, dword ptr [ebp-0x34]
00467ECF . 8D45 E4 lea eax, dword ptr [ebp-0x1C]
00467ED2 . E8 15C2F9FF call 004040EC
00467ED7 . 8B45 E4 mov eax, dword ptr [ebp-0x1C] ; 将上面取得的3位组成字符串然后转换为整数值
00467EDA . E8 FDFFF9FF call 00407EDC ; 这里不能让它引发异常,会跳过成功
00467EDF . 83F8 6E cmp eax, 0x6E
00467EE2 . 0F85 07010000 jnz 00467FEF ; 同样会跳过成功
下面还有个去MD5第0x4, 0x5, 0x6位的,类似,就不贴,还有一些会跳过成功的跳转的,我在这里总的贴下,也不细说了
00467F3C . /7D 15 jge short 00467F53 ; 这个要跳
00467FC8 . /75 25 jnz short 00467FEF ; 不准跳
这里我们说下00407edc这个函数,也就是前面说过会引发异常的函数,在00467df4这个call中可不像前面了,在这个call里面如果发生异常会跳过成功的,所以我们不能让它引发异常,触发异常的条件和前面一样,因为这次是取MD5的一些位,不知怎么弄,所以只能爆破了,下面来说下补丁的做法,改一些跳转的方法就不写了,大家都会,这里说下怎么让这个引发异常的函数该引发异常时引发异常,不该引发时不引发
首先呢,我们修改00407edc这个函数Je前面指令为Jmp xxxxxxxx, xxxxxxxx为一个空白区域地址,如果你要打文件补丁,这个地址不要选择里程序代码段底部太远,因为在od里看到的一些空白是因内存对齐造成的,文件中并不存在,这里我选择468584
下面是468554的代码
00468584 > \60 pushad
00468585 8B4424 34 mov eax, dword ptr [esp+0x34] ; 取返回地址
00468589 3D DA7E4600 cmp eax, 00467EDA ; 判断是否在467eda - 467fc8区间
0046858E 72 1B jb short 004685AB
00468590 3D C87F4600 cmp eax, 00467FC8
00468595 77 04 ja short 0046859B
00468597 3BC0 cmp eax, eax ; 在的话不应该引发异常,zf置1
00468599 EB 10 jmp short 004685AB
0046859B 3D 4F814600 cmp eax, 0046814F ; 判断是否在46814f - 4681e4区间
004685A0 72 09 jb short 004685AB
004685A2 3D E4814600 cmp eax, 004681E4
004685A7 77 02 ja short 004685AB
004685A9 3BC1 cmp eax, ecx ; 在的话应该引发异常,zf置0
004685AB 61 popad
004685AC ^ E9 41F9F9FF jmp 00407EF2
代码不难,就是判断返回值是否在需要引发异常或不需要引发异常的区间中,根据这个来修改zf标志来让je跳或不跳
[版权声明]: 本文原创于封心锁爱, 转载请注明作者并保持文章的完整, 谢谢! |
免费评分
-
查看全部评分
|