如何生成CrackMe注册机之Unicorn

本练习破解的CrackMe可以在此处下载:https://reverse.put.as/wp-content/uploads/2010/05/2-Unicorn.zip。运行截图如下。

Snip20171014_1.png

抛砖引玉——下面就来分析如何生成注册码。

0x1 静态分析

找到判断验证入口函数:

         -[UnicornAppDelegate validate:]:
00002af0         push       ebp                                                 ; Objective C Implementation defined at 0x40bc (instance method)
00002af1         mov        ebp, esp
00002af3         sub        esp, 0x38
00002af6         mov        dword [ebp+var_C], ebx
00002af9         mov        dword [ebp+var_8], esi
00002afc         mov        dword [ebp+var_4], edi
00002aff         mov        ebx, dword [ebp+self]
00002b02         mov        eax, dword [ebx+8]
00002b05         mov        esi, dword [objc_msg_stringValue]                   ; @selector(stringValue)
00002b0b         mov        dword [esp+0x38+var_34], esi                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002b0f         mov        dword [esp+0x38+var_38], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002b12         call       imp___symbol_stub__objc_msgSend
00002b17         mov        edi, eax
00002b19         mov        eax, dword [ebx+0xc]
00002b1c         mov        dword [esp+0x38+var_34], esi                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002b20         mov        dword [esp+0x38+var_38], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002b23         call       imp___symbol_stub__objc_msgSend
00002b28         mov        dword [esp+0x38+var_2C], edi
00002b2c         mov        dword [esp+0x38+var_30], eax
00002b30         mov        eax, dword [objc_msg_validateSerial_forName_]       ; @selector(validateSerial:forName:)
00002b35         mov        dword [esp+0x38+var_34], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002b39         mov        dword [esp+0x38+var_38], ebx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002b3c         call       imp___symbol_stub__objc_msgSend
00002b41         test       al, al
00002b43         jne        loc_2b6e //Badboy

可以看到[UnicornAppDelegate validate:],只是取了输入的name和serial传给selector(validateSerial:forName:)去校验,如果不通过则提示失败。所以具体的校验还得看selector(validateSerial:forName:)。代码如下:

        ; ================ B E G I N N I N G   O F   P R O C E D U R E ================

        ; Variables:
        ;    arg_C: 20
        ;    arg_8: 16
        ;    _cmd: void *12
        ;    self: void *8
        ;    var_10: -16
        ;    var_14: -20
        ;    var_18: -24


             -[UnicornAppDelegate validateSerial:forName:]:
00002a41         push       ebp                                                 ; Objective C Implementation defined at 0x40b0 (instance method)
00002a42         mov        ebp, esp
00002a44         sub        esp, 0x18
00002a47         mov        dword [esp+0x18+var_10], 0x3044                     ; @"+unicorn"
00002a4f         mov        eax, dword [objc_msg_stringByAppendingString_]      ; @selector(stringByAppendingString:)
00002a54         mov        dword [esp+0x18+var_14], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002a58         mov        eax, dword [ebp+arg_C]
00002a5b         mov        dword [esp+0x18+var_18], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002a5e         call       imp___symbol_stub__objc_msgSend
00002a63         mov        edx, dword [objc_msg_md5HexHash]                    ; @selector(md5HexHash)
00002a69         mov        dword [esp+0x18+var_14], edx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002a6d         mov        dword [esp+0x18+var_18], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002a70         call       imp___symbol_stub__objc_msgSend
00002a75         mov        edx, dword [objc_msg_uppercaseString]               ; @selector(uppercaseString)
00002a7b         mov        dword [esp+0x18+var_14], edx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002a7f         mov        dword [esp+0x18+var_18], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002a82         call       imp___symbol_stub__objc_msgSend
00002a87         mov        dword [esp+0x18+var_10], 0x14
00002a8f         mov        edx, dword [objc_msg_substringToIndex_]             ; @selector(substringToIndex:)
00002a95         mov        dword [esp+0x18+var_14], edx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002a99         mov        dword [esp+0x18+var_18], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002a9c         call       imp___symbol_stub__objc_msgSend
00002aa1         mov        edx, dword [ebp+arg_8]
00002aa4         mov        dword [esp+0x18+var_10], edx
00002aa8         mov        edx, dword [objc_msg_isEqualToString_]              ; @selector(isEqualToString:)
00002aae         mov        dword [esp+0x18+var_14], edx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002ab2         mov        dword [esp+0x18+var_18], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002ab5         call       imp___symbol_stub__objc_msgSend
00002aba         test       al, al
00002abc         setne      al
00002abf         leave
00002ac0         ret

这里看出,算法流程大概如此:
取name,加上字符串"+unicorn",得到的字符串,再做MD5HASH,得到MD5密文字符串。接着,密文字符串转为大写字母。最后截取前面的0x14子串和输入的serial校验。

0x2动态分析

在Hopper中打开调试Debug,输入name后单点运行。可以看到最后比较时,当输入name为qwer,密码 3E2E44B5F67C13E710A3已经显示出来,如下图。

Snip20171014_5.png
Snip20171014_6.png

而根据上述分析得到的Keygen算法,计算如下:

1.MD5("qwer+unicorn") = 3e2e44b5f67c13e710a3efbf509a682d
2.upperCase("3e2e44b5f67c13e710a3efbf509a682d") = 3E2E44B5F67C13E710A3EFBF509A682D
3.("3E2E44B5F67C13E710A3EFBF509A682D").substringToIndex(0x14) = 3E2E44B5F67C13E710A3

这和Debug的结果一致。输入测试,结果正确。:)!

Snip20171014_2.png
Snip20171014_3.png

你可能感兴趣的:(如何生成CrackMe注册机之Unicorn)