Загрузка MachineCode из файла в память и выполнение в C - mprotect Failing - PullRequest
5 голосов
/ 13 марта 2010

Привет. Я пытаюсь загрузить необработанный машинный код в память и запустить его изнутри программы на 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 `*'

Я еще не получил программу для доступа к этому коду, поэтому не могу увидеть, выполняет ли мой ассемблерный код то, что должен.

Ответы [ 3 ]

4 голосов
/ 13 марта 2010

Хорошо, вот ответ, согласно нашей дискуссии в комментариях:)

Область памяти должна быть выровнена по размеру системной страницы. Вызов posix_memalign () является правильным способом выделения памяти в таком случае:)

1 голос
/ 09 августа 2010

Использование всех разрешений PROT_EXEC | PROT_READ | PROT_WRIT также не нужен и довольно опасен. Вам вообще не нужен PROT_WRITE, достаточно только exec и read.

Некоторые защищенные ядра даже не допускают PROT_EXEC | PROT_WRIT.

1 голос
/ 13 марта 2010

Добавьте 0xc3 (инструкцию возврата) после ваших байтов 0x90 (noop). Ваша программа может зависать, потому что она запускается из конца NOOP и либо в неинициализированную память, которая знает, что там скрывается, либо в конец исполняемой страницы. Я не могу точно сказать, не глядя на то, что в файле, который вы загружаете.

Кстати, strace очень полезен для такого рода программ. Он сказал бы вам, в чем заключалась ошибка в mprotect.

...