吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7961|回复: 11
收起左侧

[原创] 160个CrackMe之91

[复制链接]
zbnysjwsnd8 发表于 2017-10-1 13:22
本帖最后由 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 [0x402364]             ; 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 [0x402364]             ; MessageBoxA
0040107D    FF35 54204000   push    dword ptr [0x402054]
00401083    B0 0A           mov     al, 0xA
00401085    FF15 64234000   call    dword ptr [0x402364]             ; ExitProcess

在程序目录下新建一个crueme.dat文件,内容为12345678,然后重新载入。
载入以后程序弹出了一个界面,如下图所示:
这里写图片描述
给GetWindowTextA下断点,然后随便输入一串密码,比如87654321,最后点击[Check it!]。
断下后,回溯到程序领空,找到按钮事件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 [edi]
0040125A    8A1E            mov     bl, byte ptr [esi]
0040125C    32C3            xor     al, bl                           ; 依次异或
0040125E    D0C0            rol     al, 1                            ; 循环左移一位
00401260    8806            mov     byte ptr [esi], 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 [ebp+0x8]
00401283    1E              push    ds
00401284    0E              push    cs
00401285    1f              pop     ds
00401286    8B7F 02         mov     edi, dword ptr [edi+0x2]
00401289    8B3F            mov     edi, dword ptr [edi]
0040128B    8B07            mov     eax, dword ptr [edi]
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 [0x402364]             ; crueme.00401493
004012B0    FF35 54204000   push    dword ptr [0x402054]
004012B6    B0 0A           mov     al, 0xA
004012B8    FF15 64234000   call    dword ptr [0x402364]             ; 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 [ebp+0x8]
004012D6    B0 15           mov     al, 0x15
004012D8    FF15 64234000   call    dword ptr [0x402364]             ; crueme.00401493
004012DE    68 54224000     push    00402254                         ; False password - Try again
004012E3    68 F2030000     push    0x3F2
004012E8    FF75 08         push    dword ptr [ebp+0x8]
004012EB    B0 15           mov     al, 0x15
004012ED    FF15 64234000   call    dword ptr [0x402364]             ; 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 [esi], 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 [esi], 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 [esi], 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 [esi]
004013E6    8A5E 01         mov     bl, byte ptr [esi+0x1]
004013E9    32C3            xor     al, bl
004013EB    8887 2B214000   mov     byte ptr [edi+0x40212B], 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 [esi]
004013FE    8A5E 01         mov     bl, byte ptr [esi+0x1]
00401401    32C3            xor     al, bl
00401403    8A5E 02         mov     bl, byte ptr [esi+0x2]
00401406    8A4E 03         mov     cl, byte ptr [esi+0x3]
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 [esi], 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 [edi]
00401433    3006            xor     byte ptr [esi], 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:[edi], byte ptr [esi]
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 [esi], 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[512];
    char RegisterInfo[512];
    int a1;
    unsigned char *Serial;
    unsigned char Data[4];
    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[0] ^= Data1[7];
    KeyFile[0] = rol1B(KeyFile[0]);
    Serial = (unsigned char*)&KeyFile[1];
    for(int i = 0;i < 8;i++)
    {
        Serial[i] ^= 0x50;
        Serial[i] += (8 - i);
    }
    for(int i = 0;i < 4;i++)
        Data[i] = Serial[i * 2] ^ Serial[i * 2 + 1];
    a1 = Data[0] ^ Data[1] ^ Data[2] ^ Data[3];
    if(a1 == 0)
        return 0;
    for(int i = 0;i < 8;i++)
        Serial[i] ^= a1;
    Serial[0] ^= KeyFile[0];
    for(int i = 1;i < 8;i++)
        Serial[i] ^= Data1[7 + i];
    puts("-----------------------");
    printf("%s\n",&RegisterInfo[1]);
    for(int i = 0;i < 7;i++)
    {
        Serial[i] = ror1B(Serial[i]);
        Serial[i] ^= Data1[i];
        printf("%0.2X ",Serial[i]);
    }
    printf("%0.2X\n",RegisterInfo[0]);
    system("pause");
    return 0;
}

运行程序,输入指定的第一个字节和指定的Password(我指定的第一个字节是'~',Password是"[_KaQqi]"),得到结果如下:
这里写图片描述

用二进制编辑器将4F A2 82 18 09 AA BC 7E写入到crueme.dat中,然后打开程序,输入"[_KaQqi]",在OD中查看已经通过验证。
这里写图片描述
至此,注册机编写完毕。
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 [ebp+0x8]
004012D6    B0 15           mov     al, 0x15
004012D8    FF15 64234000   call    dword ptr [0x402364]
004012DE    68 54224000     push    00402254                         ; False password - Try again
004012E3    68 F2030000     push    0x3F2
004012E8    FF75 08         push    dword ptr [ebp+0x8]
004012EB    B0 15           mov     al, 0x15
004012ED    FF15 64234000   call    dword ptr [0x402364]

其中,程序中并没有0x3F3的ControlID,然后程序修改完以后没有返回,直接把标题改成失败了,这里我怀疑可能有BUG。为了达到注册成功的目的,这里我修改了一下程序。
首先,这个程序中有设置只读属性,导致我们无法直接修改这个程序,因此我们需要去掉这个只读属性。
这里写图片描述
去掉以后,使用FFI新建一个区段。
这里写图片描述
然后修改区段属性如下图所示:
这里写图片描述
添加完以后,发现程序有重定位表,去掉。
这里写图片描述
至此,就可以使用OD来修改程序了。
OD载入,在新区段中添加如下代码:
这里写图片描述
保存程序,文件名为crueme.exe
这里写图片描述
这里写图片描述
保存以后,重新载入程序,将0x004012C9处的代码修改成如下图所示的代码。
这里写图片描述
然后保存即可。
最后打开保存的文件,输入注册码,得到结果如下:
这里写图片描述

全文完。

点评

我只想问大神学的是什么专业,太厉害了!  发表于 2017-10-1 14:17

免费评分

参与人数 8吾爱币 +14 热心值 +7 收起 理由
pk8900 + 1 + 1 总感觉这个不是BUG,却找不到能修改这里代码的代码
这是追求不是梦 + 1 + 1 热心回复!
Three_fish + 1 + 1 谢谢@Thanks!
2864095098 + 1 + 1 热心回复!
Sound + 6 + 1 已经处理,感谢您对吾爱破解论坛的支持!
hejialong + 2 + 1 谢谢@Thanks!
byh3025 + 1 + 1 热心回复!
黑龍 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

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

头像被屏蔽
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 ]
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-22 16:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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