我正在处理一个项目,我需要将一个简单的exe
文件加载到缓冲区,然后从ram中调用exe
文件的入口点。
我知道我无法加载并运行一个非常复杂的exe文件,其缓冲区有很多依赖项,但我认为可以调用exe (PE)
文件的独立函数(就像一个空的main )。
要这样做,我必须找到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
我很感激任何帮助。
由于
答案 0 :(得分:4)
你有可能想要解决错误的问题。如果您使用的是操作系统(比如Windows或Linux),那么最简单的方法就是调用system
函数,即
char* path = "address of the file";
system(path);
那将运行exe。
请注意,几乎每个为在操作系统上运行而构建的exe都不能轻易加载到内存中并运行。这是因为任何C程序的启动代码都不像您想象的那样以main()
开头。它从更深层次开始,包括加载运行时库,分配内存,最终运行时将调用main()
。
那就是说,如果你没有处理一个真正的exe文件(exe文件在Windows上是PE format而在Linux上是ELF),而是一个手工编译的二进制图像,那么你正在做什么就行了,假设代码是使用PIC选项编译以使代码可重定位,代码不依赖于C运行时库或任何动态加载的库,并且入口点是二进制文件的第一个地址。但是,我可以告诉你,没有人这样做。
答案 1 :(得分:3)
" 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()
进行分配
答案 2 :(得分:0)
如果要动态加载函数,可以考虑使用动态库。您需要构建.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
...