如何生成CrackMe注册机之SmellsGood

本练习破解的CrackMe可以在此处下载:https://reverse.put.as/wp-content/uploads/2010/05/SmellsGood.zip。
运行截图如下。破解生成这个CrackMe的注册机相对来说有点难度。主要涉及到SHA1加密算法,且代码量长。

Snip20171014_7.png

0x1 静态代码分析

在Hopper中打开SmellsGood,可以看到如下关键函数Check。


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

        ; Variables:
        ;    _cmd: void *12
        ;    self: void *8
        ;    var_14: -20
        ;    var_18: -24
        ;    var_1C: -28
        ;    var_20: -32
        ;    var_24: -36
        ;    var_28: -40


             -[SmellsGood_AppDelegate check:]:
00002a63         push       ebp                                                 ; Objective C Implementation defined at 0x4118 (instance method)
00002a64         mov        ebp, esp
00002a66         push       esi
00002a67         push       ebx
00002a68         sub        esp, 0x20
00002a6b         mov        esi, dword [ebp+self]
00002a6e         mov        eax, dword [objc_msg_stringValue]                   ; @selector(stringValue)
00002a73         mov        edx, dword [esi+8]
00002a76         mov        dword [esp+0x28+var_24], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002a7a         mov        dword [esp+0x28+var_28], edx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002a7d         call       imp___jump_table__objc_msgSend
00002a82         mov        edx, dword [esi+0xc]
00002a85         mov        ebx, eax
00002a87         mov        eax, dword [objc_msg_stringValue]                   ; @selector(stringValue)
00002a8c         mov        dword [esp+0x28+var_28], edx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002a8f         mov        dword [esp+0x28+var_24], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002a93         call       imp___jump_table__objc_msgSend
00002a98         mov        dword [esp+0x28+var_1C], ebx
00002a9c         mov        dword [esp+0x28+var_20], eax
00002aa0         mov        eax, dword [objc_msg_checkCode_forName_]            ; @selector(checkCode:forName:)
00002aa5         mov        dword [esp+0x28+var_28], esi                        ; argument #1 for method imp___jump_table__objc_msgSend
00002aa8         mov        dword [esp+0x28+var_24], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002aac         call       imp___jump_table__objc_msgSend
00002ab1         test       al, al
00002ab3         je         loc_2aef

00002ab5         mov        eax, dword [esi+4]
00002ab8         mov        dword [esp+0x28+var_18], 0x0                        ; argument #5 for method imp___jump_table__NSRunAlertPanelRelativeToWindow
00002ac0         mov        dword [esp+0x28+var_1C], 0x0                        ; argument #4 for method imp___jump_table__NSRunAlertPanelRelativeToWindow
00002ac8         mov        dword [esp+0x28+var_20], 0x3018                     ; @"Okay", argument #3 for method imp___jump_table__NSRunAlertPanelRelativeToWindow
00002ad0         mov        dword [esp+0x28+var_14], eax                        ; argument #6 for method imp___jump_table__NSRunAlertPanelRelativeToWindow
00002ad4         mov        dword [esp+0x28+var_24], 0x3028                     ; @"It worked!", argument #2 for method imp___jump_table__NSRunAlertPanelRelativeToWindow
00002adc         mov        dword [esp+0x28+var_28], 0x3038                     ; @"Success", argument #1 for method imp___jump_table__NSRunAlertPanelRelativeToWindow
00002ae3         call       imp___jump_table__NSRunAlertPanelRelativeToWindow
00002ae8         add        esp, 0x20
00002aeb         pop        ebx
00002aec         pop        esi
00002aed         leave
00002aee         ret
                        ; endp

             loc_2aef:
00002aef         add        esp, 0x20                                           ; CODE XREF=-[SmellsGood_AppDelegate check:]+80
00002af2         pop        ebx
00002af3         pop        esi
00002af4         leave
00002af5         jmp        imp___jump_table__NSBeep
                        ; endp

这是点击界面上Check按钮时触发的校验函数。这个函数的作用在于,取得输入的Name和Code,调用-[SmellsGood_AppDelegate checkCode:forName:]去判断输入是否有效。如果通过检验,提示成功,不然提示失败。所以如何校验还得看[SmellsGood_AppDelegate checkCode: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


             -[SmellsGood_AppDelegate checkCode:forName:]:
00002afa         push       ebp                                                 ; Objective C Implementation defined at 0x410c (instance method)
00002afb         mov        ebp, esp
00002afd         push       ebx
00002afe         sub        esp, 0x14
00002b01         mov        ebx, dword [ebp+arg_8]
00002b04         mov        eax, dword [objc_msg_componentsSeparatedByString_]  ; @selector(componentsSeparatedByString:)
00002b09         mov        dword [esp+0x18+var_10], 0x3048                     ; @"-"
00002b11         mov        dword [esp+0x18+var_18], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002b14         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002b18         call       imp___jump_table__objc_msgSend
00002b1d         mov        edx, dword [objc_msg_count]                         ; @selector(count)
00002b23         mov        dword [esp+0x18+var_14], edx                        ; argument #2 for method imp___jump_table__objc_msgSend
00002b27         mov        dword [esp+0x18+var_18], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002b2a         call       imp___jump_table__objc_msgSend
00002b2f         cmp        eax, 0x5
00002b32         jne        loc_2b80

00002b34         mov        eax, dword [objc_msg_uppercaseString]               ; @selector(uppercaseString)
00002b39         mov        dword [esp+0x18+var_18], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002b3c         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002b40         call       imp___jump_table__objc_msgSend
00002b45         mov        ebx, eax
00002b47         mov        eax, dword [ebp+arg_C]
00002b4a         mov        dword [esp+0x18+var_10], eax
00002b4e         mov        eax, dword [objc_msg_generateCodeForName_]          ; @selector(generateCodeForName:)
00002b53         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002b57         mov        eax, dword [ebp+self]
00002b5a         mov        dword [esp+0x18+var_18], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002b5d         call       imp___jump_table__objc_msgSend
00002b62         mov        dword [esp+0x18+var_18], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002b65         mov        dword [esp+0x18+var_10], eax
00002b69         mov        eax, dword [objc_msg_isEqualToString_]              ; @selector(isEqualToString:)
00002b6e         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002b72         call       imp___jump_table__objc_msgSend
00002b77         mov        edx, 0x1
00002b7c         test       al, al
00002b7e         jne        loc_2b82

             loc_2b80:
00002b80         xor        edx, edx                                            ; CODE XREF=-[SmellsGood_AppDelegate checkCode:forName:]+56

             loc_2b82:
00002b82         add        esp, 0x14                                           ; CODE XREF=-[SmellsGood_AppDelegate checkCode:forName:]+132
00002b85         mov        eax, edx
00002b87         pop        ebx
00002b88         leave
00002b89         ret
                        ; endp

分析此[SmellsGood_AppDelegate checkCode:forName:],首先,将输入的Code字符串通过“-”分割,判断产出的子串数,是否为5,如果不是,失败。如果等于5,继续检验。(这里给出Code的组成规则)。然后将输入的Code转为大写字符(uppercaseString);调用generateCodeForName方法,根据输入的Name产生目标Code。将此Code和输入的Code(转大写后)进行比较,相等则通过。

下面再看generateCodeForName是如何生成Code的。代码如下。



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

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


             -[SmellsGood_AppDelegate generateCodeForName:]:
00002b8a         push       ebp                                                 ; Objective C Implementation defined at 0x4100 (instance method)
00002b8b         mov        ebp, esp
00002b8d         push       ebx
00002b8e         sub        esp, 0x14
00002b91         mov        ebx, dword [ebp+self]
00002b94         mov        dword [esp+0x18+var_10], 0x4
00002b9c         mov        eax, dword [objc_msg_dataUsingEncoding_]            ; @selector(dataUsingEncoding:)
00002ba1         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002ba5         mov        eax, dword [ebp+arg_8]
00002ba8         mov        dword [esp+0x18+var_18], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002bab         call       imp___jump_table__objc_msgSend
00002bb0         mov        dword [esp+0x18+var_10], eax
00002bb4         mov        eax, dword [objc_msg_digest_]                       ; @selector(digest:)
00002bb9         mov        dword [esp+0x18+var_18], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002bbc         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002bc0         call       imp___jump_table__objc_msgSend
00002bc5         mov        dword [esp+0x18+var_10], 0x3058                     ; @" "
00002bcd         mov        edx, dword [objc_msg_componentsSeparatedByString_]  ; @selector(componentsSeparatedByString:)
00002bd3         mov        dword [esp+0x18+var_14], edx                        ; argument #2 for method imp___jump_table__objc_msgSend
00002bd7         mov        dword [esp+0x18+var_18], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002bda         call       imp___jump_table__objc_msgSend
00002bdf         mov        dword [esp+0x18+var_10], eax
00002be3         mov        eax, dword [objc_msg_shuffle_]                      ; @selector(shuffle:)
00002be8         mov        dword [esp+0x18+var_18], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002beb         mov        dword [esp+0x18+var_14], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002bef         call       imp___jump_table__objc_msgSend
00002bf4         mov        dword [esp+0x18+var_10], 0x3048                     ; @"-"
00002bfc         mov        edx, dword [objc_msg_componentsJoinedByString_]     ; @selector(componentsJoinedByString:)
00002c02         mov        dword [esp+0x18+var_14], edx                        ; argument #2 for method imp___jump_table__objc_msgSend
00002c06         mov        dword [esp+0x18+var_18], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002c09         call       imp___jump_table__objc_msgSend
00002c0e         mov        edx, dword [objc_msg_uppercaseString]               ; @selector(uppercaseString)
00002c14         mov        dword [ebp+_cmd], edx
00002c17         mov        dword [ebp+self], eax
00002c1a         add        esp, 0x14
00002c1d         pop        ebx
00002c1e         leave
00002c1f         jmp        imp___jump_table__objc_msgSend
                        ; endp

[SmellsGood_AppDelegate generateCodeForName:]方法先取得Name的二进制字节Data,传给[SmellsGood_AppDelegate digest:],进行加密。对加密的结果通过空格“ ”字符分割成数组,传给[SmellsGood_AppDelegate shuffle:]方法进行交换、重新排序,最后重新排序的字符数组通过"-"字符连接成整体,并转成大写字母。接着看是如何加密和交换的。



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

        ; Variables:
        ;    arg_8: 16
        ;    _cmd: void *12
        ;    self: void *8
        ;    var_1C: -28
        ;    var_2C: -44
        ;    var_50: -80
        ;    var_5C: -92
        ;    var_60: -96
        ;    var_64: -100
        ;    var_68: -104


             -[SmellsGood_AppDelegate digest:]:
00002c24         push       ebp                                                 ; Objective C Implementation defined at 0x40f4 (instance method)
00002c25         mov        ebp, esp
00002c27         push       edi
00002c28         push       esi
00002c29         push       ebx
00002c2a         sub        esp, 0x5c
00002c2d         mov        edi, dword [ebp+arg_8]
00002c30         call       imp___jump_table__EVP_sha1
00002c35         lea        esi, dword [ebp+var_2C]
00002c38         mov        dword [esp+0x68+var_68], esi                        ; argument #1 for method imp___jump_table__EVP_DigestInit
00002c3b         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__EVP_DigestInit
00002c3f         call       imp___jump_table__EVP_DigestInit
00002c44         mov        eax, dword [objc_msg_length]                        ; @selector(length)
00002c49         mov        dword [esp+0x68+var_68], edi                        ; argument #1 for method imp___jump_table__objc_msgSend
00002c4c         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002c50         call       imp___jump_table__objc_msgSend
00002c55         mov        dword [esp+0x68+var_68], edi                        ; argument #1 for method imp___jump_table__objc_msgSend
00002c58         mov        ebx, eax
00002c5a         mov        eax, dword [objc_msg_bytes]                         ; @selector(bytes)
00002c5f         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002c63         call       imp___jump_table__objc_msgSend
00002c68         mov        dword [esp+0x68+var_60], ebx                        ; argument #3 for method imp___jump_table__EVP_DigestUpdate
00002c6c         lea        ebx, dword [ebp+var_50]
00002c6f         mov        dword [esp+0x68+var_68], esi                        ; argument #1 for method imp___jump_table__EVP_DigestUpdate
00002c72         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__EVP_DigestUpdate
00002c76         call       imp___jump_table__EVP_DigestUpdate
00002c7b         lea        eax, dword [ebp+var_1C]
00002c7e         mov        dword [esp+0x68+var_64], ebx                        ; argument #2 for method imp___jump_table__EVP_DigestFinal
00002c82         mov        dword [esp+0x68+var_68], esi                        ; argument #1 for method imp___jump_table__EVP_DigestFinal
00002c85         mov        esi, 0x1
00002c8a         mov        dword [esp+0x68+var_60], eax                        ; argument #3 for method imp___jump_table__EVP_DigestFinal
00002c8e         call       imp___jump_table__EVP_DigestFinal
00002c93         mov        eax, dword [ebp+var_1C]
00002c96         mov        dword [esp+0x68+var_60], ebx
00002c9a         mov        dword [esp+0x68+var_5C], eax
00002c9e         mov        eax, dword [objc_msg_dataWithBytes_length_]         ; @selector(dataWithBytes:length:)
00002ca3         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002ca7         mov        eax, dword [cls_NSData]                             ; cls_NSData
00002cac         mov        dword [esp+0x68+var_68], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002caf         call       imp___jump_table__objc_msgSend
00002cb4         mov        edx, dword [objc_msg_description]                   ; @selector(description)
00002cba         mov        dword [esp+0x68+var_64], edx                        ; argument #2 for method imp___jump_table__objc_msgSend
00002cbe         mov        dword [esp+0x68+var_68], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002cc1         call       imp___jump_table__objc_msgSend
00002cc6         mov        ebx, eax
00002cc8         mov        eax, dword [objc_msg_length]                        ; @selector(length)
00002ccd         mov        dword [esp+0x68+var_68], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002cd0         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002cd4         call       imp___jump_table__objc_msgSend
00002cd9         mov        dword [esp+0x68+var_60], esi
00002cdd         mov        dword [esp+0x68+var_68], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002ce0         lea        edi, dword [eax-2]
00002ce3         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
00002ce8         mov        dword [esp+0x68+var_5C], edi
00002cec         mov        dword [esp+0x68+var_64], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002cf0         call       imp___jump_table__objc_msgSend
00002cf5         add        esp, 0x5c
00002cf8         pop        ebx
00002cf9         pop        esi
00002cfa         pop        edi
00002cfb         leave
00002cfc         ret
                        ; endp



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

        ; Variables:
        ;    arg_8: 16
        ;    _cmd: void *12
        ;    self: void *8
        ;    var_1C: -28
        ;    var_20: -32
        ;    var_24: -36
        ;    var_2C: -44
        ;    var_30: -48
        ;    var_34: -52
        ;    var_38: -56
        ;    var_3C: -60
        ;    var_40: -64
        ;    var_44: -68
        ;    var_48: -72


             -[SmellsGood_AppDelegate shuffle:]:
00002cfd         push       ebp                                                 ; Objective C Implementation defined at 0x40e8 (instance method)
00002cfe         mov        ebp, esp
00002d00         push       edi
00002d01         push       esi
00002d02         push       ebx
00002d03         sub        esp, 0x3c
00002d06         mov        eax, dword [cls_NSArray]                            ; cls_NSArray
00002d0b         mov        ebx, dword [ebp+arg_8]
00002d0e         mov        dword [esp+0x48+var_40], 0x0
00002d16         mov        dword [ebp+var_24], eax
00002d19         mov        eax, dword [objc_msg_objectAtIndex_]                ; @selector(objectAtIndex:)
00002d1e         mov        dword [esp+0x48+var_48], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002d21         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002d25         call       imp___jump_table__objc_msgSend
00002d2a         mov        dword [esp+0x48+var_48], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002d2d         mov        dword [esp+0x48+var_40], 0x2
00002d35         mov        dword [ebp+var_20], eax
00002d38         mov        eax, dword [objc_msg_objectAtIndex_]                ; @selector(objectAtIndex:)
00002d3d         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002d41         call       imp___jump_table__objc_msgSend
00002d46         mov        dword [esp+0x48+var_48], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002d49         mov        dword [esp+0x48+var_40], 0x1
00002d51         mov        dword [ebp+var_1C], eax
00002d54         mov        eax, dword [objc_msg_objectAtIndex_]                ; @selector(objectAtIndex:)
00002d59         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002d5d         call       imp___jump_table__objc_msgSend
00002d62         mov        dword [esp+0x48+var_48], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002d65         mov        dword [esp+0x48+var_40], 0x3
00002d6d         mov        edi, eax
00002d6f         mov        eax, dword [objc_msg_objectAtIndex_]                ; @selector(objectAtIndex:)
00002d74         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002d78         call       imp___jump_table__objc_msgSend
00002d7d         mov        dword [esp+0x48+var_48], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002d80         mov        dword [esp+0x48+var_40], 0x4
00002d88         mov        esi, eax
00002d8a         mov        eax, dword [objc_msg_objectAtIndex_]                ; @selector(objectAtIndex:)
00002d8f         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002d93         call       imp___jump_table__objc_msgSend
00002d98         mov        edx, dword [ebp+var_20]
00002d9b         mov        dword [esp+0x48+var_38], edi
00002d9f         mov        dword [esp+0x48+var_3C], esi
00002da3         mov        dword [esp+0x48+var_2C], 0x0
00002dab         mov        dword [esp+0x48+var_30], edx
00002daf         mov        edx, dword [ebp+var_1C]
00002db2         mov        dword [esp+0x48+var_40], eax
00002db6         mov        eax, dword [objc_msg_arrayWithObjects_]             ; @selector(arrayWithObjects:)
00002dbb         mov        dword [esp+0x48+var_34], edx
00002dbf         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002dc3         mov        eax, dword [ebp+var_24]
00002dc6         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002dc9         call       imp___jump_table__objc_msgSend
00002dce         add        esp, 0x3c
00002dd1         pop        ebx
00002dd2         pop        esi
00002dd3         pop        edi
00002dd4         leave
00002dd5         ret
                        ; endp

可以看到digest是用SHA-1算法加密,取的是加密后二进制流的description,所以有空格。
shuffle对数组重新排列规则为[1,2,3,4,5] ->[5,4,2,3,1]

0x2 Keygen 算法

通过分析(当然包括动态分析,此处略)得出Keygen算法描述:

1. A = SHA-1(name)
2. Array B = A.splitBy("  ")
3. Array C = B.shuffle(),交换规则:[1,2,3,4,5] ->[5,4,2,3,1]
4. Code = C.jointStringBy("-")

0x3 测试验证

设输入Name为123456 ,则Name的SHA-1加密为:
7c4a8d09 ca3762af 61e59520 943dc264 94f8941b
分割成数组:
[ 7c4a8d09,ca3762af,61e59520,943dc264,94f8941b ]
交换数组元素:
[ 94f8941b,943dc264,ca3762af,61e59520,7c4a8d09 ]
最后连接生成Code:
94f8941b-943dc264-ca3762af-61e59520-7c4a8d09

输入Code,程序验证Success,:)!

Snip20171015_10.png
Snip20171015_9.png

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