---
# System prepended metadata

title: reverse&pwn
tags: [CTF, 資安]

---





# reverse&pwn

## x86暫存器

![](https://hackmd.io/_uploads/SJjuJm6Fh.png)


| EIP、RIP | 指令暫存器 | 指向下一條指令位址 |
| --- | --- | --- |
| CF | Carry Flag | 運算產生借位或進位，CF亮起 |
| ZF | Zero Flag | 任何運算為0，ZF亮起 |



## x86指令

```nasm
mov rax, 1 ; rax=1
add rax, 5 ; rax+=5
sub rax, 1 ; rax-=1
xor rax, rax ; rax=rax^rax //歸零
or  rax, 0x10; rax=rax||0x10
mul ebx  ; eax=ebx*eax
dec ebx  ; ebx-=1
inc ebx  ; ebx+=1
jnz LOOP ; jmp if ZF != 1//jump if non zero
jmp HANG ; while(true)
lea rdi, [rsp+0x10] ; 不取值直接放入
cmp rax, rbx ;rax-rbx;
jz EQUAL ; jump if equal(ZF==1)
ja ABOVE ; jump if unsigned above (CF==0 or ZF==0)) //if (rax>rbx)
jle LESS ; jump less or equal
idiv dowrd ptr [rbp-8] ; edx=eax%[rbp-8]
syscall 吃rax

push rbp;//將rbp放到rsp的位址中，再將rsp向上移8bytes
pop  rbp;//將rsp位址中的值放到rbp，再將rsp向下移8bytes
byte ptr [rax]  ;只用一個byte
word ptr [rax]  ;2byte
dword ptr [rax] ;4byte
qword ptr [rax] ;8byte
oword ptr [rax] ;16byte
```


## Stack Frame

![](https://hackmd.io/_uploads/SJ5HV_2v2.png =50%x)



- Stack Frame最下面放Return Address
- 倒數第二放上一個Stack Frame的 RBP位置
- 每一格是8bytes

### Prologue

```nasm
push rbp;//將舊Stack基底位置放到新Stack最底端
mov rbp,rsp;//將rbp向上移到新stack的底端

```

### 開Stack

```nasm
sub rsp,0x20;//將rsp向上撐開一個Stack Frame
...
call func1;//call之前會把下一條指令位址push到stack上才開啟一個新的stack frame
下一條指令
```

### Epilogue

```nasm
leave;
	mov rsp,rbp;//將rsp彈回rbp位置
	pop rbp;//將rbp彈回上一個stack frame的基底位置
ret; //pop rip，將下一條要執行的指令位址放入rip中
```

**執行完後會回到上一個stack frame的狀態**

## Calling Convention
    Function傳遞參數的慣例

**x64**

- **Windows**
    - Function(rcx,rdx,r8,r9,stack)
- **Linux**
    -    Function(rdi,rsi,rdx,rcx,r8,r9,stack)

**x86**
- **都放stack**
- **__cdecl**
    -    **caller做Stack Cleanup**
    -    func(a,b,c)
    -    push c->push b->push a
-  **__stdcall**
    -    **callee做Stack Cleanup**
    -    stack放置和__cdecl一樣
-  **__fastcall**
    -  前兩個參數放到Register，再放進Stack
        -  ecx->edx->stack
function return值放在rax

### ChatGPT說

1. 32位Windows平台下，前四個整型（integer）參數依次存放在寄存器EAX、EDX、ECX和EBX中。
2. 64位Windows平台下，前四個整型參數依次存放在寄存器RCX、RDX、R8和R9中，而前四個浮點型（floating-point）參數存放在XMM0~XMM3寄存器中。
3. Linux和Unix等平台下，前六個整型參數依次存放在寄存器EDI、ESI、EDX、ECX、R8和R9中。而前八個浮點型參數存放在XMM0~XMM7寄存器中。

### info func沒東西

可能被打包起來了

```bash
upx -d file -o newfile
```

### Syscall

![](https://hackmd.io/_uploads/SytwHqdD3.png)


### FD(File Descriptor)

| File Descriptor | 名稱 | <unistd.h>符號常數[1] | <stdio.h>檔案流[2] |
| --- | --- | --- | --- |
| 0 | Standard input | STDIN_FILENO | stdin |
| 1 | Standard output | STDOUT_FILENO | stdout |
| 2 | Standard error | STDERR_FILENO | stderr |

### Section

section放不會變動的資料

- 程式碼在 .text section 有執行權限
- 常數字串放 .rodata section 有讀取權限

### ELF 保護機制

```bash
checksec file
```

- **PIE(Position Independent Executable)**
    - 程式碼以相對位置表示，非絕對位置
- **NX(No eXecute)**
    - .text之外的section不會有執行權限
- **Canary -stack protector**
    - 在stack 結尾塞入一個隨機數，return 前透過檢查隨機數是否有被修改
- **RELRO (RELocation Read-Only)**
    - 分成Full/Partial/No 三種型態，分別代表在runtime解析外部function時使用的不同機制
- **Seccomp(SECure COMPuting mode)**
    - 制定規則來禁止/允許特定syscall呼叫
- **ASLR(Address Space Layout Randomization)**
    - stack、heap會使用隨機記憶體位址作為base address
##    如何get shell
```c
execve("/bin/sh",0,0);
system("/bin/sh");
```
也可以透過syscall得到shell

###    shellcode
```python
from pwn import *

context.arch="amd64"
sc=asm(shellcraft.sh())
```

##    Memory Layout
-    **.text:** 拿來放程式碼的
-    **.rodata:** read-only data，如寫死的字串
-    **.bss:** 尚未初始化的變數
-    **heap:** 動態分配的記憶體空間，會隨執行時間增長
-    **lib:** malloc()、free()等lib的實作
-    **tls:** threat local storage
-    **stack:** 老熟了在上面

##    Buffer Overflow
###    危險function可能會出現
```c
gets();
strcat();
scanf("%s",&a);
```
###    怎麼玩
    蓋掉return address跳到其他地方
##    Heap
    在runtime分配及釋放記憶體，才能有效利用記憶體
###    Chunk
    動態記憶體分配的基本單位，最小為0x20 bytes，會對齊0x10 bytes，由於metadata會額外需
    要0x10 bytes，因此實際上會多出0x10的大小
-    使用中的Chunk->**`allocated chunk`**
-    被釋放的Chunk->**`freed chunk`**
    -    **`freed chunk`** 會被依功能放在不同的 **`bin`** 之中
    -    後續請求記憶體時會從 **`bin`** 中取出 **`chunk`** 給Heap使用

![](https://hackmd.io/_uploads/rkpqwMEu3.png)


###    有的沒的工具
```shell
objdump -M intel -d file |less #查看asm code

checksec file #檢查保護機制

ROPgadget --binary file #檢查ROP chain

upx -d file -o new_file #把被包起來的library unpack
```

####    ROPgadget
    usage: ROPgadget.py [-h] [-v] [-c] [--binary <binary>] [--opcode <opcodes>]
                    [--string <string>] [--memstr <string>] [--depth <nbyte>]
                    [--only <key>] [--filter <key>] [--range <start-end>]
                    [--badbytes <byte>] [--rawArch <arch>] [--rawMode <mode>]
                    [--rawEndian <endian>] [--re <re>] [--offset <hexaddr>]
                    [--ropchain] [--thumb] [--console] [--norop] [--nojop]
                    [--callPreceded] [--nosys] [--multibr] [--all] [--noinstr]
                    [--dump]

```shell
ROPgadget file  --binary
```
####    pwntools

```python
from pwn import *

context.arch='amd64'    #context類似環境變數的東東
context.level='debug'


#把數字變成bytes傳給電腦
packed_32=p32(0x12345678) #p32 4bytes
packed_64=p64(0x123456789abcdef1) #p64 8bytes

#把bytes變回數字
unpacked_32=u32(b'\x78\x56\x34\x12')
```
##    GOT Hijacking
:::info
**`GOT`:Global Offset Table**
>When you execute the function at first time, it would resolve the function, and finally fill the function of the GOT with the correct address of the function.
:::

*待補*



##    How to reverse engineer an unity game

我不會(目前)
https://www.kodeco.com/36285673-how-to-reverse-engineer-a-unity-game

###    DnSpy

https://blog.csdn.net/jumpe_17/article/details/115468065