吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12076|回复: 24
收起左侧

[原创] 160 个 CrackMe 之 091 - Cruehead ,避过陷阱及防护,暴力算出密码

  [复制链接]
solly 发表于 2019-6-30 03:22
本帖最后由 solly 于 2019-7-1 12:40 编辑

160 个 CrackMe 之 091 - Cruehead 在本坛中已有人研究过,不过其陷入 CrackMe 设置的陷阱,没能发现其真正的密码。
这个 CrackMe 也包含了多种反调试,包括 API 代-理,防 bpx 中断,数据加密,防静态分析,代码动态破坏/恢复,设置陷阱(真假两个密码验证,文件内容验证也没有用)。


同时, CrackMe 还要求在其目录中有一个"crueme.dat"的文件,并且其长度、内容无限制,但在假的密码验证内有进行计算等操作。
启动后,如果没有这个“crueme.dat"文件,会报个提示,并会退出,如下图:
00.png
我们用文本编辑工具生成一个这样的文件并保存到CrackMe的目录内即可。


再次启动,就可以正常启动了,界面如下:
01.png


我们重新用 OD 载入,来到  OEP,如下图:
10.png
可以看到,其第一条指令就是修改内存的值,其实这个值 0x00401493,一看就是一个地址,实际上,这个地址就是一个 API 代-理函数的入口地址,这个 代-理函数封装了42个API函数,通过 al = ”索引号“ 的方式来调用这些API函数,因此,静态分析就基本没有可能了。


下面就是 CrackMe 开头的代码:
[Asm] 纯文本查看 复制代码
00401000 c> $  C705 64234000 93144000   mov     dword ptr [402364], 00401493    ;  修正 api 代-理 call的函数入口
0040100A    .  68 D9204000              push    004020D9                        ; /pLocaltime = crueme.004020D9
0040100F    .  E8 F20C0000              call    <jmp.&KERNEL32.GetLocalTime>    ; \GetLocalTime
00401014    .  8D1C9D 00000000          lea     ebx, dword ptr [ebx*4]
0040101B    .  D12D 80234000            shr     dword ptr [402380], 1           ;  [addr]== 0x00401224
00401021    .  66:A1 E7204000           mov     ax, word ptr [4020E7]           ;  AX == 0x01AC
00401027    .  A2 63234000              mov     byte ptr [402363], al           ;  [addr]==0xAC,解码密钥
0040102C    .  E8 4A040000              call    0040147B                        ;  解码 API 代-理函数的索引表
00401031    .  83C0 05                  add     eax, 5                          ;  eax = 0x0201
00401034    .  8D0485 00000000          lea     eax, dword ptr [eax*4]
0040103B    .  83C0 05                  add     eax, 5                          ;  eax = 0x0809
0040103E    .  E8 27040000              call    0040146A                        ;  解码字符串:"Win95 File Monitor"
00401043    .  6A 00                    push    0
00401045    .  68 80000000              push    80
0040104A    .  6A 03                    push    3
0040104C    .  6A 00                    push    0
0040104E    .  6A 00                    push    0
00401050    .  68 000000C0              push    C0000000
00401055    .  68 76214000              push    00402176                        ;  文件名:CRUEME.DAT
0040105A    .  B0 1F                    mov     al, 1F                          ;  函数 CreateFileA() 的索引
0040105C    .  FF15 64234000            call    dword ptr [402364]              ;  第1条指令修改了这里的地址,改为 0x00401493,这个调用是一个API入口代-理,AL为索引参数
00401062    .  83F8 FF                  cmp     eax, -1                         ;  eax != -1,表示读取文件成功
00401065    .  75 24                    jnz     short 0040108B
00401067    .  6A 30                    push    30
00401069    .  68 A0214000              push    004021A0                        ;  ASCII "This is the end - My only friend the end!"
0040106E    .  68 CA214000              push    004021CA                        ;  ASCII "AAARGH! Where is my CRUEME.DAT file???",CR,"    I cant go on without my beloved file!"
00401073    .  6A 00                    push    0
00401075    .  B0 1A                    mov     al, 1A                          ;  MessageBoxA()
00401077    .  FF15 64234000            call    dword ptr [402364]              ;  crueme.00401493
0040107D    .  FF35 54204000            push    dword ptr [402054]
00401083    .  B0 0A                    mov     al, 0A                          ;  ExitProcess()
00401085    .  FF15 64234000            call    dword ptr [402364]              ;  crueme.00401493
0040108B    >  A3 81214000              mov     dword ptr [402181], eax         ;  保存文件句柄

可以看到      call    dword ptr [402364]      就是这个 API 代-理调用,al 为参数,如 al = 0x1F,表示调用 CreateFileA() ,al=0x1A,表示调用 MessageBoxA(),等等,并且该函数内部通过对 al 参数进行一定的计算,而且参与计算的数据中有一个数据是通过查表取得,结合在一起才能确定 API 的入口跳转位置。这个数据表是加密的,通过上面代码中的 call    0040147B 进行解码,解码后才可以用。同时上面代码中的 call 0040146A 解码了一个字符串: "Win95 File Monitor",后面会用 FindWindow()查找这个标题的窗口,防止文件访问监控。


取文件内容后,会与一组常量进行运算,不过后面真正计算密码时也没有用到这些数据。

F8 往下走,来到这里,如下图:
11.png

中间插入了生成对话框应用的代码,就是由这段代码来显示主对话框界面的。而附近有很多其它代码,其实都是没用的废代码,包括生成标准的 Windows 窗口代码,消息循环代码,WndProc代码,都是没用的。

具体代码如下:

[Asm] 纯文本查看 复制代码
00401138    .  6A 00                    push    0
0040113A    .  68 C1114000              push    004011C1                        ;  DlgProc
0040113F    .  6A 00                    push    0
00401141    .  68 E9204000              push    004020E9                        ;  字符串 (ASCII "DLG_START")
00401146    .  FF35 D6234000            push    dword ptr [4023D6]              ;  hInstance
0040114C    .  B0 12                    mov     al, 12                          ;  DialogBoxParamA()
0040114E    .  FF15 64234000            call    dword ptr [402364]              ;  crueme.00401493
00401154    .  EB 64                    jmp     short 004011BA


如下图,上面代码前面的 LoadIconA(), LoadCursorA() 等,就没什么用。

12.png



通过前面的代码,我们知道 DlgProc 的地址是 0x004011C1,其主体部分如下图所示:

13.png

只处理了 WM_COMMAND 和 WM_CLOSE 消息。具体代码如下:

[Asm] 纯文本查看 复制代码
004011C1   /.  C8 000000                enter   0, 0                            ;  DlgProc
004011C5   |.  53                       push    ebx
004011C6   |.  56                       push    esi
004011C7   |.  57                       push    edi
004011C8   |.  817D 0C 11010000         cmp     dword ptr [ebp+C], 111          ;  WM_COMMAND
004011CF   |.  0F84 2F010000            je      00401304
004011D5   |.  837D 0C 10               cmp     dword ptr [ebp+C], 10           ;  WM_CLOSE
004011D9   |.  0F84 48010000            je      00401327
004011DF   |.  B8 00000000              mov     eax, 0
004011E4   |>  5F                       pop     edi
004011E5   |.  5E                       pop     esi
004011E6   |.  5B                       pop     ebx
004011E7   |.  C9                       leave
004011E8   |.  C2 1000                  retn    10

通过跟随    je      00401304 可以找到处理 WM_COMMAND 消息的 Handler。如下图所示:
14.png
然后跟随 je 00401213 可以找到按钮”Check It!“的Click事件的 Handler。如下图所示:
15.png
具体的代码如下所示:
[Asm] 纯文本查看 复制代码
00401213   |>  BA 1D214000              mov     edx, 0040211D                   ;  保存密码的缓冲区地址
00401218   |.  8D1C85 00000000          lea     ebx, dword ptr [eax*4]          ;  (无用代码)Win9x下eax=ecx=0, WinNT下eax=ecx=DlgProc
0040121F   |.  83C3 05                  add     ebx, 5                          ;  (无用代码)改成 mov ebx, 5
00401222   |.  03DA                     add     ebx, edx                        ;  (无用代码)
00401224   |.  52                       push    edx                             ;  lParam, 缓冲区地址
00401225   |.  6A 0E                    push    0E                              ;  wParam, 可取得的最大字符数,14
00401227   |.  6A 0D                    push    0D                              ;  uMsg = WM_GETTEXT
00401229   |.  68 EA030000              push    3EA                             ;  ControlID. 密码文本框
0040122E   |.  FF75 08                  push    dword ptr [ebp+8]               ;  hInstance, 堆栈 ss:[0019F8D8]=006F0C10
00401231   |.  B0 25                    mov     al, 25                          ;  SendDlgItemMessageA(WM_GETTEXT)
00401233   |.  FF15 64234000            call    dword ptr [402364]              ;  取得注册密码"1234567890", eax为长度
00401239   |.  E8 35090000              call    00401B73                        ;  密码验证,正确返回0,错误返回1
0040123E   |.  50                       push    eax                             ;  保存验证结果
0040123F   |.  BF 01000000              mov     edi, 1
00401244   |.  E8 FD080000              call    00401B46                        ;  edi = 1,将0x00401224处的代码替成错误代码
00401249   |.  B9 08000000              mov     ecx, 8
0040124E   |.  BF 85214000              mov     edi, 00402185                   ;  文件内容 (ASCII "787878787878")
00401253   |.  BE 34214000              mov     esi, 00402134                   ;  esi ==> 常量 FF 77 88 66 99 55 AA 44 BB 33 CC 22 DD 11 EE C0
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
00401266   |.  58                       pop     eax                             ;  密码验证结果
00401267   |.  85C0                     test    eax, eax
00401269   |.  0F84 84000000            je      004012F3                        ;  密码正确则跳转

这一段代码就是真正的密码验证过程,其中算法在 call    00401B73 中,如下图所示:
16.png
继续:
17.png

其算法代码如下:
[Asm] 纯文本查看 复制代码
00401B73   /$  33FF                     xor     edi, edi
00401B75   |.  33F6                     xor     esi, esi
00401B77   |.  85C0                     test    eax, eax                        ;  长度
00401B79   |.  0F84 0F010000            je      00401C8E
00401B7F   |.  A3 72214000              mov     dword ptr [402172], eax         ;  注册密码的长度 len
00401B84   |.  BB 1D214000              mov     ebx, 0040211D                   ;  ebx ===> (ASCII "1234567890")
00401B89   |>  B9 FF000000              /mov     ecx, 0FF                       ;  循环次数, count=255
00401B8E   |>  8B03                     |/mov     eax, dword ptr [ebx]          ;  第1~4字符
00401B90   |.  05 87D61200              ||add     eax, 12D687
00401B95   |.  0343 08                  ||add     eax, dword ptr [ebx+8]        ;  第9~12字符
00401B98   |.  2D 672B0000              ||sub     eax, 2B67
00401B9D   |.  33D2                     ||xor     edx, edx                      ;  清空积高32位
00401B9F   |.  F725 72214000            ||mul     dword ptr [402172]            ;  乘以长度值,取积低32位
00401BA5   |.  8B53 04                  ||mov     edx, dword ptr [ebx+4]        ;  第5~8字符
00401BA8   |.  81C2 EAF48F04            ||add     edx, 48FF4EA
00401BAE   |.  33C2                     ||xor     eax, edx
00401BB0   |.  8B53 08                  ||mov     edx, dword ptr [ebx+8]        ;  第9~12字符
00401BB3   |.  81EA 015CBC00            ||sub     edx, 0BC5C01
00401BB9   |.  2B13                     ||sub     edx, dword ptr [ebx]          ;  第1~4字符
00401BBB   |.  81C2 672B0000            ||add     edx, 2B67
00401BC1   |.  33C2                     ||xor     eax, edx
00401BC3   |.  0D E2599302              ||or      eax, 29359E2
00401BC8   |.  03F8                     ||add     edi, eax
00401BCA   |.  233D 62214000            ||and     edi, dword ptr [402162]       ;  [addr]== 0x15263748,静态常量
00401BD0   |.  8B03                     ||mov     eax, dword ptr [ebx]          ;  第1~4字符
00401BD2   |.  2D 87D61200              ||sub     eax, 12D687
00401BD7   |.  2B43 08                  ||sub     eax, dword ptr [ebx+8]        ;  第9~12字符
00401BDA   |.  05 CE560000              ||add     eax, 56CE
00401BDF   |.  33D2                     ||xor     edx, edx                      ;  清除被除数高32位
00401BE1   |.  F735 72214000            ||div     dword ptr [402172]            ;  除以长度值
00401BE7   |.  8B53 04                  ||mov     edx, dword ptr [ebx+4]        ;  第5~8字符
00401BEA   |.  81EA EAF48F04            ||sub     edx, 48FF4EA
00401BF0   |.  33C2                     ||xor     eax, edx
00401BF2   |.  8B53 08                  ||mov     edx, dword ptr [ebx+8]        ;  第9~12字符
00401BF5   |.  81C2 015CBC00            ||add     edx, 0BC5C01
00401BFB   |.  0313                     ||add     edx, dword ptr [ebx]          ;  第1~4字符
00401BFD   |.  81EA CE560000            ||sub     edx, 56CE
00401C03   |.  33C2                     ||xor     eax, edx
00401C05   |.  25 E2599302              ||and     eax, 29359E2
00401C0A   |.  03F0                     ||add     esi, eax
00401C0C   |.  0B35 66214000            ||or      esi, dword ptr [402166]       ;  [addr] = 0x596A7B8C,静态常量
00401C12   |.  E2 02                    ||loopd   short 00401C16
00401C14   |.  EB 05                    ||jmp     short 00401C1B
00401C16   |>^ E9 73FFFFFF              |\jmp     00401B8E
00401C1B   |>  81C7 11090000            |add     edi, 911
00401C21   |.  81EE 11090000            |sub     esi, 911
00401C27   |.  FE0D 33214000            |dec     byte ptr [402133]              ;  0xFF,静态初始化的变量
00401C2D   |.  803D 33214000 00         |cmp     byte ptr [402133], 0
00401C34   |.^ 0F85 4FFFFFFF            \jnz     00401B89
00401C3A   |.  C605 33214000 FF         mov     byte ptr [402133], 0FF          ;  恢复
00401C41   |.  BB 1D214000              mov     ebx, 0040211D                   ;  ebx ===> (ASCII "1234567890")
00401C46   |.  B9 0E000000              mov     ecx, 0E                         ;  长度,14
00401C4B   |>  C603 00                  /mov     byte ptr [ebx], 0              ;  循环清除密码数据
00401C4E   |.  43                       |inc     ebx
00401C4F   |.^ E2 FA                    \loopd   short 00401C4B
00401C51   |.  81C7 AFE3FDEF            add     edi, EFFDE3AF
00401C57   |.  75 35                    jnz     short 00401C8E                  ;  等于0
00401C59   |.  81C6 238D94A4            add     esi, A4948D23
00401C5F   |.  75 2D                    jnz     short 00401C8E                  ;  等于0
00401C61   |.  BE 2C224000              mov     esi, 0040222C                   ;  ASCII "for input"
00401C66   |.  83C6 0A                  add     esi, 0A                         ;  esi ===> "Correct password - Good work!"
00401C69   |.  BF 6F224000              mov     edi, 0040226F                   ;  ASCII "Correct password - Good work!"
00401C6E   |.  B9 1D000000              mov     ecx, 1D
00401C73   |.  F3:A4                    rep     movs byte ptr es:[edi], byte pt>;  复制 "Correct password - Good work!"
00401C75   |.  68 6F224000              push    0040226F                        ;  addr ===> "Correct password - Good work!"
00401C7A   |.  68 F2030000              push    3F2
00401C7F   |.  FF75 08                  push    dword ptr [ebp+8]               ;  hInstance
00401C82   |.  B0 15                    mov     al, 15                          ;  SetDlgItemTextA()
00401C84   |.  FF15 64234000            call    dword ptr [402364]              ;  crueme.00401493
00401C8A   |.  33C0                     xor     eax, eax
00401C8C   |.  EB 05                    jmp     short 00401C93
00401C8E   |>  B8 01000000              mov     eax, 1
00401C93   \>  C3                       retn

