# 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