Executing machine code in memory

后端 未结 9 1420
盖世英雄少女心
盖世英雄少女心 2020-12-04 12:47

I\'m trying to figure out how to execute machine code stored in memory.

I have the following code:

#include 
#include          


        
相关标签:
9条回答
  • 2020-12-04 12:59

    It is more likely that that it is the code that is jumped to by the call through function-pointer that is causing the segfault rather than the call itself. There is no way from the code you have posted to determine that that code loaded into bin is valid. Your best bet is to use a debugger, switch to assembler view, break on the return statement and step into the function call to determine that the code you expect to run is indeed running, and that it is valid.

    Note also that in order to run at all the code will need to be position independent and fully resolved.

    Moreover if your processor/OS enables data execution prevention, then the attempt is probably doomed. It is at best ill-advised in any case, loading code is what the OS is for.

    0 讨论(0)
  • 2020-12-04 13:03

    It seems to me you're loading an ELF image and then trying to jump straight into the ELF header? http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

    If you're trying to execute another binary, why don't you use the process creation functions for whichever platform you're using?

    0 讨论(0)
  • 2020-12-04 13:07

    You need a page with write execute permissions. See mmap(2) and mprotect(2) if you are under unix. You shouldn't do it using malloc.

    Also, read what the others said, you can only run raw machine code using your loader. If you try to run an ELF header it will probably segfault all the same.

    Regarding the content of replies and downmods:

    1- OP said he was trying to run machine code, so I replied on that rather than executing an executable file.

    2- See why you don't mix malloc and mman functions:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    
    int main()
    {
        char *a=malloc(10);
        char *b=malloc(10);
        char *c=malloc(10);
        memset (a,'a',4095);
        memset (b,'b',4095);
        memset (c,'c',4095);
        puts (a);
        memset (c,0xc3,10); /* return */
    
        /* c is not alligned to page boundary so this is NOOP.
         Many implementations include a header to malloc'ed data so it's always NOOP. */
        mprotect(c,10,PROT_READ|PROT_EXEC);
        b[0]='H'; /* oops it is still writeable. If you provided an alligned
        address it would segfault */
        char *d=mmap(0,4096,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANON,-1,0);
        memset (d,0xc3,4096);
        ((void(*)(void))d)();
        ((void(*)(void))c)(); /* oops it isn't executable */
        return 0;
    }
    

    It displays exactly this behavior on Linux x86_64 other ugly behavior sure to arise on other implementations.

    0 讨论(0)
  • 2020-12-04 13:07

    Using malloc works fine.

    OK this is my final answer, please note I used the orignal poster's code. I'm loading from disk, the compiled version of this code to a heap allocated area "bin", just as the orignal code did (the name is fixed not using argv, and the value 0x674 is from;

    objdump -F -D foo|grep -i hoho
    08048674 <hohoho> (File Offset: 0x674):
    

    This can be looked up at run time with the BFD (Binary File Descriptor library) or something else, you can call other binaries (not just yourself) so long as they are statically linked to the same set of lib's.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/mman.h>
    
    unsigned char *charp;
    unsigned char *bin;
    
    void hohoho()
    {
       printf("merry mas\n");
       fflush(stdout);
    }
    
    int main(int argc, char **argv)
    {
       int what;
    
       charp = malloc(10101);
       memset(charp, 0xc3, 10101);
       mprotect(charp, 10101, PROT_EXEC | PROT_READ | PROT_WRITE);
    
       __asm__("leal charp, %eax");
       __asm__("call (%eax)" );
    
       printf("am I alive?\n");
    
       char *more = strdup("more heap operations");
       printf("%s\n", more);
    
       FILE* f = fopen("foo", "rb");
    
       fseek(f, 0, SEEK_END);
       unsigned int len = ftell(f);
       fseek(f, 0, SEEK_SET);
    
       bin = (char*)malloc(len);
       printf("read in %d\n", fread(bin, 1, len, f));
       printf("%p\n", bin);
    
       fclose(f);
       mprotect(&bin, 10101, PROT_EXEC | PROT_READ | PROT_WRITE);
    
       asm volatile ("movl %0, %%eax"::"g"(bin));
       __asm__("addl $0x674, %eax");
       __asm__("call %eax" );
       fflush(stdout);
    
       return 0;
    }
    

    running...

    co tmp # ./foo
    am I alive?
    more heap operations
    read in 30180
    0x804d910
    merry mas
    

    You can use UPX to manage the load/modify/exec of a file.

    P.S. sorry for the previous broken link :|

    0 讨论(0)
  • 2020-12-04 13:09

    What you are trying to do is something akin to what interpreters do. Except that an interpreter reads a program written in an interpreted language like Python, compiles that code on the fly, puts executable code in memory and then executes it.

    You may want to read more about just-in-time compilation too:

    Just in time compilation
    Java HotSpot JIT runtime

    There are libraries available for JIT code generation such as the GNU lightning and libJIT, if you are interested. You'd have to do a lot more than just reading from file and trying to execute code, though. An example usage scenario will be:

    1. Read a program written in a scripting-language (maybe your own).
    2. Parse and compile the source into an intermediate language understood by the JIT library.
    3. Use the JIT library to generate code for this intermediate representation, for your target platform's CPU.
    4. Execute the JIT generated code.

    And for executing the code you'd have to use techniques such as using mmap() to map the executable code into the process's address space, marking that page executable and jumping to that piece of memory. It's more complicated than this, but its a good start in order to understand what's going on beneath all those interpreters of scripting languages such as Python, Ruby etc.

    The online version of the book "Linkers and Loaders" will give you more information about object file formats, what goes on behind the scenes when you execute a program, the roles of the linkers and loaders and so on. It's a very good read.

    0 讨论(0)
  • 2020-12-04 13:12

    An typical executable file has:

    • a header
    • entry code that is called before main(int, char **)

    The first means that you can't generally expect byte 0 of the file to be executable; intead, the information in the header describes how to load the rest of the file in memory and where to start executing it.

    The second means that when you have found the entry point, you can't expect to treat it like a C function taking arguments (int, char **). It may, perhaps, be usable as a function taking no paramters (and hence requiring nothing to be pushed prior to calling it). But you do need to populate the environment that will in turn be used by the entry code to construct the command line strings passed to main.

    Doing this by hand under a given OS would go into some depth which is beyond me; but I'm sure there is a much nicer way of doing what you're trying to do. Are you trying to execute an external file as a on-off operation, or load an external binary and treat its functions as part of your program? Both are catered for by the C libraries in Unix.

    0 讨论(0)
提交回复
热议问题