吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 14679|回复: 34
收起左侧

[原创] 一个CrackMe的分析

  [复制链接]
zbnysjwsnd8 发表于 2017-12-10 19:03

0x00 初探
程序有ASLR,不方便分析,使用FFI去掉。
这里写图片描述
OD载入后,发现程序退出。
这里写图片描述
给ExitProcess下断点,然后重新载入程序,成功断下。修改代码为retn 4即可。
这里写图片描述
此时即可使用OD调试。运行后,[确认]按钮是禁止状态。
0x01 寻找编辑框的输入事件
用彗星探测一下编辑框的句柄
这里写图片描述
给GetWindowTextW下条件断点。
这里写图片描述
输入一个字节即可断下。
这里写图片描述
单步回到004020D9处。
程序首先计算注册码的长度:
这里写图片描述
然后判断长度是否是16个字符,不是则返回。
这里写图片描述
构造一个长度是16个字符的key即可通过。我构造的是0123456789ABCDEF。
程序将16个字符的key转换成ANSI字符的形式。
这里写图片描述
然后调用函数004017C0。
0x02 重点函数004017C0的逆向
函数比较长,我直接放代码。注释已经标记。

004017C0   $  55            push    ebp
004017C1   .  8BEC          mov     ebp, esp
004017C3   .  8B4D 08       mov     ecx, dword ptr [ebp+8]                       ;  Key
004017C6   .  83EC 08       sub     esp, 8
004017C9   .  8BC1          mov     eax, ecx
004017CB   .  56            push    esi
004017CC   .  8D70 01       lea     esi, dword ptr [eax+1]
004017CF   .  90            nop
004017D0   >  8A10          mov     dl, byte ptr [eax]
004017D2   .  40            inc     eax
004017D3   .  84D2          test    dl, dl
004017D5   .^ 75 F9         jnz     short 004017D0
004017D7   .  2BC6          sub     eax, esi                                     ;  再次得到Key的长度
004017D9   .  83F8 10       cmp     eax, 10                                      ;  不是16个字节则触发异常
004017DC   .  74 01         je      short 004017DF
004017DE      FF            db      FF
004017DF   >  BA 58145700   mov     edx, 00571458
004017E4   .  33F6          xor     esi, esi
004017E6   .  2BD1          sub     edx, ecx
004017E8   >  8A01          mov     al, byte ptr [ecx]                           ;  取出一个字符 判断是否是数字或者是大写字母
004017EA   .  3C 29         cmp     al, 29
004017EC   .  7E 08         jle     short 004017F6
004017EE   .  3C 40         cmp     al, 40
004017F0   .  7D 06         jge     short 004017F8
004017F2   .  2C 30         sub     al, 30
004017F4   .  EB 0A         jmp     short 00401800
004017F6   >  3C 40         cmp     al, 40
004017F8   >  7E 52         jle     short 0040184C
004017FA   .  3C 47         cmp     al, 47
004017FC   .  7D 4E         jge     short 0040184C                               ;  如果不是数字或者不是大写字母则返回NULL
004017FE   .  2C 37         sub     al, 37
00401800   >  88040A        mov     byte ptr [edx+ecx], al                       ;  将对应的数字或者大写字母转换成整数保存('0' -> 0;'A' -> A)
00401803   .  46            inc     esi
00401804   .  41            inc     ecx
00401805   .  83FE 10       cmp     esi, 10
00401808   .^ 7C DE         jl      short 004017E8
0040180A   .  BA 02000000   mov     edx, 2
0040180F   .  81EA 59145700 sub     edx, 00571459
00401815   .  8955 FC       mov     dword ptr [ebp-4], edx
00401818   .  33C0          xor     eax, eax
0040181A   .  BA 03000000   mov     edx, 3
0040181F   .  81EA 59145700 sub     edx, 00571459
00401825   .  53            push    ebx
00401826   .  8D48 01       lea     ecx, dword ptr [eax+1]
00401829   .  8955 F8       mov     dword ptr [ebp-8], edx
0040182C   .  57            push    edi
0040182D   .  8D49 00       lea     ecx, dword ptr [ecx]
00401830   >  8BF8          mov     edi, eax
00401832   .  83E7 01       and     edi, 1
00401835   .  75 1C         jnz     short 00401853
00401837   .  8A90 58145700 mov     dl, byte ptr [eax+571458]                    ;  取出一个字节
0040183D   .  C0E2 04       shl     dl, 4                                        ;  左移四位
00401840   .  8BF0          mov     esi, eax
00401842   .  D1EE          shr     esi, 1
00401844   .  8896 58145700 mov     byte ptr [esi+571458], dl                    ;  保存
0040184A   .  EB 19         jmp     short 00401865
0040184C   >  32C0          xor     al, al
0040184E   .  5E            pop     esi
0040184F   .  8BE5          mov     esp, ebp
00401851   .  5D            pop     ebp
00401852   .  C3            retn
00401853   >  8BD0          mov     edx, eax
00401855   .  D1EA          shr     edx, 1
00401857   .  8DB2 58145700 lea     esi, dword ptr [edx+571458]
0040185D   .  8A90 58145700 mov     dl, byte ptr [eax+571458]
00401863   .  0016          add     byte ptr [esi], dl
00401865   >  8A98 59145700 mov     bl, byte ptr [eax+571459]                    ;  再取出一个字节
0040186B   .  8BD1          mov     edx, ecx
0040186D   .  83E2 01       and     edx, 1
00401870   .  8BF1          mov     esi, ecx
00401872   .  75 0D         jnz     short 00401881
00401874   .  C0E3 04       shl     bl, 4
00401877   .  D1EE          shr     esi, 1
00401879   .  889E 58145700 mov     byte ptr [esi+571458], bl
0040187F   .  EB 0E         jmp     short 0040188F
00401881   >  D1EE          shr     esi, 1
00401883   .  009E 58145700 add     byte ptr [esi+571458], bl                    ;  和前一次运算后的结果相加
00401889   .  8DB6 58145700 lea     esi, dword ptr [esi+571458]
0040188F   >  8B75 FC       mov     esi, dword ptr [ebp-4]
00401892   .  8A98 5A145700 mov     bl, byte ptr [eax+57145A]
00401898   .  8DB406 591457>lea     esi, dword ptr [esi+eax+571459]
0040189F   .  85FF          test    edi, edi
004018A1   .  75 0D         jnz     short 004018B0
004018A3   .  C0E3 04       shl     bl, 4
004018A6   .  D1EE          shr     esi, 1
004018A8   .  889E 58145700 mov     byte ptr [esi+571458], bl
004018AE   .  EB 0E         jmp     short 004018BE
004018B0   >  D1EE          shr     esi, 1
004018B2   .  009E 58145700 add     byte ptr [esi+571458], bl
004018B8   .  8DB6 58145700 lea     esi, dword ptr [esi+571458]
004018BE   >  85D2          test    edx, edx
004018C0   .  75 1D         jnz     short 004018DF
004018C2   .  8A90 5B145700 mov     dl, byte ptr [eax+57145B]                    ;  再取出一个字节
004018C8   .  8B75 F8       mov     esi, dword ptr [ebp-8]
004018CB   .  C0E2 04       shl     dl, 4                                        ;  左移四位
004018CE   .  8DB406 591457>lea     esi, dword ptr [esi+eax+571459]
004018D5   .  D1EE          shr     esi, 1
004018D7   .  8896 58145700 mov     byte ptr [esi+571458], dl                    ;  保存
004018DD   .  EB 1E         jmp     short 004018FD
004018DF   >  8B55 F8       mov     edx, dword ptr [ebp-8]
004018E2   .  8DB402 591457>lea     esi, dword ptr [edx+eax+571459]
004018E9   .  8A90 5B145700 mov     dl, byte ptr [eax+57145B]                    ;  再取出一个字节
004018EF   .  D1EE          shr     esi, 1                                       ;  右移一位
004018F1   .  0096 58145700 add     byte ptr [esi+571458], dl                    ;  加上前一次运算后的结果
004018F7   .  8DB6 58145700 lea     esi, dword ptr [esi+571458]
004018FD   >  83C1 04       add     ecx, 4
00401900   .  83C0 04       add     eax, 4
00401903   .  83F9 11       cmp     ecx, 11
00401906   .^ 0F8C 24FFFFFF jl      00401830
0040190C   .  B8 58145700   mov     eax, 00571458
00401911   .  5F            pop     edi
00401912   .  8D50 01       lea     edx, dword ptr [eax+1]
00401915   .  5B            pop     ebx
00401916   >  8A08          mov     cl, byte ptr [eax]                           ;  取出一个字节
00401918   .  40            inc     eax
00401919   .  84C9          test    cl, cl                                       ;  判断是否是0
0040191B   .^ 75 F9         jnz     short 00401916
0040191D   .  2BC2          sub     eax, edx                                     ;  得到00字节的偏移
0040191F   .  83F8 08       cmp     eax, 8                                       ;  和8比较
00401922   .  0f95c0        setne   al                                           ;  不相等则返回1 相等返回0
00401925   .  5E            pop     esi
00401926   .  8BE5          mov     esp, ebp
00401928   .  5D            pop     ebp
00401929   .  C3            retn

分析易知,这个函数的作用就是将输入的十六进制文本转换成字节集的形式,然后判断00字节的偏移是否是8,如果是8则返回0。
返回后,程序会判断这个函数的返回值,如果返回1则激活[确定]按钮,返回0则不激活[确定]按钮
这里写图片描述
0x03 寻找按钮事件
由刚刚分析的十六进制文本转换成字节集的函数可以得知,结果被存放在00571458处。给00571458下硬件访问断点,大小是1。然后点击[确定]按钮。在0040193A处断下。接着这个函数往下分析。
这里写图片描述
这段函数再判断00字节的偏移是不是8,如果是8则成功,否则触发异常。
这个和之前那个十六进制文本转换字节集的函数的验证结果是矛盾的。
那个函数判断00字节的偏移是否是8,如果是8则不会解锁[确定]按钮。但是在[确定]的按钮事件里又判断这个偏移是否是8,如果是8则成功,不是8则触发异常。
说明这个是一个烟雾弹。不是真正的算法。
0x04 分析真正的算法
虽然按钮事件是烟雾弹,但是我猜测这个字节集绝对会用上,因此我没有删掉这个硬件断点。
再按F9,即可来到真正的算法函数。看来我的猜想是正确的。
来到00401987处,找到函数头00401970即可。
这里写图片描述
用IDA载入,发现算法函数中有调用一个call,然后用转换成十六进制的Key去解一个方程组,八元一次方程组。
这里写图片描述
先解这个八元一次方程组,我手解的时候发现后面几个字节是除不开的。。。于是只好写个脚本来跑。
代码如下:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
        int a[8];//77 33 31 6C 64 30 6E 65
        for(a[0] = 0;a[0] <= 255;a[0]++)
        {
                for(a[1] = 0;a[1] <= 255;a[1]++)
                {
                        for(a[2] = 0;a[2] <= 255;a[2]++)
                        {
                                for(a[3] = 0;a[3] <= 255;a[3]++)
                                {
                                        if((unsigned __int8)(a[3] + a[2] + a[1] + a[0]) != 71)
                                                continue;
                                        if((unsigned __int8)a[0] != (unsigned __int8)a[1] + 68)
                                                continue;
                                        if((unsigned __int8)a[1] != (unsigned __int8)a[2] + 2)
                                                continue;
                                        if((unsigned __int8)a[2] != (unsigned __int8)a[3] - 59)
                                                continue;
                                        //77 33 31 6C
                                        for(int i = 0;i < 4;i++)
                                                printf("%0.02X ",a[i]);
                                        goto NextWhile;
                                }
                        }
                }
        }
