吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8379|回复: 14
收起左侧

[原创] [反汇编练习] 160个CrackMe之034(Cruehead.3.exe)算法分析及注册机编写

  [复制链接]
pk8900 发表于 2017-12-9 09:35
本帖最后由 pk8900 于 2017-12-9 09:49 编辑

      
  昨天晚上,继续研究 了【适合破解新手的160个crackme练手】,本文内容为第34个CrackMe: Cruehead.3.exe,有些收获,分析并编写注册机后,在论坛里搜索了一下关于这个CrackMe的帖子进行参照,找到了两篇,有一篇未分析出算法,有一篇已基本将算法分析出来,但注册机编写的不是很完美,参考地址:https://www.52pojie.cn/thread-371674-1-1.html,所以写了这篇帖子,分享一下我的分析过程及注册机编写方法。
【crackme简介】
       下载地址:http://pan.baidu.com/share/link?shareid=541269&uk=4146939145
       MASM32 / TASM32编写,无壳,是一个Keyfile验证方式,界面打开窗口空白,file菜单只有一个exit,help菜单也只有一个About说明。
      分析工具:X64dbg,OD,(因X64DBG不能自动注释API函数调用参数,所以和OD结合使用)
【crackme截图】
Image 001.png
【算法分析过程】
  因为在下载crackme的时候,看见后面标注的验证方式是Keyfile,所以分析起来就省了不少事,直接搜索字符串,可以搜索到“CRACKME3.KEY”,明显的Key文件,同时还有"Good work cracker!"及"Cracked by:                 Now try the next crackme!"字符串,估计是成功后标志。直接双击“CRACKME3.KEY”来到代码处:
[Asm] 纯文本查看 复制代码
0040100C  |.  C705 F9204000>mov dword ptr ds:[0x4020F9],0x0
00401016  |.  6A 00         push 0x0                                 ; /hTemplateFile = NULL
00401018  |.  68 80000000   push 0x80                                ; |Attributes = NORMAL
0040101D  |.  6A 03         push 0x3                                 ; |Mode = OPEN_EXISTING
0040101F  |.  6A 00         push 0x0                                 ; |pSecurity = NULL
00401021  |.  6A 03         push 0x3                                 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
00401023  |.  68 000000C0   push 0xC0000000                          ; |Access = GENERIC_READ|GENERIC_WRITE
00401028  |.  68 D7204000   push Cruehead.004020D7                   ; |FileName = "CRACKME3.KEY"
0040102D  |.  E8 76040000   call <jmp.&KERNEL32.CreateFileA>         ; \CreateFileA
00401032  |.  83F8 FF       cmp eax,-0x1
00401035  |.  75 0C         jnz short Cruehead.00401043              ;  文件不存在跳走
00401037  |>  68 0E214000   push Cruehead.0040210E                   ;  ASCII "CrackMe v3.0             "
0040103C  |.  E8 B4020000   call Cruehead.004012F5
00401041  |.  EB 6B         jmp short Cruehead.004010AE
00401043  |>  A3 F5204000   mov dword ptr ds:[0x4020F5],eax          ;  kernel32.BaseThreadInitThunk
00401048  |.  B8 12000000   mov eax,0x12
0040104D  |.  BB 08204000   mov ebx,Cruehead.00402008
00401052  |.  6A 00         push 0x0                                 ; /pOverlapped = NULL
00401054  |.  68 A0214000   push Cruehead.004021A0                   ; |pBytesRead = Cruehead.004021A0
00401059  |.  50            push eax                                 ; |BytesToRead = 76753358 (1987392344.)
0040105A  |.  53            push ebx                                 ; |Buffer = 7EFDE000
0040105B  |.  FF35 F5204000 push dword ptr ds:[0x4020F5]             ; |hFile = NULL
00401061  |.  E8 30040000   call <jmp.&KERNEL32.ReadFile>            ; \ReadFile
00401066  |.  833D A0214000>cmp dword ptr ds:[0x4021A0],0x12         ;  读取字节数不为0x12(18)字节,跳走
0040106D  |.^ 75 C8         jnz short Cruehead.00401037
0040106F  |.  68 08204000   push Cruehead.00402008
00401074  |.  E8 98020000   call Cruehead.00401311
00401079  |.  8135 F9204000>xor dword ptr ds:[0x4020F9],0x12345678

