上一篇的传送门 http://blog.csdn.net/airuozhaoyang/article/details/49872887
在上一篇的调试中,我们发现esi在最后的xor前,不同电脑上的值是不一样的。esi在关键call前存在了一部明显赋值的操作
0040130E |. /75 63 jnz short CrackHea.00401373
00401310 |. |8B35 9C334000 mov esi,dword ptr ds:[0x40339C]
00401316 |. |6A 28 push 0x28 ; /Count = 28 (40.)
00401318 |. |68 C4334000 push CrackHea.004033C4 ; |Buffer = CrackHea.004033C4
0040131D |. |FF35 90314000 push dword ptr ds:[0x403190] ; |hWnd = NULL
00401323 |. |E8 4C010000 call <jmp.&USER32.GetWindowTextA> ; \GetWindowTextA
00401328 |. |E8 A5000000 call CrackHea.004013D2 ; 这是干嘛的
0040132D |. |3BC6 cmp eax,esi ; 这个地方要返回zf=0 也就是eax=esi
mov esi,dword ptr ds:[0x40339C]
可是重新载入OD,发现一开始这个内存位置是0,看来一定是经过一系列初始化才导致不同pc的这个位置的数据不同从而使每个机器的最终结果也不同的。
我们在0x40339C处下断。
内存访问断点,OD内存断点只能设置一个。且程序重新加载后就会消失、
F9运行。
断点停在了ntdll.dll系统领空,alt+f9回到用户领空。
关键代码出现了。
0040140C /$ 60 pushad
0040140D |. 6A 00 push 0x0 ; /RootPathName = NULL
0040140F |. E8 B4000000 call <jmp.&KERNEL32.GetDriveTypeA> ; \GetDriveTypeA
00401414 |. A2 EC334000 mov byte ptr ds:[0x4033EC],al ; 磁盘类型参数送内存地址4033EC al=3
00401419 |. 6A 00 push 0x0 ; /pFileSystemNameSize = NULL
0040141B |. 6A 00 push 0x0 ; |pFileSystemNameBuffer = NULL
0040141D |. 6A 00 push 0x0 ; |pFileSystemFlags = NULL
0040141F |. 6A 00 push 0x0 ; |pMaxFilenameLength = NULL
00401421 |. 6A 00 push 0x0 ; |pVolumeSerialNumber = NULL
00401423 |. 6A 0B push 0xB ; |MaxVolumeNameSize = B (11.)
00401425 |. 68 9C334000 push CrackHea.0040339C ; |VolumeNameBuffer = CrackHea.0040339C
0040142A |. 6A 00 push 0x0 ; |RootPathName = NULL
0040142C |. E8 A3000000 call <jmp.&KERNEL32.GetVolumeInformation>; \GetVolumeInformationA
00401431 |. 8D35 9C334000 lea esi,dword ptr ds:[0x40339C] ; 把crackme程序所在分区的卷标名称送到ESI 不过得到的值是0 啊
00401437 |. 0FB60D EC3340>movzx ecx,byte ptr ds:[0x4033EC] ; 磁盘类型参数地址送到ecx中 此处ecx=3
0040143E |. 33FF xor edi,edi ; edi=0
00401440 |> 8BC1 mov eax,ecx ; eax=ecx=磁盘类型的参数地址、
00401442 |. 8B1E mov ebx,dword ptr ds:[esi] ; 分区的卷标名称以数值的形式存到ebx中
00401444 |. F7E3 mul ebx ; 循环相乘 累加
00401446 |. 03F8 add edi,eax
00401448 |. 49 dec ecx
00401449 |. 83F9 00 cmp ecx,0x0
0040144C |.^ 75 F2 jnz short CrackHea.00401440
0040144E |. 893D 9C334000 mov dword ptr ds:[0x40339C],edi ; 把edi的值写回给内存地址
00401454 |. 61 popad
00401455 \. C3 retn
分析到这里 思路就清晰了、程序调用了两个windows api
GetVolumeInformation
GetDriveTypeA
得到他们的记过并进行一系列的运算,从而得出esi的值。
我这里GetDriveTypeA返回的是3.GetVolumeInformation返回的是0,
所以最后的答案也是0,如果别的电脑也像我这样磁盘返回的卷标为0的话,最后esi的值很有可能和我一样。
所以这个程序并不能做到真正的一机一码。