Skip to content
code shellcode runner
Home » How to code shellcode runner for your malware analysis

How to code shellcode runner for your malware analysis

    Introduction

    Why you should know how to code a shellcode runner for your malware analysis?
    Often during malware analysis, we met hidden shellcodes.
    In such cases, it may be much easier to extract it and analyse it separately.
    Since conditions may arise that would complicate understanding (injection or possible evasion techniques).
    In this cases we can find easier to run a dynamic analysis.
    In summary, the project will be a simple runner that:

    • take a shellcode dump as input
    • run it in a separate thread
    • stop execution by telling us where to set our breakpoint

    For more details, you can look at this post How to embed a shellcode payload into an executable .

    Preliminary part

    Anyway, this is a lot easier said than done.
    So let’s start getting our hands dirty with the code now.

    First of all, we’re going to write the required imports and definitions

    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define MAX_SHELLCODE_LEN 1024

    Main method

    Then let’s look inside the main method step by step

        HANDLE threadHandle;
        size_t shellcode_len;
        LPVOID shellcode_alloc_mem;
        unsigned char shellcode[MAX_SHELLCODE_LEN];
    
       
        HANDLE h_file = CreateFile(argv[1], GENERIC_READ ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
        BOOL retval = ReadFile(h_file, shellcode, MAX_SHELLCODE_LEN, &shellcode_len, NULL);

    The above lines simply declare the variables we will need and then read the file containing the shellcode, pass it via prompt (argv[1]) and save it as an array of unsigned char.
    Since this is only for our analysis and understanding, we don’t need to do any checking on the input.

        shellcode_alloc_mem = VirtualAlloc(0, shellcode_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        RtlMoveMemory(shellcode_alloc_mem, shellcode, shellcode_len);

    At this point, a memory area with all permissions is allocated where we’re going to move the shellcode with the help of RtlMoveMemory function.

        printf("%-20s : 0x%-16p\n ", "the shellcode payload addr, put a breakpoint here and then press a key", 
              (void *)shellcode_alloc_mem);
        printf("Press a key to continue:\n");
    
        getchar();

    This is the part of the code that indicates the area of memory where the shellcode resides and stops execution while waiting for a key press event. This is exactly where we are when we need to attach the debugger to our runner.

        if(shellcode_alloc_mem){
    
            threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)shellcode_alloc_mem, 0, 0, 0);
            WaitForSingleObject(threadHandle, INFINITE);
        }

    And finally, here is the part where we launch a new thread containing the shellcode and then wait for the end with the WaitForSingleObject method.

    Put all together

    At this point, to get a clearer picture, let’s see the full code.

    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define MAX_SHELLCODE_LEN 1024
    
    int main(int argc, char *argv[]) {
    
        HANDLE threadHandle;
        size_t shellcode_len;
        LPVOID shellcode_alloc_mem;
        unsigned char shellcode[MAX_SHELLCODE_LEN];
    
       
        HANDLE h_file = CreateFile(argv[1], GENERIC_READ ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
        BOOL retval = ReadFile(h_file, shellcode, MAX_SHELLCODE_LEN, &shellcode_len, NULL);
    
        shellcode_alloc_mem = VirtualAlloc(0, shellcode_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        RtlMoveMemory(shellcode_alloc_mem, shellcode, shellcode_len);
    
        printf("%-20s : 0x%-16p\n ", "the shellcode payload addr, put a breakpoint here and then press a key", (void *) shellcode_alloc_mem);
        printf("Press a key to continue:\n");
    
        getchar();
        if(shellcode_alloc_mem){
    
            threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)shellcode_alloc_mem, 0, 0, 0);
            WaitForSingleObject(threadHandle, INFINITE);
        }
    }

    We’re finally at the end, now all we have to do is compile.
    Open NativeTools and go to the folder containing our file, which we will call “shellcode_runner.cpp”, then run the following command:

    cl.exe  /Tcshellcode_runner.cpp /link /OUT:shellcode_runner.exe 

    And now, assuming we have saved our shellcode in a file called shellcode.bin in the same folder as our program, let’s try to launch the runner with the following command.

    shellcode_runner.exe shellcode.bin

    I hope the post was useful and that you enjoyed it, in the meantime I send you goodbye to the next article!

    Further readings

    Now that you know how to code a shellcode runner for your malware analysis I suggest you some readings: