【吾爱2013CM大赛解答】-- 2013CM - Crack晓晓爆破&补丁
本帖最后由 封心锁爱 于 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 >> 这里
004343F2|>5B pop ebx
004343F3\.C3 retn
然后来运行程序,输入用户名和密码,点按钮后断下,然后F7,单步走一段,到下面这里
00468102 .8B45 FC mov eax, dword ptr ;eax = 用户名
00468105 .8038 35 cmp byte ptr , 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:
00468119 .64:8920 mov dword ptr fs:, esp ;构造SEH
0046811C .3E:0000 add byte ptr , 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:, edx
00468127 .E9 D1000000 jmp 004681FD
0046812C .^ E9 A7B4F9FF jmp 004035D8 ;跳向异常处理程序
00468131 .8B45 FC mov eax, dword ptr ;eax = 用户名
00468134 .8078 02 50 cmp byte ptr , 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:
00468149 .64:8920 mov dword ptr fs:, esp ;同样是构造SEH,在0x00468116下段
0046814C .8B45 DC mov eax, dword ptr
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:, edx
0046815C .E9 97000000 jmp 004681F8
00468161 .^ E9 72B4F9FF jmp 004035D8
00468166 .8B45 F8 mov eax, dword ptr
00468169 .8078 01 32 cmp byte ptr , 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:
0046817E .64:8920 mov dword ptr fs:, esp ;seh
00468181 .8B45 F8 mov eax, dword ptr
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:, edx
00468191 .EB 60 jmp short 004681F3
00468193 .^ E9 40B4F9FF jmp 004035D8
00468198 .8B45 F4 mov eax, dword ptr
0046819B .8078 04 4A cmp byte ptr , 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:
004681AC .64:8920 mov dword ptr fs:, esp ;seh
004681AF .8B45 E4 mov eax, dword ptr
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:, edx
004681BF .EB 2D jmp short 004681EE
004681C1 .^ E9 12B4F9FF jmp 004035D8
004681C6 .8B45 F0 mov eax, dword ptr
004681C9 .8078 03 6F cmp byte ptr , 0x6F;第4位是否为'o'
004681CD .75 1A jnz short 004681E9
004681CF .8B45 EC mov eax, dword ptr
004681D2 .8078 06 65 cmp byte ptr , 0x65;第7位是否为'e'
004681D6 .75 11 jnz short 004681E9
004681D8 .8B45 F4 mov eax, dword ptr
004681DB .8078 05 69 cmp byte ptr , 0x69;第8位是否为'i'
004681DF .75 08 jnz short 004681E9
004681E1 .8B45 DC mov eax, dword ptr ; 至此我们可以知道用户名为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:
00468119 .64:8920 mov dword ptr fs:, 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 , 0x0
00407EF2 >74 19 je short 00407F0D ;这里不跳会引发异常
00407EF4 .895C24 04 mov dword ptr , ebx
可以看到,引不引发异常,je来控制,经过跟踪发现,在call 00402b74中会判断,如果密码中存在字符或密码根据下面式子
Sum = 0, Sum += Sum * 10 + Key一位的整数值, 当Sum > 0x0ccccccc时除才不为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 , esi
00467E05 .40 inc eax
00467E06 .0045 FC add byte ptr , 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 ;取3次加密后的MD50 x1d位
00467E78 .8850 01 mov byte ptr , dl
00467E7B .C600 01 mov byte ptr , 0x1
00467E7E .8D55 D8 lea edx, dword ptr
00467E81 .8D45 D4 lea eax, dword ptr
00467E84 .E8 AFABF9FF call 00402A38
00467E89 .8D45 D0 lea eax, dword ptr
00467E8C .8B55 F8 mov edx, dword ptr
00467E8F .8A52 1E mov dl, byte ptr ;取MD5值 0x1e位
00467E92 .8850 01 mov byte ptr , dl
00467E95 .C600 01 mov byte ptr , 0x1
00467E98 .8D55 D0 lea edx, dword ptr
00467E9B .8D45 D4 lea eax, dword ptr
00467E9E .B1 02 mov cl, 0x2
00467EA0 .E8 63ABF9FF call 00402A08
00467EA5 .8D55 D4 lea edx, dword ptr
00467EA8 .8D45 CC lea eax, dword ptr
00467EAB .E8 88ABF9FF call 00402A38
00467EB0 .8D45 D0 lea eax, dword ptr
00467EB3 .8B55 F8 mov edx, dword ptr
00467EB6 .8A52 1F mov dl, byte ptr ;取MD5 0x1f位
00467EB9 .8850 01 mov byte ptr , dl
00467EBC .C600 01 mov byte ptr , 0x1
00467EBF .8D55 D0 lea edx, dword ptr
00467EC2 .8D45 CC lea eax, dword ptr
00467EC5 .B1 03 mov cl, 0x3
00467EC7 .E8 3CABF9FF call 00402A08
00467ECC .8D55 CC lea edx, dword ptr
00467ECF .8D45 E4 lea eax, dword ptr
00467ED2 .E8 15C2F9FF call 004040EC
00467ED7 .8B45 E4 mov eax, dword ptr ;将上面取得的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 ;取返回地址
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跳或不跳
[版权声明]: 本文原创于封心锁爱, 转载请注明作者并保持文章的完整, 谢谢! 有时间仔细拜读{:301_993:} 好像很复杂呀,,,
我有点看不懂呀
要学习了 楼主辛苦了。 只能默默点赞,完全不懂 就这样伎俩被大牛分析的很透彻
膜拜了 {:1_932:}分析得很详细,膜拜
页:
[1]