将 MachineCode 从文件加载到内存中并在 C 中执行 -- mprotect 失败

发布于 2024-08-24 19:32:38 字数 1320 浏览 7 评论 0原文

您好,我正在尝试将原始机器代码加载到内存中并从 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 `*'

我还没有让程序达到此代码,所以我无法查看我的汇编代码是否正在执行其应该执行的操作。

Hi I'm trying to load raw machine code into memory and run it from within a C program, right now when the program executes it breaks when trying to run mprotect on the memory to make it executable. I'm also not entirely sure that if the memory does get set right it will execute. I am currently running this on Ubuntu Linux x86 (Maybe the problem is Ubuntu's over-protection?)

What I currently have is the following:

#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;
}

I do get the compiler warning:

/tmp/ccVnhHak.s: Assembler messages:
/tmp/ccVnhHak.s:107: Warning: indirect call without `*'

I've not gotten the program to reach this code yet so I am unable to see if my assembler code is doing what it should.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

温柔戏命师 2024-08-31 19:32:38

好的,根据我们在评论中的讨论,这就是答案:)

内存区域应该与系统页面大小对齐。在这种情况下,posix_memalign() 调用是分配内存的正确方法:)

Ok, here's the answer, according to our discussion in the comments :)

The memory region should be aligned to the system page size. posix_memalign() call is a right way to allocate memory in such case :)

他夏了夏天 2024-08-31 19:32:38

在 0x90(noop)字节后添加 0xc3(返回指令)。您的程序可能会崩溃,因为它超出了 NOOP 的末尾,并且要么进入未初始化的内存(谁知道那里潜藏着什么),要么进入可执行页面的末尾。如果不查看您正在加载的文件中的内容,我真的无法判断。

顺便说一句,strace 对于此类程序非常有用。它会告诉您 mprotect 中的错误是什么。

Add an 0xc3 (return instruction) after your 0x90 (noop) bytes. Your program might be crashing because it runs off the end of the NOOPs and either into uninitialized memory, who knows what lurks there, or into the end of the executable page. I can't really tell without looking at what's in the file you're loading.

BTW strace is very useful for these sorts of programs. It would have told you what the error in mprotect was.

黑寡妇 2024-08-31 19:32:38

使用所有权限 PROT_EXEC | PROT_READ | PROT_WRIT 也不需要并且有点危险。
一般不需要PROT_WRITE,只需exec和read就足够了。

一些安全内核甚至不允许 PROT_EXEC | PROT_WRIT。

Using all perms PROT_EXEC | PROT_READ | PROT_WRIT is also not needed and kinda dangerous.
You don't need PROT_WRITE generally, just exec and read is enough.

Some secured kernels don't even allow PROT_EXEC | PROT_WRIT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文