8

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
Iowa15
  • 3,027
  • 6
  • 28
  • 35
  • 2
    Is this homework? This isn't really a question, but an assignment. You should tell us what you've tried already and where you got lost. – carmenism Jun 28 '12 at 20:55
  • 2
    **Did you try** to to declare a function pointer to rawData (care calling convention, please) and then invoke that function??? Moreover this may be denied by Windows (if you're using Windows) because of DEP (just disable it). – Adriano Repetti Jun 28 '12 at 20:56
  • 1
    Do not cycle the array, the memory allocated for the array is the program itself (like a pointer to a _normal_ function). Just call it once. To disable DEP...Google, procedure is a little bit different between Windows versions. – Adriano Repetti Jun 28 '12 at 21:02
  • To enable direct execution you should allocate the array and mark the page as Executable. See my answer below with a working solution – Viktor Latypov Jun 28 '12 at 22:32

5 Answers5

8

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.

Viktor Latypov
  • 14,289
  • 3
  • 40
  • 55
4

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.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • Thanks, so do I just cycle through for the array – Iowa15 Jun 28 '12 at 20:57
  • 1
    This is why they call C one step up from assembler! – Preet Sangha Jun 28 '12 at 20:57
  • 2
    Yea, this is correct. There are, however, possible complications. 1) whether the assembly actually follows the C calling convention (you may be able to call it, but it may not come back). 2) You may not be able to do it at as modern systems frown upon converting what is ostensibly "just data" in to executable code. The data segment that the array may be in may be marked as not executable. That depends on all sorts of things (platform, os, compile and link options, etc.) – Will Hartung Jun 28 '12 at 20:59
  • I wonder if this could have any use for implementing crude reflection in C. You read the opcodes for a function from the program's binary and do manual editing of the opcodes, then execute the modified function with that function pointer... hm. – JAB Jun 28 '12 at 21:00
  • @WillHartung: "modern systems frown upon converting what is ostensibly "just data" in to executable code." I say all data should be usable as code if you're prepared to deal with the complications. Then again, I really like languages that are highly reflexive. – JAB Jun 28 '12 at 21:00
  • @ouah: This works from time to time. On most systems one gets the access violation because the page where 'rawData' resides is not marked as 'executable'. But you answer is a good starting point. – Viktor Latypov Jun 28 '12 at 22:21
  • @JAB black hat hackers share your point of view. Folks decry the "walled gardens" that are the modern mobile and tablet landscape, which specifically prevent this from happening. And a large contributor to why they're locked down is exploits and malware through vectors such as this. – Will Hartung Jun 28 '12 at 22:26
  • @WillHartung I did say, "_if_ you're prepared to deal with the complications." – JAB Jun 29 '12 at 12:32
4

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"
BenMorel
  • 34,448
  • 50
  • 182
  • 322
yang wen
  • 427
  • 4
  • 15
1

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

alinsoar
  • 15,386
  • 4
  • 57
  • 74
-1

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.

Daniel
  • 6,595
  • 9
  • 38
  • 70
  • That'd only work if the hex codes form a properly-executable program and not just, say, a function. – JAB Jun 28 '12 at 21:02