C : 运行 来自 ram 的编译函数

C : running a compiled function from ram

我正在做一个项目,我需要将一个简单的 exe 文件加载到缓冲区,然后从 ram 中调用 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;
}

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

这里有一个 link 试图为 meterpreter 做同样的事情(想法是一样的):

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

如果有任何帮助,我将不胜感激。

谢谢

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

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

这将 运行 exe。

请注意,几乎每个在 OS 上构建到 运行 的 exe 都不是简单的加载到内存和 运行。这是因为任何 C 程序的启动代码都不像您想象的那样以 main() 开头。它从更深层次开始,涉及加载 运行 时间库、分配内存,最终 运行 时间将调用 main().

就是说,如果您处理的不是真正的 exe 文件(exe 文件是 Windows 上的 PE format 和 Linux 上的 ELF),而是手动编译的二进制图像,那么你正在做的事情将起作用,假设代码是使用 PIC 选项编译以使代码可重定位,代码不依赖于 C 运行time 库或任何动态加载的库,入口点是二进制文件的首地址。但是,我可以告诉你,没有人会这样做。

"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()

进行分配

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

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

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

在 Windows,您需要 LoadLibrary...