How to make a C program that can run x86 hex codes

独自空忆成欢 提交于 2020-01-01 03:16:08

问题


I have an array of hex codes that translate into assembly instructions and I want to create program in C that can execute these.

unsigned char rawData[5356] = {
    0x4C, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0C, 0x00, 0x00,
    0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x2E, 0x74, 0x65, 0x78,
    0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xB4, 0x05, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x68, 0x08, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x60,
    0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x40, 0x00, 0x30, 0xC0, 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x30, 0xC0, 0x2F, 0x34, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x14, 0x00, 0x00, 0x00, 0x58, 0x07, 0x00, 0x00, 0x32, 0x0C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x10, 0x30, 0x60,
    0x2F, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x6C, 0x07, 0x00, 0x00,...and so on

回答1:


With the x86 it is possible.

Here's a small sample. Allocate the page with write/exec privileges and copy your opcodes there.

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#endif


int main(){
    char opcodes[] = { ..... }; 

    #ifdef _WIN32

    HANDLE mem_handle = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0,  length, NULL);

    void* mem_map = MapViewOfFile( mem_handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0x0, 0x0, length);

    #else // posix
    void* mem_map = mmap(NULL, sizeof(opcodes), PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
    #endif

    memcpy(mem_map, opcodes, sizeof(opcodes));

    (( void(*)() )mem_map)();

    return 0;
}

For POSIX systems use the mmap() call.

Also read about trampolines. See the link: http://pages.cs.wisc.edu/~weinrich/papers/method_dispatch.pdf

You didn't tell if this is a complete program or a single function. There might be problems with relative/absolute adressing.

Small remark: this code works also with PowerPC and ARMs with MMU enabled.




回答2:


Declare a function pointer then call the function.

void (*f)(void) = (void (*)(void)) rawData;
f();

Of course this is undefined behavior and not guaranteed to work.




回答3:


On some platform, you can not just declare:

void (*f)(void) = (void (*)(void)) rawData;

and try

f(); 

to run the hexed code.

As the data page may NOT executable. A convenient way to define a function without caring about the content of it is to add a .s file to your project.

Compile it with GNU as, and link it's object file to your final program.

for example:

main.c

int main()
{
    helloasm();
    return 0;
}

x.s

the code works like C statment: printf("Hello ASM\n"); exit(11);

.global helloasm
helloasm:
.byte 0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, 0xe8, 0x0b, 0x00, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c
.byte 0x6f, 0x20, 0x41, 0x53, 0x4d, 0x21, 0x0a, 0x5e, 0x48, 0xc7, 0xc2, 0x0b, 0x00, 0x00, 0x00, 0xb8
.byte 0x01, 0x00, 0x00, 0x00, 0x0f, 0x05, 0xbf, 0x0b, 0x00, 0x00, 0x00, 0xb8, 0x3c, 0x00, 0x00, 0x00
.byte 0x0f, 0x05

Compile & run

as x.s -o x.o
gcc main.c x.o -o main
./main
Hello ASM!

In addtion, if your hexed code array is in a binary file, like a.bin

hexdump -C a.bin
00000000  48 c7 c7 01 00 00 00 e8  0b 00 00 00 48 65 6c 6c  |H...........Hell|
00000010  6f 20 41 53 4d 21 0a 5e  48 c7 c2 0b 00 00 00 b8  |o ASM!.^H.......|
00000020  01 00 00 00 0f 05 bf 0b  00 00 00 b8 3c 00 00 00  |............<...|
00000030  0f 05                                             |..|
00000032

Then your x.s may be:

.global helloasm
helloasm:
.incbin "a.bin"



回答4:


Look at the header file elf.h .

You need to complete the fields from these structures with OPCodes.

In x86 there is a protocol to load the executable, othewise after the linker passes the control to the loaded code, it crashes.

Look here how to create a valid executable :

http://bellard.org/otcc/otccelfn.c




回答5:


Couldn't you just output those to a file and then use the system() call? That way you don't have to worry about whether that array follows C calling convention.



来源:https://stackoverflow.com/questions/11252707/how-to-make-a-c-program-that-can-run-x86-hex-codes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!