本文只是对只会玩爆破但想学算法的新手看的,高手飘过,第一次作品,错误请指出。
算法都少不了call,但是稍复杂一点的程序里面会有很多call(在关键部分附近),我们怎么知道哪个是关键call?而且进入关键call后我们要关注哪些数据?这些大牛们都讨论了N多遍,但他们的水平非我等小辈可比,他们会根据步过call后的寄存器变化就可以判断出它的作用,我们就茫然,所以看他们的文章就有点郁闷(是我太菜吧,反正我是不懂)。今天就来说说哪些call对结果有用,应关注哪些数据。说的只是一个思路(大牛们把这个当作一个当然,所以他们把这一步省了),具体的算法没写,但你可以从简单的入手。
首先找一个目标:我找的就是看雪大哥(他不认识我,我就厚着脸叫一声)的解密教学的“序列号保护方式习题的第九个”。
这个没加壳,我们就直接按字符串参考定位到关键跳转(只截一部分):
0042DB95 |> \8D55 FC lea edx, dword ptr [ebp-4]
0042DB98 |. 8B83 E4010000 mov eax, dword ptr [ebx+1E4]
0042DB9E |. E8 85C6FEFF call 0041A228
0042DBA3 |. 837D FC 00 cmp dword ptr [ebp-4], 0
0042DBA7 |. 75 1A jnz short 0042DBC3 //判断输入是否为空,否则跑到相应处
0042DBA9 |. 6A 00 push 0
0042DBAB |. 66:8B0D 1CDD4> mov cx, word ptr [42DD1C]
0042DBB2 |. B2 02 mov dl, 2
0042DBB4 |. B8 7CDD4200 mov eax, 0042DD7C ; please enter your serial !
0042DBB9 |. E8 82F2FFFF call 0042CE40
0042DBBE |. E9 2D010000 jmp 0042DCF0
0042DBC3 |> 8BC7 mov eax, edi //跑到这里,算法一定在这下面,在这里下断
0042DBC5 |. E8 7A59FDFF call 00403544
0042DBCA |. C706 02000000 mov dword ptr [esi], 2
0042DBD0 |> 8D55 FC /lea edx, dword ptr [ebp-4]
0042DBD3 |. 8B83 E0010000 |mov eax, dword ptr [ebx+1E0]
0042DBD9 |. E8 4AC6FEFF |call 0041A228
0042DBDE |. 8B45 FC |mov eax, dword ptr [ebp-4]
0042DBE1 |. 8B16 |mov edx, dword ptr [esi]
0042DBE3 |. 0FB64410 FF |movzx eax, byte ptr [eax+edx-1]
0042DBE8 |. 8D55 F8 |lea edx, dword ptr [ebp-8]
0042DBEB |. E8 8889FDFF |call 00406578
0042DBF0 |. 8B55 F8 |mov edx, dword ptr [ebp-8]
0042DBF3 |. 8BC7 |mov eax, edi
0042DBF5 |. E8 CE5BFDFF |call 004037C8
0042DBFA |. FF06 |inc dword ptr [esi]
0042DBFC |. 833E 07 |cmp dword ptr [esi], 7
0042DBFF |.^ 75 CF \jnz short 0042DBD0
0042DC01 |. 8D45 F8 lea eax, dword ptr [ebp-8]
0042DC04 |. 50 push eax
0042DC05 |. B9 03000000 mov ecx, 3
0042DC0A |. BA 01000000 mov edx, 1
0042DC0F |. 8B07 mov eax, dword ptr [edi]
0042DC11 |. E8 AE5DFDFF call 004039C4 ; 步过后两个数据都没变化
0042DC16 |. 8B45 F8 mov eax, dword ptr [ebp-8]
0042DC19 |. E8 8A89FDFF call 004065A8 ; 虽然步过后没改变,但下一条指令它的返回值改变第一个
0042DC1E |. A3 58F74200 mov dword ptr [42F758], eax
0042DC23 |. 8BC7 mov eax, edi
0042DC25 |. E8 1A59FDFF call 00403544 ;没改变
0042DC2A |. 8BC3 mov eax, ebx
0042DC2C |. E8 B3FCFFFF call 0042D8E4 ; 改变第一个
0042DC31 |. A1 50F74200 mov eax, dword ptr [42F750]
0042DC36 |. A3 50F74200 mov dword ptr [42F750], eax
0042DC3B |. 8BC3 mov eax, ebx
0042DC3D |. E8 F2FCFFFF call 0042D934 ; 改变第一个
0042DC42 |. A1 58F74200 mov eax, dword ptr [42F758]
0042DC47 |. A3 58F74200 mov dword ptr [42F758], eax
0042DC4C |. 8BC3 mov eax, ebx
0042DC4E |. E8 35FDFFFF call 0042D988 ; 改变第一个
0042DC53 |. 8BC3 mov eax, ebx
0042DC55 |. E8 7EFDFFFF call 0042D9D8 ; 改变第一个
0042DC5A |. A1 58F74200 mov eax, dword ptr [42F758]
0042DC5F |. A3 58F74200 mov dword ptr [42F758], eax
0042DC64 |. 8BC3 mov eax, ebx
0042DC66 |. E8 B1FDFFFF call 0042DA1C ; 没改变,暂时没用
0042DC6B |. 8BC3 mov eax, ebx
0042DC6D |. E8 B6FDFFFF call 0042DA28 ; 没改变
0042DC72 |. A1 58F74200 mov eax, dword ptr [42F758]
0042DC77 |. A3 58F74200 mov dword ptr [42F758], eax
0042DC7C |. 8BC3 mov eax, ebx
0042DC7E |. E8 B1FDFFFF call 0042DA34 ; 变第一个
0042DC83 |. 8BC3 mov eax, ebx
0042DC85 |. E8 F2FDFFFF call 0042DA7C
0042DC8A |. 8BC3 mov eax, ebx
0042DC8C |. E8 0BFEFFFF call 0042DA9C ; 变第一个
0042DC91 |. A1 50F74200 mov eax, dword ptr [42F750]
0042DC96 |. 0105 58F74200 add dword ptr [42F758], eax ; 操作,这里我们下一步可就多了一个关注对象( eax也就是42f750)了,这是下一步的关注对象,我们先关注当前的对象(一个一个先后关注),所以这里就先不管了
0042DC9C |. 8D55 FC lea edx, dword ptr [ebp-4]
0042DC9F |. 8B83 E4010000 mov eax, dword ptr [ebx+1E4]
0042DCA5 |. E8 7EC5FEFF call 0041A228 ; 没改变
0042DCAA |. 8B45 FC mov eax, dword ptr [ebp-4]
0042DCAD |. E8 F688FDFF call 004065A8
0042DCB2 |. A3 60F74200 mov dword ptr [42F760], eax ; 返回值赋给第二个
0042DCB7 |. A1 58F74200 mov eax, dword ptr [42F758]
0042DCBC |. 3B05 60F74200 cmp eax, dword ptr [42F760]
0042DCC2 |. 75 17 jnz short 0042DCDB ; 关键跳!!!
0042DCC4 |. 6A 00 push 0
0042DCC6 |. 66:8B0D 1CDD4>mov cx, word ptr [42DD1C]
0042DCCD |. B2 02 mov dl, 2
0042DCCF |. B8 A0DD4200 mov eax, 0042DDA0 ; good serial, thanks for trying this crackme by niabi !
0042DCD4 |. E8 67F1FFFF call 0042CE40
0042DCD9 |. EB 15 jmp short 0042DCF0
0042DCDB |> 6A 00 push 0
0042DCDD |. 66:8B0D 1CDD4>mov cx, word ptr [42DD1C]
0042DCE4 |. B2 02 mov dl, 2
0042DCE6 |. B8 E0DD4200 mov eax, 0042DDE0 ; bad name or serial number !!!!!
0042DCEB |. E8 50F1FFFF call 0042CE40
首先看关键跳处(关键跳我已标明),我们看它成功的条件是什么?要成功就必须0042DCBC处的eax和42f760地址里的(四个字节)数要相等,而看上面知道eax又等于42f758处的数,所以我们知道,成功的条件就是42f758(记为第一个地址)和42f760(记为第二个)处的数值相等!爆破的哥们当然就改这个地方就行,但是我们得弄算法啊!那么这两个地方的数是怎么来的?我们当然得往上看了。可以看到这里有好多call!思路不要乱,现在我们关注的就是(只是)那两处的数据(此为关注对象,现在知道该关注什么了吧)。那么我们可以想当然的认为,如果步过一个call我们那两处的数据不变,且下面也没有其返回结果传给这两处的话,那么这个call就没用(这里要想明白)。
我们把程序加载后,在我指示的地方下好断,然后把数据窗口打开,找到我们要关注的两处地址,接着就死死的盯着这两处!
然后我们F9运行,输入abcdef和123456( 至少6位),点cheak!程序断下,可以看到这两处都为0。盯着那两处,我们按F2单步,如果有地方执行过后这两处数据有变我们就注一下。我已做好注了,大家可以参考,可以定出对结果有影响的call来!
定出关键call后我们就可以进入其中分析算法,当然我们的关注对象还是那两处(中间可能会增加要关注的对象)。当把这两个对象的算法弄明白之后,我们再来关注下一个对象(像上面0042DC96处的eax,它影响到我们的对象了)。一个一个弄明白之后,呵呵,这个算法也就浮出水面。这个方法如果配合内存断点就完美了(ccdebuger大可的教程里已经说明了这个思路)。
我没时间弄算法了,就这样吧,只是给新手一个思路,有时间的话再自己写个简单的程序作例详细分析。
总结:
1.看成功的条件(条件有多个就一个一个分析) 2.根据条件定出关注对象 3.单步测试是不是关键的 4.进入关键call弄懂算法,再关注下一个对象 (下一个,再下一个。。。。) 5.完成!
(很抱歉,本来有图的,但不知道怎么插入,对不住了)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)