吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12893|回复: 30
收起左侧

[原创] [反汇编练习] 160个CrackMe之039(damn.exe)算法分析及PATCH过程(有自较验)

  [复制链接]
pk8900 发表于 2017-12-13 12:17
本帖最后由 pk8900 于 2017-12-14 08:26 编辑

      
  昨晚,继续研究 了【适合破解新手的160个crackme练手】第39个CrackMe: damn.exe,虽然不是太难,还是琢磨了一晚上,分析完后编写了注册机,进行第二步PATCH探索,搜索论坛未找到关于这个CrackMe的帖子,所以把我分析的过程写下来:
【crackme简介】
       下载地址:http://pan.baidu.com/share/link?shareid=541269&uk=4146939145
      FASM,壳:ASPack 1.08.03 -> Alexey Solodovnikov,Name+Key验证方式,界面下另有一个LOCKED!按钮,看作者的About说明,分两部分,写出注册机,PATCH使程序显示UNLOCKED,因为程序有自较验,这块有些难度,我开始绕了不少弯路。
      分析工具:X64dbg,OD,注册机编写:VS2013
【crackme截图】
Image 1.png
【算法分析过程】
  对<user32.GetDlgItemTextA>函数下断点,很快定位到程序算法处,共分为两部分。
0x01、对用户名进行处理,得到一个DWORD值:
[Asm] 纯文本查看 复制代码
004012F4 | 8B 0D 89 23 40 00         | mov ecx, dword ptr ds:[0x402389]    | [0x00402389] --用户名长度
004012FA | 85 C9                     | test ecx, ecx                       |
004012FC | 74 71                     | je damn_d.40136F                    | 用户名不为空
004012FE | 49                        | dec ecx                             | 长度-1
004012FF | 8B F1                     | mov esi, ecx                        | ESI为循环判断数
00401301 | BF 53 23 40 00            | mov edi, damn_d.402353              | 402353: 用户名指针
00401306 | BB 4E 4D 41 44            | mov ebx, 0x44414D4E                 | EBX 初始为0x44414D4E(SERIAL)
0040130B | 33 D2                     | xor edx, edx                        | EDX:用户名字节累加值(SUM)
0040130D | 8B CA                     | mov ecx, edx                        | ECX计数器清零=N
0040130F | 33 C0                     | xor eax, eax                        | 循环开始
00401311 | 8A 04 0F                  | mov al, byte ptr ds:[edi+ecx]       | AL 循环压入用户名字节[N]
00401314 | 03 D0                     | add edx, eax                        | 用户名字节累加
00401316 | D1 CB                     | ror ebx, 0x1                        | SERAL 循环右移 1位
00401318 | D3 CB                     | ror ebx, cl                         | SERAL 循环右移 N位
0040131A | 33 DA                     | xor ebx, edx                        | SERAL 异或 SUM
0040131C | 3B CE                     | cmp ecx, esi                        |
0040131E | 74 03                     | je damn_d.401323                    |
00401320 | 41                        | inc ecx                             | 累加计数器N
00401321 | EB EC                     | jmp damn_d.40130F                   |
00401323 | 81 CB 10 10 10 10         | or ebx, ksfmon.10101010             | SERAL 位或 0x10101010 即最终SERAL
00401329 | 87 DA                     | xchg edx, ebx                       |
0040132B | BF 21 23 40 00            | mov edi, damn_d.402321              | 402321:输入序列号的指针


  以上代码通过用户名算出正确的序列号过程,最终得到一个DWORD值,即为对应我们输入的用户名的序列号,接下来会进行对比较验:
[Asm] 纯文本查看 复制代码
00401323 | 81 CB 10 10 10 10         | or ebx, ksfmon.10101010             | SERAL 位或 0x10101010 即最终SERAL
00401329 | 87 DA                     | xchg edx, ebx                       |
0040132B | BF 21 23 40 00            | mov edi, damn_d.402321              | 402321:输入序列号的指针
00401330 | 8B 0D 8D 23 40 00         | mov ecx, dword ptr ds:[0x40238D]    |
00401336 | 83 F9 08                  | cmp ecx, 0x8                        | 判断位数:必须为8位
00401339 | 75 34                     | jne damn_d.40136F                   |
0040133B | 33 C9                     | xor ecx, ecx                        |
0040133D | 33 C0                     | xor eax, eax                        |
0040133F | C1 C2 08                  | rol edx, 0x8                        | 循环右移8位,将最高位字节移至最低位
00401342 | 8A C2                     | mov al, dl                          |
00401344 | 8A D8                     | mov bl, al                          | 取出 最高位1节位
00401346 | 24 0F                     | and al, 0xF                         | AL 为低位
00401348 | C0 EB 04                  | shr bl, 0x4                         | BL 为高位
0040134B | 80 E3 0F                  | and bl, 0xF                         | 以下四步为转十六进制为ASCII
0040134E | 3C 0A                     | cmp al, 0xA                         | A:'\n'
00401350 | 1C 69                     | sbb al, 0x69                        |
00401352 | 2F                        | das                                 |
00401353 | 38 44 4F 01               | cmp byte ptr ds:[edi+ecx*2+0x1], al | 与序列号对应位进行比较
00401357 | 75 16                     | jne damn_d.40136F                   |
00401359 | 8A C3                     | mov al, bl                          |
0040135B | 3C 0A                     | cmp al, 0xA                         | 以下四步为转十六进制为ASCII
0040135D | 1C 69                     | sbb al, 0x69                        |
0040135F | 2F                        | das                                 |
00401360 | 38 04 4F                  | cmp byte ptr ds:[edi+ecx*2], al     | 与序列号对应位进行比较
00401363 | 75 0A                     | jne damn_d.40136F                   |
00401365 | 41                        | inc ecx                             |
00401366 | 83 F9 04                  | cmp ecx, 0x4                        |
00401369 | 75 D2                     | jne damn_d.40133D                   | 循环4次
0040136B | 33 C0                     | xor eax, eax                        |
0040136D | 40                        | inc eax                             | 比较成功的关键标志,返回1
0040136E | C3                        | ret                                 |
0040136F | 33 C0                     | xor eax, eax                        | 比较成功的关键标志,返回0
00401371 | C3                        | ret                                 |

0x02:序列号比较部分:
  通过上段代码分析,程序通过循环右移8位,依次取出SERAL的1个字节,然后拆分为高位和低位,转成ASCII值后也我们输入的序列号进行对比,完全一样的话,执行inc eax  ,将EAX置1,这是比较成功的关键标志。
       比较部分代码中这四句很意思,也很经典:
[Asm] 纯文本查看 复制代码
0040134B | 80 E3 0F                  | and bl, 0xF                         | 以下四步为转十六进制为ASCII
0040134E | 3C 0A                     | cmp al, 0xA                         | A:'\n'
00401350 | 1C 69                     | sbb al, 0x69                        |

00401352 | 2F                        | das          
               
       短短4句代码,将16进制直接转为ASCII字符,百度一下,好像和BCD码有关,资料不多,也没太清楚这个BCD码的具体原理。
  通过上述算法分析,就可以编写注册机了。
  C++代码如下:
[C++] 纯文本查看 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <windows.h>
using namespace std;

void myRor1(DWORD * myd, unsigned char n);
char * yourname;
unsigned long serial;
void main()
{
        serial = 0x44414D4E;
        unsigned long name_add =0;
        yourname = new char[260];
        memset(yourname, 0, 260);
        cout << "Enter your name:";
        gets(yourname);
        for (unsigned char x = 0; x < strlen(yourname); x++)
        {
                name_add += yourname[x];
                myRor1(&serial, 1);
                myRor1(&serial, x);
                serial ^= name_add;
        }
        serial |= 0x10101010;
        cout << "your serial is:" << hex << uppercase << serial << endl;
system("pause");
delete[] yourname;
}
void  myRor1(DWORD * myd, unsigned char n)
{
        _asm
                {
        MOV EBX, myd;
        MOV eax, [EBX];
        MOV cl, n;
        ROR EAX,cl;
        MOV [EBX], eax;
                }
}


  提供一组测试用户名:52pojie.cn 序列号:BB5274B2
  接下来是第二部分,PATCH程序使程序显示为UNLOCKED。
  通过程序API调用,<user32.LoadBitmapA>,很快定位到相应改变图片的代码位置:
