###### tags: `程安` # CS 2019 Fall - Homework 0x08 ### [0x08] EDU 2019 election * 先 checksec : 不意外的全開 * 關鍵點 * ![](https://i.imgur.com/PTe5gWI.png) * 位置︰`main()` * 可以利用這邊來猜出 canary 和`__libc_csu_init`的 address * 避免`__stack_chk_fail`和推算出 PIE base address * 同時`buf`位於 data segment,可以作為之後要 stack migration 的地方 * ![](https://i.imgur.com/MTAiW9e.png) * 位置︰`voting()` * `candidates.votes`為`uint8_t`,最大值為 255 * 在`votes = 255`時,覆蓋`old rbp`和`return address`來進行 stack migration * 其他細節 * 由於我們一開始只有 PIE base address,所以我們還要再 leak libc base address * 拿到 libc base address 之後,我們要找一個地方寫我們最後的`one_gadget`,然後再 migrate 過去。但這裡會遇到一個問題,如果要用`read()`,就需要一個能控制`rdx`的 gadget,這時候就需要用到`ret2csu` * payload︰![](https://i.imgur.com/Xu5wm3i.png) :::success ![](https://i.imgur.com/39pD9gv.png) ::: --- ### [0x08] Note++ * off by one * ![](https://i.imgur.com/uZ4KzqN.png) * 這裡的`scanf`會自動多一個`'\0'`在`description`的後面 可以把下一個`notes`的`is_freed`蓋成`false` * 只能用 fastbin * ![](https://i.imgur.com/pZ3641d.png) * 這邊被限制大小了QQ * 但為了拿到 libc base address,我們必須要想辦法弄到一塊不歸類為 fastbin 的 chunk 然後 uaf 他來 leak address --- #### 流程 :::info * writeup 參考︰["Halcyon Heap"](https://ctftime.org/writeup/14625) * 方格︰notes array * 綠色︰`is_freed = 0` * 橘色︰`is_freed = 0` by `scanf` off by one * 紅色︰`is_freed = 1` * 圓圈︰chunk ::: * 因為只能用 fastbin,所以先想辦法弄出 heap address,之後想辦法 heap overlap * 弄成下面的樣子之後就可以藉由`list()`來 leak C 的位置,反推出 heap base address。順便把`notes[1]`弄成`is_freed = 0`等等會用來 double free B ![](https://i.imgur.com/0aAQ5hN.png) * 捏造一個可以拿來 free 掉而且會進 unsorted bin 的 chunk * 先用 fastbin attack,捏造一個歪掉的 chunk 用來改寫別的 chunk 的 header ![](https://i.imgur.com/nYRWrZq.png) * 中途拿到 A 的時候順手幫 A+0x10 捏造 size,拿到 C 的時候也要準備一下等等用來 bypass security check (這個 C 的拿法要用 double free 的方式再拿回來,因為他原本已經從 fastbin list 上消失了) ![](https://i.imgur.com/lvHRhSt.png) * 拿到 A+0x10,並在最後 16bytes 與 B header 重疊的部份串改 B 的 size 成 0x90。再多要一塊 D 來確保等等 free B 的時候不會被 check 到 ![](https://i.imgur.com/JcLEMGX.png) * 前面準備工作都做好後就可以 free B 來 leak libc base address 了! ![](https://i.imgur.com/ZcpbHz6.png) * 後面就是跟`[lab] Note`一樣去把`__malloc_hook`改成 one_gadget * 但很可惜的,沒有一個 one_gadget 可以用。 那就試著像上課的時候一樣,在`free()`噴錯的時候觸發 one_gadget 因為 heap 已經被我搞亂,我就 free 掉一個會壞掉的 chunk 來試試 結果就 get shell 了 XD :::success ![](https://i.imgur.com/7thMlbD.png) :::