2.
我設 breakpoint 在 line 9 ,並且在 run 之後輸入 x/40bx $rbx
來取得
3.
在 call one 的時候會把 return address push 進去 stack 。在 one 裡面,我們用 pop rbx
把 return address 放到 rbx 裡面,我們的 return address 是指向 two 的/bin/sh
,因此我們可以把它 mov [rbx+8], rbx
放到 rbx + 8 的位置,就是我們在 two 那邊預留的 db ’AAAAAAAA’
,因此我們就成功把 /bin/sh
放到 argv[0]
。接著由於 rax 是存 0 ,我們把它放到 mov [rbx+16], rax
rbx + 16 這個位置,記事我們在 two 那邊預留的 db ’BBBBBBBB’
,因此我們就成功把 0
放到 argv[1]
。
In conclusion, line 12 mov [rbx+8], rbx
and line 14 mov [rbx+16], rax
set the values for argv[0]
and argv[1]
, respectively.
4.
mov rdi, rbx
和 lea rsi, [rbx+8]
代表的是把數值帶入 execve 的參數裡。rdi
代表第一個參數, rsi
代表第二個參數,我把 rbx
這個 /bin/sh
放入第一個參數,再把 rbx+8
也就是 argv 的記憶體位置用 lea
放進去第二個參數。
mov rax, 0x00
, mov rdx, 0x00
, mov rax, 59
這三個會有 0 。
第一種方式(jmp-call-pop)把所有字串資料集中放在程式碼段後方,透過 call 跳回來取得位址,用偏移量組成參數,整體看起來更簡潔、邏輯集中,也比較接近實際 exploit 用的 shellcode 結構。相比之下,第二種方式則是直接在堆疊中逐步組裝字串與參數,較為繁瑣且容易出錯,雖然直觀,但閱讀上較混亂。整體來說,我喜歡第一種,因為資料集中、邏輯清楚且維護起來比較輕鬆。
我比較喜歡第一種方式,因為它使用 jmp-call-pop 技巧讓資料和程式碼分離,架構清楚,且利用偏移量操作記憶體可以讓整體邏輯更集中易讀。相較於第二種手動 push 每一段字串、需要注意對齊與順序,第一種方式更有系統,也更像實際 shellcode 的寫法。
system()
的地址是 0xf7dbf760
exit()
的地址是 0xf7dabd00
_exit()
的地址是 0xf7e54170
/bin/sh
address is 0xffffd60f
助教你敢相信嗎,我的 exit() 的記憶體位置最後是 00 ,所以 strcpy 會失敗,我想說我運氣真的太差了,所以我到 digitalocean 上重新開一個 vps ,並且重新安裝 seedlab ,結果又一樣,是 00 結尾。
最後我想到可以改用 _exit()
,exit() 也是呼叫 _exit()
,只是會把 file stream 關掉而已,所以我改用這個,我真的不想再開一個 vps 了。
也是可以攻擊,只是因為沒有給它 exit()
的記憶體位置,所以當 system()
結束時會跳到不知道哪個地方,而造成 segmentation fault ,就像 L 紀上課說的,會比較丑而已,不然沒關係。
會失敗,因為我們的 /bin/sh
的記憶體位置為變,當我們的檔案長度不一樣的時候,這個 L 紀也講過,也在前面的 seedlab 有提到,所以老師上課才會取名 env55
,確保檔案名稱長度一樣。
execv()
address is 0xf7e54b40
將程式在溢位後的 return address 改為指向 libc 裡的 execv 函式,並在 stack 上準備好 execv 所需要的參數。首先在輸入資料中擺上 /bin/bash 和 -p 的字串,接著在這些字串之後建立一個 argv 陣列,內容包含 /bin/bash、-p 的地址以及 NULL。這些資料會因為被寫入到 main 的 input buffer,而存在記憶體的某個位置,我們可以預測它們的地址並填入給 execv 使用。最後,透過 overflow 改掉 return address,讓程式回傳後跳到 execv,並且傳入準備好的字串與 argv 陣列位置,成功執行 /bin/bash -p 而不會掉權,取得 root shell。
成功了
foo()
的地址是 0x5655623c
_exit()
的地址是 0xf7e54170
參考老師上課寫的 code
盡力了,我的電腦是 msi 的,我打算直接用我電腦的 bios 做,但我實在找不到 NX bit 要在哪 disable 。
https://www.youtube.com/watch?v=E22LPY8GlHI
https://www.youtube.com/watch?v=IzAnxcr6WRI
https://www.youtube.com/watch?v=Pp3QfVGBbFo
https://www.youtube.com/watch?v=zL5KZVS6vxA
https://forum-en.msi.com/index.php?threads/nx-bit-in-bios.262039/
https://download-2.msi.com/archive/mnu_exe/mb/AMDAM5BIOStc.pdf
我也查閱了很多資料,但我這款就是找不到在哪裡關
我有看到 advanced CPU configuration ,但是點進去,沒有可以關的地方,我也嘗試過查詢的方式,右上角那個按鈕,但是輸入相關字眼,execution
, NX
, bit
,依然無果。
因此這題我就查了相關資訊,並且給出判斷,我認為如果從 BIOS 那邊把 NX bit disable 掉,我們就可以直接在 stack 和 heap 上執行,而不用加上 -z execstack
。
我也附上我在這題用到的程式碼:
stack_shellcode.c
heap_shellcode.c
如果成功執行,我們就可以得到一個 shell 。
我們編譯過後的執行檔叫做 test
-g
參數.rodata
-g
的,所以再加一個這題是 https://blog.ch3nyang.top/post/seedlab_return2libc/ 的 Task 5 教我寫的,不是我自己想出來怎麼寫的。
攻擊 seedlab 提供的 retlib.c
/bin/sh
address is 0xffffd610
setuid()
address is 0xf7e75f10
_exit()
address is 0xf7e54170
system()
address is 0xf7dbf760
sprintf()
address is 0xf7dcd550
leave
address is 0x5655622a
ebp_bof
address is 0xffffcfb8
foo()
address is 0x5655622c