如何生成CrackMe注册机之Doughnuts

本练习破解的CrackMe可以在此处下载:https://reverse.put.as/wp-content/uploads/2010/05/CrackMe.1.by_.James_.Moriarty.zip。运行截图如下。当然,此CrackMe相对简单,仅作为破解入门练习,抛砖引玉。因为简单,如果暴力破解,相对容易,但是这不是破解CrackMe的目的。这里主要从代码分析入手,一步一步理解CrackMe注册码的生成规则,从而达到完美产生注册码的目的—— Keygen,所以,本文乃注册机生成之旅。

Snip20171013_8.jpg

0x1 代码静态分析

在Hopper 中反汇编CrackMe,很容易看到validar:方法(validar 为西班牙语,对应英语validate),因为简单,不用怀疑,这就是验证name和serial的方法。代码如下:

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

        ; Variables:
        ;    _cmd: 12
        ;    self: 8
        ;    var_10: -16
        ;    var_24: -36
        ;    var_28: -40
        ;    var_2C: -44
        ;    var_3C: -60
        ;    var_40: -64
        ;    var_44: -68
        ;    var_48: -72


             -[Control validar:]:
000025d8         push       ebp                                                 ; Objective C Implementation defined at 0x4314 (instance method)
000025d9         mov        ebp, esp
000025db         push       ebx
000025dc         push       edi
000025dd         push       esi
000025de         sub        esp, 0x3c
000025e1         mov        eax, dword [___stack_chk_guard_301c]                ; ___stack_chk_guard_301c
000025e6         mov        eax, dword [eax]
000025e8         mov        dword [ebp+var_10], eax
000025eb         mov        esi, dword [ebp+self]
000025ee         mov        eax, dword [esi+8]
000025f1         mov        ecx, dword [objc_msg_stringValue]                   ; @selector(stringValue)
000025f7         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000025fb         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000025fe         call       imp___symbol_stub__objc_msgSend
00002603         mov        edi, eax
00002605         mov        eax, dword [esi+4]
00002608         mov        ecx, dword [objc_msg_stringValue]                   ; @selector(stringValue)
0000260e         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002612         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002615         call       imp___symbol_stub__objc_msgSend
0000261a         mov        dword [ebp+var_28], eax
0000261d         mov        eax, dword [objc_msg_length]                        ; @selector(length)
00002622         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002626         mov        eax, dword [ebp+var_28]
00002629         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000262c         call       imp___symbol_stub__objc_msgSend
00002631         mov        esi, eax
00002633         mov        eax, dword [objc_msg_length]                        ; @selector(length)
00002638         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
0000263c         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000263f         call       imp___symbol_stub__objc_msgSend
00002644         mov        dword [ebp+var_2C], eax
00002647         mov        eax, dword [objc_msg_length]                        ; @selector(length)
0000264c         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002650         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002653         call       imp___symbol_stub__objc_msgSend
00002658         mov        ecx, dword [objc_msg_substringFromIndex_]           ; @selector(substringFromIndex:)
0000265e         add        eax, 0xfffffffe
00002661         mov        dword [esp+0x48+var_40], eax
00002665         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002669         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000266c         call       imp___symbol_stub__objc_msgSend
00002671         mov        ecx, dword [objc_msg_intValue]                      ; @selector(intValue)
00002677         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
0000267b         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000267e         call       imp___symbol_stub__objc_msgSend
00002683         mov        ebx, eax
00002685         cmp        dword [ebp+var_28], 0x0
00002689         je         loc_28d4

0000268f         mov        eax, dword [objc_msg_isEqual_]                      ; @selector(isEqual:)
00002694         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002698         mov        eax, dword [ebp+var_28]
0000269b         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000269e         mov        dword [esp+0x48+var_40], 0x3058                     ; @""
000026a6         call       imp___symbol_stub__objc_msgSend
000026ab         test       al, al
000026ad         jne        loc_28d4

000026b3         cmp        esi, 0x4
000026b6         jl         loc_28d4

