160个CrackMe之123

我并不是大神,所以哪里写的不对,还请各位大佬们指出来。

0x0 分析算法
OD载入,搜索字符串,发现关键函数0x004013C0,给这个函数下断点,然后随便输入一串注册码,程序成功断下。

首先,程序将字符串”ABCDEFGHIJKLMNOPQRSTUVWXYZ”拷贝到一个新的地址处

00401421    B9 06000000     mov     ecx, 0x6
00401426    BE 4C304000     mov     esi, 0040304C                               ; ABCDEFGHIJKLMNOPQRSTUVWXYZ
0040142B    8D7C24 24       lea     edi, dword ptr [esp+0x24]
0040142F    8D4424 14       lea     eax, dword ptr [esp+0x14]
00401433    F3:A5           rep     movs dword ptr es:[edi], dword ptr [esi]
00401435    66:A5           movs    word ptr es:[edi], word ptr [esi]

然后取出Code和Serial

00401437    50              push    eax
00401438    68 EA030000     push    0x3EA
0040143D    8BCD            mov     ecx, ebp
0040143F    C64424 50 04    mov     byte ptr [esp+0x50], 0x4
00401444    A4              movs    byte ptr es:[edi], byte ptr [esi]
00401445    E8 0A030000     call    <jmp.&MFC42.#3097>                          ; 取出Code
0040144A    8D4C24 10       lea     ecx, dword ptr [esp+0x10]
0040144E    51              push    ecx
0040144F    68 E9030000     push    0x3E9
00401454    8BCD            mov     ecx, ebp
00401456    E8 F9020000     call    <jmp.&MFC42.#3097>                          ; 取出Serial

然后用sscanf函数将Serial转换成整数

0040145B    8B4424 10       mov     eax, dword ptr [esp+0x10]
0040145F    8D5424 18       lea     edx, dword ptr [esp+0x18]
00401463    52              push    edx                                         ; Serial的整数形式
00401464    68 48304000     push    00403048                                    ; %d
00401469    50              push    eax                                         ; Serial
0040146A    FF15 84214000   call    dword ptr [<&MSVCRT.sscanf>]                ; msvcrt.sscanf

然后程序用srand函数设置一个随机数种子,种子值就是Serial的整数形式。

00401470    8B4C24 24       mov     ecx, dword ptr [esp+0x24]                   ; Serial的整数形式
00401474    51              push    ecx                                         ; Serial的整数形式
00401475    FF15 B0214000   call    dword ptr [<&MSVCRT.srand>]                 ; msvcrt.srand

然后调用rand函数,将rand函数返回的随机数除以0x1A,用余数取出”ABCDEFGHIJKLMNOPQRSTUVWXYZ”中的一个字符,一共进行12次。

0040147B    8B3D B8214000   mov     edi, dword ptr [<&MSVCRT.rand>]             ; msvcrt.rand
00401481    83C4 10         add     esp, 0x10
00401484    BE 0C000000     mov     esi, 0xC
00401489    FFD7            call    edi
0040148B    99              cdq
0040148C    B9 1A000000     mov     ecx, 0x1A
00401491    F7F9            idiv    ecx
00401493    8D4C24 0C       lea     ecx, dword ptr [esp+0xC]
00401497    8A5414 24       mov     dl, byte ptr [esp+edx+0x24]
0040149B    52              push    edx
0040149C    E8 AD020000     call    <jmp.&MFC42.#940>                           ; 转换成字符串
004014A1    4E              dec     esi
004014A2  ^ 75 E5           jnz     short 00401489

其中,Code所对应的每个余数如下:

int DATA[] = {0x13,0x12,0x12,0x5,0x13,0xC,0x4,0x19,0x3,0xF,0xA,0x12};

最后将转换成的字符串和Code比较,如果相等就成功,否则失败。

004014A4    8B4424 14       mov     eax, dword ptr [esp+0x14]
004014A8    8B4C24 0C       mov     ecx, dword ptr [esp+0xC]
004014AC    50              push    eax                                         ; Code
004014AD    51              push    ecx
004014AE    FF15 BC214000   call    dword ptr [<&MSVCRT._mbscmp>]               ; msvcrt._mbscmp
004014B4    83C4 08         add     esp, 0x8
004014B7    85C0            test    eax, eax
004014B9    75 12           jnz     short 004014CD                              ; 失败则转移

0x1 计算注册码
首先看一下srand函数是如何实现的:
函数取出保存随机数种子的地址,然后将参数1(即种子值)保存进去。

7404CAB0 >  8BFF            mov     edi, edi
7404CAB2    55              push    ebp
7404CAB3    8BEC            mov     ebp, esp
7404CAB5    E8 AAA20000     call    74056D64
7404CABA    8B4D 08         mov     ecx, dword ptr [ebp+0x8]         ; 取出种子值
7404CABD    8948 14         mov     dword ptr [eax+0x14], ecx        ; 保存种子值
7404CAC0    5D              pop     ebp
7404CAC1    C3              retn

然后再看一下rand函数是如何实现的:
函数首先取出保存随机数种子的地址,然后取出种子值,进行如下运算:

Seed = Seed * 0x343FD + 0x269EC3

其中,Seed就是取出的种子值。
最后程序将Seed进行如下运算,返回结果,这个结果就是随机数。

Seed >> 0x10 & 0x7FFF

在程序中的代码如下:

7404CA80 >  E8 DFA20000     call    74056D64
7404CA85    6948 14 FD43030>imul    ecx, dword ptr [eax+0x14], 0x343FD
7404CA8C    81C1 C39E2600   add     ecx, 0x269EC3
7404CA92    8948 14         mov     dword ptr [eax+0x14], ecx
7404CA95    C1E9 10         shr     ecx, 0x10
7404CA98    81E1 FF7F0000   and     ecx, 0x7FFF
7404CA9E    8BC1            mov     eax, ecx
7404CAA0    C3              retn

因为程序中有进行模运算(即取余数),因此无法逆向,考虑枚举。
枚举代码如下:
这里写图片描述
运行结果如图所示:
这里写图片描述
放到CM中测试一下,可以通过。
这里写图片描述

全文完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值