看雪CTF 2016_第五题分析

这个题是一道穷举题,考察的应该是编程能力吧!

本题算法不是很难,也是挺好分析的。

 
 
 

这个程序可以下 GetDlgItem 这个api可以定位到关键地方。

 
 

00401183 > /8A540C 20 mov dl,byte ptr ss:[esp+ecx+0x20] 指向输入的假码

00401187 . |80FA 30 cmp dl,0x30 检测输入的假码是否小于30 即是否小于0

0040118A . |7C 0C jl short CrackMe.00401198

0040118C . |80FA 39 cmp dl,0x39 检测输入的假码是否大于39 即是否大于9

0040118F . |7F 07 jg short CrackMe.00401198

00401191 . |41 inc ecx

00401192 . |3BC8 cmp ecx,eax

00401194 .^72 ED jb short CrackMe.00401183

0040119A > 83F8 06 cmp eax,0x6 检测注册码长度是否为6

0040119D . 75 56 jnz short CrackMe.004011F5

0040119F . 85FF test edi,edi

004011A1 . 74 52 je short CrackMe.004011F5

004011A3 . 8D4C24 20 lea ecx,dword ptr ss:[esp+0x20]

这两段代码主要是检测输入的注册码是否为数字0-9,还有就是长度是否为6位。

004011A7 . 50 push eax

004011A8 . 51 push ecx

004011A9 . E8 52FEFFFF call CrackMe.00401000 ;

004011AE . 83C4 08 add esp,0x8

进入call 关键算法

00401020 |. 8D7C24 18 lea edi,dword ptr ss:[esp+0x18]

00401024 |. 33C0 xor eax,eax

00401026 |> 884404 18 /mov byte ptr ss:[esp+eax+0x18],al

0040102A |. 40 |inc eax ; 创建0-ff的数据

0040102B |. 3D 00010000 |cmp eax,0x100

00401030 |.^ 7C F4 jl short CrackMe.00401026

创建0-FF数据矩阵。

 
 

0040103B |. C74424 10 000>mov dword ptr ss:[esp+0x10],0x100 循环次数256

00401043 |> 8BB424 1C0100>/mov esi,dword ptr ss:[esp+0x11C] ; 指向假码

0040104A |. 8A0F |mov cl,byte ptr ds:[edi] 指向0-FF矩阵表

0040104C |. 8A1C30 |mov bl,byte ptr ds:[eax+esi] ; 依次取出假码

0040104F |. 02D9 |add bl,cl 进行加法操作

00401051 |. 02D3 |add dl,bl

00401053 |. 40 |inc eax

00401054 |. 885424 14 |mov byte ptr ss:[esp+0x14],dl 相加后的结果dl 赋值给esi

00401058 |. 8B7424 14 |mov esi,dword ptr ss:[esp+0x14]

0040105C |. 81E6 FF000000 |and esi,0xFF esiFF进行位与操作

00401062 |. 3BC5 |cmp eax,ebp

00401064 |. 8A5C34 18 |mov bl,byte ptr ss:[esp+esi+0x18] 将位与后的结果指向0-FF矩阵数据

00401068 |. 8D7434 18 |lea esi,dword ptr ss:[esp+esi+0x18]

0040106C |. 881F |mov byte ptr ds:[edi],bl 进行数据互换

0040106E |. 880E |mov byte ptr ds:[esi],cl 同上

00401070 |. 75 02 |jnz short CrackMe.00401074

00401072 |. 33C0 |xor eax,eax

00401074 |> 8B4C24 10 |mov ecx,dword ptr ss:[esp+0x10]

00401078 |. 47 |inc edi

00401079 |. 49 |dec ecx

0040107A |. 894C24 10 |mov dword ptr ss:[esp+0x10],ecx

0040107E |.^ 75 C3 jnz short CrackMe.00401043

这里的操作 用易语言代码表达:

这样就生成新的10 X 10矩阵表

 
 

00401089 |> /8A5404 18 /mov dl,byte ptr ss:[esp+eax+0x18] ; 指向新的矩阵表头部 然后依次加1指向

0040108D |. |8A19 |mov bl,byte ptr ds:[ecx] ; 指向新的矩阵表尾部 然后依次减1指向

0040108F |. |02D3 |add dl,bl ; 相加操作

00401091 |. |8A98 30604000 |mov bl,byte ptr ds:[eax+0x406030] ; 指向新的大小为0x80的矩阵表

00401097 |. |32DA |xor bl,dl ; 异或操作

00401099 |. |8898 30604000 |mov byte ptr ds:[eax+0x406030],bl ; 结果存放到刚才的0x80大小的矩阵数据里面

0040109F |. |40 |inc eax

004010A0 |. |49 |dec ecx

004010A1 |. |3D 80000000 |cmp eax,0x80 ; 循环128

004010A6 |.^7C E1 jl short CrackMe.00401089

最后生成大小为0x80的矩阵表
 
 

004010C8 |> /33C0 /xor eax,eax

004010CA |. |8A81 30604000 |mov al,byte ptr ds:[ecx+0x406030] 逐个拿出最后生成的矩阵表数据

004010D0 |. |99 |cdq

004010D1 |. |03F8 |add edi,eax 进行相加操作

004010D3 |. |13F2 |adc esi,edx

004010D5 |. |41 |inc ecx

004010D6 |. |81F9 80000000 |cmp ecx,0x80

004010DC |.^7C EA jl short CrackMe.004010C8

004010DE |. 81FF 79290000 cmp edi,0x2979 相加后的结果和0x2979进行对比,不相等的话,证明破解失败

004010E4 |. 75 0C jnz short CrackMe.004010F2

004010E6 |. 85F6 test esi,esi

004010E8 |. 75 08 jnz short CrackMe.004010F2

004010EA |. 5F pop edi

004010EB |. B8 01000000 mov eax,0x1

004010F0 |. 5E pop esi

004010F1 |. C3 retn

 
然后来到这里进行最后一步判断,把刚才得出最后的一张矩阵表每一个数据进行相加操作,然后和0x2979进行对比。

所以很明显,我们需要自己编写一个穷举程序来进行穷举。要进行穷举的范围为:000000-999999 只要结果等于0x2979 这个就是真正的注册码。

所以进行穷举后得出正确注册码为:771535

高清文档和源码:http://www.vdisk.cn/down/index/19748718

原文地址:https://www.cnblogs.com/Sendige/p/9601033.html