本次破解练习的对象下载地址如下:https://github.com/GeoSn0w/Reverse-Engineering-Tutorials。选择了其中的Level 3, cat 这个例子。cat这个程序是个命令行程序,运行时输入正确的Serial即可通过验证。截图如下:
Snip20171025_1.png
这个例子比较简单,主要目的是演示如何用Hopper调试命令行程序。程序自带说明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中可以看到代码如下。只有一个_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 \\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
静态分析代码,知 loc_100000b77为关键跳转。
loc_100000b77:
0000000100000b77 cmp dword [rbp+var_51C], 0x4f4 ; CODE XREF=_main+235
0000000100000b81 jne loc_100000c56
此处条件跳转,比较[rbp+var_51C]与0x4f4的大小,相等则通过。0x4f4为多少呢?转为十进制为1268。如下图。
Snip20171025_7.png
0x2动态分析
[rbp+var_51C] 的值是如何计算得来的呢?Hopper提供了动态调试功能,也能单步骤调试运行命令行程序。
见下图。Arguments 输入参数,Application Output窗口打印程序的输出。
Snip20171025_3.png
切换窗口到GPR,也可以看到各个寄存器值。
Snip20171025_2.png
通过运行,得知,程序遍历输入的参数,进行累加,最后的结果与1268相比较,相等则通过验证。
0x3验证
根据分析,可以算出Serial。例如:1268 = 120*10+68 ; ASCII码120对应的字符为x,ASCII码68对应的字符为D,所以Serial可以为:xxxxxxxxxxD。代入程序验证,成功。:)!
Snip20171025_8.png
打开练习对应的源码,分析也是对的。如下。
//GeoSn0w's Reverse Engineering Tutorial
//Use the code as you want, WTFPL
#include
#include
#include
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\n");
printf("Or you can do what hackers do the best...\n");
}
return 0;
}