本練習(xí)破解的CrackMe可以在此處下載:https://reverse.put.as/wp-content/uploads/2010/05/CrackMe.1.by_.James_.Moriarty.zip千扶。運(yùn)行截圖如下丐膝。當(dāng)然车胡,此CrackMe相對(duì)簡(jiǎn)單,僅作為破解入門練習(xí)凫海,拋磚引玉猫缭。因?yàn)楹?jiǎn)單病往,如果暴力破解凰萨,相對(duì)容易,但是這不是破解CrackMe的目的侦高。這里主要從代碼分析入手嫉柴,一步一步理解CrackMe注冊(cè)碼的生成規(guī)則,從而達(dá)到完美產(chǎn)生注冊(cè)碼的目的—— Keygen奉呛,所以计螺,本文乃注冊(cè)機(jī)生成之旅。
0x1 代碼靜態(tài)分析
在Hopper 中反匯編CrackMe瞧壮,很容易看到validar:方法(validar 為西班牙語(yǔ)登馒,對(duì)應(yīng)英語(yǔ)validate),因?yàn)楹?jiǎn)單咆槽,不用懷疑陈轿,這就是驗(yàn)證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
這個(gè)方法比較長(zhǎng)秦忿,看偽代碼就比較清晰了:
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法褥,然后分別計(jì)算length。
后面是校驗(yàn)酬屉,判斷edi的長(zhǎng)度為15,var_28的長(zhǎng)度不小于4揍愁,截取后面edi(substringFromIndex) 存入ebx呐萨,比較ebx的值與var_28的長(zhǎng)度是否相等, 然后取edi的0xa 莽囤、0xb 谬擦、 0xc 處的substring,分別比較k朽缎,n惨远,k谜悟,看是否相等。如這些條件都滿足北秽,對(duì)var_28 進(jìn)行CC_SHA1加密葡幸,分別截取edi、截取CC_SHA1加密后的字符串贺氓,比較兩者是否相等蔚叨。如果相等,則是合法的注冊(cè)碼辙培。
name是edi蔑水?,serial是var_28扬蕊?這些截取子串的范圍是多少呢搀别?下面動(dòng)態(tài)調(diào)試分析。
0x2動(dòng)態(tài)分析
此CrackMe有反debug的措施尾抑,見(jiàn)如下的方法领曼。
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
此方法會(huì)檢測(cè)ptrace,所以先將
0000257b call imp___symbol_stub__ptrace
改為:
0000257b nop dword [eax+eax]
去掉反debug蛮穿,這樣便可以在Hopper中直接debug運(yùn)行了庶骄。運(yùn)行如下:
經(jīng)單步調(diào)試,得知:
name 存var_28, serial 存edi, name的長(zhǎng)度不少于4践磅,serial的長(zhǎng)度為15单刁。其中serial后兩位為name的長(zhǎng)度值,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
驗(yàn)證測(cè)試骨望,結(jié)果正確: