在上一篇文章《進程切換的本質是什么?》中舉了一個示例,也就是這段代碼:
void funcC() {
printf("jump to funcC !!!\\n") ;
exit(-1) ;
}
void funcB() {
long *p = NULL ;
p = (long*)&p ;
*(p+2) = (long)funcC ;
}
void funcA() {
funcB();
}
int main() {
funcA() ;
return 0 ;
}
有同學問不能在自己的機器上復現,并給出了編譯后的機器指令:
00000000004005ee
: 4005ee: 55 push %rbp
4005ef: 48 89 e5 mov %rsp,%rbp
4005f2: 48 83 ec 10 sub $0x10,%rsp
4005f6: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
4005fd: 00 00
4005ff: 48 89 45 f8 mov %rax,-0x8(%rbp)
400603: 31 c0 xor %eax,%eax
400605: 48 c7 45 f0 00 00 00 movq $0x0,-0x10(%rbp)
40060c: 00
40060d: 48 8d 45 f0 lea -0x10(%rbp),%rax
400611: 48 89 45 f0 mov %rax,-0x10(%rbp)
400615: 48 8b 45 f0 mov -0x10(%rbp),%rax
400619: 48 83 c0 10 add $0x10,%rax
40061d: ba d6 05 40 00 mov $0x4005d6,%edx
400622: 48 89 10 mov %rdx,(%rax)
400625: 90 nop
400626: 48 8b 45 f8 mov -0x8(%rbp),%rax
40062a: 64 48 33 04 25 28 00 xor %fs:0x28,%rax
400631: 00 00
400633: 74 05 je 40063a
400635: e8 66 fe ff ff callq 4004a0 <__stack_chk_fail@plt>
40063a: c9 leaveq
40063b: c3 retq
仔細看這段代碼,有這樣一段可疑的指令:
mov %fs:0x28,%rax
mov %rax,-0x8(%rbp)
這兩行指令將fs:[0x28] (段尋址的方式)處的值push到了調用棧上(%rbp偏移8字節),并在函數即將返回的時候又檢查了一遍該值有沒有被修改:
mov -0x8(%rbp),%rax
xor %fs:0x28,%rax
接下來如果保存到棧上的值不等于fs:[0x28]處的值(xor指令進行比較)那么跳轉到__stack_chk_fail函數,我們的疑問是為什么要有這么一遍檢查呢?
本質上我們在開頭給出的代碼相對于緩沖區溢出攻擊,做法是修改上一個棧幀的返回地址,將其修改為某個特定地址(黑客希望跳轉到的地方);
在開頭的這段代碼中本來funcA函數調用完funcB后需要返回funcA,但在我們的“精心”設計下調用完funcB后卻跳轉到了funcC ,那么我們有沒有辦法防范這種攻擊呢?
答案是肯定的,這種方法要追溯到很久很久以前。
在上世紀初,煤礦開采是一項很危險的工作,因為煤礦中的有毒氣體通常極難被人類察覺,這給礦工的生命帶來很大的威脅,而金絲雀對毒氣非常敏感,這樣礦工可以利用金絲雀來監控礦區,從而提早發現險情。
這里也是一樣的道理,我們可以在棧區中放置一個“金絲雀”(fs:[0x28]處的值):
當函數返回時我們會再次拿fs:[0x28]處的值與棧上的“金絲雀”進行對比, 一旦發現這兩個值不同我們就可以認為當前的棧已經被破壞了,由于棧上的數據已然不可信,因此我們必須及早撤離礦區 ,也就是調用__stack_chk_fail函數提前終止進程。
而金絲雀也就是fs:[0x28]是隨機產生的(每次程序運行時都不一樣),因此攻擊者很難提前知道該值是多少。
當然我們也可以看到,添加堆棧保護功能需要增加額外的機器指令,這些也會稍稍對性能產生影響,代價就是需要額外多執行一部分機器指令。
這就是編譯器的堆棧保護功能,當然這個功能也是可以去掉的,編譯時添加-fno-stack-protector編譯選項(在這里感謝小風哥微信技術群里同學的提示),這樣即可關閉堆棧保護功能,生成的代碼就可以復現上一篇文章《進程切換的本質是什么》中提到的效果了。
怎么樣,想成為黑客還是沒那么容易吧,就好比只有真正理解法律才能鉆空子一樣,只有真正理解計算機的工作原理才能hack它,當然,想成為頂尖黑客只有對計算機的理解還不夠,你還需要有想象力。
-
緩沖區
+關注
關注
0文章
33瀏覽量
9107 -
堆棧
+關注
關注
0文章
182瀏覽量
19753 -
代碼
+關注
關注
30文章
4779瀏覽量
68524
發布評論請先 登錄
相關推薦
評論