---
# System prepended metadata

title: NCtfU - 10/12 (Reverse)(A204)
tags: [新手場, nctfu2022fall]

---

# NCtfU - 10/12 (Reverse)(A204)
###### tags: `新手場` `nctfu2022fall` 

:::success
:::spoiler 目錄
[toc]
:::

:::info
[簡報連結](https://speakerdeck.com/terrynini/cheng-gong-gao-zhong-jiang-yi)
[直播連結](https://youtu.be/RGrblEmUzlg)
[錄影連結](https://www.youtube.com/watch?v=OvAG7V1UUvI)
[Slido](https://app.sli.do/event/8AC7pxgapD3fShni2vzizc)
:::

## Lab 連結

[reverse lab.zip](https://drive.google.com/drive/folders/1NW8rKibP7aUks64TOLiOgg9r1bBNyHiW?usp=sharing)

## 共筆
- GCC
GCC(GNU Compiler Collection)
- 執行檔怎麼來的

```bash
Windows PowerShell 或 cmd 或 linux terminal

前處理
gcc -E HelloWorld.c -o HelloWorld.i
編譯
gcc -S HelloWorld.c -o HelloWorld.s
組譯
gcc -c HelloWorld.c -o HelloWorld.o
完成
gcc HelloWorld.c -o HelloWorld

優化(O0 ~ O3。0為不優化，3為所有優化)
gcc -O3 HelloWorld.c -o HelloWorld

編譯為 32bit 要加-m32
```
- intel vs AT&T 表示法
    - intel 目標暫存器在前來源暫存器在後，AT&T 相反
    - AT&T 暫存器前有 % 常數前有 $，intel 沒有

### 組合語言型別

- RISC vs CISC
    - CISC: x86, ...
    - RISC: ARM, MIPS, ...

### 型態
```assambly
BYTE (8 bit)
WORD (16bit)
DWORD(32bit)
QWORD(64bit)
```
:::info
[Note] 1 Byte = 8 bit = 16進位的2位數
例如：0xAB = (1010 1011)~b~ 為8bit → 1 Byte
:::
### 暫存器
- RAX(64bit) EAX(32bit) AX(16bit) AH AL(8bit)
- RAX, RBX, RCX, RDX 通用型暫存器
- ESP (指向stack頂部) EBP (指向stack底部)
- EDI, ESI 陣列索引使用
- EIP 下一個指令執行位置

* EAX
    * AX(後16bit)
        * AH(前8bit)
        * AL (後8bit)
* EBX
    * BX(後16bit)
        * BH(前8bit)
        * BL (後8bit)
* ECX(可決定迴圈結束)
    * CX(後16bit)
        * CH(前8bit)
        * CL (後8bit)
* EDX
    * DX(後16bit)
        * DH(前8bit)
        * DL (後8bit)
* ESI(可用於陣列位置)
* EDI(可用於陣列位置)
* ESP(指向STACK頂部)
* EBP(指向STACK底部)
* EIP(下一指令，一般不可手動設定 ~~但如果BOF...~~)

### Little endian
數字高(低)位，放記憶體編號較大(小)的位置

eg. AB CD EF 10 -> 0x10EFCDAB

反之則為 big endian

### Assembly
- add/sub/mul/div 四則運算
- inc/dec 遞增遞減
    - e.g. `inc eax` (eax++)
- mov 賦值
    - e.g. `mov eax, ebx` (eax = ebx)
- lea 計算記憶體位置
    - e.g. ESI = 0xffffcf35
    - `lea EAX, DWORD PTR [ESI + 4]`
    - EAX = 0xffffcf39
- and/or/not/xor  logic gate(位元運算，數字的每個位元都分別拿來算)
    - 舉例：`1010 and 1100 == 1000` 
    - `xor EAX, EAX` == `mov EAX, 0`
        - 一般來說會用前者方式清零，因暫存器運算會比記憶體取值來的快很多
- neg 取負數(2補數, 取一補數補上1)
    - 101001 -> (取一補數) -> 010110 -> (+1) -> 010111
- test 同 and，但不會將結果儲存 (但是會影響旗標暫存器 EFLAGS)
- cmp 就compare
    - cmp eax, ebx

| ZF | CF | Result |
| -------- | -------- | -------- |
| False | True | eax < ebx |
| False | False | eax > ebx |
| True | False | eax == ebx |
### 各種jump
| 符號 | 解釋                     |
| ---- | ------------------------ |
| J    | Jump if(如果...則跳轉)   |
| N    | Not(不是)                |
| A    | Above(無號整數：前>後)   |
| B    | Below(無號整數：前<後)   |
| G    | Greater(有號整數：前>後) |
| L    | Less(有號整數：前<後)    |
| E    | Equal(前=後)             |

如果括號內成立，則跳轉
unsigned int
```
JA /JNBE(>)
JAE/JNB (>=)
JB /JNAE(<)
JBE/JNA (<=)
```
signed int
```
JG /JNLE(>)
JGE/JNL (>=)
JL /JNGE(<)
JLE/JNG (<=)
```
other
```
JE (==)
JNE(!=)
JMP(True)
```
舉例：jle 如果上一行結果為(前<=後)，則跳轉
 ```assembly=
     mov eax, 1
     mov eax, 2
 
     cmp eax, ebx
     jle target ; jump to target if eax <= ebx
 
 target:
     mov eax 1
 ```
 等同
```cpp=
int eax = 1,
    ebx = 2;

if(eax <= ebx)
    goto target;// 直接去target所在行數

target:
    eax = 1;
```
||https://i.redd.it/osoqocy36za71.jpg||

其他相關判斷指令:
- jl: <
- jge: >=
- jg: >
- jz/je: ==
- jnz/jne: !=

> 以上是有號數，無號數的話就是把 g 改 a、l 改 b

### EFLAGS
>注意：mov不會影響Flag
- OF 判斷當作有號數時，運算後有沒有 overflow
- SF 數字是不是負數
- ZF 運算後值是否為 0
- CF 當作無號數時，運算後是否~~進位~~overflow

### Analyze
- static 靜態: objdump, Ghidra(這好像也可以算dynamic analyze?)
- dynamic 動態: gdb, x64DBG


### Calling convention
- 非強制，視 compiler 廠商設定
- 一般來說，call function 時，參數右至左 push 進 stack
- push: 放到stack頂部 e.g. `push rbp` 將rbp push到stack頂部(記憶體低位)
- pop: 取出stack頂部 e.g. `pop rbp` 將最頂端的東西移至rbp
- stack由記憶體高位往低位長
- caller: call function 的
- callee: 被 call 的
- leave: `mov esp, ebp; pop ebp`
- ret: `pop eip`

### 記憶體中的stack
Virtual Address Space 結構 (非實際上實體記憶體位置)
(高位)OS → stack → HEAP → BSS(未初始化) → DATA(初始化) → TEXT(低位)



| structure | 
| --------- | 
| OS(high)  |
| stack     |
|           |
|           |
|           |
|           |
| heap      |
| bss       |
| data      |
| text(low) |

call function時:
```assembly
call func    ; 呼叫函數func (push eip; jmp func)

; function prologue
push ebp     ; 呼叫函數前，此時stack會用來執行函數
mov ebp, esp

; function裡的東西
leave        ;回復call前的esp ebp (mov esp, ebp; pop ebp)，stack還給外面
ret          ;將eip設為call前的下一個instruction (pop eip)
```
:::danger
當stack撞到HEAP(例如過多次的遞迴造成)，程式就會崩潰 (stack overflow)

> linux 的 process 上 ，每個 segment 都有各自大小，一個 segment 會分配給 stack，如果存取地址上不存在 segment 或沒有權限，就會發生 Segmentation fault 
> [name=r8]


如果程式沒有限制寫入大小(`gets()`)便**有機會**能控制eip <- 這邊應該是指 buffer overflow? 跟 stack overflow 不太一樣 <- Y
:::
