---
# System prepended metadata

title: Pwntools
tags: [Computer Science Security]

---

# Pwntools

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

(這裡)[https://github.com/Gallopsled/pwntools?tab=readme-ov-file]

> 請問 markdown 的 「超連結語法」 是一種 usb 語法嗎 我每次都打反

### example

```python=
from pwn import *
import sys
import time
context.log_level = "debug"
context.terminal = ["tmux", "splitw", "-h"]
context.arch = "amd64"
if len(sys.argv) == 1:
    r = process("./binary")
    if args.GDB:
        gdb.attach(r,"set max-visualize-chunk-size 0x50")
elif len(sys.argv) == 3:
    r = remote(sys.argv[1], sys.argv[2])
else:
    print("Usage: python3 {} [GDB | REMOTE_IP PORT]".format(sys.argv[0]))
    sys.exit(1)
```

### import


```python=
from pwn import *
```


### context


```python=
context.os = "linux"
context.arch = "amd64"
context.log_level = 'debug'
```

> `context.log_level = 'debug'` 可以看到詳細的 `debug` 狀態

> 可以直接使用下面這個，會直接幫你設定好
```python=
context.binary = './challenge-binary'
```



### ELF


```python=
e = ELF('/bin/cat')
```
> 開一個 ELF File，並且交由變數 `e` 管理

> 常使用於 `libc.so.x`，我們可以很簡單的去 Parse 這個 Dynamic Library，然後找到好用的 gadget (e.g. `bin/sh`)

```python=
e.address = elf file init address
```
> 這邊可以把 leak 出來的 libc base address  assign 給 `address` 這個 member variable

```python=
write_address = e.symbols['write']
read_address = e.symbols['read']
```
> 設定好 address 後，因為符號與整個檔案的相對位置不會改變，所以可以使用 `symbols[symbolname]`，去找你想要的 symbol address

### process

```python=
p = process("/path/2/ur/binary")
p = remote('ip','port')
```
> `p = process("/path/2/ur/binary")` 把 binary 跑起來，並且交由變數 `p` 管理

> `p = remote('ip','port')` 遠端連線到指定 ip:port



```python=
p.send("ur_payload")
p.sendline("ur_payload")
```

> 傳送 `ur_payload` 給 process

> `send` & `sendline` 差別在於最後有沒有換行(`\n`)


```python=
p.sendlineafter(">",b'ur_payload')
p.sendlineafter(">",str(ur_payload))
```

> 在接收到 `>` 後傳送 `ur_payload` 給 process

:::warning
TODO: `b'a'` and `str(a)` 的差別 (一個是 send byte，一個是 send string)
:::

```python=
recv = p.recv()
recv = p.recv(N)
p.recvline()
p.recvuntil(b'w')
p.interactive()
```
> `p.recv()` 接收 process 的 data，並且把 data 交由變數 `recv` 管理

> `p.recv(N)` 設定接收 N 個 Bytes

> `p.recvline()` 接收一整行

> `p.recvuntil(b'w')` 接收 data 直到 `w`，假如 Process 發送的資料是 `hello,world`，那我們會接收到 `hello,w`

> `p.interactive()` 讓我們可以直接與 process interactive



### 


### pack and unpack

```python=
>>> p8(0)
b'\x00'
>>> p32(0xdeadbeef)
b'\xef\xbe\xad\xde'
>>> p32(0xdeadbeef, endian='big')
b'\xde\xad\xbe\xef'
```

> `p32` 就是把 data pack 成 32-bits 小端的資料型態

> `u32` 就是 `p32` 的 逆運算

> 如果要 pack 成 64-bits 就使用 `p64` & `u64`

### gdb attach

每次寫完 expolit 都自己爛掉，我都要額外 attach 上去看哪裡有問題 = =

```python=
gdb.attach(p)
# p 是你要 attach 上的 binary 實例
```
然後也可以下 `pause()`，然後 `gdb -p pid` attach 上去