在分配的内存中手工制作x86组件

时间:2013-03-26 10:16:10

标签: c assembly x86 mmap machine-code

我尝试使用mmap来分配可读,可写和可执行的内存。

我编写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”并终止。如果您对此问题有任何暗示,我将不胜感激。

1 个答案:

答案 0 :(得分: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;
}