iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0

前言

沒開玩笑,真的要猜拳。
今天選的是 picoCTF 的 RPS,本來以為是什麼 per second,點進去看才知道是 rock, paper, scissors,總之來猜拳吧 XD

Write-up

I hear something good happens if you win 5 times in a row.

題目說要我們連贏五次,應該是可以拿到 flag 吧,我們先連看看題目:
https://ithelp.ithome.com.tw/upload/images/20231013/20162615NQh5KuyqpS.png

一開始先選擇 1 開始遊戲,然後打 rock/paper/scisssors 來猜拳。並且時間到還會被踢下線 XD
https://ithelp.ithome.com.tw/upload/images/20231013/20162615925AJoDFpx.png

接著來看程式碼,從 main() 開始看,會看到呼叫了 tgetinput() 來取得 user 的輸入,tgetinput() 中有一行比較特別的:

ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);

這邊使用了 select(),查詢了一下發現是一個 syscall,用途是在多個 file descriptor (e.g. stdin, stdout, socket) 中選擇一個或多個進行操作(讀/寫),還可以設定 timeout ,剛才我被踢下線應該就是這個地方造成的。

我們再往後看會看到 read_bytes = read(0, input, l-1);,可以發現傳進 tgetinput() 的第二個參數 l 是讀取的長度,因此我們在輸入猜拳時的允許長度是 100,總之雖然看起來蠻多行,但這個 function 都是在處理輸入。

接著看 play(),判定輸贏的方式是用尋找字串的方式,我們直接舉個例子:
假設電腦出布,我們如果出剪刀會贏布,程式會在我們的輸入中尋找 scissors 的字串,聽起來好像很合理?

有沒有發現可以打的點?

老實說,一開始的思路走的是找什麼 overflow 之類的,但一無所獲。靜下來思考一下,跟朋友玩猜拳時,偶爾耍白爛想說只要一手出一個,有一手贏的機率就高很多。啊這題好像可以一次出三種耶 XD

程式檢查的邏輯是在輸入中找尋可以贏的那個的字串,並且大小限制是 100,那我們三個都出呢?
https://ithelp.ithome.com.tw/upload/images/20231013/20162615CSxJvrNJdX.png

果然是這樣 XD,雖然可以用複製貼上大法,這邊還是寫個 exploit 給它個尊重:

from pwn import *

p = remote("saturn.picoctf.net", 62039)
context.log_level = "debug"

payload = b"rock/paper/scissors"

for i in range(5):
    p.sendlineafter("exit the program", b"1")
    p.sendlineafter("(rock/paper/scissors):", payload)
flag = p.recvuntil(b"}")
print(flag)

後記

看來有時候漏洞不見得需要用高深的技巧來挖掘,也有可能只是一些邏輯不夠縝密,算是學到一課 XD


上一篇
Day 28. Pwn - Buffer Overflow 實戰
下一篇
Day 30. 參賽心得 & Pwn 學習資源
系列文
進了資安公司當後端 RD 才入門資安會不會太晚了30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言