# Simple Reverse - 0x01(Lab - Sacred Arts) ## Background * [X86組合語言/基本指令集](https://zh.wikibooks.org/wiki/X86%E7%B5%84%E5%90%88%E8%AA%9E%E8%A8%80/%E5%9F%BA%E6%9C%AC%E6%8C%87%E4%BB%A4%E9%9B%86) * [neg (Negate) instruction](https://www.ibm.com/docs/en/aix/7.1?topic=set-neg-negate-instruction) 實作:先在執行`neg rax`之前把`$rax`設定成2,執行指令之後剛好是2的補數 ```! gef➤ set $rax=2 gef➤ info r $rax rax 0x2 0x2 gef➤ ni 0x00000000004010e0 in ?? () gef➤ info r $rax rax 0xfffffffffffffffe 0xfffffffffffffffe ``` * [X86組合語言/基本指令集/IA32指令:xchg](https://zh.wikibooks.org/zh/X86%E7%B5%84%E5%90%88%E8%AA%9E%E8%A8%80/%E5%9F%BA%E6%9C%AC%E6%8C%87%E4%BB%A4%E9%9B%86/IA32%E6%8C%87%E4%BB%A4:xchg) 實作:執行`xchg ah, al`之前先看一下`$rax`的狀態 ```! gef➤ info r $rax rax 0xfffffffffffffffe 0xfffffffffffffffe gef➤ ni 0x00000000004010e2 in ?? () gef➤ info r $rax rax 0xfffffffffffffeff 0xfffffffffffffeff ``` ## Source Code :::spoiler IDA Pro Disassembler Code ```= start: ; 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`打開[^system_call_大全][^note1],如果有找到該檔案就會通過cmp然後跳到loc_40106F,並且讀取裡面的內容,然後loc_4010C3就看不懂了,==這時候就直接用gdb跟一下流程==,就會發現其實IDA的翻譯是有問題的,因為後面有一個`cmp rax, QWORD PTR [rbx+rdx*1]`,所以就稍微看一下內容是甚麼, ``` $rax : 0x0 $rbx : 0x000000000040108b → mov bl, 0xba $rcx : 0x7 $rdx : 0x30 ``` 這不就是byte_40108B的所在位置嗎,而實際的`rbx+rdx*1`存的內容如下 ``` gef➤ x/g $rbx+$rdx*1 0x4010bb: 0xffffffffffffcf82 ``` 我們必須修正IDA的錯誤翻譯,可以善用d快捷鍵然後把每一個data長度變成dq,正確翻譯如下 ``` qword_40108B dq 8D909984B8BEBAB3h ; DATA XREF: .text:loc_4010CA↓o dq 8D9A929E98D18B92h dq 0D0888BD19290D29Ch dq 8C9DC08F978FBDD1h dq 0D9C7C7CCCDCB92C2h dq 0C8CFC7CEC2BE8D91h dq 0FFFFFFFFFFFFCF82h ``` 所以整體流程應該就蠻清楚了,這支程式就是先讀取/tmp/flag的資料然後從後面讀取8個bytes後==做了一些操作==和qword_40108B的每一個dq做比較,如果比較的結果不符合就會跳到loc_401035(print出wrong後直接exit(0)),如果每一個dq都是正確的就會到下面的loc_4010FD然後print出一些東西,所以很明顯的是那些<b>==操作==</b>到底做了甚麼事情,如果跟一下gdb就會發現只是 1. 把數值變成負數 2. 交換ah和al暫存器 ## Exploit 1. 先把ah和al的數值交換 2. 取補數 ```python= fake_flag = ["8D909984B8BEBAB3", "8D9A929E98D18B92", "D0888BD19290D29C", "8C9DC08F978FBDD1", "D9C7C7CCCDCB92C2", "C8CFC7CEC2BE8D91", "FFFFFFFFFFFFCF82"] BIG_NUM = 1<<64 FLAG = [] for i in fake_flag: tmp = i[:12] + i[14:16] + i[12:14] print(tmp) tmp = BIG_NUM - int(tmp, 16) FLAG.append(bytes.fromhex(hex(tmp)[2:]).decode('utf-8')[::-1]) print("".join(FLAG)) ``` ## Reference [^system_call_大全]:[Linux System Call Table for x86 64](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/) [^note1]:如果要打開的檔案存在則$rax的數值就會是一個大於零的數值,反之就會是小於零