昨天大致介紹了 CTF 的賽制,也順便帶到了打卡題,今天就來正式介紹 CTF 的題目類型,之後的幾天大家就可以根據標題寫的題目類型來決定要不要看文章了 (X)
跟 <獵人> 的念能力系統一樣,CTF 的題目類型也大致可以分成六個種類,如下圖:
system("/bin/sh")
某 crypto 大神曾經說過: 沒有 source 的 crypto 題目都是來鬧的
通靈
上面雖然歸納了六個類型,但題目和分類並不是 1-to-1 的關係,經常有題目是橫跨多個領域,像是:有些題目要先透過 reverse 看懂 crypto 的演算法才能解題、或是需要透過 web 手段才能觸發 overflow 等等,另外 CTF 進行時主辦方經常也會根據自己的特色而不一定按照上述的分類方式,像是 3XC3 CTF 就經常出 browser exploit 類型的題目,就會專門為他們開一個分類,近期 pwn 題也多出一些環繞於 shellcode 出題的題目,因此會幫題目分出 shellcode
的類型。
猜數字是個歷久不衰的經典遊戲,也應該算是我第一次解的 CTF 題目,同時也是交大某一年程式安全的第一個作業,由於當時原始題目和解題環境已經隨著時間流逝而不可考,因此我簡單描述一下題目和當時的解法 XD
程式碼大概是這樣:
int main()
{
srand(time());
int ans = rand() % 10000;
int n = 0;
for (int i = 0; i < 3; i++) {
printf("give me a number:")
scanf("%d", &n);
if (n == ans) {
printf("%s", get_flag());
return 0;
}
print_XAXB(num, ans):
}
return 0;
}
這題其實現在來看真的是超級簡單 XD 但對當時剛接觸的我還是想了很久,這題的問題在於透過 time()
來當 random seed 是有機會被預測的,但當時因為上課學的亂數寫法的是這樣寫,因此第一時間並沒有看出有什麼不對,不過跟一起修課的同學討論了一陣子,並透過 google 大神的指點之後,確定基於 time 來亂數產生方式不夠安全,因此有機會被利用,但對當時還是新手的我們來說,即使看出了這點還是不知道該怎麼解這題,最後想到的做法是:
雖然這題看起來簡單,但如今工作了一陣子,才知道還真的很多人會用這樣的方式來產生 random number....,即使不是用 time 來當 seed,也有些 RD 會 call 的程式語言內建的 random function,但卻沒搞清楚使用情境而採用了不夠安全的 PRNG
最後補充一下,如果要安全的拿到亂數,Linux 上唯一不可預測的亂數只有透過 /dev/urandom
取得,但由於讀取的 cost 相對大,通常會只拿個 4 byte 當做 srand()
的 seed,真正需要亂數時再用 rand()
得到亂數,細節在下一篇文章說明