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

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

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 
+8
c x86 inline-assembly
source share
5 answers

With x86 this is possible.

Here is a small example. Select the page using write / exec privileges and copy your operation codes 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 Link: http://pages.cs.wisc.edu/~weinrich/papers/method_dispatch.pdf

You did not indicate whether this is a complete program or a single function. There may be problems with the relative / absolute address.

A quick note: this code also works with PowerPC and ARM with MMU enabled.

+8
source share

Declare a pointer to a function, then call the function.

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

Of course, this behavior is undefined and operation is not guaranteed.

+4
source share

On some platform, you cannot just declare:

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

and try

 f(); 

to run the hex code.

Because the data page can NOT be executed. A convenient way to define a function without worrying about its contents is to add the .s file to the project.

Compile it with GNU as and link it to the final program.

eg:

main.c

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

xs

the code works like C statment: printf("Hello ASM\n"); exit(11); 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 and run

 as xs -o xo gcc main.c xo -o main ./main Hello ASM! 

In addition, if your array with hexadecimal code is in a binary file, for example 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 xs might be:

 .global helloasm helloasm: .incbin "a.bin" 
+4
source share

Look at the header file elf.h.

You need to fill in the fields from these OPCodes structures.

In x86, there is a protocol for loading the executable file, otherwise after the linker transfers control to the loaded code, it will work.

See how to create a valid executable:

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

+1
source share

Could you just print them to a file and then use the system() call? This way, you don't have to worry about whether this array should follow the C-call convention.

-one
source share

All Articles