---
# System prepended metadata

title: pwntools
tags: [112-1]

---

pwntools
===

:::info
時間：9/26 19:00~21:00
地點：蘭潭校區 學活中心三樓 第三會議室
主題：pwntools


> [name=Curious]
:::

:::success
報名：[連結](https://forms.gle/F7o34NW6HG26qwtD8)
簽到：[連結]()
簡報：[連結](https://drive.google.com/file/d/1hotAmJ-0IMFZ0HmvG0VXWtyUt4s_VQmh/view?usp=share_link)
Lab：[連結](http://172.104.90.38)
Flag Format：`NCYU_HACKERS{.*}`
回饋：[連結](https://forms.gle/Aj4CC2QykH6H3KsLA)
:::

<!-- 以下區域開放共筆 -->

## 先備知識
### ASCII
#### 字元和數字相互轉換
- 用`chr(num)`把數字轉成字元
- 用`ord(char)`把字元轉成數字 
#### 數字只包含0~127


:::spoiler Welcome
先使用VScode
```python=
a = "78 67 89 85 95 72 65 67 75 69 82 83 123 87 51 108 67 48 77" #初始字串
a = "78 67 89 85 95 72 65 67 75 69 82 83 123 87 51 108 67 48 77 69 95 49 49 50 95 49 125"
# 分割成各個數字字串的 list
a = a.split()
# 把 list 中的元素轉成 int
a = [int(num) for num in a]
# 把 int 轉成 ASCII 對應的 char
a = [chr(num) for num in a]
# 把 list 中所有 char 合併成一個 str
a = ''.join(a)

print(a)
```
```python
# 講師想秀一行解決
a = '78 67 89 85 95 72 65 67 75 69 82 83 123 87 51 108 67 48 77 69 95 49 49 50 95 49 125'
a = ''.join([chr(int(num)) for num in a.split()])
print(a)
```
:::


### python
#### 執行方法
如何執行Python?
三種方法：執行檔案、Interactive Shell、Interactive Shell Pro
VScode(直接在VScode的terminal執行), ipython3, python3

還可以?
在Linux上用vim的指令建立一個python檔案`vim test.py`，在command line輸入`python3 test.py`，就可以執行惹 
如果不會vim的指令，可以自己上網查

#### Python 資料型別
int：整數
str：字串
bytes：位元組
> 可以用`type(obj)`來確認物件的型別
```python=
In [1]:type(1)
Out[1]:int

In [2]:type("Hello") #由字元組成
Out[2]:str

In [3]:type(b"Hello") #由數字組成，但顯示時如果該數字轉成字元可視就會以字元顯示
Out[3]:bytes
```

#### Python 資料轉換
- int -> str
- int -> bytes
- int -> hex
- int -> ASCII
```python=
In [1]:str(3)
Out[1]:'3'

In [2]:bytes([3]) 
Out[2]:b'\x03'

In [3]:hex(12)
Out[3]:'0xc'

In [4]:chr(97)
Out[4]:'a'
```

- str -> int
- bytes -> int
- hex -> int
- ASCII -> int
```python=
In [1]:int('3')
Out[1]:3

In [2]:b'\x03'[0]
Out[2]:3

In [3]:int('0xc', 16)
Out[3]:12

In [4]:ord('a')
Out[4]:97
```

- str -> bytes
- hex -> bytes
- int -> bytes
- int -> str -> bytes

> `encode()` string -> bytes
> `decode()` bytes -> string

```python=
In [1]:'Hello'.encode()
Out[1]:b'Hello'

In [2]:bytes.fromhex('437572696f7573')
Out[2]:b'Curious'

In [3]:bytes([7])
Out[3]:b'\x07'  #這裡儲存起來的數字是7

In [4]:str(7).encode()
Out[4]:b'7'     #這裡儲存起來的數字是55(查閱ASCII)
```

- bytes -> str
- bytes -> hex 
- bytes -> int
- bytes -> str -> int

> `encode()` string -> bytes
> `decode()` bytes -> string

```python=
In [1]:b'Hello'.decode()
Out[1]:'Hello'

In [2]:b'Curious'.hex()
Out[2]:'437572696f7573'

In [3]:b'\x07'[0]
Out[3]:7

In [4]:int(b'7')
Out[4]:7     
```


## PPC 介紹

- 指令 `nc <IP/Domain> <Port>`
通常拿來和指定的 IP 或 Domain 上的 Port 建立連線，透過 terminal 上的 stdin 和 stdout 來和 server 互動

>stdin -> 0
stdout -> 1
stderror -> 2

- 指令 `socat TCP-LISTEN:<Port>,fork EXEC:"<cmd>"`
將指定指令的服務綁到本機（127.0.0.1）的 Port 上，當這個 Port 收到 TCP 請求後，執⾏指定的 cmd


## pwntools
### 安裝說明
[感謝Curious的贊助](https://hackmd.io/@akvo-fajro/Pwntools_Installation_Guide)

### pwntools基本用法
```python=
from pwn import *

r = remote('172.104.90.38', 10000)

# Do something with r (remote object)

r.interactive()
```

### Remote object 方法總結
## Send Data:
- `r.send(payload)` 送出payload
- `r.sendline(payload)` 送出payload並換行
- `r.sendafter(p1, p2)` 接收到p1之後送出p2
- `r.sendlineafter(p1, p2` 接收到p1之後送出p2並換行

## Recv Data:
- `r.recv(n)` 接收n個bytes
- `r.recvuntil(payload)` 接收到payload為止
- `r.recvline()` 接收一行(但換行為止)
- `r.recvlines(n)` 接收n行

## Other:
- `r.interactive()` 切換到互動模式
- `r.close()` 關閉連線

:::spoiler PPC Lab-Welcome
Solve Script : 
```python=
from pwn import *

r = remote('172.104.90.38',  10001)

r.recvlines(8)

# str.strip()/bytes.strip() 是用來把 str/bytes 前後的空白和 bytes 清除掉的
# str.split(str)/bytes.split(bytes) 會去匹配指定的 str/bytes，然後以匹配到的作為分割點
num_list = r.recvline().strip().split(b' : ')[1].decode()
num_list = [int(num) for num in num_list.split()]
num_list.sort()

nth = int(r.recvline().strip().split(b' : ')[1])

r.sendlineafter(b'Answer >', str(num_list[-nth]).encode())

r.interactive()
```
:::

:::spoiler PPC Lab - Count
Solve Script : 
```python=
from pwn import *

r = remote('172.104.90.38', 10002)

r.recvlines(2)

for i in range(100):
    print(i)
    r.recvline()
    r.sendlineafter(b'> ', str(i + 1).encode())

r.interactive()
```
:::

### remote object error
- 卡死
通常是因為 recv 相關的參數錯誤，導致 server 已經發完訊息，但 Pwntools 還在監聽
- EOF
通常是因為程式錯誤，server 那邊把連線斷掉



<!--共筆結束-->

<!-- 如果你能夠把它變得更好看再修改code -->
<!-- 否則我會去找你 :D -->
<style>
    .navbar-brand::after{content: " x NCYU_HACERS"; }
</style>