2013-03-26 35 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; 
}