NextWhile:
        for(a[4] = 0;a[4] <= 255;a[4]++)
        {
                for(a[5] = 0;a[5] <= 255;a[5]++)
                {
                        for(a[6] = 0;a[6] <= 255;a[6]++)
                        {
                                for(a[7] = 0;a[7] <= 255;a[7]++)
                                {
                                        if((unsigned __int8)(a[7] + a[6] + a[5]) != 3)
                                                continue;
                                        if((unsigned __int8)a[6] != (unsigned __int8)a[4] + 10)
                                                continue;
                                        if((unsigned __int8)a[6] != (unsigned __int8)a[7] + 9)
                                                continue;
                                        if((unsigned __int8)a[4] != (unsigned __int8)a[5] + 52)
                                                continue;
                                        //64 30 6E 65
                                        for(int i = 4;i < 8;i++)
                                                printf("%0.02X ",a[i]);
                                        goto Next;
                                }
                        }
                }
        }
Next:
        puts("");
        system("pause");
        return 0;
}

运行结果如图所示:
这里写图片描述
由此可以得知,正确Key的十六进制形式应为77 33 31 6C 64 30 6E 65
0x05 重点函数00401970的逆向
函数代码如图所示:
这里写图片描述
这段算法是Rijndael算法中的S-Box变换。
Flag只有16个字节,每个字节都是从00~FF的,因此我用的枚举。
方式就是一个字节一个字节枚举,和刚刚的解方程的代码的枚举方式差不多。
为了节省时间,我写了一个DLL来做这些工作,然后注入进去枚举Key,得到正确的Key后用信息框提示。
代码如下:
这里写图片描述
Hex函数的功能就是将十六进制的字节(00~FF)转换成文本。
这里写图片描述
将这些代码编译成一个DLL,然后注入到CM的进程中即可。得到结果如下:
这里写图片描述
拿到Flag:C7C536FC625CEFCD
放到原版CM中验证一下,可以通过。
这里写图片描述
全文完。



