首页 > 解决方案 > 如何编译带有额外代码洞穴的 C/C++ 程序?

问题描述

我想用代码洞穴做一些测试。给定一个 C 或 C++ 程序,我怎样才能让编译器(gcc、clang 等)在二进制文件中插入额外的代码洞穴?

(我不想直接在我的代码中添加后门,而是在编译后插入代码。)

标签: compilation

解决方案


这归结为在您想要放置任何有效负载的阶段拥有一块虚拟内存,它是a)可读+可执行和b)可写的。第二个约束决定了您根据需要在何处以及如何创建此类空间。

堆栈分配

如果你只是想在一个地方转储一点 shellcode 以在进程中运行,你可以简单地堆栈分配一个数组:

void my_vulnerable_function() {
    char foo[32];
    gets(foo);
}

为了使这可行,请确保使用传递给 GCC 的-fno-stack-protector标志-z execstack进行编译。您可能还想关闭 ASLR,以便您的堆栈位于可预测的位置。老实说,我从来没有尝试使用 clang 故意使程序不安全,所以我不知道在这种情况下你会使用什么标志。

内存映射区域

如果你想让一些东西更长寿,但在内存中,你可以mmap使用 rwx 访问的区域:

mmap(0, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

现在只需在其中编写一些代码,并在准备好时跳入其中。

可执行文件占位符

如果您想要可执行文件中的占位符是可执行的并且可以使用十六进制编辑器进行编辑,只需确保您的编译器发出对字符串文字的引用,即:

int main() { 
    char* copyright = "Copyright 2019 John Zhau. All rights reserved.";
    puts(copyright);
}

然后,您可以在 ELF 文件本身中修补该字符串的内容。您的程序将需要跳转到字符串中的地址(考虑到由 ASLR/ELF 加载执行的任何重定位)。这是一个简单的方法:

int main() { 
    char* copyright = "Copyright 2019 John Zhau. All rights reserved.";
    void (*foo)(void ) = ((void (*)(void)) copyright);
    foo();
    // or, more succinctly,
    (*(void(*)()) copyright)(); 
}

这会将指向字符串第一个字符的指针转换为指向函数的指针。通过该指针调用该“函数”将导致执行跳转到您的缓冲区——希望到那时它将具有有效的 shellcode。


推荐阅读