zbnysjwsnd8 发表于 2017-10-1 13:22

160个CrackMe之91

本帖最后由 zbnysjwsnd8 于 2017-10-1 18:21 编辑

依然是先写到博客然后复制到这里的。

个人感觉这个CM是我玩过的最另类的一个了,如果有什么不对的地方还请各位大佬更正。
**0x0 寻找按钮事件**
OD载入,发现程序打开crueme.dat文件,如果打开失败则提示错误然后结束程序。

```
00401043    6A 00         push    0x0
00401045    68 80000000   push    0x80
0040104A    6A 03         push    0x3
0040104C    6A 00         push    0x0
0040104E    6A 00         push    0x0
00401050    68 000000C0   push    0xC0000000
00401055    68 76214000   push    00402176                         ; CRUEME.DAT
0040105A    B0 1F         mov   al, 0x1F
0040105C    FF15 64234000   call    dword ptr              ; CreateFileA
00401062    83F8 FF         cmp   eax, -0x1
00401065    75 24         jnz   short 0040108B
00401067    6A 30         push    0x30
00401069    68 A0214000   push    004021A0                         ; This is the end - My only friend the end!
0040106E    68 CA214000   push    004021CA                         ; AAARGH! Where is my CRUEME.DAT file???\r    I cant go >
00401073    6A 00         push    0x0
00401075    B0 1A         mov   al, 0x1A
00401077    FF15 64234000   call    dword ptr              ; MessageBoxA
0040107D    FF35 54204000   push    dword ptr
00401083    B0 0A         mov   al, 0xA
00401085    FF15 64234000   call    dword ptr              ; ExitProcess
```
在程序目录下新建一个crueme.dat文件,内容为12345678,然后重新载入。
载入以后程序弹出了一个界面,如下图所示:
![这里写图片描述](http://img.blog.csdn.net/20171001122142980?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
给GetWindowTextA下断点,然后随便输入一串密码,比如87654321,最后点击。
断下后,回溯到程序领空,找到按钮事件0x00401213处,下断,然后重新载入程序即可。
**0x1 分析算法1**
程序首先改写了0x00401224到0x00401247处的代码。
```
0040123F    BF 01000000   mov   edi, 0x1
00401244    E8 FD080000   call    00401B46                         ; 代码改写
```
然后将crueme.dat中的内容和一串数据逐位异或然后循环左移一位。
```
00401249    B9 08000000   mov   ecx, 0x8                         ; 循环八次
0040124E    BF 85214000   mov   edi, 00402185                  ; crueme.dat中的内容
00401253    BE 34214000   mov   esi, 00402134                  ; 一个数据
00401258    8A07            mov   al, byte ptr
0040125A    8A1E            mov   bl, byte ptr
0040125C    32C3            xor   al, bl                           ; 依次异或
0040125E    D0C0            rol   al, 1                            ; 循环左移一位
00401260    8806            mov   byte ptr , al               ; 保存
00401262    47            inc   edi
00401263    46            inc   esi
00401264^ E2 F2         loopd   short 00401258
```
其中,0x00402134处的数据如下:

> FF 77 88 66 99 55 AA 44

然后检测user32!GetDlgItemTextA函数的断点

```
0040126F    BF 141E4000   mov   edi, <jmp.&USER32.GetDlgItemText>
00401274    6A 0A         push    0xA
00401276    68 1D214000   push    0040211D
0040127B    68 EA030000   push    0x3EA
00401280    FF75 08         push    dword ptr
00401283    1E            push    ds
00401284    0E            push    cs
00401285    1f            pop   ds
00401286    8B7F 02         mov   edi, dword ptr
00401289    8B3F            mov   edi, dword ptr
0040128B    8B07            mov   eax, dword ptr
0040128D    1f            pop   ds
0040128E    25 FF000000   and   eax, 0xFF
00401293    3D CC000000   cmp   eax, 0xCC
00401298    75 24         jnz   short 004012BE
0040129A    6A 30         push    0x30
0040129C    68 8D224000   push    0040228D                         ; Breakpoints - just say no!
004012A1    68 A8224000   push    004022A8                         ; So - You're trying to put a breakpoint on GetDlgItemTe>
004012A6    6A 00         push    0x0
004012A8    B0 1A         mov   al, 0x1A
004012AA    FF15 64234000   call    dword ptr              ; crueme.00401493
004012B0    FF35 54204000   push    dword ptr
004012B6    B0 0A         mov   al, 0xA
004012B8    FF15 64234000   call    dword ptr              ; crueme.00401493
```
然后调用user32!GetDlgItemTextA函数获取用户输入的Password,最后调用一个函数,如果这个函数返回0则失败。

```
004012BE    FFD7            call    edi                              ; GetDlgItemTextA
004012C0    E8 EC000000   call    004013B1                         ; 算法
004012C5    85C0            test    eax, eax
004012C7    74 15         je      short 004012DE
004012C9    68 36224000   push    00402236                         ; Correct password - Good work!
004012CE    68 F3030000   push    0x3F3
004012D3    FF75 08         push    dword ptr
004012D6    B0 15         mov   al, 0x15
004012D8    FF15 64234000   call    dword ptr              ; crueme.00401493
004012DE    68 54224000   push    00402254                         ; False password - Try again
004012E3    68 F2030000   push    0x3F2
004012E8    FF75 08         push    dword ptr
004012EB    B0 15         mov   al, 0x15
004012ED    FF15 64234000   call    dword ptr              ; crueme.00401493
```
**0x2 分析算法2**
来到0x004013B1处,发现程序检测了Password的长度,如果长度不为8则失败。

```
004013B1    3C 08         cmp   al, 0x8
004013B3    0F85 9E000000   jnz   00401457
......
00401457    33C0            xor   eax, eax
00401459    BE 1D214000   mov   esi, 0040211D                  ; ASCII "87654321"
0040145E    B9 08000000   mov   ecx, 0x8
00401463    C606 00         mov   byte ptr , 0x0
00401466    46            inc   esi
00401467^ E2 FA         loopd   short 00401463
00401469    C3            retn
```
程序首先将用户输入的Password的每个字节和0x50异或。

```
004013B9    B9 08000000   mov   ecx, 0x8
004013BE    BE 1D214000   mov   esi, 0040211D                  ; ASCII "87654321"
004013C3    8036 50         xor   byte ptr , 0x50
004013C6    46            inc   esi
004013C7^ E2 FA         loopd   short 004013C3
```
然后加上剩余的循环次数(第一个字节加8,第二个字节加7,以此类推,一直加到Password的最后一个字节),最后的结果记为s

```
004013C9    B9 08000000   mov   ecx, 0x8
004013CE    BE 1D214000   mov   esi, 0040211D                  ; ASCII "87654321"
004013D3    000E            add   byte ptr , cl
004013D5    46            inc   esi
004013D6^ E2 FB         loopd   short 004013D3
```
然后两个字符两个字符异或,保存到0x0040212B处。

```
004013D8    33FF            xor   edi, edi
004013DA    BE 1D214000   mov   esi, 0040211D                  ; ASCII "87654321"
004013DF    B9 04000000   mov   ecx, 0x4
004013E4    8A06            mov   al, byte ptr
004013E6    8A5E 01         mov   bl, byte ptr
004013E9    32C3            xor   al, bl
004013EB    8887 2B214000   mov   byte ptr , al
004013F1    83C6 02         add   esi, 0x2
004013F4    47            inc   edi
004013F5^ E2 ED         loopd   short 004013E4
```
然后将0x0040212B的每个字节异或(记为a1),如果a1是0就会失败。

```
004013F7    BE 2B214000   mov   esi, 0040212B
004013FC    8A06            mov   al, byte ptr
004013FE    8A5E 01         mov   bl, byte ptr
00401401    32C3            xor   al, bl
00401403    8A5E 02         mov   bl, byte ptr
00401406    8A4E 03         mov   cl, byte ptr
00401409    32D9            xor   bl, cl
0040140B    32C3            xor   al, bl
0040140D    84C0            test    al, al
0040140F    74 46         je      short 00401457                   ; 失败
```
然后s的每个字节和a1异或。

```
00401411    BE 1D214000   mov   esi, 0040211D                  ; ASCII "87654321"
00401416    B9 08000000   mov   ecx, 0x8
0040141B    3006            xor   byte ptr , al
0040141D    46            inc   esi
0040141E^ E2 FB         loopd   short 0040141B
```
再和0x0040213B的每个字节异或。

```
00401420    B9 10000000   mov   ecx, 0x10
00401425    D1E9            shr   ecx, 1
00401427    BE 1D214000   mov   esi, 0040211D                  ; ASCII "87654321"
0040142C    BF 3B214000   mov   edi, 0040213B
00401431    8A07            mov   al, byte ptr
00401433    3006            xor   byte ptr , al
00401435    47            inc   edi
00401436    46            inc   esi
00401437^ E2 F8         loopd   short 00401431
```
最后和0x00402134的每个字节比较,如果相等则成功,否则失败。

```
00401439    1E            push    ds
0040143A    07            pop   es
0040143B    B9 08000000   mov   ecx, 0x8
00401440    BF 34214000   mov   edi, 00402134
00401445    BE 1D214000   mov   esi, 0040211D                           ; ASCII "87654321"
0040144A    F3:A6         repe    cmps byte ptr es:, byte ptr
0040144C    85C9            test    ecx, ecx
0040144E    75 07         jnz   short 00401457
00401450    B8 01000000   mov   eax, 0x1
00401455    EB 02         jmp   short 00401459
00401457    33C0            xor   eax, eax
00401459    BE 1D214000   mov   esi, 0040211D                           ; ASCII "87654321"
0040145E    B9 08000000   mov   ecx, 0x8
00401463    C606 00         mov   byte ptr , 0x0
00401466    46            inc   esi
00401467^ E2 FA         loopd   short 00401463
00401469    C3            retn
```
这里有一点要注意:0x00402134 + 8 - 1 == 0x0040213B
因此这是属于一段数据中的。
其中0x0040213B中的数据如下(第一个字节随着crueme.dat文件的内容变化而变化):

> 44 BB 33 CC 22 DD 11 EE

**0x3 注册机的编写**

因为有一个字节是未知的,所以可以自己指定,分析出算法以后,编写出的注册机如下:

```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char rol1B(char a)
{
        char result;
        _asm
        {
                mov al,a
                rol al,1
                mov result,al
        }
        return result;
}
char ror1B(char a)
{
        char result;
        _asm
        {
                mov al,a
                ror al,1
                mov result,al
        }
        return result;
}
int main(void)
{
        char KeyFile;
        char RegisterInfo;
        int a1;
        unsigned char *Serial;
        unsigned char Data;
        unsigned char Data1[] = {
                0xFF,0x77,0x88,0x66,0x99,
                0x55,0xAA,0x44,0xBB,0x33,
                0xCC,0x22,0xDD,0x11,0xEE};
        /*
                Input:char + Password

                Output:Password + crueme.dat
        */
        scanf("%s",KeyFile);
        strcpy(RegisterInfo,KeyFile);
        if(strlen(KeyFile) != 9)
                return 0;
        KeyFile ^= Data1;
        KeyFile = rol1B(KeyFile);
        Serial = (unsigned char*)&KeyFile;
        for(int i = 0;i < 8;i++)
        {
                Serial ^= 0x50;
                Serial += (8 - i);
        }
        for(int i = 0;i < 4;i++)
                Data = Serial ^ Serial;
        a1 = Data ^ Data ^ Data ^ Data;
        if(a1 == 0)
                return 0;
        for(int i = 0;i < 8;i++)
                Serial ^= a1;
        Serial ^= KeyFile;
        for(int i = 1;i < 8;i++)
                Serial ^= Data1;
        puts("-----------------------");
        printf("%s\n",&RegisterInfo);
        for(int i = 0;i < 7;i++)
        {
                Serial = ror1B(Serial);
                Serial ^= Data1;
                printf("%0.2X ",Serial);
        }
        printf("%0.2X\n",RegisterInfo);
        system("pause");
        return 0;
}
```
运行程序,输入指定的第一个字节和指定的Password(我指定的第一个字节是'~',Password是""),得到结果如下:
![这里写图片描述](http://img.blog.csdn.net/20171001125813207?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

用二进制编辑器将4F A2 82 18 09 AA BC 7E写入到crueme.dat中,然后打开程序,输入"",在OD中查看已经通过验证。
![这里写图片描述](http://img.blog.csdn.net/20171001125951957?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
至此,注册机编写完毕。
**0x4 修改程序**
仔细观察代码,发现这个程序的有一点奇怪。

```
004012C5    85C0            test    eax, eax
004012C7    74 15         je      short 004012DE
004012C9    68 36224000   push    00402236                         ; Correct password - Good work!
004012CE    68 F3030000   push    0x3F3
004012D3    FF75 08         push    dword ptr
004012D6    B0 15         mov   al, 0x15
004012D8    FF15 64234000   call    dword ptr
004012DE    68 54224000   push    00402254                         ; False password - Try again
004012E3    68 F2030000   push    0x3F2
004012E8    FF75 08         push    dword ptr
004012EB    B0 15         mov   al, 0x15
004012ED    FF15 64234000   call    dword ptr
```

其中,程序中并没有0x3F3的ControlID,然后程序修改完以后没有返回,直接把标题改成失败了,这里我怀疑可能有BUG。为了达到注册成功的目的,这里我修改了一下程序。
首先,这个程序中有设置只读属性,导致我们无法直接修改这个程序,因此我们需要去掉这个只读属性。
![这里写图片描述](http://img.blog.csdn.net/20171001130740342?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
去掉以后,使用FFI新建一个区段。
![这里写图片描述](http://img.blog.csdn.net/20171001130828225?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
然后修改区段属性如下图所示:
![这里写图片描述](http://img.blog.csdn.net/20171001130916883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
添加完以后,发现程序有重定位表,去掉。
![这里写图片描述](http://img.blog.csdn.net/20171001131005596?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
至此,就可以使用OD来修改程序了。
OD载入,在新区段中添加如下代码:
![这里写图片描述](http://img.blog.csdn.net/20171001131207834?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
保存程序,文件名为crueme.exe
![这里写图片描述](http://img.blog.csdn.net/20171001131302582?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![这里写图片描述](http://img.blog.csdn.net/20171001131309652?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
保存以后,重新载入程序,将0x004012C9处的代码修改成如下图所示的代码。
![这里写图片描述](http://img.blog.csdn.net/20171001131434866?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
然后保存即可。
最后打开保存的文件,输入注册码,得到结果如下:
![这里写图片描述](http://img.blog.csdn.net/20171001131728576?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTk0NTk4NTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

全文完。

hejialong 发表于 2017-10-1 14:29

时有语默 发表于 2017-10-1 14:44

看不懂。。。

pzhzshun 发表于 2017-10-1 14:51

感谢分享,收藏学习!

Jingk 发表于 2017-10-2 00:22

厉害的大佬~~~

2864095098 发表于 2017-10-2 23:38

楼主真厉害

西交范略 发表于 2017-10-8 16:59

CRUEME.DAT似乎是烟雾弹
我这边编辑框输入WYHE000000就可以成功

据说预设的Key是Cracking4U

zbnysjwsnd8 发表于 2017-10-8 17:08

西交范略 发表于 2017-10-8 16:59
CRUEME.DAT似乎是烟雾弹
我这边编辑框输入WYHE000000就可以成功



感谢。
我一会再看一下

zbnysjwsnd8 发表于 2017-10-8 17:14

西交范略 发表于 2017-10-8 16:59
CRUEME.DAT似乎是烟雾弹
我这边编辑框输入WYHE000000就可以成功



确实是烟雾弹
有一个算法的Call我没注意看
还是你厉害的。。

zbnysjwsnd8 发表于 2018-1-22 12:18

@pk8900 的确不是bug
当时没仔细看。
有一组预设key是Cracking4U 范略师傅给的
另外我自己找了一组(去掉中括号)
["2s ]
页: [1] 2
查看完整版本: 160个CrackMe之91