本次破解練習(xí)的對(duì)象下載地址如下:https://github.com/GeoSn0w/Reverse-Engineering-Tutorials涌矢。選擇了其中的Level 3坤学, cat 這個(gè)例子。cat這個(gè)程序是個(gè)命令行程序黍图,運(yùn)行時(shí)輸入正確的Serial即可通過驗(yàn)證。截圖如下:
這個(gè)例子比較簡(jiǎn)單,主要目的是演示如何用Hopper調(diào)試命令行程序靶庙。程序自帶說明Readme如下。
- The level 3 consists into a binary that requires a serial number to work. Once a serial number (the correct one) is fed to the app, a function executes that prints out data about the Kernel (uname).
Your challenge is to bypass the signature check so that any serial would do.
0x1 代碼分析
Hopper中可以看到代碼如下娃属。只有一個(gè)_main方法六荒。
_main:
0000000100000a50 push rbp
0000000100000a51 mov rbp, rsp
0000000100000a54 sub rsp, 0x580
0000000100000a5b lea rax, qword [0x100000d3c] ; "Welcome to the iOS Reverse Engineering Level 3! \\n"
0000000100000a62 mov rcx, qword [___stack_chk_guard_100001000]
0000000100000a69 mov rcx, qword [rcx]
0000000100000a6c mov qword [rbp+var_8], rcx
0000000100000a70 mov dword [rbp+var_50C], 0x0
0000000100000a7a mov dword [rbp+var_510], edi
0000000100000a80 mov qword [rbp+var_518], rsi
0000000100000a87 mov rdi, rax ; argument "format" for method imp___stubs__printf
0000000100000a8a mov al, 0x0
0000000100000a8c call imp___stubs__printf
0000000100000a91 lea rdi, qword [0x100000d6e] ; "Created by GeoSn0w (@FCE365)\\n\\n", argument "format" for method imp___stubs__printf
0000000100000a98 mov dword [rbp+var_524], eax
0000000100000a9e mov al, 0x0
0000000100000aa0 call imp___stubs__printf
0000000100000aa5 lea rdi, qword [0x100000d8d] ; "The challenge is to hack this application so that you can use it without any serial number and obtain the flag! \\n\\n", argument "format" for method imp___stubs__printf
0000000100000aac mov dword [rbp+var_528], eax
0000000100000ab2 mov al, 0x0
0000000100000ab4 call imp___stubs__printf
0000000100000ab9 lea rdi, qword [0x100000e00] ; "**************** START **************** \\n\\n", argument "format" for method imp___stubs__printf
0000000100000ac0 mov dword [rbp+var_52C], eax
0000000100000ac6 mov al, 0x0
0000000100000ac8 call imp___stubs__printf
0000000100000acd cmp dword [rbp+var_510], 0x2
0000000100000ad4 mov dword [rbp+var_530], eax
0000000100000ada jne loc_100000c83
0000000100000ae0 lea rdi, qword [0x100000e2b] ; "Preparing to check access key: %s\\n", argument "format" for method imp___stubs__printf
0000000100000ae7 mov rax, qword [rbp+var_518]
0000000100000aee mov rsi, qword [rax+8]
0000000100000af2 mov al, 0x0
0000000100000af4 call imp___stubs__printf
0000000100000af9 mov dword [rbp+var_51C], 0x0
0000000100000b03 mov dword [rbp+var_520], 0x0
0000000100000b0d mov dword [rbp+var_534], eax
loc_100000b13:
0000000100000b13 movsxd rax, dword [rbp+var_520] ; CODE XREF=_main+290
0000000100000b1a mov rcx, qword [rbp+var_518]
0000000100000b21 mov rdi, qword [rcx+8] ; argument "s" for method imp___stubs__strlen
0000000100000b25 mov qword [rbp+var_540], rax
0000000100000b2c call imp___stubs__strlen
0000000100000b31 mov rcx, qword [rbp+var_540]
0000000100000b38 cmp rcx, rax
0000000100000b3b jae loc_100000b77
0000000100000b41 movsxd rax, dword [rbp+var_520]
0000000100000b48 mov rcx, qword [rbp+var_518]
0000000100000b4f mov rcx, qword [rcx+8]
0000000100000b53 movsx edx, byte [rcx+rax]
0000000100000b57 add edx, dword [rbp+var_51C]
0000000100000b5d mov dword [rbp+var_51C], edx
0000000100000b63 mov eax, dword [rbp+var_520]
0000000100000b69 add eax, 0x1
0000000100000b6c mov dword [rbp+var_520], eax
0000000100000b72 jmp loc_100000b13
loc_100000b77:
0000000100000b77 cmp dword [rbp+var_51C], 0x4f4 ; CODE XREF=_main+235
0000000100000b81 jne loc_100000c56
0000000100000b87 lea rdi, qword [0x100000e4e] ; "Welcome! F.C.E. 365 Tool v36.1\\n", argument "format" for method imp___stubs__printf
0000000100000b8e mov al, 0x0
0000000100000b90 call imp___stubs__printf
0000000100000b95 lea rdi, qword [0x100000e6e] ; "\\n", argument "format" for method imp___stubs__printf
0000000100000b9c mov dword [rbp+var_544], eax
0000000100000ba2 mov al, 0x0
0000000100000ba4 call imp___stubs__printf
0000000100000ba9 lea rdi, qword [0x100000e70] ; "Blimey! You're not a good man! You've hacked the app!\\n \\n", argument "format" for method imp___stubs__printf
0000000100000bb0 mov dword [rbp+var_548], eax
0000000100000bb6 mov al, 0x0
0000000100000bb8 call imp___stubs__printf
0000000100000bbd lea rdi, qword [0x100000ea9] ; "Flag: 0x038948FFFF83--DS \\n", argument "format" for method imp___stubs__printf
0000000100000bc4 mov dword [rbp+var_54C], eax
0000000100000bca mov al, 0x0
0000000100000bcc call imp___stubs__printf
0000000100000bd1 lea rdi, qword [0x100000ec4] ; "System Identity:\\n", argument "format" for method imp___stubs__printf
0000000100000bd8 mov dword [rbp+var_550], eax
0000000100000bde mov al, 0x0
0000000100000be0 call imp___stubs__printf
0000000100000be5 lea rdi, qword [rbp+var_508] ; argument "name" for method imp___stubs__uname
0000000100000bec mov dword [rbp+var_554], eax
0000000100000bf2 call imp___stubs__uname
0000000100000bf7 lea rdi, qword [0x100000ed6] ; "%s Release %s (Version %s) on %s\\n", argument "format" for method imp___stubs__printf
0000000100000bfe lea rcx, qword [rbp+var_508]
0000000100000c05 mov rdx, rcx
0000000100000c08 add rdx, 0x200
0000000100000c0f mov rsi, rcx
0000000100000c12 add rsi, 0x300
0000000100000c19 mov r8, rcx
0000000100000c1c add r8, 0x400
0000000100000c23 mov qword [rbp+var_560], rsi
0000000100000c2a mov rsi, rcx
0000000100000c2d mov rcx, qword [rbp+var_560]
0000000100000c34 mov dword [rbp+var_564], eax
0000000100000c3a mov al, 0x0
0000000100000c3c call imp___stubs__printf
0000000100000c41 mov dword [rbp+var_50C], 0x0
0000000100000c4b mov dword [rbp+var_568], eax
0000000100000c51 jmp loc_100000cb5
loc_100000c56:
0000000100000c56 lea rdi, qword [0x100000ef8] ; "The serial number is not correct!\\n", argument "format" for method imp___stubs__printf, CODE XREF=_main+305
0000000100000c5d mov al, 0x0
0000000100000c5f call imp___stubs__printf
0000000100000c64 lea rdi, qword [0x100000f1b] ; "The application is locked!\\n", argument "format" for method imp___stubs__printf
0000000100000c6b mov dword [rbp+var_56C], eax
0000000100000c71 mov al, 0x0
0000000100000c73 call imp___stubs__printf
0000000100000c78 mov dword [rbp+var_570], eax
0000000100000c7e jmp loc_100000cab
loc_100000c83:
0000000100000c83 lea rdi, qword [0x100000f37] ; "This application requires a serial number to work! You can validate it with <key>\\n", argument "format" for method imp___stubs__printf, CODE XREF=_main+138
0000000100000c8a mov al, 0x0
0000000100000c8c call imp___stubs__printf
0000000100000c91 lea rdi, qword [0x100000f8a] ; "Or you can do what hackers do the best...\\n", argument "format" for method imp___stubs__printf
0000000100000c98 mov dword [rbp+var_574], eax
0000000100000c9e mov al, 0x0
0000000100000ca0 call imp___stubs__printf
0000000100000ca5 mov dword [rbp+var_578], eax
loc_100000cab:
0000000100000cab mov dword [rbp+var_50C], 0x0 ; CODE XREF=_main+558
loc_100000cb5:
0000000100000cb5 mov rax, qword [___stack_chk_guard_100001000] ; CODE XREF=_main+513
0000000100000cbc mov ecx, dword [rbp+var_50C]
0000000100000cc2 mov rax, qword [rax]
0000000100000cc5 cmp rax, qword [rbp+var_8]
0000000100000cc9 mov dword [rbp+var_57C], ecx
0000000100000ccf jne loc_100000ce4
0000000100000cd5 mov eax, dword [rbp+var_57C]
0000000100000cdb add rsp, 0x580
0000000100000ce2 pop rbp
0000000100000ce3 ret
; endp
loc_100000ce4:
0000000100000ce4 call imp___stubs____stack_chk_fail ; CODE XREF=_main+639
; endp
靜態(tài)分析代碼,知 loc_100000b77為關(guān)鍵跳轉(zhuǎn)矾端。
loc_100000b77:
0000000100000b77 cmp dword [rbp+var_51C], 0x4f4 ; CODE XREF=_main+235
0000000100000b81 jne loc_100000c56
此處條件跳轉(zhuǎn)掏击,比較[rbp+var_51C]與0x4f4的大小,相等則通過秩铆。0x4f4為多少呢砚亭?轉(zhuǎn)為十進(jìn)制為1268。如下圖殴玛。
0x2動(dòng)態(tài)分析
[rbp+var_51C] 的值是如何計(jì)算得來的呢捅膘?Hopper提供了動(dòng)態(tài)調(diào)試功能,也能單步驟調(diào)試運(yùn)行命令行程序滚粟。
見下圖寻仗。Arguments 輸入?yún)?shù),Application Output窗口打印程序的輸出凡壤。
切換窗口到GPR署尤,也可以看到各個(gè)寄存器值耙替。
通過運(yùn)行,得知曹体,程序遍歷輸入的參數(shù)俗扇,進(jìn)行累加,最后的結(jié)果與1268相比較混坞,相等則通過驗(yàn)證狐援。
0x3驗(yàn)證
根據(jù)分析,可以算出Serial究孕。例如:1268 = 120*10+68 啥酱; ASCII碼120對(duì)應(yīng)的字符為x,ASCII碼68對(duì)應(yīng)的字符為D厨诸,所以Serial可以為:xxxxxxxxxxD镶殷。代入程序驗(yàn)證,成功微酬。:)绘趋!
打開練習(xí)對(duì)應(yīng)的源碼,分析也是對(duì)的颗管。如下陷遮。
//GeoSn0w's Reverse Engineering Tutorial
//Use the code as you want, WTFPL
#include <string.h>
#include <stdio.h>
#include <sys/utsname.h>
int main(int argc, char *argv[]) {
printf("Welcome to the iOS Reverse Engineering Level 3! \n");
printf("Created by GeoSn0w (@FCE365)\n\n");
printf("The challenge is to hack this application so that you can use it without any serial number and obtain the flag! \n\n");
printf("**************** START **************** \n\n");
if(argc==2) {
printf("Preparing to check access key: %s\n", argv[1]);
int hex = 0;
for(int access=0; access<strlen(argv[1]); access++){
hex += (int)argv[1][access];
}
if(hex==1268) {
printf("Welcome! F.C.E. 365 Tool v36.1\n");
printf("\n");
printf("Blimey! You're not a good man! You've hacked the app!\n \n");
printf("Flag: 0x038948FFFF83--DS \n");
printf("System Identity:\n");
struct utsname u;
uname (&u);
printf ("%s Release %s (Version %s) on %s\n", u.sysname, u.release, u.version, u.machine);
return 0;
}
else {
printf("The serial number is not correct!\n");
printf("The application is locked!\n");
}
}
else {
printf("This application requires a serial number to work! You can validate it with <key>\n");
printf("Or you can do what hackers do the best...\n");
}
return 0;
}