# **Pwntools學習筆記**
###### Date: `2023/01/01`
## :memo: 何謂 pwntools ?
* pwntools是一個CTF框架和漏洞利用開發套件。
* ==用Python開發==。
* 旨在讓使用者簡單快速的編寫exploit(漏洞利用)。
## :memo: 匯入 pwntools 套件
```python=
from pwn import *
```
## :memo: pwntools 連接方式
### 1.透過 nc 連接 (明文傳送)
**格式**:連線名稱 = `remote(‘IP address‘, port)`
**範例**:conn = `remote(‘140.110.112.195‘, 2400)`
### 2.透過 ssh 連接 (密文傳送)
**格式**:連線名稱 = `ssh(host=‘IP address‘, user=‘XXX’, port=???, password=‘XXXXX’)`
**範例**:`shell = ssh(host='192.168.14.144', user='root', port=2222, password='123456')`
## :memo: pwntools 傳送及接收數據函數
### 傳送:
* `send(payload)`:發送payload(需為字串)
* `sendline(payload)`:發送payload,並換行(末尾\n)
* `sendafter(some_string, payload)`:接收到 some_string 後, 發送 payload
* `sendlineafter(some_string, payload)`:接收到 some_string 後, 發送 payload並換行
* **範例:**`conn.sendline(ans.encode())` # 將ans轉換成Byte 字串傳送至連接端
### 接收:
* `recvn(N)`:接受 N 個字元
* `recvline()`:接收一行資料
* `recvlines(N)`:接收 N 行資料
* `recvuntil(some_string)`:接收到 some_string 為止
**範例:**
* `conn.recvline()`:從連接端接收一行資料
* `conn.recvlines(7)`:從連接端接收七行資料
* `conn.recvuntil(b’answer: ’)`:從連接端接收資料,直到 ’answer: ’字串
## :memo: pwntools 連接送出答案後,取得flag方法
1. `interactive()`:與 shell 互動,輸入 logout 離開連接端 shell
**範例:**`conn.interactive()`:回到 shell,可取得 flag
2. 用 `recvline()`:接收 flag 後再印出
**範例:** `aaa = conn.recvline()`:將接收的 flag 存到 aaa 變數
`print(aaa.decode())`:將 aaa 變數轉成字元字串再輸出至螢幕上
3. 最後加上```close()```關閉連結
**範例:** ```conn.close()```:關閉連結
:::warning
:bulb:透過 python 的 `remote()` 函數連線,傳送接收資料皆為本機程式與連接端之間傳遞,不會於螢幕上顯示過程
:::
## :memo: 練習題1:count
### 題目:
* 題目說1就輸入1,說2就輸入2,以此類推。

### 我的程式碼:
```python=
from pwn import *
r = remote('140.110.112.214', 2403)
r.recvlines(3)
for i in range(100):
r.recvlines(2)
r.sendline(str(i+1).encode())
r.interactive()
r.close()
```
### 解題心得:
* 透過題目給的網址進行nc連線,開一個python檔,完成程式碼執行後,發現有錯誤,檢查後發現原來是程式碼中的網址輸入錯誤導致!修正後即成功獲得標籤(倒數第三行)。
## :memo: 練習題2:3rd
### 題目:
* 從題目給的數據中找出第三大的數。

### 我的程式碼:
```python=
from pwn import *
r = remote('140.110.112.214', 2400)
r.recvlines(7)
r.recvuntil(b'numbers : ')
l = r.recvline()
num = [int(x) for x in l.split()]
num.sort(reverse=True)
print(num[2])
r.recvuntil(b'answer : ')
r.sendline(str(num[2]).encode())
print(r.recvline().decode())
r.interactive()
r.close()
```
### 解題心得:
* 把題目給的數據存到一個list裡面,再透過排序即可找到第三大的數字為何!
## :memo: 練習題3:beautify
### 題目:
* 把題目給的字串中'-'或'_'轉換成' ',並且整句轉為小寫。

