├── Dockerfile ├── Makefile ├── README.md ├── build_and_run.sh ├── include ├── embedded.h └── static-pie-loader.h ├── static-pie-loader.c ├── static-pie.ld ├── strip_headers.py └── test.c /Dockerfile: -------------------------------------------------------------------------------- 1 | from ubuntu:19.04 2 | RUN apt-get update -y 3 | RUN apt-get install build-essential -y 4 | RUN apt-get install gcc-9 -y 5 | RUN apt-get install python -y 6 | RUN apt-get install xxd -y 7 | RUN mkdir ./SHELF 8 | COPY ./ ./SHELF 9 | WORKDIR ./SHELF 10 | RUN make 11 | RUN ./loader 12 | RUN sleep 1000 13 | 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc-9 --static-pie -ggdb -T ./static-pie.ld -o test test.c 3 | python strip_headers.py ./test 4 | echo "_Alignas(char) const " >> ./include/embedded.h 5 | xxd -i test >> ./include/embedded.h 6 | gcc-9 -Os -T static-pie.ld -static-pie static-pie-loader.c -o loader\ 7 | -Wl,--gc-sections -Wl,-z,max-page-size=1 -Wl,-z,common-page-size=1\ 8 | -mmanual-endbr -nostartfiles -nodefaultlibs -nolibc -nostdlib\ 9 | -fdata-sections -ffunction-sections 10 | clean: 11 | rm test loader 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SHELF 2 | Evasive ELF Static PIE User-Land-Exec featured in [Tmpout Vol 1](https://tmpout.sh/1/10/). 3 | Courtesy of @Anynomous && @ulexec 4 | -------------------------------------------------------------------------------- /build_and_run.sh: -------------------------------------------------------------------------------- 1 | docker build -t shelf . & 2 | sleep 15 3 | sudo docker cp $(sudo docker ps -l | awk -F 'CONTAINER' '{print $1}' | awk -F ' ' '{print $1}'):/SHELF/loader . 4 | -------------------------------------------------------------------------------- /include/static-pie-loader.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define STACK_SZ (1024 * 32) 8 | #define PAGEALIGN(k) (((k)+((0x1000)-1))&(~((0x1000)-1))) 9 | #define PAGEALIGNDOWN(k) (((k)+((0x1000)-1))&(~((0x1000)-1))) - 0x1000 10 | #define PAGEALIGNUP(k) (((k)+((0x1000)-1))&(~((0x1000)-1))) + 0x1000 11 | #define O_ACCMODE 00000003 12 | #define O_RDONLY 00000000 13 | #define O_WRONLY 00000001 14 | #define O_RDWR 00000002 15 | #define NULL 0 16 | #define offsetof(type, member) (__builtin_offsetof(type, member)) 17 | #define RLONG(base, offset) ((long)base[offset + 7] << (64 - 8) | (long)base[offset + 6] << (64 - 8 * 2) | (long)base[offset + 5] << (64 - 8 * 3) | (long)base[offset + 4] << (64 - 8 * 4) | (long)base[offset + 3] << (64 - 8 * 5) | (long)base[offset + 2] << (64 - 8 * 6) | (long)base[offset + 1] << (64 - 8 * 7) | (long)base[offset + 0] << (64 - 8 * 8)) 18 | #define RSHORT(base, offset) ((short)base[offset + 1] << (16 - 8) | (short)base[offset + 0] << (16 - 8 * 2)) 19 | #define PIC_RESOLVE_ADDR(target) (get_rip() - ((char *)&get_rip_label - (char *)target)) 20 | extern unsigned long get_rip_label; 21 | 22 | unsigned long get_rip(void) { 23 | unsigned long ret; 24 | 25 | asm volatile( 26 | "call get_rip_label \n" 27 | ".globl get_rip_label \n" 28 | "get_rip_label: \n" 29 | "pop %%rax \n" 30 | "mov %%rax, %0" : "=r"(ret) 31 | ); 32 | 33 | return ret; 34 | } 35 | 36 | asm ( 37 | ".text\n" 38 | ".global mmap\n" 39 | ".type mmap,@function\n" 40 | "mmap:\n\t" 41 | "mov %rcx,%r10\n\t" 42 | "mov $0x9,%eax\n\t" 43 | "syscall \n\t" 44 | "cmp $0xfffffffffffff001,%rax\n\t" 45 | "jae .Lx1\n\t" 46 | ".Lx2:\n\t" 47 | "retq \n\t" 48 | ".Lx1:\n\t" 49 | "mov 2623486(%rip),%rcx\n\t" 50 | "xor %edx,%edx\n\t" 51 | "sub %rax,%rdx\n\t" 52 | "mov %edx,%fs:(%rcx)\n\t" 53 | "or $0xffffffffffffffff,%rax\n\t" 54 | "jmp .Lx2\n" 55 | ); 56 | 57 | int mprotect(void *addr, unsigned long len, int prot) { 58 | long ret; 59 | asm volatile ("syscall" : "=a" (ret) : "a" (__NR_mprotect), 60 | "D" (addr), "S" (len), "d" (prot) : 61 | "cc", "memory", "rcx", 62 | "r8", "r9", "r10", "r11" ); 63 | if (ret < 0) { 64 | ret = -1; 65 | } 66 | return (int) ret; 67 | } 68 | 69 | void * memcpy(void *dest, const void *src, unsigned long n) { 70 | unsigned long i; 71 | unsigned char *d = (unsigned char *)dest; 72 | unsigned char *s = (unsigned char *)src; 73 | 74 | for (i = 0; i < n; ++i) 75 | d[i] = s[i]; 76 | 77 | return dest; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /static-pie-loader.c: -------------------------------------------------------------------------------- 1 | /* Minimalistic User Land Exec for STATIC-PIE ELF64 Binaries by @ulexec */ 2 | 3 | #include "include/embedded.h" 4 | #include "include/static-pie-loader.h" 5 | 6 | _Alignas(char) struct ST_stack_template { 7 | Elf64_auxv_t auxv[6]; 8 | } __attribute__((packed)) stack_template = { 9 | .auxv = { 10 | [0].a_type = AT_PHDR, 11 | [0].a_un.a_val = 0, 12 | [1].a_type = AT_PHNUM, 13 | [1].a_un.a_val = G_AT_PHNUM, 14 | [2].a_type = AT_ENTRY, 15 | [2].a_un.a_val = G_IMAGEBASE + G_AT_ENTRY, 16 | [3].a_type = AT_RANDOM, 17 | [3].a_un.a_val = G_IMAGEBASE, 18 | [4].a_type = AT_PHENT, 19 | [4].a_un.a_val = sizeof(Elf64_Phdr), 20 | [5].a_type = AT_NULL 21 | } 22 | }; 23 | 24 | int load_embedded_file(uint8_t *buff, size_t buff_size) { 25 | void *dest_address; 26 | Elf64_Phdr *_phdr; 27 | Elf64_Ehdr *ehdr; 28 | uint8_t *mapped; 29 | register uint8_t *stack_top; 30 | uint64_t entry_offset; 31 | uint64_t delta; 32 | uint64_t _rip; 33 | 34 | _phdr = (Elf64_Phdr*)phdr; 35 | dest_address = (void *)((uint8_t*)PAGEALIGN(_phdr->p_vaddr) + G_IMAGEBASE); 36 | delta = sizeof(Elf64_Ehdr)+(G_AT_PHNUM*sizeof(Elf64_Phdr)); 37 | 38 | if((mapped = mmap(dest_address, PAGEALIGNUP(_phdr->p_memsz) + STACK_SZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0)) == MAP_FAILED) { 39 | return false; 40 | } 41 | memcpy((uint8_t*)mapped+delta, buff, _phdr->p_filesz); 42 | 43 | if(mprotect(mapped, _phdr->p_memsz + STACK_SZ, _phdr->p_flags)) { 44 | return false; 45 | } 46 | 47 | stack_top = mapped + (PAGEALIGNUP(_phdr->p_memsz) + STACK_SZ); 48 | entry_offset = G_IMAGEBASE + G_AT_ENTRY; 49 | 50 | stack_template.auxv[0].a_un.a_val = PIC_RESOLVE_ADDR(phdr); 51 | memcpy(stack_top-sizeof(stack_template), &stack_template, sizeof(stack_template)); 52 | 53 | asm volatile ( 54 | "push %0\n" 55 | "pop %%rsp\n" 56 | "mov %1, %%eax\n" 57 | "xor %%edx, %%edx\n" 58 | "jmp *%%rax\n" 59 | : 60 | : "irm"(stack_top - (sizeof(stack_template) + (sizeof(long) * 3))), 61 | "irm"(entry_offset) 62 | : "rax", "rdx" 63 | ); 64 | } 65 | 66 | __attribute__((naked)) void _start(int argc, char **argv, char **envp) { 67 | load_embedded_file(test, test_len); 68 | } 69 | -------------------------------------------------------------------------------- /static-pie.ld: -------------------------------------------------------------------------------- 1 | /* Script for -pie -z combreloc -z now -z relro: position independent executable, combine & sort relocs */ 2 | /* Copyright (C) 2014-2019 Free Software Foundation, Inc. 3 | Copying and distribution of this script, with or without modification, 4 | are permitted in any medium without royalty provided the copyright 5 | notice and this notice are preserved. */ 6 | OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", 7 | "elf64-x86-64") 8 | OUTPUT_ARCH(i386:x86-64) 9 | ENTRY(_start) 10 | SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/ 11 | usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib"); 12 | PHDRS { 13 | text PT_LOAD FILEHDR PHDRS; 14 | /* data PT_LOAD; */ 15 | dynamic PT_DYNAMIC; 16 | tls PT_TLS; 17 | } 18 | SECTIONS 19 | { 20 | /* Read-only sections, merged into text segment: */ 21 | PROVIDE (__executable_start = SEGMENT_START("text-segment", 0)); 22 | . = SEGMENT_START("text-segment", 0) + SIZEOF_HEADERS; 23 | .interp : { *(.interp) } : text 24 | .note.gnu.build-id : { *(.note.gnu.build-id) } 25 | .hash : { *(.hash) } 26 | .gnu.hash : { *(.gnu.hash) } 27 | .dynsym : { *(.dynsym) } 28 | .dynstr : { *(.dynstr) } 29 | .gnu.version : { *(.gnu.version) } 30 | .gnu.version_d : { *(.gnu.version_d) } 31 | .gnu.version_r : { *(.gnu.version_r) } 32 | .rela.dyn : 33 | { 34 | *(.rela.init) 35 | *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) 36 | *(.rela.fini) 37 | *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) 38 | *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) 39 | *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) 40 | *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) 41 | *(.rela.ctors) 42 | *(.rela.dtors) 43 | *(.rela.got) 44 | *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) 45 | *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) 46 | *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) 47 | *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) 48 | *(.rela.ifunc) 49 | } 50 | .rela.plt : 51 | { 52 | *(.rela.plt) 53 | *(.rela.iplt) 54 | } 55 | .init : 56 | { 57 | KEEP (*(SORT_NONE(.init))) 58 | } 59 | .plt : { *(.plt) *(.iplt) } 60 | .plt.got : { *(.plt.got) } 61 | .plt.sec : { *(.plt.sec) } 62 | .text : 63 | { 64 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 65 | *(.text.exit .text.exit.*) 66 | *(.text.startup .text.startup.*) 67 | *(.text.hot .text.hot.*) 68 | *(.text .stub .text.* .gnu.linkonce.t.*) 69 | /* .gnu.warning sections are handled specially by elf32.em. */ 70 | *(.gnu.warning) 71 | } 72 | .fini : 73 | { 74 | KEEP (*(SORT_NONE(.fini))) 75 | } 76 | PROVIDE (__etext = .); 77 | PROVIDE (_etext = .); 78 | PROVIDE (etext = .); 79 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 80 | .rodata1 : { *(.rodata1) } 81 | .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } 82 | .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } 83 | .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } 84 | .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } 85 | /* These sections are generated by the Sun/Oracle C++ compiler. */ 86 | .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) } 87 | /* Adjust the address for the data segment. We want to adjust up to 88 | the same address within the page on the next page up. */ 89 | . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); 90 | /* Exception handling */ 91 | .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } 92 | .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } 93 | .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } 94 | .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } 95 | /* Thread Local Storage sections */ 96 | .tdata : 97 | { 98 | PROVIDE_HIDDEN (__tdata_start = .); 99 | *(.tdata .tdata.* .gnu.linkonce.td.*) 100 | } /*:data*/:text :tls 101 | .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } :tls 102 | .preinit_array : 103 | { 104 | PROVIDE_HIDDEN (__preinit_array_start = .); 105 | KEEP (*(.preinit_array)) 106 | PROVIDE_HIDDEN (__preinit_array_end = .); 107 | } /*:data*/:text 108 | .init_array : 109 | { 110 | PROVIDE_HIDDEN (__init_array_start = .); 111 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 112 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 113 | PROVIDE_HIDDEN (__init_array_end = .); 114 | } 115 | .fini_array : 116 | { 117 | PROVIDE_HIDDEN (__fini_array_start = .); 118 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 119 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 120 | PROVIDE_HIDDEN (__fini_array_end = .); 121 | } /*:data*/:text 122 | .ctors : 123 | { 124 | /* gcc uses crtbegin.o to find the start of 125 | the constructors, so we make sure it is 126 | first. Because this is a wildcard, it 127 | doesn't matter if the user does not 128 | actually link against crtbegin.o; the 129 | linker won't look for a file to match a 130 | wildcard. The wildcard also means that it 131 | doesn't matter which directory crtbegin.o 132 | is in. */ 133 | KEEP (*crtbegin.o(.ctors)) 134 | KEEP (*crtbegin?.o(.ctors)) 135 | /* We don't want to include the .ctor section from 136 | the crtend.o file until after the sorted ctors. 137 | The .ctor section from the crtend file contains the 138 | end of ctors marker and it must be last */ 139 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 140 | KEEP (*(SORT(.ctors.*))) 141 | KEEP (*(.ctors)) 142 | } 143 | .dtors : 144 | { 145 | KEEP (*crtbegin.o(.dtors)) 146 | KEEP (*crtbegin?.o(.dtors)) 147 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 148 | KEEP (*(SORT(.dtors.*))) 149 | KEEP (*(.dtors)) 150 | } 151 | .jcr : { KEEP (*(.jcr)) } 152 | .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } /*:data*/:text 153 | .dynamic : { *(.dynamic) } :dynamic /*:data*/:text 154 | .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } 155 | . = DATA_SEGMENT_RELRO_END (0, .); 156 | .data : 157 | { 158 | *(.data .data.* .gnu.linkonce.d.*) 159 | _foo = 100; 160 | SORT(CONSTRUCTORS) 161 | } 162 | .data1 : { *(.data1) } 163 | _edata = .; PROVIDE (edata = .); 164 | . = .; 165 | __bss_start = .; 166 | .bss : 167 | { 168 | *(.dynbss) 169 | *(.bss .bss.* .gnu.linkonce.b.*) 170 | *(COMMON) 171 | /* Align here to ensure that the .bss section occupies space up to 172 | _end. Align after .bss to ensure correct alignment even if the 173 | .bss section disappears because there are no input sections. 174 | FIXME: Why do we need it? When there is no .bss section, we do not 175 | pad the .data section. */ 176 | . = ALIGN(. != 0 ? 64 / 8 : 1); 177 | } 178 | .lbss : 179 | { 180 | *(.dynlbss) 181 | *(.lbss .lbss.* .gnu.linkonce.lb.*) 182 | *(LARGE_COMMON) 183 | } 184 | . = ALIGN(64 / 8); 185 | . = SEGMENT_START("ldata-segment", .); 186 | .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : 187 | { 188 | *(.lrodata .lrodata.* .gnu.linkonce.lr.*) 189 | } 190 | .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : 191 | { 192 | *(.ldata .ldata.* .gnu.linkonce.l.*) 193 | . = ALIGN(. != 0 ? 64 / 8 : 1); 194 | } 195 | . = ALIGN(64 / 8); 196 | _end = .; PROVIDE (end = .); 197 | . = DATA_SEGMENT_END (.); 198 | /* Stabs debugging sections. */ 199 | .stab 0 : { *(.stab) } 200 | .stabstr 0 : { *(.stabstr) } 201 | .stab.excl 0 : { *(.stab.excl) } 202 | .stab.exclstr 0 : { *(.stab.exclstr) } 203 | .stab.index 0 : { *(.stab.index) } 204 | .stab.indexstr 0 : { *(.stab.indexstr) } 205 | .comment 0 : { *(.comment) } 206 | .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } 207 | /* DWARF debug sections. 208 | Symbols in the DWARF debugging sections are relative to the beginning 209 | of the section so we begin them at 0. */ 210 | /* DWARF 1 */ 211 | .debug 0 : { *(.debug) } 212 | .line 0 : { *(.line) } 213 | /* GNU DWARF 1 extensions */ 214 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 215 | .debug_sfnames 0 : { *(.debug_sfnames) } 216 | /* DWARF 1.1 and DWARF 2 */ 217 | .debug_aranges 0 : { *(.debug_aranges) } 218 | .debug_pubnames 0 : { *(.debug_pubnames) } 219 | /* DWARF 2 */ 220 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } 221 | .debug_abbrev 0 : { *(.debug_abbrev) } 222 | .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } 223 | .debug_frame 0 : { *(.debug_frame) } 224 | .debug_str 0 : { *(.debug_str) } 225 | .debug_loc 0 : { *(.debug_loc) } 226 | .debug_macinfo 0 : { *(.debug_macinfo) } 227 | /* SGI/MIPS DWARF 2 extensions */ 228 | .debug_weaknames 0 : { *(.debug_weaknames) } 229 | .debug_funcnames 0 : { *(.debug_funcnames) } 230 | .debug_typenames 0 : { *(.debug_typenames) } 231 | .debug_varnames 0 : { *(.debug_varnames) } 232 | /* DWARF 3 */ 233 | .debug_pubtypes 0 : { *(.debug_pubtypes) } 234 | .debug_ranges 0 : { *(.debug_ranges) } 235 | /* DWARF Extension. */ 236 | .debug_macro 0 : { *(.debug_macro) } 237 | .debug_addr 0 : { *(.debug_addr) } 238 | .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } 239 | /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } 240 | } 241 | -------------------------------------------------------------------------------- /strip_headers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import struct 4 | import random 5 | import time 6 | 7 | page_align = lambda k: (((k)+((0x1000)-1))&(~((0x1000)-1))) 8 | 9 | class Elf64Phdr: 10 | def __init__(self, bytes): 11 | (self.p_type, 12 | self.p_offset, 13 | self.p_vaddr, 14 | self.p_paddr, 15 | self.p_filesz, 16 | self.p_memsz, 17 | self.p_flags, 18 | self.p_align, 19 | ) = struct.unpack("2I6Q", bytes[:struct.calcsize("2I6Q")]) 20 | 21 | class Elf64Ehdr: 22 | def __init__(self, bytes): 23 | (self.e_type, 24 | self.e_machine, 25 | self.e_version, 26 | self.e_entry, 27 | self.e_phoff, 28 | self.e_shoff, 29 | self.e_flags, 30 | self.e_ehsize, 31 | self.e_phentsize, 32 | self.e_phnum, 33 | self.e_shentsize, 34 | self.e_shnum, 35 | self.e_shstrndx) = struct.unpack("2HI3QI6H", bytes[16:struct.calcsize("2HI3QI6H")+16]) 36 | 37 | def main(path): 38 | with open(path, 'rb') as fd: 39 | buff = fd.read() 40 | ehdr = Elf64Ehdr(buff) 41 | phdr = buff[ehdr.e_phoff:ehdr.e_phoff+(ehdr.e_phnum * ehdr.e_phentsize)] 42 | 43 | delta = (ehdr.e_ehsize + (ehdr.e_phnum * ehdr.e_phentsize)) 44 | with open(path, 'wb') as fd: 45 | fd.write(buff[delta:]) 46 | 47 | os.system("xxd -i test > %s" % os.path.join("./include", "embedded.h")) 48 | 49 | with open(os.path.join("./include", "embedded.h"), "wb") as fd: 50 | fd.write("#define G_AT_ENTRY " + hex(ehdr.e_entry) + "\n") 51 | fd.write("#define G_AT_PHNUM " + hex(ehdr.e_phnum) + "\n") 52 | 53 | random.seed(time.time()) 54 | fd.write("#define G_IMAGEBASE " + hex(page_align(random.randint(0x100000, 0xffffffff))) + "\n") 55 | 56 | with open("phdr", "wb") as fd: 57 | fd.write(phdr) 58 | 59 | os.system("xxd -i phdr >> %s" % os.path.join("./include", "embedded.h")) 60 | os.system("rm ./phdr") 61 | 62 | if __name__ == '__main__': 63 | main(sys.argv[1]) 64 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | puts("Hello World"); 6 | puts("Hello World"); 7 | puts("Hello World"); 8 | puts("Hello World"); 9 | puts("Hello World"); 10 | puts("Hello World"); 11 | puts("Hello World"); 12 | puts("Hello World"); 13 | puts("Hello World"); 14 | fopen("./hello", "rb"); 15 | exit(0); 16 | return 0; 17 | } 18 | --------------------------------------------------------------------------------