如何生成CrackMe注册机之MSJ Challenge #1

本破解练习来自MSJ2009 Challenge#1,下载地址如下:https://reverse.put.as/wp-content/uploads/2010/05/MSJ20091.zip。
破解起来稍显麻烦,主要是Keygen的算法比较晦涩难懂。
打开运行,如下。输入正确的Name及Serial才能注册。

Snip20171021_2.png
Snip20171021_1.png

0x1 代码分析

在Hopper中打开Challenge #1,可以看到关键校验代码如下。



        ; ================ 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_1C: -28
        ;    var_20: -32
        ;    var_24: -36
        ;    var_28: -40
        ;    var_2C: -44
        ;    var_30: -48
        ;    var_3C: -60
        ;    var_40: -64
        ;    var_44: -68
        ;    var_48: -72


             -[Level1 validateSerial:forName:]:
00002a9e         push       ebp                                                 ; Objective C Implementation defined at 0x40f4 (instance method)
00002a9f         mov        ebp, esp
00002aa1         push       edi
00002aa2         push       esi
00002aa3         push       ebx
00002aa4         sub        esp, 0x3c
00002aa7         mov        eax, dword [objc_msg_length]                        ; @selector(length)
00002aac         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002ab0         mov        eax, dword [ebp+arg_8]
00002ab3         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002ab6         call       imp___jump_table__objc_msgSend
00002abb         cmp        eax, 0x8
00002abe         jne        loc_2c4e

00002ac4         mov        eax, dword [objc_msg_lossyCString]                  ; @selector(lossyCString)
00002ac9         mov        esi, 0x4
00002ace         xor        ebx, ebx
00002ad0         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002ad4         mov        eax, dword [ebp+arg_C]
00002ad7         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002ada         call       imp___jump_table__objc_msgSend
00002adf         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__strlen
00002ae2         mov        edi, eax
00002ae4         call       imp___jump_table__strlen
00002ae9         xor        ecx, ecx
00002aeb         mov        dword [ebp+var_30], eax
00002aee         jmp        loc_2b27

             loc_2af0:
00002af0         movsx      eax, byte [edi+ebx]                                 ; CODE XREF=-[Level1 validateSerial:forName:]+140
00002af4         inc        ebx
00002af5         imul       eax, esi
00002af8         add        esi, 0x4
00002afb         mov        edx, eax
00002afd         shl        edx, 0x4
00002b00         sub        edx, eax
00002b02         mov        eax, 0x68db8bad
00002b07         lea        ecx, dword [edx+ecx+0x29a]
00002b0e         imul       ecx
00002b10         mov        eax, ecx
00002b12         sar        eax, 0x1f
00002b15         sar        edx, 0xc
00002b18         sub        edx, eax
00002b1a         mov        eax, ecx
00002b1c         imul       edx, edx, 0x2710
00002b22         sub        eax, edx
00002b24         mov        dword [ebp+var_20], eax

             loc_2b27:
00002b27         cmp        dword [ebp+var_30], ebx                             ; CODE XREF=-[Level1 validateSerial:forName:]+80
00002b2a         ja         loc_2af0

00002b2c         mov        eax, dword [ebp+var_20]
00002b2f         mov        esi, 0x4
00002b34         xor        ebx, ebx
00002b36         mov        dword [esp+0x48+var_40], 0x3078                     ; @"%i"
00002b3e         mov        dword [esp+0x48+var_3C], eax
00002b42         mov        eax, dword [objc_msg_stringWithFormat_]             ; @selector(stringWithFormat:)
00002b47         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002b4b         mov        eax, dword [cls_NSString]                           ; cls_NSString
00002b50         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002b53         call       imp___jump_table__objc_msgSend
00002b58         mov        dword [esp+0x48+var_48], edi                        ; argument #1 for method imp___jump_table__strlen
00002b5b         mov        dword [ebp+var_28], eax
00002b5e         call       imp___jump_table__strlen
00002b63         xor        ecx, ecx
00002b65         mov        dword [ebp+var_2C], eax
00002b68         jmp        loc_2b9c

             loc_2b6a:
00002b6a         movsx      eax, byte [edi+ebx]                                 ; CODE XREF=-[Level1 validateSerial:forName:]+257
00002b6e         inc        ebx
00002b6f         imul       eax, esi
00002b72         add        esi, 0x8
00002b75         lea        edx, dword [eax+eax*4]
00002b78         lea        edx, dword [eax+edx*2+0x2d]
00002b7c         mov        eax, 0x68db8bad
00002b81         add        ecx, edx
00002b83         imul       ecx
00002b85         mov        eax, ecx
00002b87         sar        eax, 0x1f
00002b8a         sar        edx, 0xc
00002b8d         sub        edx, eax
00002b8f         mov        eax, ecx
00002b91         imul       edx, edx, 0x2710
00002b97         sub        eax, edx
00002b99         mov        dword [ebp+var_1C], eax

             loc_2b9c:
00002b9c         cmp        ebx, dword [ebp+var_2C]                             ; CODE XREF=-[Level1 validateSerial:forName:]+202
00002b9f         jb         loc_2b6a

00002ba1         mov        eax, dword [ebp+var_1C]
00002ba4         mov        esi, 0x4
00002ba9         xor        ebx, ebx
00002bab         mov        dword [esp+0x48+var_40], 0x3078                     ; @"%i"
00002bb3         mov        edi, 0x4
00002bb8         mov        dword [esp+0x48+var_3C], eax
00002bbc         mov        eax, dword [objc_msg_stringWithFormat_]             ; @selector(stringWithFormat:)
00002bc1         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002bc5         mov        eax, dword [cls_NSString]                           ; cls_NSString
00002bca         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002bcd         call       imp___jump_table__objc_msgSend
00002bd2         mov        dword [esp+0x48+var_40], ebx
00002bd6         mov        dword [esp+0x48+var_3C], esi
00002bda         mov        dword [ebp+var_24], eax
00002bdd         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
00002be2         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002be6         mov        eax, dword [ebp+arg_8]
00002be9         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002bec         call       imp___jump_table__objc_msgSend
00002bf1         mov        dword [esp+0x48+var_40], esi
00002bf5         mov        dword [esp+0x48+var_3C], edi
00002bf9         mov        ebx, eax
00002bfb         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
00002c00         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002c04         mov        eax, dword [ebp+arg_8]
00002c07         mov        dword [esp+0x48+var_48], eax                        ; argument #1 for method imp___jump_table__objc_msgSend
00002c0a         call       imp___jump_table__objc_msgSend
00002c0f         mov        dword [esp+0x48+var_48], ebx                        ; argument #1 for method imp___jump_table__objc_msgSend
00002c12         mov        esi, eax
00002c14         mov        eax, dword [ebp+var_28]
00002c17         mov        dword [esp+0x48+var_40], eax
00002c1b         mov        eax, dword [objc_msg_isEqual_]                      ; @selector(isEqual:)
00002c20         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002c24         call       imp___jump_table__objc_msgSend
00002c29         test       al, al
00002c2b         je         loc_2c4e

00002c2d         mov        eax, dword [ebp+var_24]
00002c30         mov        dword [esp+0x48+var_48], esi                        ; argument #1 for method imp___jump_table__objc_msgSend
00002c33         mov        dword [esp+0x48+var_40], eax
00002c37         mov        eax, dword [objc_msg_isEqual_]                      ; @selector(isEqual:)
00002c3c         mov        dword [esp+0x48+var_44], eax                        ; argument #2 for method imp___jump_table__objc_msgSend
00002c40         call       imp___jump_table__objc_msgSend
00002c45         mov        edx, 0x1
00002c4a         test       al, al
00002c4c         jne        loc_2c50

             loc_2c4e:
00002c4e         xor        edx, edx                                            ; CODE XREF=-[Level1 validateSerial:forName:]+32, -[Level1 validateSerial:forName:]+397

             loc_2c50:
00002c50         add        esp, 0x3c                                           ; CODE XREF=-[Level1 validateSerial:forName:]+430
00002c53         mov        eax, edx
00002c55         pop        ebx
00002c56         pop        esi
00002c57         pop        edi
00002c58         leave
00002c59         ret
                        ; endp


首先,判断Serial的长度是否为8位,见下面代码。如不是8位,则失败,如果等于8位则继续下一步。

00002ab6         call       imp___jump_table__objc_msgSend
00002abb         cmp        eax, 0x8
00002abe         jne        loc_2c4e

接着, loc_2af0 代码段为一段循环,遍历输入的Name,取其中每一位字符ASCII码计算,算法见loc_2af0。计算的结果为Serial的第一部分Part1。loc_2b6a代码段为第二个循环,同样遍历输入的Name,取其中每一位字符ASCII码计算,算法见loc_2b6a。计算的结果为Serial的第二部分Part2。

最后一段【00002ba1-00002c4c】代码,分别取输入的Serial的前4位和后4位字符串与上面计算等到的Part1 、Part2比较,相等则验证通过。

0x2 Keygen算法

根据分析,可以得出Keygen算法。具体的实现,使用一个小技巧,就是用高级语言完全复制上述计算Part1、Part2的汇编代码。这里用Objective C示例如下。


- (NSString*)part1ByName:(NSString *)name {
    signed long esi = 0x4;
    signed long ecx = 0;
    signed long edx = 0;
    signed long eax = 0;
    for (int i = 0; i>32>>0x1f;
        eax = ecx;
        eax = eax>>0x1f;
        edx =((ecx * 0x68db8bad) & 0xffffffff00000000)>>32>>(0xc);
        edx = edx - eax;
        eax = ecx;
        edx *= 0x2710;
        eax = eax - edx;
    }
    return [NSString stringWithFormat:@"%d",eax];
}
- (NSString*)part2ByName:(NSString *)name {
    signed long esi = 0x4;
    signed long ecx = 0;
    signed long edx = 0;
    signed long eax = 0;
    for (int i = 0; i>32>>0x1f;
        eax = ecx;
        eax = eax>>0x1f;
        edx =((ecx * 0x68db8bad) & 0xffffffff00000000)>>32>>(0xc);
        edx = edx - eax;
        eax = ecx;
        edx *= 0x2710;
        eax = eax - edx;
    }
    return [NSString stringWithFormat:@"%d",eax];
}
- (NSString *)keyGen:(id)sender {
    NSString *name = @"qwer";
    NSString *serial = [NSString stringWithFormat:@"%@%@",
                     [self part1ByName:name],
                     [self part2ByName:name]];
  return serial;
}

0x3 程序验证

设输入的Name为qwer,根据上述Keygen算法得Serial为92648192,代入程序,验证Success,:)!

Snip20171022_3.png
Snip20171022_4.png

你可能感兴趣的:(如何生成CrackMe注册机之MSJ Challenge #1)