您好我正在尝试将原始机器代码加载到内存中并在C程序中运行它,现在当程序执行时它会在尝试在内存上运行mprotect以使其可执行时中断。我也不完全确定如果内存设置正确,它将执行。我目前在Ubuntu Linux x86上运行它(也许问题是Ubuntu的过度保护?)
我目前拥有以下内容:
#include <memory.h>
#include <sys/mman.h>
#include <stdio.h>
int main ( int argc, char **argv )
{
FILE *fp;
int sz = 0;
char *membuf;
int output = 0;
fp = fopen(argv[1],"rb");
if(fp == NULL)
{
printf("Failed to open file, aborting!\n");
exit(1);
}
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
fseek(fp, 0L, SEEK_SET);
membuf = (char *)malloc(sz*sizeof(char));
if(membuf == NULL)
{
printf("Failed to allocate memory, aborting!\n");
exit(1);
}
memset(membuf, 0x90, sz*sizeof(char));
if( mprotect(membuf, sz*sizeof(char), PROT_EXEC | PROT_READ | PROT_WRITE) == -1)
{
perror("mprotect");
printf("mprotect failed!!! aborting!\n");
exit(1);
}
if(!(fread(membuf, sz*sizeof(char), 1, fp)))
{
perror("fread");
printf("Read failed, aborting!\n");
exit(1);
}
__asm__
(
"call %%eax;"
: "=a" (output)
: "a" (membuf)
);
printf("Output = %x\n", output);
return 0;
}
我收到编译器警告:
/tmp/ccVnhHak.s: Assembler messages:
/tmp/ccVnhHak.s:107: Warning: indirect call without `*'
我还没有让程序达到这个代码,所以我无法看到我的汇编代码是否正在做它应该做的事情。
答案 0 :(得分:4)
好的,这是答案,根据我们在评论中的讨论:)
内存区域应与系统页面大小对齐。 posix_memalign()调用是在这种情况下分配内存的正确方法:)
答案 1 :(得分:1)
在0x90(noop)字节后添加0xc3(返回指令)。你的程序可能会崩溃,因为它运行在NOOP的末尾,并且运行到未初始化的内存,谁知道潜伏在那里,或者到可执行页面的末尾。如果不查看您正在加载的文件中的内容,我无法确定。
BTW strace对于这些类型的程序非常有用。它会告诉你mprotect中的错误是什么。
答案 2 :(得分:1)
使用所有权限PROT_EXEC | PROT_READ | PROT_WRIT也不需要,有点危险。 你一般不需要PROT_WRITE,只需exec和read即可。
某些安全内核甚至不允许PROT_EXEC | PROT_WRIT。