###### tags: `程安` # CS 2019 Fall - Homework 0x07 ### [0x07] Casino++ * 先 checksec ``` NX : ENABLED --> 與Casino只差在這 ``` * 主要流程 ![](https://i.imgur.com/AEp2ZNd.png) * 詳細步驟 1. 將`puts@got`竄改成`casino()` * 因為`name`所在的區域以無法被執行,竄改`puts@got`成為這次唯一的突破口。 * 同時我們想保留這個跨界竄改的能力,於是我們將`puts@got`改成`casino()`。也就是說只要我們能猜對`lottery`觸發`puts`,就等於再 call 一次`casino()`,再獲得一次跨界竄改的機會。即上面那個流程圖的樣子。 * 有了這個無限竄改的能力,我們就能以同樣在`casino()`中會被呼叫的`srand()`當作目標進行 got hijacking,最終目標是 hijack 成`system`或 one_gadget 之類的 2. 確保`rand()`回傳值可被預測 * 剛剛提到會以`srand()`為目標做 got hijacking,那我們必須先確保隨後被呼叫的`rand()`回傳值是可被預測的,不然就無法猜對`lottery`進而無法再進行竄改 * 回傳值會放在`eax`,於是我們找看看有沒有直接指定`eax`的 gadget 可以用。但很可惜,沒有一個 gadget 是單純 `mov eax, ?` 之類的。 * 最後,我們選擇使用最單純的`ret`,也就是讓`rand()`等於沒做事。那`eax`呢?`eax`會保留原先的狀態,也就是`srand()`的回傳值。反正之後`srand()`會被我們改成別的 function,只要那個 function 的回傳值是可以預測的就好。 4. Information leak︰將`srand(seed)`竄改成`printf(atoi@got)` * 既然要使用 libc 中的`system`或 one_gadget,我們必須先知道 libc 的 base address。那我們就先將`srand(seed)`改成`printf(atoi@got)`,製造 information leak 1. `seed`改成`atoi@got` * 下一輪的`rand()` = `srand(atoi@got)`。但`srand()`本身是`void`,所以會是 0 2. `srand()`改成`printf()` * 下一輪的`rand()` = `printf(atoi@got)` = 印出多少個`char` = 6 (`"\x??" * 6`) 6. 開 shell︰將`srand(seed)`竄改成`system("/bin/sh")` * 這邊使用`system`的原因為較單純,而且這時一開始的`name`就可以拿來放的參數`"/bin/sh"`。 1. `seed`改成`&name` * 下一輪的`rand()` = `printf(name)` = 7 (`"/bin/sh"`) 2. `srand()`改成`system()` * 完成 :::success ![](https://i.imgur.com/Yz9yliT.png) :::