Simple Reverse - 0x01(Lab - Sacred Arts)

Simple Reverse - 0x01(Lab - Sacred Arts)

Background

  • X86組合語言/基本指令集
  • neg (Negate) instruction

    實作:先在執行neg rax之前把$rax設定成2,執行指令之後剛好是2的補數

    1
    2
    3
    4
    5
    6
    7
      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

    實作:執行xchg ah, al之前先看一下$rax的狀態

    1
    2
    3
    4
    5
    6
      gef➤  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
    73
                          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打開12,如果有找到該檔案就會通過cmp然後跳到loc_40106F,並且讀取裡面的內容,然後loc_4010C3就看不懂了,這時候就直接用gdb跟一下流程,就會發現其實IDA的翻譯是有問題的,因為後面有一個cmp rax, QWORD PTR [rbx+rdx*1],所以就稍微看一下內容是甚麼

1
2
3
4
$rax   : 0x0
$rbx   : 0x000000000040108b  →   mov bl, 0xba
$rcx   : 0x7
$rdx   : 0x30

這不就是byte_40108B的所在位置嗎,而實際的rbx+rdx*1存的內容如下

1
2
gef➤  x/g $rbx+$rdx*1
0x4010bb:       0xffffffffffffcf82

我們必須修正IDA的錯誤翻譯,可以善用d快捷鍵然後把每一個data長度變成dq,正確翻譯如下

1
2
3
4
5
6
7
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出一些東西,所以很明顯的是那些操作到底做了甚麼事情,如果跟一下gdb就會發現只是

  1. 把數值變成負數
  2. 交換ah和al暫存器

Exploit

  1. 先把ah和al的數值交換
  2. 取補數
1
2
3
4
5
6
7
8
9
10
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

  1. Linux System Call Table for x86 64 

  2. 如果要打開的檔案存在則$rax的數值就會是一個大於零的數值,反之就會是小於零