Simple Reverse - 0x01(Lab - Sacred Arts)
Background
- X86組合語言/基本指令集
-
實作:先在執行
neg rax之前把$rax設定成2,執行指令之後剛好是2的補數1
2
3
4
5
6
7gef➤ set $rax=2 gef➤ info r $rax rax 0x2 0x2 gef➤ ni 0x00000000004010e0 in ?? () gef➤ info r $rax rax 0xfffffffffffffffe 0xfffffffffffffffe -
實作:執行
xchg ah, al之前先看一下$rax的狀態1
2
3
4
5
6gef➤ info r $rax rax 0xfffffffffffffffe 0xfffffffffffffffe gef➤ ni 0x00000000004010e2 in ?? () gef➤ info r $rax rax 0xfffffffffffffeff 0xfffffffffffffeff
Source Code
- IDA Pro Disassembler Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73start: ; DATA XREF: LOAD:0000000000400018↑o ; LOAD:0000000000400088↑o 48 C7 C0 02 00 00 00 mov rax, 2 48 C7 C7 1C 10 40 00 mov rdi, offset aTmpFlag ; "/tmp/flag" 48 C7 C6 00 00 00 00 mov rsi, 0 0F 05 syscall ; LINUX - sys_open 49 89 C7 mov r15, rax EB 0A jmp short loc_401026 ; --------------------------------------------------------------------------- 2F 74 6D 70 2F 66 6C 61+aTmpFlag db '/tmp/flag',0 ; DATA XREF: .text:0000000000401007↑o ; --------------------------------------------------------------------------- loc_401026: ; CODE XREF: .text:000000000040101A↑j 48 83 F8 00 cmp rax, 0 7E 09 jle short loc_401035 EB 41 jmp short loc_40106F ; --------------------------------------------------------------------------- 77 72 6F 6E 67 0A 00 aWrong db 'wrong',0Ah,0 ; DATA XREF: .text:0000000000401043↓o ; --------------------------------------------------------------------------- loc_401035: ; CODE XREF: .text:000000000040102A↑j ; .text:00000000004010E6↓j 48 C7 C0 01 00 00 00 mov rax, 1 48 C7 C7 01 00 00 00 mov rdi, 1 48 C7 C6 2E 10 40 00 mov rsi, offset aWrong ; "wrong\n" 48 BA 07 00 00 00 00 00+ mov rdx, 7 0F 05 syscall ; LINUX - sys_write loc_401056: ; CODE XREF: .text:000000000040111E↓j 48 C7 C0 3C 00 00 00 mov rax, 3Ch 48 C7 C7 00 00 00 00 mov rdi, 0 0F 05 syscall ; LINUX - sys_exit loc_401066: ; DATA XREF: .text:000000000040110B↓o 63 6F 72 movsxd ebp, dword ptr [rdi+72h] 72 65 jb short near ptr loc_4010CA+6 63 74 0A 00 movsxd esi, dword ptr [rdx+rcx+0] loc_40106F: ; CODE XREF: .text:000000000040102C↑j 48 83 EC 40 sub rsp, 40h 48 C7 C0 00 00 00 00 mov rax, 0 4C 89 FF mov rdi, r15 48 89 E6 mov rsi, rsp 48 C7 C2 32 00 00 00 mov rdx, 32h 0F 05 syscall ; LINUX - sys_read EB 38 jmp short loc_4010C3 ; --------------------------------------------------------------------------- B3 BA BE B8 84 byte_40108B db 0B3h, 0BAh, 0BEh, 0B8h, 84h ; DATA XREF: .text:loc_4010CA↓o 99 90 8D 92 8B D1 98 9E+ dq 9E98D18B928D9099h, 0D19290D29C8D9A92h, 8F978FBDD1D0888Bh 92 9A 8D 9C D2 90 92 D1+ dq 0CCCDCB92C28C9DC0h, 0CEC2BE8D91D9C7C7h, 0FFFFFFCF82C8CFC7h FF FF FF db 3 dup(0FFh) ; --------------------------------------------------------------------------- loc_4010C3: ; CODE XREF: .text:0000000000401089↑j 48 C7 C1 07 00 00 00 mov rcx, 7 loc_4010CA: ; CODE XREF: .text:0000000000401069↑j 48 C7 C3 8B 10 40 00 mov rbx, offset byte_40108B loc_4010D1: ; CODE XREF: .text:00000000004010EC↓j 48 8D 14 CD F8 FF FF FF lea rdx, ds:0FFFFFFFFFFFFFFF8h[rcx*8] 48 8B 04 14 mov rax, [rsp+rdx] 48 F7 D8 neg rax 86 C4 xchg al, ah 48 3B 04 13 cmp rax, [rbx+rdx] 0F 85 49 FF FF FF jnz loc_401035 E2 E3 loop loc_4010D1 EB 0D jmp short loc_4010FD ; --------------------------------------------------------------------------- 68 65 6C 6C 6F 20 77 6F+aHelloWorld db 'hello world',0Ah,0 ; --------------------------------------------------------------------------- loc_4010FD: ; CODE XREF: .text:00000000004010EE↑j 48 C7 C0 01 00 00 00 mov rax, 1 48 C7 C7 01 00 00 00 mov rdi, 1 48 C7 C6 66 10 40 00 mov rsi, offset loc_401066 48 BA 09 00 00 00 00 00+ mov rdx, 9 0F 05 syscall ; LINUX - sys_write E9 33 FF FF FF jmp loc_401056 _text ends end start
Recon
這一題就只是單純的用工人智慧看組語,我的想法是先看一下system call,他先把/tmp/flag打開12,如果有找到該檔案就會通過cmp然後跳到loc_40106F,並且讀取裡面的內容,然後loc_4010C3就看不懂了,這時候就直接用gdb跟一下流程,就會發現其實IDA的翻譯是有問題的,因為後面有一個cmp rax, QWORD PTR [rbx+rdx*1],所以就稍微看一下內容是甚麼
1 | |
這不就是byte_40108B的所在位置嗎,而實際的rbx+rdx*1存的內容如下
1 | |
我們必須修正IDA的錯誤翻譯,可以善用d快捷鍵然後把每一個data長度變成dq,正確翻譯如下
1 | |
所以整體流程應該就蠻清楚了,這支程式就是先讀取/tmp/flag的資料然後從後面讀取8個bytes後做了一些操作和qword_40108B的每一個dq做比較,如果比較的結果不符合就會跳到loc_401035(print出wrong後直接exit(0)),如果每一個dq都是正確的就會到下面的loc_4010FD然後print出一些東西,所以很明顯的是那些操作到底做了甚麼事情,如果跟一下gdb就會發現只是
- 把數值變成負數
- 交換ah和al暫存器
Exploit
- 先把ah和al的數值交換
- 取補數
1 | |
Reference
-
如果要打開的檔案存在則$rax的數值就會是一個大於零的數值,反之就會是小於零 ↩