【问题标题】:C : running a compiled function from ramC:从 ram 运行编译函数
【发布时间】:2017-01-02 18:55:54
【问题描述】:

我正在做一个项目,我需要将一个简单的exe 文件加载到缓冲区,然后从内存中调用exe 文件的入口点。

我知道我无法加载和运行一个非常复杂的 exe 文件,它有很多来自缓冲区的依赖项,但我认为它可以调用 exe (PE) 文件的独立函数(如空主文件)。

为此,我必须找到 exe 文件的入口点地址(它的偏移量),然后将该地址(现在加载到缓冲区中)转换为指向函数的指针,然后调用它,它可能会调用 ram 中加载的函数,但我不知道如何找到地址。

这是我到目前为止所做的:

int main(){

    void (* function)();
    unsigned char* buffer;
    FILE* fp;
    size_t size;
    char* path = "address of the file";
    fp = fopen(path, "rb");
    fseek(fp, 0, SEEK_END); 
    size = ftell(fp);         /*calc the size needed*/
    fseek(fp, 0, SEEK_SET); 
    buffer = (unsigned char *) malloc(size);
    fclose(fp);

    /*problem : i have to sum the buffer address with that offset here*/
    function = (void (*)())(buffer);

    function();

    return 0;
}

我认为从代码中可以清楚地看出我在做什么。

这是一个尝试为meterpreter 做同样事情的链接(想法是一样的):

https://github.com/rsmudge/metasploit-loader/blob/master/src/main.c

我将不胜感激。

谢谢

【问题讨论】:

标签: c memory-address


【解决方案1】:

您很可能试图解决错误的问题。如果您使用的是操作系统(例如 Windows 或 Linux),那么最简单的方法就是调用 system 函数,即

char* path = "address of the file";
system(path);

这将运行 exe。

请注意,几乎每个构建为在操作系统上运行的 exe 都不是简单的加载到内存中并运行。那是因为任何 C 程序的启动代码都不像你想象的那样以main() 开头。它从更深层次开始,包括加载运行时库、分配内存,最终运行时将调用main()。

也就是说,如果您处理的不是真正的 exe 文件(Windows 上的 exe 文件是 PE format,Linux 上是 ELF),而是手动编译的二进制映像,那么假设该代码使用 PIC 选项编译以使代码可重定位,该代码不依赖于 C 运行时库或任何动态加载的库,并且入口点是二进制文件的第一个地址。但是,我可以告诉你,没有人会这样。

【讨论】:

  • 我知道我做错了。我的最终目标是能够从套接字接收 exe 文件并直接从缓冲区运行它。以上只是举例。但无论如何,谢谢,您能否提供有关最后一段的更多详细信息?!如果我使用 PIC 选项编译我的代码,我应该如何找到入口点地址?谢谢。
  • 为什么不把exe文件保存到/tmp,然后调用system()呢?
  • 我不想在硬盘上留下任何痕迹。由于某些原因,我不希望我的客户拥有可执行文件。
【解决方案2】:

“exe”文件更适合称为Portable Executable。入口点(请注意,这很可能不是main())在 OpationalHeader 中作为 AddressOfEntryPoint 属性。

PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS pe;
void (* function)();

dos = (PIMAGE_DOS_HEADER)data;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
    return NULL;
}

pe = (PIMAGE_NT_HEADERS)&((const unsigned char *)(buffer))[dos->e_lfanew];
if (pe->Signature != IMAGE_NT_SIGNATURE) {
    return NULL;
}

function = pe->OptionalHeader.AddressOfEntryPoint + buffer;
function();

您想要执行的应用程序在没有固定重定位或导入的情况下工作的可能性基本上是无限小的——因此您应该使用现有的解决方案。

另外请注意,现在运行的大多数 PC 都启用了 Data Execution Prevention,因此您应该使用 VirtualAllocate() 进行分配

【讨论】:

    【解决方案3】:

    如果您想动态加载函数,可以考虑使用动态库。您需要构建 .so 文件而不是 exe 文件。在 Linux 上,这是 dlopen 和 dlsym API。

    http://man7.org/linux/man-pages/man3/dlopen.3.html

    http://man7.org/linux/man-pages/man3/dlsym.3.html

    在 Windows 上,您需要LoadLibrary...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多