分析此块代码:
       1、CreateFileA参数Mode = OPEN_EXISTING,也就是打开已存在的文件,若文件不存在,函数返回-1,是用来验证Key文件是否存在的。
       2、ReadFile函数读取文件内容,参数pBytesRead = Cruehead.004021A0是读取文件返回的字节数,接下来一句代码cmp dword ptr ds:[0x4021A0],0x12,如果读取的字节数少于0x12(18)个,则跳至失败处。
       于是我们在CrackMe目录下新建一个文件CRACKME3.KEY,并写入不少于18个字节的数据,内容随意。
      再次载入程序,在ReadFile后代码进行跟踪。
[Asm] 纯文本查看 复制代码
00401066  |.  833D A0214000>cmp dword ptr ds:[0x4021A0],0x12         ;  读取字节数不为0x12(18)字节,跳走
0040106D  |.^ 75 C8         jnz short Cruehead.00401037
0040106F  |.  68 08204000   push Cruehead.00402008                   ;  123123123123111111
00401074  |.  E8 98020000   call Cruehead.00401311                   ;  子程序1
00401079  |.  8135 F9204000>xor dword ptr ds:[0x4020F9],0x12345678   ;  [0x4020F9] XOR 0x12345678
00401083  |.  83C4 04       add esp,0x4
00401086  |.  68 08204000   push Cruehead.00402008                   ;  123123123123111111
0040108B  |.  E8 AC020000   call Cruehead.0040133C                   ;  子程序2
00401090  |.  83C4 04       add esp,0x4
00401093  |.  3B05 F9204000 cmp eax,dword ptr ds:[0x4020F9]          ;  比较
00401099  |.  0F94C0        sete al                                          比较标志存入AL
0040109C  |.  50            push eax                                 ;  kernel32.BaseThreadInitThunk
0040109D  |.  84C0          test al,al                                        测试AL值
0040109F  |.^ 74 96         je short Cruehead.00401037               ;  跳转
004010A1  |.  68 0E214000   push Cruehead.0040210E                   ;  CrackMe v3.0  - Uncracked
004010A6  |.  E8 9B020000   call Cruehead.00401346

  上面这段代码可以看出,程序先后两次对文件中读取的字符串地址压栈,调用了两个子程序处理,然后是一个cmp比较和一个JE跳转。关键算法就是这里了,先分析子程序1(call Cruehead.00401311
[Asm] 纯文本查看 复制代码
00401311  /$  33C9          xor ecx,ecx
00401313  |.  33C0          xor eax,eax
00401315  |.  8B7424 04     mov esi,dword ptr ss:[esp+0x4]           ;  读入key字符串指针
00401319  |.  B3 41         mov bl,0x41                              ;  用于异或解密的字符
0040131B  |>  8A06          /mov al,byte ptr ds:[esi]
0040131D  |.  32C3          |xor al,bl
0040131F  |.  8806          |mov byte ptr ds:[esi],al
00401321  |.  46            |inc esi                                 ;  key字符串指针+1
00401322  |.  FEC3          |inc bl                                  ;  异或解密字符+1
00401324  |.  0105 F9204000 |add dword ptr ds:[0x4020F9],eax         ;  累加解密后字符ASCII值至0x4020F9
0040132A  |.  3C 00         |cmp al,0x0
0040132C  |.  74 07         |je short Cruehead.00401335              ;  解密后为0(空字符)则结束
0040132E  |.  FEC1          |inc cl
00401330  |.  80FB 4F       |cmp bl,0x4F                             ;  解密字符累加至4F结束
00401333  |.^ 75 E6         \jnz short Cruehead.0040131B
00401335  |>  890D 49214000 mov dword ptr ds:[0x402149],ecx
0040133B  \.  C3            retn

  此段代码把从KEY文件中读取的字符串进行异或解密,解密字符从0x41开始,一直到0X4E共14位,中间如果解密出来的字符若是\0(空字符)则结束,(注意:这里在判断字符为\0时,字符与解密字符的异或值已经被累加,存入[0x4020F9]中,因此写注册机的时候要注意判断时机),取出的共18个字节,后4个是不进行解密的。
  子程序调用结束返回后,将[0x4020F9]地址的累加值与0x12345678 异或。
  接下来进入子程序2:
[Asm] 纯文本查看 复制代码
0040133C  /$  8B7424 04     mov esi,dword ptr ss:[esp+0x4]           ;  Cruehead.00402008
00401340  |.  83C6 0E       add esi,0xE                              ;  从KEY字符串偏移14
00401343  |.  8B06          mov eax,dword ptr ds:[esi]               ;  取key字符串后4位
00401345  \.  C3            retn

  子程序2的代码非常简单,就是从读取的Key字符串中取出后4个字节。子程序2返回后,将后4个字节值与子程序1累加并异或的值比较,来确定是否真的注册成功,注册成功后,程序将解密的14字节用户名写入字符串"Cracked by:                 Now try the next crackme!"中间的14个空格位置,调用信息框显示成功信息
【注册机编写】
  经分析得知,程序读取Key文件中前18个字节得到一个字符串(准确点说应该是字节集),解密前14个字节并累加其ASCII值,遇0结束,也就是正好是我们的用户名部分。所以我们可以自己指定用户名,通过异或加密0x41开始的字符后,写入KEY文件1-14字节,长则截去,短则添0,然后累加ASCII值,后与0x12345678 异或,将这个值写到KEY文件第15-18字节,至此注册机即可实现写KEY文件,完成注册。
注册机C++代码:
[C++] 纯文本查看 复制代码
#include<iostream>
#include <windows.h>
using namespace std;
int main()
{
        char * path = "E:\\crackme\\CRACKME3.KEY";
        FILE * keyfile;
        char * youkey = new char[260];         //输入用户名
        unsigned long retvalue=0;           //后4字节检验值
        memset(youkey, 0, 260);
        cout << "Enter your name:";
        gets(youkey);
        for (int x = 0; x < 0xE; x++)
        {
                
                retvalue += (youkey[x]);
                youkey[x] = youkey[x] ^ (0x41 + x);
                if ((youkey[x] ^ (0x41 + x ))== 0)      //这里要先累加,然后进行判断
                        break;
        }
        retvalue ^= 0x12345678;
        errno_t err = fopen_s(&keyfile, path, "w+b");
        if (err != 0)
        {
                cout << "file open or create failed!" << endl;
                system("pause");
                return -1;
        }
        rewind(keyfile);
        fwrite(youkey, sizeof(byte), 0xE, keyfile);
        fseek(keyfile, 0xE, 0);
        fwrite((char *)&retvalue, sizeof(byte), 4, keyfile);
        fclose(keyfile);
        cout <<"write file:"<< youkey<< hex << retvalue << endl;
        delete[] youkey;
system("pause");
return 1;
}

附个成功注册的截图图:
Image 002.png
  欢迎大家回贴交流,共同探讨。

点评

楼主分析一下这个:https://www.52pojie.cn/thread-673339-1-1.html  发表于 2017-12-9 12:50

免费评分

参与人数 3威望 +1 吾爱币 +12 热心值 +3 收起 理由
Hmily + 1 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
朱朱你堕落了 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
545400m + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

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

dice1412 发表于 2017-12-9 10:39
支持楼主
hmf505 发表于 2017-12-9 20:16
s3nake 发表于 2017-12-9 23:29
Halry 发表于 2017-12-10 11:57
学习了,谢谢分享
linclon 发表于 2017-12-10 15:14
厉害厉害,感谢楼主分享
qvbzyx 发表于 2017-12-10 15:44
学习的乐趣,就是不停的进步
newchange452pj 发表于 2017-12-10 17:16
学习了,谢谢分享
电脑疯了 发表于 2017-12-12 14:19
膩害,學習了。。
LUGY! 发表于 2018-3-14 21:41
学到了谢谢 加油
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-3-28 23:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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