[Asm] 纯文本查看 复制代码
00401190 | FF 75 08                  | push dword ptr ss:[ebp+0x8]         | HANDLE hDlg
00401193 | E8 61 02 00 00            | call <damn_d.GetDlgItem>            | GetDlgItem
00401198 | A3 85 23 40 00            | mov dword ptr ds:[0x402385], eax    |
0040119D | E8 D0 01 00 00            | call <damn_d.sub_401372>            |
004011A2 | BF E7 22 40 00            | mov edi, damn_d.4022E7              | EDI指针:&L"f"
004011A7 | A1 13 23 40 00            | mov eax, dword ptr ds:[0x402313]    | 关键偏移值
004011AC | 03 C0                     | add eax, eax                        |
004011AE | 03 C0                     | add eax, eax                        |
004011B0 | 03 F8                     | add edi, eax                        |
004011B2 | 8B 3F                     | mov edi, dword ptr ds:[edi]         |
004011B4 | 8B 07                     | mov eax, dword ptr ds:[edi]         |
004011B6 | 50                        | push eax                            | LPCTSTR lpBitmapName
004011B7 | FF 35 95 23 40 00         | push dword ptr ds:[0x402395]        | HMODULE hInstance
004011BD | E8 49 02 00 00            | call <damn_d.LoadBitmapA>           | LoadBitmapA
004011C2 | A3 0F 23 40 00            | mov dword ptr ds:[0x40230F], eax    |


  分析上述代码,可以得知,GetDlgItem取得按钮的句柄,LoadBitmapA用来改变按钮图片, LPCTSTR lpBitmapName为显示的图片名,EDI指针:最开始指向"f",加上:[0x402313]*2*2的偏移后,来确定显示哪个图片,如果:[0x402313]==0,EDI指针无偏移,f图片为Locded,:[0x402313]==1时,EDI指针指向"f",f图片为Cracked,[0x402313]==2时,EDI指针指向"g",g图片为UnLockked,
Image 2.png
所以关键值就是[0x402313],现在往上看这个调用:0040119D | E8 D0 01 00 00            | call <damn_d.sub_401372>,其代码如下:
[Asm] 纯文本查看 复制代码
00401372 | BF 00 20 40 00            | mov edi, damn_d.402000              |
00401377 | BE 00 10 40 00            | mov esi, <damn_d.EntryPoint>        | 401000:"j"
0040137C | B9 20 03 00 00            | mov ecx, 0x320                      | 循环较验 0042000+0x320段320字节代码
00401381 | 33 DB                     | xor ebx, ebx                        |
00401383 | 33 C0                     | xor eax, eax                        |
00401385 | 8A 04 0F                  | mov al, byte ptr ds:[edi+ecx]       |
00401388 | 03 D8                     | add ebx, eax                        |
0040138A | D1 CB                     | ror ebx, 0x1                        |
0040138C | 33 D9                     | xor ebx, ecx                        |
0040138E | 49                        | dec ecx                             |
0040138F | 75 F2                     | jne damn_d.401383                   |
00401391 | B9 B2 03 00 00            | mov ecx, 0x3B2                      | 循环较验 0041000+0x3B2段0x3B2字节代码
00401396 | 33 D2                     | xor edx, edx                        |
00401398 | 33 C0                     | xor eax, eax                        |
0040139A | 8A 04 0E                  | mov al, byte ptr ds:[esi+ecx]       |
0040139D | 03 D0                     | add edx, eax                        |
0040139F | D1 CA                     | ror edx, 0x1                        |
004013A1 | 33 D1                     | xor edx, ecx                        |
004013A3 | 49                        | dec ecx                             |
004013A4 | 75 F2                     | jne damn_d.401398                   |
004013A6 | 33 DA                     | xor ebx, edx                        |
004013A8 | C1 C3 03                  | rol ebx, 0x3                        |
004013AB | 03 D3                     | add edx, ebx                        |
004013AD | 81 E2 55 55 55 55         | and edx, 0x55555555                 |
004013B3 | 90                        | nop                                 |
004013B4 | 81 F2 45 54 14 11         | xor edx, 0x11145445                 | 检验值为:0x11145445,异或结果存入EDX
004013BA | 74 08                     | je damn_d.4013C4                    |
004013BC | 33 D2                     | xor edx, edx                        |
004013BE | 42                        | inc edx                             | EDX置为1,程序最终显示Cracked
004013BF | E9 58 0C 00 00            | jmp damn_d.40201C                   |
004013C4 | E9 37 0C 00 00            | jmp damn_d.402000                   |

