【问题标题】:Trying to execute any binary from c [closed]尝试从 c 执行任何二进制文件 [关闭]
【发布时间】:2016-02-10 14:52:47
【问题描述】:

我按照thread 来执行一些二进制代码。

tinky_winky 的答案,当我尝试执行另一个二进制文件时工作但没有工作。

比如我写了这个程序:

#include <stdio.h>
int main ()
{
   printf("Prueba\n");
   return(0);
}

用gcc编译(不带任何参数)然后把生成的二进制放到code变量上

char code[] = {0x7f,0x45,0x4c,0x46,0x02,0x01,0x01,0x00,0x00,...};

然后尝试编译新文件,但出现分段错误错误。

可以在 c(或 c++)中实际运行任何类型的任意代码,还是只能在裸 asm 代码中运行函数(如在原始线程中)?

【问题讨论】:

  • 事情远比你想象的要复杂。可执行文件包含的不仅仅是机器代码。为了执行可执行文件(二进制文件),操作系统将文件加载到内存中,并在实际执行代码之前做很多复杂的事情。

标签: c++ c gcc assembly


【解决方案1】:

它当然是特定于实现的,实际上取决于您的operating system 和处理器instruction set(以及ABIcalling conventions)。

(我猜并希望您使用的是 Linux;但您的问题不清楚)

在 Linux/x86_64 上,virtual address space 中的大部分内存不可 可执行(出于安全原因)。尝试使用strace(1) 运行您的程序以了解相关的系统调用。同时使用调试器gdb。您可能需要使包含二进制代码的段可执行,例如与mprotect(2)。如果您的进程是 1234,请在其他终端尝试cat /proc/1234/maps(以查询其虚拟地址空间)。阅读更多关于proc(5)的详细信息。

也许您应该考虑JIT compilation 技术和库,如asmjitGCCJIT 等...

顺便说一句,ELF 的可执行文件非常复杂,并且不以可执行的machine code 开头。另请阅读elf(5)。使用 objdump(1)readelf(1) 探索和理解 ELF 可执行文件。这或许可以解释您的实验失败的原因(但我们不知道您是如何获得 char code[] = {0x7f,0x45,0x4c,0x46 的……这几个字节看起来像一些 ELF 标头)

如果您想继续,您可能应该小心从您的 ELF 可执行文件中提取一些函数(即它们的机器代码和数据)并处理 relocations(和 name mangling,对于 C++)你的实验。在Linkers & Loaders 上阅读 Levine 的书会很有帮助。

【讨论】:

    【解决方案2】:

    你可以运行这样的十六进制代码,但是你不能得到一个未经修改的可执行文件。有用于操作系统的文件前缀,而不是汇编操作码。

    【讨论】:

    • 请澄清“文件前缀”。哪些操作系统使用文件前缀?
    • @ThomasMatthews 了解 ELF (Linux) 或 PE (Windows) 文件格式。除了真正的可执行指令外,开头还有带有可执行信息的结构。简而言之,它可以称为“前缀”。你同意吗?
    【解决方案3】:

    我假设这是在您的个人电脑或笔记本电脑或您正在阅读此网页的任何计算机上。每个程序都无法在内存中运行任意代码,甚至无法访问其空间之外的代码。你有一个程序,你有一个数组中的数据,你可能知道它是指令,但操作系统和编译器等知道是数据。因此,您必须与操作系统交谈以请求它允许您执行该代码。在 stackoverflow 或网上搜索自我修改代码。如果在 linux 上运行,可能想使用 mmap()。

    【讨论】:

    • 例如,如果在微控制器上运行裸机,那么您可以简单地分支到指令数组,它应该可以正常工作(只要它们正确对齐并且实际上是正确终止的指令或以循环结束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 2019-05-14
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多