### 我的程式碼:
```python=
from pwn import *
r = remote('140.110.112.214', 2401,level='debug')
r.recvlines(8)
r.recvuntil(b'sentence : ')
s = r.recvline()
s = s.replace(b'-',b' ')
s = s.replace(b'_',b' ')
s = s.lower()
r.sendlineafter(b'answer : ',s)
r.interactive()
r.close()
```
### 解題心得:
* 一開始字串前面忘記加上'b'導致出現type error,以後要記得將字串前面加上'b'轉成byte字串。
* 在port後面加上```level='debug'```可以在執行時顯示過程,方便除錯。
## :memo: 練習題4:calender
### 題目:
* 判斷閏年

### 我的程式碼:
```python=
from pwn import *
a=remote('140.110.112.214',2402,level='debug')
a.recvlines(9)
for i in range(100):
a.recvline()
a.recvuntil(b'year : ')
b=a.recvn(4)
b=int(b)
if b%4 == 0:
if b%100 == 0:
if b%400 == 0:
a.sendlineafter(b'answer : ','leap')
else:
a.sendlineafter(b'answer : ','ordinary')
else:
a.sendlineafter(b'answer : ','leap')
else:
a.sendlineafter(b'answer : ','ordinary')
a.interactive()
a.close()
```
### 解題心得:
* 判斷閏年題目之前用C++寫過,所以這題比較容易!
## :memo: 練習題 5 money:
### 題目:
* 計算本金加上利率的結果。

### 我的程式碼:
```python=
from pwn import *
r = remote('140.110.112.214', 2407,level='debug')
r.recvlines(8)
for i in range(100):
r.recvline()
r.recvuntil(b'money : ')
o = r.recvline()
o = int(o)
r.recvuntil(b'interest : ')
p = r.recvline()
print(p)
p = p[:-2]
print(p)
p = int(p)
o = o+o*(p/100)
o = int(o)
r.sendlineafter(b'answer : ',str(o))
r.interactive()
r.close()
```
### 解題心得:
* 送出的結果要是字串。
* p有可能為小數,要轉整數。
* p接收時接收到換行和%,所以要去掉!
## :memo: 練習題 6 id:
### 題目:
* 規則⼀ : 開頭會是⼤寫的英⽂文字⺟ A-Z
* 規則⼆ : 後面接著 9 個數字
* 規則三 : 9 個數字的總和要是 3 的倍數

### 我的程式碼:
```python=
from pwn import *
r = remote('140.110.112.214', 2406,level='debug')
r.recvlines(14)
for i in range(100):
r.recvline()
r.recvn(5)
o = r.recvline()
o = o[:-1]
ans = True
if 'A'<=chr(o[0])<='Z': ans = True
else: ans = False
print(chr(o[0]), ans)
if len(o)!=10:
ans = False
o = o[1:]
sum = 0
for i in o:
i = int(i)
sum+= i
if sum % 3!=0:
ans = False
if ans == True:
p = b'valid'
else:
p = b'invalid'
r.sendlineafter(b'answer : ',p)
r.interactive()
r.close()
```
### 解題心得:
* 在寫這題後我學習到要判斷一個數字是否介在A到Z之間要用```chr```轉字元,不能用```str```,因為把一個文字母的ASCII碼轉成字元才能做比較!
## :memo: 練習題7:tros
### 題目:
* 把題目給的字串依照Z到A排序,一百筆測資。

### 我的程式碼:
```python=
from pwn import *
r = remote('140.110.112.214', 2409,level='debug')
r.recvlines(5)
for i in range(100):
r.recvline()
r.recvn(7)
o = r.recvline()
o = o[:-1]
l = []
for y in o:
l.append(y)
l.sort(reverse=True)
r.recvn(9)
for j in l:
r.send(chr(j))
r.sendline()
r.interactive()
r.close()
```
### 解題心得:
* 利用ASCII碼由大到小排序儲存到一個List,在依序由排序過的list中取出答案。