上面这段代码会进行自检验,范围为0x 0042000~0x00402320和0041000~0x004013B2,取得异或和,与0x11145445进行异或比较,来进行自检验,检验值存在EDX中,最后的JMP跳转,分别如下:

[Asm] 纯文本查看 复制代码
0040201C | 89 15 13 23 40 00         | mov dword ptr ds:[0x402313], edx    |
00402022 | C3                        | ret                                 |

[Asm] 纯文本查看 复制代码
00402000 | A1 0B 23 40 00            | mov eax, dword ptr ds:[0x40230B]    |
00402005 | 85 C0                     | test eax, eax                       |
00402007 | 75 13                     | jne damn_d.40201C                   |
00402009 | E8 00 00 00 00            | call <damn_d.sub_40200E>            | call $0
0040200E | 5F                        | pop edi                             |
0040200F | C6 47 0B 42               | mov byte ptr ds:[edi+0xB], 0x42     | 这两句代码会修改程序本身代码,使检验失败
00402013 | 66 C7 47 0C D1 E2         | mov word ptr ds:[edi+0xC], 0xE2D1   |
00402019 | EB 90                     | jmp damn_d.401FAB                   |
0040201B | 40                        | inc eax                             |
0040201C | 89 15 13 23 40 00         | mov dword ptr ds:[0x402313], edx    |
00402022 | C3                        | ret                                 |


这两段代码都会把自校验的值EDX赋给:[0x402313](全局常量),如果异或后的值为2,刚可以实现程序的UnLocked效果,所以修改代码:

[Asm] 纯文本查看 复制代码
004013B4 | 81 F2 45 54 14 11         | xor edx, 0x11145445                 | 检验值为:0x11145445,异或结果存入EDX
004013BA | 74 08                     | je damn_d.4013C4                    |

[Asm] 纯文本查看 复制代码
004013B4 | 81 F2 45 54 14 11         | xor edx, 0x11145447                 | 改检验值为:0x11145447,异或结果存入EDX
004013BA | 74 08                     | jmp  damn_d.4013C4                | 改Jmp跳转    


这样就可以避开程序的自校验范围,实现PATCH效果。当然也可以在别的地方修改,可能会麻烦一点。           |
附CrackMe三种状态的截图:
Image 4.png

分析过程有不对或不到位的地方,欢迎大家回贴交流,共同探讨。

免费评分

参与人数 5威望 +2 吾爱币 +14 热心值 +5 收起 理由
lin_xop + 1 + 1 热心回复!
Hmily + 2 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
废宅小五 + 1 + 1 谢谢@Thanks!
测试中…… + 1 + 1 用心讨论,共获提升!
朱朱你堕落了 + 1 + 1 向大神学习!666

查看全部评分

本帖被以下淘专辑推荐:

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

