2013-03-26 34 views
0

我尝试使用mmap来分配可读,可写和可执行的内存。在分配的内存中制作手工x86组件

我写的是x86_32汇编语言。

内存中的代码基本上试图跳转到一个函数,但我总是得到分段错误。

以下是我的C代码。

#include<stdio.h> 
#include<stdlib.h> 
#include<sys/mman.h> 

void print(); 

char*p; 

void out8(char v) 
{ 
*p = v; 
p++; 
} 
int main() 
{ 

int j; 
int addr; 
int cnt = 0; 
int * ptr; 
addr = (int)(&print); 
p = (char*)mmap (NULL, 100, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 
printf("p : %x\n",(int)p); 
int relAddr = addr; 
void(*f)() = (void(*)())p; 
if(p == MAP_FAILED)puts("map failed"); 

out8('\x55'); // push esp 
out8('\x89'); out8('\xe5'); // mov esp ebp 
out8('\x50'); // push eax 
out8('\x51'); // push ecx 
out8('\x52'); // push edx 

out8('\xe9'); // relative jump opcode 
relAddr = ((int)p) - ((int)print) + 4; 
out8((relAddr) & 0xff); 
out8((relAddr>>8) & 0xff); 
out8((relAddr>>16) & 0xff); 
out8((relAddr>>24) & 0xff); 

    f(); 

return 0; 
} 

void print() 
{ 
fprintf(stderr,"hi\n"); 
exit(1);  
} 

我期望程序打印“hi”并终止。如果您对这个问题有任何暗示,我将不胜感激。

+0

是不是相对地址跳转减去周围走错了路? – harold 2013-03-26 10:51:05

+0

旧的答案给出了这种类型的问题的示例代码:http://stackoverflow.com/a/5006231/512360 - 使用绝对跳转,但可以用相同的方式编码(即使用'call'或'jmp')...假设“蹦床缓冲区”和实际的目标函数地址在2GB之内。 – 2013-03-26 12:32:50

回答

1

这里是一个修正版本:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/mman.h> 
#include <stdint.h> 

char * buf; // start of buffer             
char * p; // current pointer in buffer           

void out8 (uint8_t x) 
{ 
    *p++ = (char)x; 
} 

void out32 (uint32_t x) 
{ 
    out8 (x & 0xFF); 
    out8 ((x >> 8) & 0xFF); 
    out8 ((x >> 16) & 0xFF); 
    out8 (x >> 24); 
} 

void init_buffer() 
{ 
    buf = mmap (NULL, 100, PROT_READ|PROT_WRITE|PROT_EXEC, 
       MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 
    if (buf == MAP_FAILED) { 
     perror ("mmap"); 
     exit (EXIT_FAILURE); 
    } 

    p = buf; 
} 

void run_buffer() 
{ 
    (*((void (*)())buf))(); 
} 

void emit_call (intptr_t &addr) 
{ 
    intptr_t rel_addr; 

    rel_addr = addr - ((intptr_t)p + 5); 
    out8('\xe8'); 
    out32(rel_addr); 
} 

void emit_ret() 
{ 
    out8('\xc3'); 
} 

void hello() 
{ 
    printf ("Hello World!\n"); 
} 

void fill_buffer() 
{ 
    emit_call ((intptr_t)&hello); 
    emit_ret();            
} 

int main() 
{ 
    init_buffer(); 
    fill_buffer(); 
    run_buffer() 

    return EXIT_SUCCESS; 
}