附:CrackMe源文件和两个脚本的源代码
CTF CrackMe.zip (867.28 KB, 下载次数: 158)

免费评分

参与人数 15吾爱币 +15 热心值 +15 收起 理由
丿猎狐 + 1 太牛白了
姚小宝 + 1 + 1 我很赞同!
wmsuper + 2 + 1 谢谢@Thanks!
小俊 + 1 + 1 谢谢@Thanks!
hzcdong + 1 + 1 我很赞同!
610100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
2669636795 + 1 + 1 支持,获益良多
Johnny.Y + 1 + 1 用心讨论,共获提升!
xiaofengzi + 1 + 1 热心回复!
wy510000 + 1 + 1 热心回复!
Dispa1r + 1 + 1 星斗师傅搞基不
dlweixiu + 2 + 1 葱白崇拜你!!!!
jinger666888 + 1 + 1 我很赞同!
朱朱你堕落了 + 1 + 1 好牛B!
WYWZ + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

kk1212 发表于 2017-12-10 19:23
很难得的学习笔记。感谢、
丨烟花丶易冷 发表于 2017-12-10 22:09
不羡云卿颜_ 发表于 2017-12-10 23:12
Dispa1r 发表于 2017-12-11 08:16
幸好没玩这个,这么复杂
rendercc 发表于 2017-12-11 08:35

幸好没玩这个,这么复杂
郁郁之风 发表于 2017-12-11 08:49
感谢楼主分享
h19981126g 发表于 2017-12-11 09:50
略叼,看不懂!~~~
xiaofengzi 发表于 2017-12-11 14:42
下载下来实际操作操作,学学楼主的分析过程
a763947059 发表于 2017-12-11 15:15 来自手机
不懂^_^^_^^_^^_^
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-29 00:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表