朱朱你堕落了 发表于 2017-12-14 23:25
楼主大神,希望有时间分析下这个算法:
链接: https://pan.baidu.com/s/1kVKNZvT 密码: mjfu

我的感觉是这个软件无法生成一个注册码,即,无法本地构造出来一个合法的注册码,
软件既可以在线注册,又可以本地注册,但是我好像发现这两个是相互矛盾的,
即:如果注册码的检测条件满足在线注册的话,软件走向在线注册流程,但是在线
注册,那肯定是不能通过的,所以不能让程序走在线注册,只能在本地验证流程,
但是本地流程的话,他的验证码符合条件又和在注册注册时的符合条件冲突了,所以
本地验证好像也是走不通的。。

所以我最后感觉就是这个软件只有一条在线注册的流程可以走,但是在线注册,肯定不可能注册成功。。
也可能我在本地验证的分析地方,哪里有问题,所以请楼主有时间分析一下。

我的部分分析:
如果不走在线注册:那么一定要让程序走到这里,eax返回0才行。
100020D5    83C4 04         add esp,0x4
100020D8    8945 D4         mov dword ptr ss:[ebp-0x2C],eax
100020DB    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]                ; magicski.10005E7E
100020DE    0345 D4         add eax,dword ptr ss:[ebp-0x2C]
100020E1    33D2            xor edx,edx
100020E3    B9 9F860100     mov ecx,0x1869F
100020E8    F7F1            div ecx
100020EA    3955 DC         cmp dword ptr ss:[ebp-0x24],edx
100020ED    75 14           jnz short magicski.10002103
100020EF    8B45 FC         mov eax,dword ptr ss:[ebp-0x4]               
100020F2    0345 D4         add eax,dword ptr ss:[ebp-0x2C]         
100020F5    33D2            xor edx,edx
100020F7    B9 9F860100     mov ecx,0x1869F
100020FC    F7F1            div ecx
100020FE    3955 E4         cmp dword ptr ss:[ebp-0x1C],edx
10002101    74 22           je short magicski.10002125
10002103    C785 5CFFFFFF 0>mov dword ptr ss:[ebp-0xA4],0x0
1000210D    8D4D F4         lea ecx,dword ptr ss:[ebp-0xC]
10002110    E8 49360000     call <jmp.&MFC42.#CString::~CString_800>
10002115    8D4D E8         lea ecx,dword ptr ss:[ebp-0x18]
10002118    E8 03330000     call magicski.10005420
1000211D    8B85 5CFFFFFF   mov eax,dword ptr ss:[ebp-0xA4]
10002123    EB 20           jmp short magicski.10002145
10002125    C785 58FFFFFF 0>mov dword ptr ss:[ebp-0xA8],0x1
1000212F    8D4D F4         lea ecx,dword ptr ss:[ebp-0xC]
10002132    E8 27360000     call <jmp.&MFC42.#CString::~CString_800>
10002137    8D4D E8         lea ecx,dword ptr ss:[ebp-0x18]
1000213A    E8 E1320000     call magicski.10005420
1000213F    8B85 58FFFFFF   mov eax,dword ptr ss:[ebp-0xA8]
10002145    8BE5            mov esp,ebp
10002147    5D              pop ebp                                       ; 0012F8DC
10002148    C2 0800         retn 0x8


但是如果满足了上面不走在线注册流程的条件,那么下面这个本地条件有就有矛盾,矛盾点在于,本地无法验证了,
它一路走下去,最后一个就跳过能本地注册成功的线路了,无论如何构造注册码。