可见,在上面函数包括了验证算法,并且验证通过,则会修改界面静态文本标签(控件ID为 0x03F2)的内容为"Correct password - Good work!",不会象另一个假的验证过程,会在一个无效的控件ID(0x03F3)上显示,正确标签控件上还是会显示错误提示。
这个算法并不复杂,但对数据计算是破坏性的,并且循环计算256x256次,好象无法逆推,只好暴破。暴破条件就是最后 edi 和 esi 都等于0时,则输入的密码有效。如下图所示位置,就是所需的条件:
18.png
先回到界面,输入假码:
02.png
进行验证处理,可了解其算法,并写出暴力计算密码代码。通过35分钟计算,得到一组4字符的密码:
”*A*
其中引号是半角的。这里说明一下,虽然算法中用到了 12 个字符密码,但并没有要求一定要 12 个字符,只要长度大于 0 即可,其它位置可以置 '\0'代替,所以暴力计算密码时可以从1 ~ 12 逐个增加密码长度,控制一定的计算量,不然,一开始就测试 12 位的密码,那只有请 "神威·太湖之光" 出马了。
输入这个密码,如下图:
03.png
再次按“Check it!”,可得到正确的提示“Correct password - Good work!”。


下面看看其陷阱,call 00401B73 中如果验证错误,则没有显示提示直接返回,来到下面代码处,如下图:
19.png
先对  API 函数 GetDlgItemTextA 进行检查,看看有没有 BPX GetDlgItemTextA 进行中断跟踪。有则提示并退出。没有则来到下面的代码:
20.png
可以看到 call 004013B1 又对密码进行了一番操作,但是返回后,并没有正确的进行提示。如下代码:
[Asm] 纯文本查看 复制代码
004012BE   |>  FFD7                     call    edi                             ;  call GetDlgItemTextA(),读取密码
004012C0   |.  E8 EC000000              call    004013B1                        ;  对密码进行操作
004012C5   |.  85C0                     test    eax, eax
004012C7   |.  74 15                    je      short 004012DE
004012C9   |.  68 36224000              push    00402236                        ;  addr ===> (ASCII "Correct password - Good work!")
004012CE   |.  68 F3030000              push    3F3                             ;  ControlID,这个控件ID是错误的
004012D3   |.  FF75 08                  push    dword ptr [ebp+8]
004012D6   |.  B0 15                    mov     al, 15                          ;  SetDlgItemTextA()
004012D8   |.  FF15 64234000            call    dword ptr [402364]              ;  crueme.00401493,提示完成但并没有跳转,而是又直接显示失败的提示了
004012DE   |>  68 54224000              push    00402254                        ;  addr ===>(ASCII "False password - Try again")
004012E3   |.  68 F2030000              push    3F2                             ;  提示框 ControlID
004012E8   |.  FF75 08                  push    dword ptr [ebp+8]               ;  hInstance
004012EB   |.  B0 15                    mov     al, 15                          ;  SetDlgItemTextA()
004012ED   |.  FF15 64234000            call    dword ptr [402364]              ;  crueme.00401493
004012F3   |>  33FF                     xor     edi, edi                        ;  edi = 0 恢复代码
004012F5   |.  E8 4C080000              call    00401B46                        ;  恢复代码
004012FA   |.  B8 01000000              mov     eax, 1
004012FF   |.^ E9 E0FEFFFF              jmp     004011E4

不管call    004013B1 返回什么值,最终我们能看到的提示都是“False password - Try again”。所以这里就是个陷阱,并不是真正的密码验证的地方。

另一个需要说明一下的是,在真正的算法函数的前面,CrackMe 是通过 SendDlgItemMessageA(WM_GETTEXT)来取得的密码,并不是常用的 GetDlgItemTextA()函数。并且通过API代-理封装,不注意就很难断下其真正取密码和验证的位置。因为后面假验函数是用的 GetDlgItemTextA()取的密码,并且没有进行API代-理封装,是明文调用的,更具迷惑性,很容易上当掉入其陷阱。

下面交出暴破代码,使用 Dev-C++调试通过(没有逆推,如果谁有能力,看看是否可以逆推或优化,我这个在 i5 4670K 上计算了2047秒):
[C++] 纯文本查看 复制代码
#include <iostream>
#include <string.h>

int checkPassword(char * password);

int getPassword(int len);
int genPassword(int index, int len, char * testPassword); 

int main(int argc, char** argv) {
        
        //char password[] = "1234567890";
        //char password[] = "\"*A*";
        //checkPassword(password);
        
        /// 暴破密码 
        int len = 4;
        int b = getPassword(len);
        
        return 0;
}

int checkPassword(char * password) {
        union {
                char pwd[16];
                unsigned long key[4];
        } passwd;
        
        /// 初始化缓冲区 
        passwd.key[0] = 0;
        passwd.key[1] = 0;
        passwd.key[2] = 0;
        passwd.key[3] = 0;
        
        long n = strlen(password);
        if(n<=0) {
                return -1;
        }
        
        /// 长度处理,最长12个字符 
        if (n>12) {
                n = 12;
                password[12] = '\0'; /// 截断 
        }
        
        //// 存入计算缓冲区
        strcpy(passwd.pwd, password);
        
        long a, d;
        
        long check1 = 0;  /// edi
        long check2 = 0;  /// esi
        
        for(long i=255; i>0; i--) {
                for(long j=255; j>0; j--) {
                        a = passwd.key[0];
                        a += 0x0012D687;
                        a += passwd.key[2];
                        a -= 0x00002B67;
                        a *= n;
                        
                        d = passwd.key[1];
                        d += 0x048FF4EA;
                        a ^= d;  // xor
                        
                        d = passwd.key[2];
                        d -= 0x00BC5C01;
                        d -= passwd.key[0];
                        d += 0x00002B67;
                        a ^= d;
                        a |= 0x029359E2;
                        
                        check1 += a;
                        check1 &= 0x15263748;
                        
                        a = passwd.key[0];
                        a -= 0x0012D687;
                        a -= passwd.key[2];
                        a += 0x000056CE;
                        //a &= 0xFFFFFFFF;
                        a /= n;
                        
                        d = passwd.key[1];
                        d -= 0x048FF4EA;
                        a ^= d;
                        
                        d = passwd.key[2];
                        d += 0x00BC5C01;
                        d += passwd.key[0];
                        d -= 0x000056CE;
                        a ^= d;
                        a &= 0x029359E2;
                        
                        check2 += a;
                        check2 |= 0x596A7B8C;
                }
                check1 += 0x00000911;
                check2 -= 0x00000911;
        }
        //printf("check: 0x%08X - 0x%08X\n", check1, check2);

        check1 += 0xEFFDE3AF;
        check2 += 0xA4948D23;

        //// check1 = 0x05201300,check2 = 0x000EFFEE
        //printf("check: 0x%08X - 0x%08X\n", check1, check2);
        
        if(check1 | check2) {
                return 1; //// ERROR
        }
        
        return 0; ///OK
}

int getPassword(int len) {
        char password[16];
        for(int i=0; i<16;i++) {
                password[i] = '\0';
        }
        
        int b = genPassword(0, len, password);
        if(b) {
                printf("Password not found.\n");
        } else {
                printf("Found Password: %s\n", password);
        }

        
        return b;
} 

int genPassword(int index, int len, char * testPassword) {
        if(index == len) {
                return checkPassword(testPassword);
        }
        
        for(int i=0x20; i<0x7F; i++) { // printable characters,有 
        //for(int i=0x30; i<=0x39; i++) { // '0'~'9',无 
        //for(int i=0x41; i<=0x5A; i++) { // 'A'~'Z',无 
        //for(int i=0x61; i<=0x7A; i++) {  // 'a'~'z',无 
                testPassword[index] = (char)i;
                int b = genPassword(index+1, len, testPassword);
                if(b==0) {
                        return 0;
                }
        }
        
        return 1;
}



计算结果:
[HTML] 纯文本查看 复制代码
Found Password: "*A*

--------------------------------
Process exited after 2047 seconds with return value 0




分析完毕!!!

更新一下,算码程序用 VC6 编译,只要120秒左右即可算出4位密码。

2019-07-01 整理调整了一下算法,Dev-C++下 465 秒,VC6下70秒,都是 Release 编译,VC 还是牛。
[Asm] 纯文本查看 复制代码
#include <iostream>
#include <string.h>
 
int checkPassword(char * password);
 
int getPassword(int len);
int genPassword(int index, int len, char * testPassword); 
 
int main(int argc, char** argv) {
         
        //char password[] = "1234567890";
        //char password[] = "\"*A*";
        //int a = checkPassword(password);
        //if(a) {
        //        printf("test failure!\n");
        //} else {
        //        printf("test seccuss!\n");
        //}
         
        /// 暴破密码 
        int len = 4;
        int b = getPassword(len);
         
        return 0;
}
 
int checkPassword(char * password) {
        union {
                char pwd[16];
                unsigned long key[4];
        } passwd;
         
        /// 初始化缓冲区 
        passwd.key[0] = 0;
        passwd.key[1] = 0;
        passwd.key[2] = 0;
        passwd.key[3] = 0;
         
        long n = strlen(password);
        if(n<=0) {
                return -1;
        }
         
        /// 长度处理,最长12个字符 
        if (n>12) {
                n = 12;
                password[12] = '\0'; /// 截断 
        }
         
        //// 存入计算缓冲区
        strcpy(passwd.pwd, password);
         
        //long a, d;
         
        long check1 = 0;  /// edi
        long check2 = 0;  /// esi

        long A1, D1;        
        long A2, D2;
////=================================================================
        A1 = (passwd.key[0] + passwd.key[2] + 0x0012AB20) * n;
        D1 = passwd.key[1] + 0x048FF4EA;
        A1 ^= D1;  // xor        
////-----------------------------------------------------------------
        D1 = passwd.key[2] - passwd.key[0] - 0x00BC309A;
        A1 ^= D1;
        A1 |= 0x029359E2;
        
////=================================================================
        A2 = (passwd.key[0] - passwd.key[2] - 0x00127FB9) / n;
        D2 = passwd.key[1] - 0x048FF4EA;
        A2 ^= D2;  // Xor
///------------------------------------------------------------------
        D2 = passwd.key[2] + passwd.key[0] + 0x00BC0533;
        A2 ^= D2;
        A2 &= 0x029359E2;

///==================================================================
        for(long i=255; i>0; i--) {
                for(long j=255; j>0; j--) {
                         
                        check1 += A1; //a;
                        check1 &= 0x15263748;
                         
                        check2 += A2; //a;
                        check2 |= 0x596A7B8C;
                }
                check1 += 0x00000911;
                check2 -= 0x00000911;
        }
        
        //printf("check: 0x%08X - 0x%08X\n", check1, check2);
 
        check1 += 0xEFFDE3AF;
        check2 += 0xA4948D23;
 
        //// check1 = 0x05201300,check2 = 0x000EFFEE
        //printf("check: 0x%08X - 0x%08X\n", check1, check2);
         
        if(check1 | check2) {
                return 1; //// ERROR
        }
         
        return 0; //// OK
}
 
int getPassword(int len) {
        char password[16];
        for(int i=0; i<16;i++) {
                password[i] = '\0';
        }
         
        int b = genPassword(0, len, password);
        if(b) {
                printf("Password not found.\n");
        } else {
                printf("Found Password: %s\n", password);
        }

        return b;
} 
 
int genPassword(int index, int len, char * testPassword) {
        if(index == len) {
                return checkPassword(testPassword);
        }
         
        for(int i=0x20; i<0x7F; i++) { // printable characters,有 
        //for(int i=0x30; i<=0x39; i++) { // '0'~'9',无 
        //for(int i=0x41; i<=0x5A; i++) { // 'A'~'Z',无 
        //for(int i=0x61; i<=0x7A; i++) {  // 'a'~'z',无 
                testPassword[index] = (char)i;
                int b = genPassword(index+1, len, testPassword);
                if(b==0) {
                        return 0;
                }
        }
         
        return 1;
}


免费评分

参与人数 9吾爱币 +8 热心值 +8 收起 理由
lin10001 + 1 谢谢@Thanks!
oslven + 1 鼓励转贴优秀软件安全工具和文档!
MintPrince + 1 + 1 谢谢@Thanks!
陈世界 + 1 + 1 谢谢@Thanks!
天空藍 + 1 + 1 谢谢@Thanks!
F0rM + 1 + 1 谢谢@Thanks!
笙若 + 1 + 1 谢谢@Thanks!
wuaipojiee + 1 + 1 热心回复!
461735945 + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

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

bohansang 发表于 2019-7-26 20:28
膜拜大神呀
 楼主| solly 发表于 2019-7-30 16:30
本帖最后由 solly 于 2019-7-30 16:32 编辑
darksmile 发表于 2019-7-30 12:19
楼主好厉害!如果是8位密码,暴力破解需要算几天?!

8位密码,用可见字符尝试,次数最多为94的9次方减1,等于 572994802228616704 - 1 次。每一次尝试,光循环的计算有65000多次,加上前后的计算则更多。几天只怕解决不了滴。。。
Elisaa 发表于 2019-6-30 04:44
whg118 发表于 2019-6-30 12:10
好复杂,看的都晕。
wmwamy 发表于 2019-6-30 18:32
技术贴,完全看不懂,有空再对照看看
灬小霸道灬 发表于 2019-6-30 22:15
这个教程确实很溜
学士天下 发表于 2019-7-1 08:50
坚持学习,谢谢!!!
alstar 发表于 2019-7-1 11:30
给大佬,磕头,牛
一个软件被植入了,注册码
需要付费,给作者钱,所以求大神看看
https://www.lanzouj.com/i4sgw1g
む人生似梦 发表于 2019-7-27 07:38
吾爱破解论坛最帅的人是谁?
Yuliangmin1991 发表于 2019-7-27 15:53
大佬们   小弟在此膜拜你们了;。、
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

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

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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