Winesap's Blog

Codegate CTF Preliminary 2015

| Comments

這次摸到的題目有 systemshock, sokoban, icbm 和 bookstore,都是 pwnable
其實重點是吐槽 sokoban... 他的精美程度讓我想到以前打 ACM 時某賽 (?) 的題目風格
要說的話大概是個 input n = 100000,結果官方解是 O(n!) 之類的吧

systemshock

經典 stack overflow,輾掉 argv 後讓 strlen(argv[0]) = 0,所以原本用來檢查 argv[0] 的迴圈不會作用。
之後可以注入 ;system() 去。

strcat(dest, argv[1]); // overflow & overwrite argv @ [rbp-140h]
for ( i = 0; i < strlen(argv[1]) + 3; ++i )
{
  v3 = (*__ctype_b_loc())[dest[i]];
  if ( !(v3 & 8) && dest[i] != ' ' )
    goto FAIL;
}
system(dest);

sokoban

我覺得這題完全就瞎爆了 = =
雖然前面的漏洞還算藏得不錯

一般的關卡都有設邊界,移動時雖然沒有檢查但不會出界。
但一開始計算關卡總數不正確,會多出 1。
所以在隨機選關時有機率抽到超出範圍的這一關,會是空白盤面。
所以可以走出盤面範圍,然後原本推箱子的功能可以把一個非零 byte 推到一個相鄰的位置上 (+32, -32, +1, -1)

接下來利用的方式就瞎了...
預期的目標是看能不能跳到 0x401A9A 並且先把 eax 設為 1,這樣接下來會執行 sub_401678() 印出 flag。
但只能修改一個 0 byte 這樣的漏洞超級難用... 最後唯一可以利用的是修改 rand() 在 .got.plt 的值:

  1. rand() 的 offset@libc 是 0x3d060,在 ASLR 下有 1/16 的機會隨機到 ?0060,這個 0 byte 位在 0x60C121
  2. 0x3e260@libc 是一個神奇的 gadget: add rsp, 0x28; (pop XX)*6; ret
  3. rand() 在重新隨機盤面時會被呼叫,然後 rsp 偏移 0x58 byte 的結果是... stack 頂端的值剛好是原本要 return 回 0x401A9A 的這個位址
  4. 更瞎的地方是,有個隱藏的功能: 按 v 鍵可以把 0x60C121 處的值加 0x12。看來沒什麼用,不過 e260 和 d060 剛好差 0x12 ... 所以如果補成 1260 的話剛好可以跳到這個 gadget
.got.plt:000000000060C110 off_60C110      dq offset rand

.bss:000000000060C8E0 ; char board[640]
.bss:000000000060C8E0 board           db 280h dup(?)    

    3e260:       48 83 c4 28             add    rsp,0x28
    3e264:       5b                      pop    rbx
    3e265:       5d                      pop    rbp
    3e266:       41 5c                   pop    r12
    3e268:       41 5d                   pop    r13
    3e26a:       41 5e                   pop    r14
    3e26c:       41 5f                   pop    r15
    3e26e:       c3                      ret

另外,在 'press any key' 時送 '\x00' 可以把 eax 設為 1,_wgetch()rand() 前最後一次改到 eax 的地方。總之一切都是完美的巧合。

icbm

前半段是個簡單的 format string + buffer overflow。
後半段是個 crypto,控制 CBC AES 的 IV,如果成功造出 '\xeb\xfe' 就會卡住,用這種方式暴出 IV。

bookstore

洞是皮皮找的,不過基於比較利益原則我寫了 exploit。
大致上是 book[20] (0-based) 和某個暫存 book 重疊了,然後改一改可以 leak 出某個 function pointer 解出 code base address。再改一改可以反過來寫掉 function pointer,總之先寫成 printf(name) 弄成 format string 漏洞就對了。

Comments

comments powered by Disqus