100039EB    8945 D4         mov dword ptr ss:[ebp-0x2C],eax
100039EE    C745 E8 0000000>mov dword ptr ss:[ebp-0x18],0x0
100039F5    8B45 14         mov eax,dword ptr ss:[ebp+0x14]               ; videoedi.0044D3D0
100039F8    0345 D4         add eax,dword ptr ss:[ebp-0x2C]
100039FB    33D2            xor edx,edx
100039FD    B9 9F860100     mov ecx,0x1869F
10003A02    F7F1            div ecx
10003A04    3955 1C         cmp dword ptr ss:[ebp+0x1C],edx
10003A07    75 18           jnz short magicski.10003A21
10003A09    8B45 10         mov eax,dword ptr ss:[ebp+0x10]
10003A0C    0345 D4         add eax,dword ptr ss:[ebp-0x2C]
10003A0F    33D2            xor edx,edx
10003A11    B9 9F860100     mov ecx,0x1869F
10003A16    F7F1            div ecx
10003A18    3955 20         cmp dword ptr ss:[ebp+0x20],edx
10003A1B    0F84 500C0000   je magicski.10004671


所以很纠结,也可能水平不行,希望楼主有时间分析下看看。
 楼主| pk8900 发表于 2017-12-15 22:19
本帖最后由 pk8900 于 2017-12-15 22:21 编辑
朱朱你堕落了 发表于 2017-12-15 21:45
测试了楼主的注册码是可用的,有几个疑问啊,
这个应该是在线验证网址的函数吧,感觉应该没错。

因为有联网验证,我先搜索了网址字符串,对所有网址字符串下了断点,后来断在www.sunisoft.com有几次,至你们说的下面那个网址验证,会返回2,应该是你注册的类型,可查看注册表。HKLM\SOFTWARE\GSLLC\21851,这里是WorkMode,我没验证,是猜测的。
另外提供一组:
10369-21532-21851-71640-60477-63097,可以把后面的第六组数字,随意换一下,就能注册成功。
关键算法位置:
[Asm] 纯文本查看 复制代码
100020D0 | E8 BA 30 00 00            | call magics.1000518F                     | 内有固定数值:50108
100020D5 | 83 C4 04                  | add esp, 0x4                             |
100020D8 | 89 45 D4                  | mov dword ptr ss:[ebp-0x2C], eax         |
100020DB | 8B 45 F8                  | mov eax, dword ptr ss:[ebp-0x8]          | 第二组的值
100020DE | 03 45 D4                  | add eax, dword ptr ss:[ebp-0x2C]         |
100020E1 | 33 D2                     | xor edx, edx                             | eax:78996
100020E3 | B9 9F 86 01 00            | mov ecx, 0x1869F                         | 99999
100020E8 | F7 F1                     | div ecx                                  |
100020EA | 39 55 DC                  | cmp dword ptr ss:[ebp-0x24], edx         | 余数和第四组比较应相同
100020ED | 75 14                     | jne magics.10002103                      |
100020EF | 8B 45 FC                  | mov eax, dword ptr ss:[ebp-0x4]          | 第一组
100020F2 | 03 45 D4                  | add eax, dword ptr ss:[ebp-0x2C]         | 固定数值:50108
100020F5 | 33 D2                     | xor edx, edx                             |
100020F7 | B9 9F 86 01 00            | mov ecx, 0x1869F                         |
100020FC | F7 F1                     | div ecx                                  |
100020FE | 39 55 E4                  | cmp dword ptr ss:[ebp-0x1C], edx         | 余数和第五组比较应相等
10002101 | 74 22                     | je magics.10002125                       |
10002103 | C7 85 5C FF FF FF 00 00 0 | mov dword ptr ss:[ebp-0xA4], 0x0         |

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
随时随地 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

whatdos 发表于 2017-12-13 13:00
12083 发表于 2017-12-13 13:10 来自手机
感谢楼主
AwYe 发表于 2017-12-13 13:11
支持一下,学习学习。
测试中…… 发表于 2017-12-13 13:12
支持一下~~
meng4450 发表于 2017-12-13 14:28
不懂,觉得很强大
feng1234 发表于 2017-12-13 17:17 来自手机
学习学习
heqiu000 发表于 2017-12-13 19:36
谢谢楼主 分享 吾爱有你更精彩
iqzoj69m 发表于 2017-12-13 19:43
学习学习  大佬是怎样练成的
火之国 发表于 2017-12-13 23:52
学习一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-15 13:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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