使用 mmap 在共享内存中执行 shellcode

Executing shellcode in shared memory with mmap

我正在尝试将程序代码放入共享内存区域并执行。初始化和分配共享内存以及将 shellcode 复制到 "new" 内存中按预期工作,但一旦我尝试执行它,它就不起作用。有人知道问题出在哪里吗?

我认为 write(1, 0x6000d8, 13) = -1 EFAULT (Bad address) 可能是错误?可能是什么原因造成的?

我包括了代码和错误输出。 C 代码基于 Adam Rosenfield in this Question.

的答案

C 代码

#include <string.h>
#include <sys/mman.h>

// My own shellcode, obtained through objdump
// works on its own (a hello world-program)
const char shellcode[] = "\xb8\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x48\xbe\xd8\x00\x60\x00\x00\x00\x00\x00\xba\x0d\x00\x00\x00\x0f\x05\xb8\x3c\x00\x00\x00\xbf\x00\x00\x00\x00\x0f\x05";

int main(int argc, char **argv)
{
    void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

    memcpy(mem, shellcode, sizeof(shellcode));

    mprotect(mem, sizeof(shellcode), PROT_READ|PROT_WRITE|PROT_EXEC);

    int (*func)();
    func = (int (*)())mem;
    (int)(*func)();

    munmap(mem, sizeof(shellcode));

    return 0;
}

Strace 日志

execve("./memory", ["./memory"], [/* 17 vars */]) = 0
brk(NULL) = 0x557b5e17e000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb8ba434000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=92611, ...}) = 0
mmap(NULL, 92611, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb8ba41d000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "7ELF[=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=]>[=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=][=11=]"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1856752, ...}) = 0
mmap(NULL, 3959200, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb8b9e4c000
mprotect(0x7fb8ba009000, 2097152, PROT_NONE) = 0
mmap(0x7fb8ba209000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7fb8ba209000
mmap(0x7fb8ba20f000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb8ba20f000
close(3) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb8ba41b000
arch_prctl(ARCH_SET_FS, 0x7fb8ba41b700) = 0
mprotect(0x7fb8ba209000, 16384, PROT_READ) = 0
mprotect(0x557b5dd04000, 4096, PROT_READ) = 0
mprotect(0x7fb8ba437000, 4096, PROT_READ) = 0
munmap(0x7fb8ba41d000, 92611)           = 0
mmap(NULL, 40, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fb8ba433000
mprotect(0x7fb8ba433000, 40, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
write(1, 0x6000d8, 13) = -1 EFAULT (Bad address)
exit(0) = ?
+++ exited with 0 +++

shellcode的来源

section .data
    msg db      "hello, world!"

section .text
    global _start
_start:
    mov     rax, 1
    mov     rdi, 1
    mov     rsi, msg
    mov     rdx, 13
    syscall
    mov    rax, 60
    mov    rdi, 0
    syscall

将建议的副本应用于您的代码

当您注入此 shell 代码时,您不知道消息中的内容:

mov     rsi, msg

在注入过程中,它可以是任何东西,但不会是"Hello world!\r\n",因为它在.data section

section .data
    msg db      "hello, world!"

而您只转储了 .text 部分。

您可以看到您的 shell 代码没有 "Hello world!\r\n" (\x68\x65\x6c\x6c\x6f....)