对于上面的006的破解还是比较简单的,我们现在打开第二个破解exe。
注意到 you cannot patch the.exe
好吧, 作者是让我们分析出其算法。
打开文件运行,用dede分析后,断点在两个button函数的入口:
我们分析Register的button函数,通过dede的分析看到setvisible函数我们可以明确到关键的代码分析点如下:
00442FB9 |. E8 EAF9FFFF call aLoNg3x_.004429A8 ; 判断的关键函数
00442FBE |. 84C0 test al,al
00442FC0 74 30 je short aLoNg3x_.00442FF2
00442FC2 |. 33D2 xor edx,edx
00442FC4 |. 8B83 CC020000 mov eax,dword ptr ds:[ebx+0x2CC] ; DWrite.61592074
00442FCA E8 6101FEFF call aLoNg3x_.00423130 ; setvisible
进去查看call aLoNg3x_.004429A8 函数,里面有如下循环:
004429F6 |> /8B45 F8 /mov eax,[local.2]
004429F9 |. |E8 3610FCFF |call aLoNg3x_.00403A34
004429FE |. |83F8 01 |cmp eax,0x1
00442A01 |. |7C 1D |jl short aLoNg3x_.00442A20
00442A03 |> |8B55 F8 |/mov edx,[local.2]
00442A06 |. |0FB65432 FF ||movzx edx,byte ptr ds:[edx+esi-0x1]
00442A0B |. |8B4D F8 ||mov ecx,[local.2]
00442A0E |. |0FB64C01 FF ||movzx ecx,byte ptr ds:[ecx+eax-0x1]
00442A13 |. |0FAFD1 ||imul edx,ecx ; aLoNg3x_.0041E570
00442A16 |. |0FAFD7 ||imul edx,edi
00442A19 |. |03DA ||add ebx,edx
00442A1B |. |48 ||dec eax
00442A1C |. |85C0 ||test eax,eax
00442A1E |.^|75 E3 |\jnz short aLoNg3x_.00442A03
00442A20 |> |46 |inc esi
00442A21 |. |FF4D F4 |dec [local.3]
00442A24 |.^\75 D0 \jnz short aLoNg3x_.004429F6
分析出改循环是将输入的name进行一个循环相乘叠加,举例如下:
比如输入foyjog,那么ans=’f’ * ‘g’ * edi + ‘f’‘o’*edi + ‘f’ ‘j’ *edi …..
当然溢出的时候ans会被剪掉,不想写keygen,就这么简单的表示一下,通过跟踪很容易明确代码的目的。
那么这个edi从哪里来呢?
004429B1 |. 894D F8 mov [local.2],ecx ; aLoNg3x_.0041E570
004429B4 |. 8955 FC mov [local.1],edx
004429B7 |. 8BF8 mov edi,eax
往上翻可以容易的看到从eax来,那么我们往上层跟踪代码发现
00442FB4 |. A1 30584400 mov eax,dword ptr ds:[0x445830]
那么这个dword ptr ds:[0x445830]从哪里来,在往上翻
00442F86 |. A3 30584400 mov dword ptr ds:[0x445830],eax
跟踪这条代码的上一个函数 aLoNg3x_.00442A8C发现里面还有一个循环如下:
00442AD2 |> /8B45 FC /mov eax,[local.1]
00442AD5 |. |0FB60408 |movzx eax,byte ptr ds:[eax+ecx]
00442AD9 |. |BF 11000000 |mov edi,0x11
00442ADE |. |33D2 |xor edx,edx
00442AE0 |. |F7F7 |div edi
00442AE2 |. |42 |inc edx
00442AE3 |. |8B45 FC |mov eax,[local.1]
00442AE6 |. |0FB64408 FF |movzx eax,byte ptr ds:[eax+ecx-0x1]
00442AEB |. |0FAFD0 |imul edx,eax
00442AEE |. |03F2 |add esi,edx
00442AF0 |. |41 |inc ecx ; aLoNg3x_.0041E570
00442AF1 |. |4B |dec ebx
00442AF2 |.^\75 DE \jnz short aLoNg3x_.00442AD2
跟踪代码得出以下的简单表示方式:
输入serial如下12345678910,为什么要输入这么长的,因为要进入这个代码区域就必须使serial>0x80000000,
00442F59 |. E8 FAF9FBFF call aLoNg3x_.00402958
00442F5E |. 8BF0 mov esi,eax
00442F60 |. 837D FC 00 cmp [local.1],0x0
00442F64 |. 74 37 je short aLoNg3x_.00442F9D
00442F66 |. B8 38304400 mov eax,aLoNg3x_.00443038 ; ASCII 59,"ou MUST insert a valid Long Integer Value in the Code Editor... Thank you :)"
从这段代码可以跟踪得出以上结论。
继续讲函数的用途,用c写出大概如下:
char input[100];
int ans = 0x37B;
for(int ii=0;ii<strlen(input);ii++)
{
ans1 += (input[ii+1]/11+1)*input[ii];
}
那么我们得到004429A8函数循环叠加的结果,那么跟谁比较呢,接着看代码如下:
00442A26 |> \8BC3 mov eax,ebx
00442A28 |. 99 cdq
00442A29 |. 33C2 xor eax,edx
00442A2B |. 2BC2 sub eax,edx
00442A2D |. B9 2A2C0A00 mov ecx,0xA2C2A
00442A32 |. 99 cdq
00442A33 |. F7F9 idiv ecx ; aLoNg3x_.0041E570
00442A35 |. 8BDA mov ebx,edx
00442A37 |. 8B45 FC mov eax,[local.1]
00442A3A |. B9 59000000 mov ecx,0x59
00442A3F |. 99 cdq
00442A40 |. F7F9 idiv ecx ; aLoNg3x_.0041E570
00442A42 |. 8BC8 mov ecx,eax
00442A44 |. 8B45 FC mov eax,[local.1]
00442A47 |. BE 50000000 mov esi,0x50
00442A4C |. 99 cdq
00442A4D |. F7FE idiv esi
00442A4F |. 03CA add ecx,edx
00442A51 |. 41 inc ecx ; aLoNg3x_.0041E570
00442A52 894D FC mov dword ptr ss:[ebp-0x4],ecx ; aLoNg3x_.0041E570
00442A55 |. 3B5D FC cmp ebx,[local.1]
关键在于 cmp ebx,[local.1],[local.1]是输入的serial的值,函数的大概意思如下:
用得出的ebx与eax xor,然后巴拉拉一系列操作,得出结果再次放入ebx,后面的代码的作用为:
ans2=serial/59+serial%50 +1 ;然后与ebx进行判断,这就牵扯到一个问题,如果上面代码的edi一直是0的话,那么ebx肯定也是0,就无法成功了,所以我们需要首先输入一个超出0x80000000的值,使得edi不为0,比如输入12345678910,之后能得到ebx不为0的值,通过ebx的值再去反推出ans2的serial值,我推出其中一组数据如下:
name:foyjog
serial1:12345678910
serial2:47999040
输入之后会弹出另一个button名为again,那么再输入一次即可: