[PrOZel]CrackMe
引用作者PrOZel的话:
用vc6写的,没有壳,没有修改IAT,有Anti-Debug代码,算法不难
http://bbs.pediy.com/showthread.php?threadid=12375
请指正,谢谢!
本人思路:
OD不能调试,Win32ASM没有串参考,只好Trw2000跟踪:bpx hmemcpy
gaojianhui:87654321
2次F12,n次F10到此处:
1.算法分析:
016F:00401546 CALL `MFC42!ord_000018BE`
016F:0040154B MOV EAX,[ESI+64] [esi+64]=6542A0='87654321'
016F:0040154E MOV EBP,[004031D4]
016F:00401554 PUSH DWORD 004040EC
016F:00401559 PUSH EAX
016F:0040155A CALL EBP 返回eax=1
016F:0040155C ADD ESP,BYTE +08
016F:0040155F TEST EAX,EAX
016F:00401561 JZ 004015DD
注:判断注册码是否为空
016F:00401563 MOV EAX,[ESI+60] [esi+60]=6552928='gaojianhui'
016F:00401566 LEA EBX,[ESI+60]
016F:00401569 PUSH DWORD 004040EC
016F:0040156E PUSH EAX
016F:0040156F CALL EBP 返回eax=1
016F:00401571 ADD ESP,BYTE +08
016F:00401574 TEST EAX,EAX
016F:00401576 JZ 004015DD
注:判断用户名是否为空
016F:00401578 MOV ECX,[ESI+64]
016F:0040157B XOR EAX,EAX
016F:0040157D MOVSX EDX,BYTE [ECX+EAX] edx=38,37,...,31,0
016F:00401581 XOR EDX,AA edx=92,9D,...,9B,AA
016F:00401587 ADD EDI,EDX edi=92,12F,...,4D4,57E
016F:00401589 INC EAX eax=0,1,...,8 到9的时候就不计算了。
016F:0040158A CMP EAX,BYTE +09 不管注册码几个,都计算9次。
016F:0040158D JL 0040157D 循环计算输入的注册码
016F:0040158F PUSH EDI 注册码计算值edi=57e
016F:00401590 PUSH ECX ecx=6524a0='87654321'
注:以上段码循环计算注册码‘87654321’,得到一个值57e保存在edi,这个值在后面4019c3与另一个注册码计算值进行比较。
016F:00401591 MOV ECX,ESP
016F:00401593 MOV [ESP+1C],ESP
016F:00401597 PUSH EBX
016F:00401598 CALL `MFC42!ord_00000217` eax=63F7C0
016F:0040159D MOV ECX,ESI
016F:0040159F CALL 00401930 见下面的分析。
016F:004015A4 TEST EAX,EAX 错误注册码eax=0,正确eax=1
016F:004015A6 JZ 004015C2 此处不能被爆破。
【一】
016F:004015A8 XOR EDI,EDI
016F:004015AA MOV AL,[ESP+EDI+18]
016F:004015AE LEA ECX,[ESP+10]
016F:004015B2 XOR AL,AA
016F:004015B4 PUSH EAX
016F:004015B5 CALL `MFC42!ord_000003AC`
016F:004015BA INC EDI
016F:004015BB CMP EDI,BYTE +0A
016F:004015BE JL 004015AA
016F:004015C0 JMP SHORT 004015F6
【二】
016F:004015C2 XOR EDI,EDI
016F:004015C4 MOV CL,[ESP+EDI+24]
016F:004015C8 XOR CL,AA
016F:004015CB PUSH ECX
016F:004015CC LEA ECX,[ESP+14]
016F:004015D0 CALL `MFC42!ord_000003AC`
016F:004015D5 INC EDI
016F:004015D6 CMP EDI,BYTE +0A
016F:004015D9 JL 004015C4
016F:004015DB JMP SHORT 004015F6
从15c4到15d9,循环10次,ecx=...,A
【三】
016F:004015DD XOR EDI,EDI
016F:004015DF MOV DL,[ESP+EDI+30]
016F:004015E3 LEA ECX,[ESP+10]
016F:004015E7 XOR DL,AA
016F:004015EA PUSH EDX
016F:004015EB CALL `MFC42!ord_000003AC`
016F:004015F0 INC EDI
016F:004015F1 CMP EDI,BYTE +14
016F:004015F4 JL 004015DF
016F:004015F6 MOV EAX,[ESP+10]
016F:004015FA PUSH BYTE +00
016F:004015FC PUSH BYTE +00
016F:004015FE PUSH EAX
016F:004015FF MOV ECX,ESI
016F:00401601 CALL `MFC42!ord_00001080`
2.分析:
算法计算过程有3种结果:
【三】没有输入用户名或者注册码,
016F:00401561 JZ 004015DD
016F:00401576 JZ 004015DD
016F:00401601 CALL `MFC42!ord_00001080` 提示框:请输入用户名+注册码。
【二】输入了错误的用户名+注册码
016F:004015A6 JZ 004015C2
016F:00401601 CALL `MFC42!ord_00001080` 提示框:错误的注册码。
【一】正确的用户名+注册码
016F:00401601 CALL `MFC42!ord_00001080` 提示框:正确的注册码。
因此在016F:004015A6 JZ 004015C2处爆破,修改为JNZ后,程序不能运行,还是不能爆破。
3.关键call:
从016F:0040159F CALL 00401930来的:
:00401930 6AFF push FFFFFFFF
:00401932 6838204000 push 00402038
:00401937 64A100000000 mov eax, dword ptr fs:[00000000]
:0040193D 50 push eax
:0040193E 64892500000000 mov dword ptr fs:[00000000], esp
:00401945 83EC0C sub esp, 0000000C
:00401948 53 push ebx 63FD60
:00401949 56 push esi 63FD00
:0040194A 57 push edi 57E(016F:0040158F计算得到)
:0040194B 8B542428 mov edx, dword ptr [esp+28]
:0040194F B04B mov al, 4B
:00401951 8844240C mov byte ptr [esp+0C], al
:00401955 88442410 mov byte ptr [esp+10], al
:00401959 8B4AF8 mov ecx, dword ptr [edx-08]
:0040195C B04E mov al, 4E
:0040195E 88442412 mov byte ptr [esp+12], al
:00401962 88442414 mov byte ptr [esp+14], al
:00401966 33FF xor edi, edi
:00401968 33F6 xor esi, esi
:0040196A 33C0 xor eax, eax
:0040196C C644240D45 mov [esp+0D], 45
:00401971 85C9 test ecx, ecx
:00401973 C644240E59 mov [esp+0E], 59
:00401978 C644240F2D mov [esp+0F], 2D
:0040197D C644241141 mov [esp+11], 41
:00401982 C64424134F mov [esp+13], 4F
:00401987 7E0B jle 00401994
注:以上段码好像是初始化注册码,注册码好像存放在[esp+0C]到[esp+14],分别为:4B,45,59,2D,4B,41,4E,4F,4E,即KEY-KANON
:00401989 0FBE1C10 movsx ebx, byte ptr [eax+edx]
:0040198D 03F3 add esi, ebx
:0040198F 40 inc eax
:00401990 3BC1 cmp eax, ecx
:00401992 7CF5 jl 00401989
注:顺序取[eax+edx]=‘gaojianhui’的ASCII码,累加到esi=41F
:00401994 33C9 xor ecx, ecx
:00401996 0FBE440C0C movsx eax, byte ptr [esp+ecx+0C] EAX顺序取'KEY-KANON'
:0040199B 0FAFC6 imul eax, esi
:0040199E 99 cdq
:0040199F BB1A000000 mov ebx, 0000001A
:004019A4 F7FB idiv ebx
:004019A6 83C261 add edx, 00000061
:004019A9 81F2AA000000 xor edx, 000000AA
:004019AF 03FA add edi, edx
:004019B1 41 inc ecx
:004019B2 83F909 cmp ecx, 00000009
:004019B5 7CDF jl 00401996
注:顺序取'KEY-KANON'的ASCII码计算,循环9次,得到值赋给edi并进行累加。
edi=C2,19E,25E,32E,3F0,4B4,57F,659,724.
:004019B7 8B44242C mov eax, dword ptr [esp+2C] [esp+2C]=57E='0063F7C4'
:004019BB C7442420FFFFFFFF mov [esp+20], FFFFFFFF
:004019C3 3BF8 cmp edi, eax 关键比较edi=724,eax=57E
:004019C5 5F pop edi
:004019C6 5E pop esi
:004019C7 5B pop ebx
:004019C8 8D4C241C lea ecx, dword ptr [esp+1C]
:004019CC 751B jne 004019E9
:004019CE E837020000 Call 00401C0A
:004019D3 B801000000 mov eax, 00000001
:004019D8 8B4C240C mov ecx, dword ptr [esp+0C]
:004019DC 64890D00000000 mov dword ptr fs:[00000000], ecx
:004019E3 83C418 add esp, 00000018
:004019E6 C20800 ret 0008
:004019E9 E81C020000 Call 00401C0A
:004019EE 8B4C240C mov ecx, dword ptr [esp+0C]
:004019F2 33C0 xor eax, eax
:004019F4 64890D00000000 mov dword ptr fs:[00000000], ecx
:004019FB 83C418 add esp, 00000018
:004019FE C20800 ret 0008
注::004019C3 cmp edi, eax比较edi和eax的值,注册码正确就相等,不跳,在4019D3处赋值eax=1;注册码错误,跳到4019e9,在4019F2赋值eax=0。
4.分析:
从关键比较:004019C3 3BF8 cmp edi, eax可以看出:要让eax与edi相等,输入的注册码计算值应该为724,即依次累加的和分别为:C2,19E,25E,32E,3F0,4B4,57F,659,724
即每次的计算值为:C2,DC,C0,D0,C2,C4,CB,DA,CB.
程序对输入的注册码计算过程如下:
016F:0040157B XOR EAX,EAX
016F:0040157D MOVSX EDX,BYTE [ECX+EAX]
016F:00401581 XOR EDX,AA
016F:00401587 ADD EDI,EDX
016F:00401589 INC EAX
016F:0040158A CMP EAX,BYTE +09
016F:0040158D JL 0040157D
由C2,DC,C0,D0,C2,C4,CB,DA,CB逆向运算获得[ECX+EAX]='hvjzhnapa'
gaojianhui:hvjzhnapa注册成功!
5.总结:
该crackme对注册码验证通过2个不同的算法来运算的。
对输入的注册码计算:非常简单,就是顺序取数字,然后016F:00401581 XOR EDX,AA,对结果edx进行累加得到注册值A。
对输入的用户名进行计算:0040198D add esi, ebx得到一个累加值esi,然后顺序取‘KEY-KANON’数字×esi,然后再进行计算、累加004019AF add edi, edx得到注册值B。
最后对这两个注册值进行比较::004019C3 cmp edi, eax。相等即注册成功。
另外:不管注册码几位,只要前9为正确即注册成功。因为不管注册码输入多少位,0040158A CMP EAX,BYTE +09只计算前9位就退出循环。也因为它本身只设置了‘KEY-KANON’9位用来计算正确的注册值。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)