000026bc         test       edi, edi
000026be         je         loc_28d4

000026c4         mov        eax, dword [objc_msg_isEqual_]                      ; @selector(isEqual:)
000026c9         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000026cd         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000026d0         mov        dword [esp+0x48+var_40], 0x3058                     ; @""
000026d8         call       imp___symbol_stub__objc_msgSend
000026dd         test       al, al
000026df         jne        loc_28d4

000026e5         cmp        dword [ebp+var_2C], 0xf
000026e9         jne        loc_28d4

000026ef         cmp        esi, ebx
000026f1         jne        loc_28d4

000026f7         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
000026fc         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002700         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002703         mov        dword [esp+0x48+var_3C], 0x1
0000270b         mov        dword [esp+0x48+var_40], 0xa
00002713         call       imp___symbol_stub__objc_msgSend
00002718         mov        esi, eax
0000271a         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
0000271f         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002723         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002726         mov        dword [esp+0x48+var_3C], 0xa
0000272e         mov        dword [esp+0x48+var_40], 0x0
00002736         call       imp___symbol_stub__objc_msgSend
0000273b         mov        ebx, eax
0000273d         mov        eax, dword [objc_msg_isEqualToString_]              ; @selector(isEqualToString:)
00002742         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002746         mov        dword [esp+0x48+var_48], esi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002749         mov        dword [esp+0x48+var_40], 0x3038                     ; @"k"
00002751         call       imp___symbol_stub__objc_msgSend
00002756         test       al, al
00002758         je         loc_28d4

0000275e         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
00002763         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002767         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000276a         mov        dword [esp+0x48+var_3C], 0x1
00002772         mov        dword [esp+0x48+var_40], 0xb
0000277a         call       imp___symbol_stub__objc_msgSend
0000277f         mov        ecx, dword [objc_msg_isEqualToString_]              ; @selector(isEqualToString:)
00002785         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002789         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000278c         mov        dword [esp+0x48+var_40], 0x3048                     ; @"n"
00002794         call       imp___symbol_stub__objc_msgSend
00002799         test       al, al
0000279b         je         loc_28d4

000027a1         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
000027a6         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000027aa         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000027ad         mov        dword [esp+0x48+var_3C], 0x1
000027b5         mov        dword [esp+0x48+var_40], 0xc
000027bd         call       imp___symbol_stub__objc_msgSend
000027c2         mov        ecx, dword [objc_msg_isEqualToString_]              ; @selector(isEqualToString:)
000027c8         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000027cc         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000027cf         mov        dword [esp+0x48+var_40], 0x3038                     ; @"k"
000027d7         call       imp___symbol_stub__objc_msgSend
000027dc         test       al, al
000027de         je         loc_28d4

000027e4         mov        eax, dword [objc_msg_dataUsingEncoding_]            ; @selector(dataUsingEncoding:)
000027e9         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000027ed         mov        eax, dword [ebp+var_28]
000027f0         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000027f3         mov        dword [esp+0x48+var_40], 0x4
000027fb         call       imp___symbol_stub__objc_msgSend
00002800         mov        esi, eax
00002802         mov        eax, dword [objc_msg_length]                        ; @selector(length)
00002807         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
0000280b         mov        dword [esp+0x48+var_48], esi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000280e         call       imp___symbol_stub__objc_msgSend
00002813         mov        edi, eax
00002815         mov        eax, dword [objc_msg_bytes]                         ; @selector(bytes)
0000281a         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
0000281e         mov        dword [esp+0x48+var_48], esi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002821         call       imp___symbol_stub__objc_msgSend
00002826         lea        ecx, dword [ebp+var_24]
00002829         mov        dword [esp+0x48+var_40], ecx                        ; argument "md" for method imp___symbol_stub__CC_SHA1
0000282d         mov        dword [esp+0x48+var_44], edi                        ; argument "len" for method imp___symbol_stub__CC_SHA1
00002831         mov        dword [esp+0x48+var_48], eax                        ; argument "data" for method imp___symbol_stub__CC_SHA1
00002834         call       imp___symbol_stub__CC_SHA1
00002839         mov        eax, dword [cls_NSMutableString]                    ; cls_NSMutableString
0000283e         mov        ecx, dword [objc_msg_string]                        ; @selector(string)
00002844         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002848         mov        dword [esp+0x48+var_48], eax                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000284b         xor        esi, esi
0000284d         call       imp___symbol_stub__objc_msgSend
00002852         mov        edi, eax

             loc_2854:
00002854         movzx      eax, byte [ebp+esi+var_24]                          ; CODE XREF=-[Control validar:]+675
00002859         mov        ecx, dword [objc_msg_appendFormat_]                 ; @selector(appendFormat:)
0000285f         mov        dword [esp+0x48+var_3C], eax
00002863         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002867         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
0000286a         mov        dword [esp+0x48+var_40], 0x3068                     ; @"%02x"
00002872         call       imp___symbol_stub__objc_msgSend
00002877         inc        esi
00002878         cmp        esi, 0x14
0000287b         jne        loc_2854

0000287d         mov        eax, dword [objc_msg_substringWithRange_]           ; @selector(substringWithRange:)
00002882         mov        dword [esp+0x48+var_44], eax                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
00002886         mov        dword [esp+0x48+var_48], edi                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
00002889         mov        dword [esp+0x48+var_3C], 0xa
00002891         mov        dword [esp+0x48+var_40], 0x0
00002899         call       imp___symbol_stub__objc_msgSend
0000289e         mov        ecx, dword [objc_msg_isEqualToString_]              ; @selector(isEqualToString:)
000028a4         mov        dword [esp+0x48+var_40], eax
000028a8         mov        dword [esp+0x48+var_44], ecx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000028ac         mov        dword [esp+0x48+var_48], ebx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000028af         call       imp___symbol_stub__objc_msgSend
000028b4         test       al, al
000028b6         je         loc_28d4

000028b8         mov        eax, dword [ebp+self]
000028bb         mov        ecx, dword [eax+0xc]
000028be         mov        edx, dword [objc_msg_orderFront_]                   ; @selector(orderFront:)
000028c4         mov        dword [esp+0x48+var_40], eax
000028c8         mov        dword [esp+0x48+var_44], edx                        ; argument "selector" for method imp___symbol_stub__objc_msgSend
000028cc         mov        dword [esp+0x48+var_48], ecx                        ; argument "instance" for method imp___symbol_stub__objc_msgSend
000028cf         call       imp___symbol_stub__objc_msgSend

             loc_28d4:
000028d4         mov        eax, dword [___stack_chk_guard_301c]                ; ___stack_chk_guard_301c, CODE XREF=-[Control validar:]+177, -[Control validar:]+213, -[Control validar:]+222, -[Control validar:]+230, -[Control validar:]+263, -[Control validar:]+273, -[Control validar:]+281, -[Control validar:]+384, -[Control validar:]+451, -[Control validar:]+518, -[Control validar:]+734
000028d9         mov        eax, dword [eax]
000028db         cmp        eax, dword [ebp+var_10]
000028de         jne        loc_28e8

000028e0         add        esp, 0x3c
000028e3         pop        esi
000028e4         pop        edi
000028e5         pop        ebx
000028e6         pop        ebp
000028e7         ret
                        ; endp

             loc_28e8:
000028e8         call       imp___symbol_stub____stack_chk_fail                 ; CODE XREF=-[Control validar:]+774
                        ; endp 

这个方法比较长,看伪代码就比较清晰了:

void -[Control validar:](void * self, void * _cmd, void * arg2) {
    var_10 = *___stack_chk_guard;
    edi = [*(self + 0x8) stringValue];
    var_28 = [*(self + 0x4) stringValue];
    esi = [var_28 length];
    var_2C = [edi length];
    ebx = [[edi substringFromIndex:[edi length] + 0xfffffffe] intValue];
    if (((((((var_28 != 0x0) && ([var_28 isEqual:@""] == 0x0)) && (esi >= 0x4)) && (edi != 0x0)) && ([edi isEqual:@""] == 0x0)) && (var_2C == 0xf)) && (esi == ebx)) {
            esi = [edi substringWithRange:0xa];
            ebx = [edi substringWithRange:0x0];
            if ([esi isEqualToString:@"k"] != 0x0) {
                    if ([[edi substringWithRange:0xb] isEqualToString:@"n"] != 0x0) {
                            if ([[edi substringWithRange:0xc] isEqualToString:@"k"] != 0x0) {
                                    esi = [var_28 dataUsingEncoding:0x4];
                                    edi = [esi length];
                                    eax = [esi bytes];
                                    CC_SHA1(eax, edi, var_24);
                                    esi = 0x0;
                                    edi = [NSMutableString string];
                                    do {
                                            [edi appendFormat:@"%02x"];
                                            esi = esi + 0x1;
                                    } while (esi != 0x14);
                                    if ([ebx isEqualToString:[edi substringWithRange:0x0]] != 0x0) {
                                            [*(self + 0xc) orderFront:self];
                                    }
                            }
                    }
            }
    }
    if (*___stack_chk_guard != var_10) {
            __stack_chk_fail();
    }
    return;
  }

可以看出,先取了输入的name ,serial的值放在edi ,var_28,然后分别计算length。
后面是校验,判断edi的长度为15,var_28的长度不小于4,截取后面edi(substringFromIndex) 存入ebx,比较ebx的值与var_28的长度是否相等, 然后取edi的0xa 、0xb 、 0xc 处的substring,分别比较k,n,k,看是否相等。如这些条件都满足,对var_28 进行CC_SHA1加密,分别截取edi、截取CC_SHA1加密后的字符串,比较两者是否相等。如果相等,则是合法的注册码。
name是edi?,serial是var_28?这些截取子串的范围是多少呢?下面动态调试分析。

0x2动态分析

此CrackMe有反debug的措施,见如下的方法。

     sub_2556:
00002556         push       ebp                                                 ; CODE XREF=EntryPoint+48
00002557         mov        ebp, esp
00002559         sub        esp, 0x18
0000255c         mov        dword [esp+0x18+var_C], 0x0                         ; argument "data" for method imp___symbol_stub__ptrace
00002564         mov        dword [esp+0x18+var_10], 0x0                        ; argument "addr" for method imp___symbol_stub__ptrace
0000256c         mov        dword [esp+0x18+var_14], 0x0                        ; argument "pid" for method imp___symbol_stub__ptrace
00002574         mov        dword [esp+0x18+var_18], 0x1f                       ; argument "request" for method imp___symbol_stub__ptrace
0000257b         call       imp___symbol_stub__ptrace
00002580         add        esp, 0x18
00002583         pop        ebp
00002584         jmp        imp___symbol_stub__NSApplicationMain

此方法会检测ptrace,所以先将
0000257b call imp___symbol_stub__ptrace
改为:
0000257b nop dword [eax+eax]
去掉反debug,这样便可以在Hopper中直接debug运行了。运行如下:

Snip20171013_7.jpg
Snip20171013_5.png
Snip20171013_6.png

经单步调试,得知:
name 存var_28, serial 存edi, name的长度不少于4,serial的长度为15。其中serial后两位为name的长度值,serial 的11,12,13位为k、n、k,serial剩下的前10位为SHA1加密name后的字符串的前10位。因此,Keygen算法如下:

1. name.length >= 4
2. searial.length = 15
3. searial =SHA1(name).subStringWithRange(0,10) +"k"+"n"+"k"+(name).length

例如输入name 为qwer,则name的SHA1加密为:1161e6ffd3637b302a5cd74076283a7bd1fc20d3。按照上述算法,得出serial:
1161e6ffd3knk04
验证测试,结果正确:

Snip20171012_3.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容