作者:creantan 小葡萄爸爸
工具列表:
Hopper disassembler(静态分析)
lldb (动态调试)
撸起:
先来个最简单的,直接用Hopper disassembler分析:
直接把第一个crackme拖到Hopper里面,看下左边窗口,看下这个crackme的Labels
很容易就找到这个methed实现methImpl_AppDelegate_checkifisok_
点击它看下汇编:
0x0000000100001110 55 push rbp
0x0000000100001111 4889E5 mov rbp, rsp
0x0000000100001114 4883EC70 sub rsp, 0x70
0x0000000100001118 488D0551180000 lea rax, qword [ds:cfstring_Length_of_the_serial_string_is___lx] ; @"Length of the serial string is: %lx"
0x000000010000111f 488D0DBA160000 lea rcx, qword [ds:objc_msg_length] ; @selector(length)
0x0000000100001126 4C8D0523180000 lea r8, qword [ds:cfstring_Length_of_the_name_string_is___lx] ; @"Length of the name string is: %lx"
0x000000010000112d 4C8D0DFC170000 lea r9, qword [ds:cfstring_uh_] ; @"uh?"
0x0000000100001134 48897DF8 mov qword [ss:rbp-0x70+var_104], rdi
0x0000000100001138 488975F0 mov qword [ss:rbp-0x70+var_96], rsi
0x000000010000113c 488955E8 mov qword [ss:rbp-0x70+var_88], rdx
0x0000000100001140 4C89CF mov rdi, r9
0x0000000100001143 488945B0 mov qword [ss:rbp-0x70+var_32], rax
0x0000000100001147 B000 mov al, 0x0
0x0000000100001149 4C8945A8 mov qword [ss:rbp-0x70+var_24], r8
0x000000010000114d 48894DA0 mov qword [ss:rbp-0x70+var_16], rcx
0x0000000100001151 E8C6030000 call imp___stubs__NSLog
0x0000000100001156 488B4DF8 mov rcx, qword [ss:rbp-0x70+var_104]
0x000000010000115a 488B152F190000 mov rdx, qword [ds:0x100002a90]
0x0000000100001161 488B0C11 mov rcx, qword [ds:rcx+rdx]
0x0000000100001165 488B350C160000 mov rsi, qword [ds:objc_sel_stringValue] ; @selector(stringValue)
0x000000010000116c 4889CF mov rdi, rcx
0x000000010000116f E8B4030000 call imp___stubs__objc_msgSend
0x0000000100001174 488945E0 mov qword [ss:rbp-0x70+var_80], rax
0x0000000100001178 488B45E0 mov rax, qword [ss:rbp-0x70+var_80]
0x000000010000117c 4889C7 mov rdi, rax
0x000000010000117f 488B75A0 mov rsi, qword [ss:rbp-0x70+var_16]
0x0000000100001183 FF1557160000 call qword [ds:objc_msg_length] ; @selector(length)
0x0000000100001189 488945D8 mov qword [ss:rbp-0x70+var_72], rax
0x000000010000118d 488B75D8 mov rsi, qword [ss:rbp-0x70+var_72]
0x0000000100001191 488B7DA8 mov rdi, qword [ss:rbp-0x70+var_24]
0x0000000100001195 B000 mov al, 0x0
0x0000000100001197 E880030000 call imp___stubs__NSLog
0x000000010000119c 488B4DF8 mov rcx, qword [ss:rbp-0x70+var_104]
0x00000001000011a0 488B15F1180000 mov rdx, qword [ds:0x100002a98]
0x00000001000011a7 488B0C11 mov rcx, qword [ds:rcx+rdx]
0x00000001000011ab 488B35C6150000 mov rsi, qword [ds:objc_sel_stringValue] ; @selector(stringValue)
0x00000001000011b2 4889CF mov rdi, rcx
0x00000001000011b5 E86E030000 call imp___stubs__objc_msgSend
0x00000001000011ba 488945D0 mov qword [ss:rbp-0x70+var_64], rax
0x00000001000011be 488B45D0 mov rax, qword [ss:rbp-0x70+var_64]
0x00000001000011c2 4889C7 mov rdi, rax
0x00000001000011c5 488B75A0 mov rsi, qword [ss:rbp-0x70+var_16]
0x00000001000011c9 FF1511160000 call qword [ds:objc_msg_length] ; @selector(length)
0x00000001000011cf 488945C8 mov qword [ss:rbp-0x70+var_56], rax
0x00000001000011d3 488B75C8 mov rsi, qword [ss:rbp-0x70+var_56]
0x00000001000011d7 488B7DB0 mov rdi, qword [ss:rbp-0x70+var_32]
0x00000001000011db B000 mov al, 0x0
0x00000001000011dd E83A030000 call imp___stubs__NSLog
0x00000001000011e2 48817DC80A000000 cmp qword [ss:rbp-0x70+var_56], 0xa
0x00000001000011ea 0F86BF000000 jbe 0x1000012af //判断密码长度是否大于10
; Basic Block Input Regs: rbp - Killed Regs: <nothing>
0x00000001000011f0 48817DC80F000000 cmp qword [ss:rbp-0x70+var_56], 0xf
0x00000001000011f8 0F83B1000000 jnc 0x1000012af //判断密码长度是否小于15
; Basic Block Input Regs: rbp - Killed Regs: <nothing>
0x00000001000011fe 48817DD807000000 cmp qword [ss:rbp-0x70+var_72], 0x7
0x0000000100001206 0F86A3000000 jbe 0x1000012af //判断用户名长度是否大于7
; Basic Block Input Regs: rbp - Killed Regs: <nothing>
0x000000010000120c 48817DD80F000000 cmp qword [ss:rbp-0x70+var_72], 0xf
0x0000000100001214 0F8395000000 jnc 0x1000012af // 判断用户名长度是否小于15
; Basic Block Input Regs: <nothing> - Killed Regs: rax rcx rdx rbp rsi rdi
0x000000010000121a 488D05CF150000 lea rax, qword [ds:objc_msg_isEqualToString_] ; @selector(isEqualToString:)
0x0000000100001221 488D0D68170000 lea rcx, qword [ds:cfstring_] ; @""
0x0000000100001228 488B15D9150000 mov rdx, qword [ds:bind__OBJC_CLASS_$_NSCharacterSet]
0x000000010000122f 488B354A150000 mov rsi, qword [ds:objc_sel_alphanumericCharacterSet] ; @selector(alphanumericCharacterSet)
0x0000000100001236 4889D7 mov rdi, rdx
0x0000000100001239 48894598 mov qword [ss:rbp-0x70+var_8], rax
0x000000010000123d 48894D90 mov qword [ss:rbp-0x70+var_0], rcx
0x0000000100001241 E8E2020000 call imp___stubs__objc_msgSend //获取字母和数字集合 NSCharacterSet *alphanumericSet = [ NSCharacterSetalphanumericCharacterSet ];
0x0000000100001246 488945C0 mov qword [ss:rbp-0x70+var_48], rax
0x000000010000124a 488B45D0 mov rax, qword [ss:rbp-0x70+var_64]
0x000000010000124e 488B55C0 mov rdx, qword [ss:rbp-0x70+var_48]
0x0000000100001252 488B352F150000 mov rsi, qword [ds:objc_sel_stringByTrimmingCharactersInSet_] ; @selector(stringByTrimmingCharactersInSet:)
0x0000000100001259 4889C7 mov rdi, rax
0x000000010000125c E8C7020000 call imp___stubs__objc_msgSend //格式化密码,去除密码中含alphanumericSet中的字符 NSString *trimmedString = [passwdString stringByTrimmingCharactersInSet:alphanumericSet];
0x0000000100001261 4889C7 mov rdi, rax
0x0000000100001264 488B7598 mov rsi, qword [ss:rbp-0x70+var_8]
0x0000000100001268 488B5590 mov rdx, qword [ss:rbp-0x70+var_0]
0x000000010000126c FF157E150000 call qword [ds:objc_msg_isEqualToString_] ; @selector(isEqualToString:)//判断trimmedString是否和@“”空串相等
0x0000000100001272 8845BF mov byte [ss:rbp-0x70+var_47], al
0x0000000100001275 807DBF00 cmp byte [ss:rbp-0x70+var_47], 0x0
0x0000000100001279 0F8418000000 je 0x100001297 //不等则显示错误
; Basic Block Input Regs: rbp - Killed Regs: rax rsi rdi
0x000000010000127f 488B45F8 mov rax, qword [ss:rbp-0x70+var_104]
0x0000000100001283 488B3506150000 mov rsi, qword [ds:objc_sel_yes] ; @selector(yes)
0x000000010000128a 4889C7 mov rdi, rax
0x000000010000128d E896020000 call imp___stubs__objc_msgSend
0x0000000100001292 E913000000 jmp 0x1000012aa
; Basic Block Input Regs: rbp - Killed Regs: rax rsi rdi
0x0000000100001297 488B45F8 mov rax, qword [ss:rbp-0x70+var_104] ; XREF=0x100001279
0x000000010000129b 488B35F6140000 mov rsi, qword [ds:objc_sel_no] ; @selector(no)
0x00000001000012a2 4889C7 mov rdi, rax
0x00000001000012a5 E87E020000 call imp___stubs__objc_msgSend
; Basic Block Input Regs: <nothing> - Killed Regs: <nothing>
0x00000001000012aa E913000000 jmp 0x1000012c2 ; XREF=0x100001292
; Basic Block Input Regs: rbp - Killed Regs: rax rsi rdi
0x00000001000012af 488B45F8 mov rax, qword [ss:rbp-0x70+var_104] ; XREF=0x1000011ea, 0x1000011f8, 0x100001206, 0x100001214
0x00000001000012b3 488B35DE140000 mov rsi, qword [ds:objc_sel_no] ; @selector(no)
0x00000001000012ba 4889C7 mov rdi, rax
0x00000001000012bd E866020000 call imp___stubs__objc_msgSend
; Basic Block Input Regs: <nothing> - Killed Regs: rsp rbp
0x00000001000012c2 4883C470 add rsp, 0x70 ; XREF=0x1000012aa
0x00000001000012c6 5D pop rbp
0x00000001000012c7 C3 ret
复原代码如下:
/**
* 用户名密码验证
* 用户名密码长度验证,密码字母和数字验证,密码只能包含数字和字母
* @return 返回YES or NO
*/
-(BOOL)checkifisok{
NSString* name = [nameTextField text];
NSString* serial = [serialTextField text];
int nameLength = [name length];
int serialLength = [serial length];
if(serialLength > 10 && serialLength < 15){
if(nameLength > 7 && nameLength < 15){
NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet];
NSString *trimmedString = [serial stringByTrimmingCharactersInSet:alphanumericSet];
if([trimmedString isEqualToString:@""]){
returnYES;
}
}else{
returnNO
}
}else{
returnNO;
}
}
第二个使用lldb动态调试:
lldb crackme2.app
r
ctl+c
br s -a 0x2a9e
0x00002a9e 55 push ebp
0x00002a9f 89E5 mov ebp,esp
0x00002aa1 57 push edi
0x00002aa2 56 push esi
0x00002aa3 53 push ebx
0x00002aa4 83EC3C sub esp,0x3c
0x00002aa7 A140400000 mov eax, dword [ds:objc_msg_length] ; @selector(length)
0x00002aac 89442404 mov dword [ss:esp+0x4],eax
0x00002ab0 8B4510 mov eax, dword [ss:ebp-0x48+arg_8]
0x00002ab3 890424 mov dword [ss:esp],eax
0x00002ab6 E8A3250000 call imp___jump_table__objc_msgSend
0x00002abb 83F808 cmp eax,0x8 //判断注册码长度是否为8位
0x00002abe 0F858A010000 jne 0x2c4e //不等跳往错误提示
; Basic Block Input Regs: ecx ebx ebp - Killed Regs: eax ecx ebx esp ebp esi edi
0x00002ac4 A144400000 mov eax, dword [ds:objc_msg_lossyCString]; @selector(lossyCString)
0x00002ac9 BE04000000 mov esi,0x4 //esi初始化为4
0x00002ace 31DB xor ebx,ebx
0x00002ad0 89442404 mov dword [ss:esp+0x4],eax
0x00002ad4 8B4514 mov eax, dword [ss:ebp-0x48+arg_C]
0x00002ad7 890424 mov dword [ss:esp],eax
0x00002ada E87F250000 call imp___jump_table__objc_msgSend
0x00002adf 890424 mov dword [ss:esp],eax
0x00002ae2 89C7 mov edi,eax
0x00002ae4 E87A250000 call imp___jump_table__strlen
0x00002ae9 31C9 xor ecx,ecx
0x00002aeb 8945D0 mov dword [ss:ebp-0x48+var_24],eax
0x00002aee EB37 jmp 0x2b27
; Basic Block Input Regs: ebx esi edi - Killed Regs: eax ecx edx ebx ebp esi
0x00002af0 0FBE041F movsx eax, byte [ds:edi+ebx] ; XREF=0x2b2a //取用户名的一个字符
0x00002af4 43 inc ebx //循环累加器
0x00002af5 0FAFC6 imul eax,esi //取出来的字符与esi相乘
0x00002af8 83C604 add esi,0x4 //esi+4
0x00002afb 89C2 mov edx,eax
0x00002afd C1E204 shl edx,0x4 //edx << 0x4
0x00002b00 29C2 sub edx,eax
0x00002b02 B8AD8BDB68 mov eax,0x68db8bad
0x00002b07 8D8C0A9A020000 lea ecx, dword [ds:edx+ecx+0x29a]
0x00002b0e F7E9 imul ecx
0x00002b10 89C8 mov eax,ecx
0x00002b12 C1F81F sar eax,0x1f
0x00002b15 C1FA0C sar edx,0xc
0x00002b18 29C2 sub edx,eax
0x00002b1a 89C8 mov eax,ecx
0x00002b1c 69D210270000 imul edx,edx,0x2710
0x00002b22 29D0 sub eax,edx
0x00002b24 8945E0 mov dword [ss:ebp-0x48+var_40],eax
; Basic Block Input Regs: ebx ebp - Killed Regs: <nothing>
0x00002b27 395DD0 cmp dword [ss:ebp-0x48+var_24],ebx ; XREF=0x2aee
0x00002b2a 77C4 jnbe 0x2af0
; Basic Block Input Regs: ecx ebx ebp edi - Killed Regs: eax ecx ebx esp ebp esi
0x00002b2c 8B45E0 mov eax, dword [ss:ebp-0x48+var_40]
0x00002b2f BE04000000 mov esi,0x4
0x00002b34 31DB xor ebx,ebx
0x00002b36 C744240878300000 mov dword [ss:esp+0x8],0x3078 ; @"%i"
0x00002b3e 8944240C mov dword [ss:esp+0xc],eax
0x00002b42 A128400000 mov eax, dword [ds:objc_msg_stringWithFormat_]; @selector(stringWithFormat:)
0x00002b47 89442404 mov dword [ss:esp+0x4],eax
0x00002b4b A154400000 mov eax, dword [ds:cls_NSString]
0x00002b50 890424 mov dword [ss:esp],eax
0x00002b53 E806250000 call imp___jump_table__objc_msgSend //将结果格式化为NSString
0x00002b58 893C24 mov dword [ss:esp],edi
0x00002b5b 8945D8 mov dword [ss:ebp-0x48+var_32],eax
0x00002b5e E800250000 call imp___jump_table__strlen
0x00002b63 31C9 xor ecx,ecx
0x00002b65 8945D4 mov dword [ss:ebp-0x48+var_28],eax
0x00002b68 EB32 jmp 0x2b9c
; Basic Block Input Regs: ebx esi edi - Killed Regs: eax ecx edx ebx ebp esi
0x00002b6a 0FBE041F movsx eax, byte [ds:edi+ebx] ; XREF=0x2b9f
0x00002b6e 43 inc ebx
0x00002b6f 0FAFC6 imul eax,esi
0x00002b72 83C608 add esi,0x8
0x00002b75 8D1480 lea edx, dword [ds:eax+eax*4]
0x00002b78 8D54502D lea edx, dword [ds:eax+edx*2+0x2d]
0x00002b7c B8AD8BDB68 mov eax,0x68db8bad
0x00002b81 01D1 add ecx,edx
0x00002b83 F7E9 imul ecx
0x00002b85 89C8 mov eax,ecx
0x00002b87 C1F81F sar eax,0x1f
0x00002b8a C1FA0C sar edx,0xc
0x00002b8d 29C2 sub edx,eax
0x00002b8f 89C8 mov eax,ecx
0x00002b91 69D210270000 imul edx,edx,0x2710
0x00002b97 29D0 sub eax,edx
0x00002b99 8945E4 mov dword [ss:ebp-0x48+var_44],eax
; Basic Block Input Regs: ebx ebp - Killed Regs: <nothing>
0x00002b9c 3B5DD4 cmp ebx, dword [ss:ebp-0x48+var_28] ; XREF=0x2b68
0x00002b9f 72C9 jc 0x2b6a
; Basic Block Input Regs: ebx ebp - Killed Regs: eax ebx esp ebp esi edi
0x00002ba1 8B45E4 mov eax, dword [ss:ebp-0x48+var_44]
0x00002ba4 BE04000000 mov esi,0x4
0x00002ba9 31DB xor ebx,ebx
0x00002bab C744240878300000 mov dword [ss:esp+0x8],0x3078 ; @"%i"
0x00002bb3 BF04000000 mov edi,0x4
0x00002bb8 8944240C mov dword [ss:esp+0xc],eax
0x00002bbc A128400000 mov eax, dword [ds:objc_msg_stringWithFormat_]; @selector(stringWithFormat:)
0x00002bc1 89442404 mov dword [ss:esp+0x4],eax
0x00002bc5 A154400000 mov eax, dword [ds:cls_NSString]
0x00002bca 890424 mov dword [ss:esp],eax
0x00002bcd E88C240000 call imp___jump_table__objc_msgSend //将结果格式化为NSString
0x00002bd2 895C2408 mov dword [ss:esp+0x8],ebx
0x00002bd6 8974240C mov dword [ss:esp+0xc],esi
0x00002bda 8945DC mov dword [ss:ebp-0x48+var_36],eax
0x00002bdd A148400000 mov eax, dword [ds:objc_msg_substringWithRange_]; @selector(substringWithRange:)
0x00002be2 89442404 mov dword [ss:esp+0x4],eax
0x00002be6 8B4510 mov eax, dword [ss:ebp-0x48+arg_8]
0x00002be9 890424 mov dword [ss:esp],eax
0x00002bec E86D240000 call imp___jump_table__objc_msgSend //截取密码前4位验证
0x00002bf1 89742408 mov dword [ss:esp+0x8],esi
0x00002bf5 897C240C mov dword [ss:esp+0xc],edi
0x00002bf9 89C3 mov ebx,eax
0x00002bfb A148400000 mov eax, dword [ds:objc_msg_substringWithRange_]; @selector(substringWithRange:)
0x00002c00 89442404 mov dword [ss:esp+0x4],eax
0x00002c04 8B4510 mov eax, dword [ss:ebp-0x48+arg_8]
0x00002c07 890424 mov dword [ss:esp],eax
0x00002c0a E84F240000 call imp___jump_table__objc_msgSend//截取密码后4位验证
0x00002c0f 891C24 mov dword [ss:esp],ebx
0x00002c12 89C6 mov esi,eax
0x00002c14 8B45D8 mov eax, dword [ss:ebp-0x48+var_32]
0x00002c17 89442408 mov dword [ss:esp+0x8],eax
0x00002c1b A108400000 mov eax, dword [ds:objc_msg_isEqual_] ; @selector(isEqual:)
0x00002c20 89442404 mov dword [ss:esp+0x4],eax
0x00002c24 E835240000 call imp___jump_table__objc_msgSend //判断是否相等
0x00002c29 84C0 test al,al
0x00002c2b 7421 je 0x2c4e
; Basic Block Input Regs: ebp esi - Killed Regs: eax edx esp
0x00002c2d 8B45DC mov eax, dword [ss:ebp-0x48+var_36]
0x00002c30 893424 mov dword [ss:esp],esi
0x00002c33 89442408 mov dword [ss:esp+0x8],eax
0x00002c37 A108400000 mov eax, dword [ds:objc_msg_isEqual_] ; @selector(isEqual:)
0x00002c3c 89442404 mov dword [ss:esp+0x4],eax
0x00002c40 E819240000 call imp___jump_table__objc_msgSend//判断是否相等
0x00002c45 BA01000000 mov edx,0x1
0x00002c4a 84C0 test al,al
0x00002c4c 7502 jne 0x2c50
; Basic Block Input Regs: edx - Killed Regs: edx
0x00002c4e 31D2 xor edx,edx ; XREF=0x2abe, 0x2c2b
; Basic Block Input Regs: edx - Killed Regs: eax ebx esp esi edi
0x00002c50 83C43C add esp,0x3c ; XREF=0x2c4c
0x00002c53 89D0 mov eax,edx
0x00002c55 5B pop ebx
0x00002c56 5E pop esi
0x00002c57 5F pop edi
0x00002c58 C9 leave
0x00002c59 C3 ret
keygen代码如下:
int main(int argc, constchar * argv[]) {
@autoreleasepool {
unsignedlong nameLength = strlen(argv[1]);
constchar* index = argv[1];
unsignedint eax = 0;
int ecx=0,edx=0,esi = 4;
int serial_1=0;
long constValue = 0x68db8bad;
for (int i = 0; i<nameLength; i++) {
eax = (int)(*index);
eax = eax * esi;
esi+=4;
edx = (eax << 0x4) - eax;
ecx = edx + ecx+0x29a;
edx = constValue*ecx >> 32;
serial_1 = ecx - ((edx >> 0xc)-(ecx >> 0x1f)) * 0x2710;
index++;
}
int serial_2=0;
index = argv[1];
eax = 0,ecx=0,edx=0,esi = 4;
for (int i = 0; i<nameLength; i++) {
eax = (int)(*index);
eax = eax * esi;
esi+=8;
edx = eax+(eax+eax*4)*2+0x2d;
ecx += edx;
edx = constValue*ecx >> 32;
serial_2 = ecx - ((edx >> 0xc) - (ecx >> 0x1f)) * 0x2710;
index++;
}
NSLog(@"\nname:%s\nserial:%d%d",argv[1],serial_1,serial_2);
}
return0;
}