├── Dockerfile ├── Makefile ├── README.md ├── bin └── crackme ├── build_and_run.sh ├── docker-entrypoint.sh ├── layer1 ├── include │ ├── anti_debugging.h │ ├── anti_debugging.h.gch │ ├── block_cipher.h │ ├── compile_time_obfuscation.h │ ├── crc32_test.h │ ├── huffman.h │ ├── huffman_encoding.h │ ├── huffman_old.h │ ├── rc4_test.h │ ├── ul_exec.h │ └── ul_execP.h └── src │ ├── .launcher.c.swp │ ├── anti_debugging.c │ ├── block_cipher.c │ ├── crc32_test.c │ ├── embed.c │ ├── hbreaks.c │ ├── huffman.c │ ├── launcher.c │ ├── layer1.ld │ ├── libc.a │ ├── load.c │ ├── lz77.c │ ├── rc4.c │ ├── rc4_test.c │ ├── save.c │ ├── switch32.asm │ ├── ul_exec.c │ └── unmap.c ├── layer2 ├── include │ ├── c_primitives.h │ ├── huffman.h │ ├── huffman_encoding.h │ ├── ul_exec.h │ └── ul_execP.h └── src │ ├── .c_primitives.c.swp │ ├── .embed.c.swp │ ├── .launcher.asm.swp │ ├── .rc4.c.swp │ ├── c_primitives.c │ ├── embed.c │ ├── huffman.c │ ├── launcher.asm │ ├── layer2.ld │ ├── layer2_sigaction.c │ ├── libc.a │ ├── load.c │ ├── rc4.c │ ├── rc4_embed.c │ ├── save.c │ └── ul_exec.c └── reloc ├── Makefile └── reloc.c /Dockerfile: -------------------------------------------------------------------------------- 1 | from 32bit/ubuntu:16.04 2 | RUN apt-get update -y 3 | RUN apt-get install dietlibc-dev -y 4 | RUN apt-get install nasm -y 5 | RUN apt-get install make gcc -y 6 | RUN apt-get install libcapstone-dev -y 7 | RUN mkdir ./elflock 8 | COPY ./ ./elflock 9 | WORKDIR ./elflock 10 | ENTRYPOINT ["./docker-entrypoint.sh"] 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-m32 --static -funroll-loops -Os -Wall -fno-stack-protector -c -Qn -fomit-frame-pointer -fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables 3 | 4 | DIET=diet 5 | DIETFLAGS=-m32 -funroll-loops -s -Wl,-T 6 | 7 | AS=nasm 8 | ASFLAGS=-felf32 9 | 10 | LD=ld 11 | LDFLAGS=-melf_i386 -s -no-ld-generated-unwind-info -T 12 | 13 | all: layer1 layer2 final 14 | 15 | layer1: rebased layer1_embed layer1_module 16 | layer1_embed: 17 | $(CC) -m32 layer1/src/embed.c \ 18 | layer1/src/block_cipher.c \ 19 | layer1/src/crc32_test.c \ 20 | layer1/src/rc4_test.c \ 21 | -o bin/layer1_embed.bin 22 | layer1_module: 23 | $(AS) $(ASFLAGS) layer1/src/switch32.asm -o switch32.o 24 | $(CC) $(CFLAGS) layer1/src/hbreaks.c -o hbreaks.o 25 | $(DIET) $(CC) $(DIETFLAGS) layer1/src/layer1.ld \ 26 | layer1/src/load.c \ 27 | layer1/src/save.c \ 28 | layer1/src/huffman.c \ 29 | layer1/src/ul_exec.c \ 30 | layer1/src/anti_debugging.c \ 31 | layer1/src/launcher.c \ 32 | layer1/src/block_cipher.c \ 33 | layer1/src/rc4_test.c \ 34 | layer1/src/crc32_test.c \ 35 | switch32.o \ 36 | hbreaks.o \ 37 | -o bin/layer1.bin 38 | bin/layer1_embed.bin bin/layer1.bin ./bin/crackme_rebased bin/layer1_test.bin 39 | chmod 777 bin/layer1_test.bin 40 | #bin/layer1_test.bin 41 | 42 | rebased: 43 | $(CC) ./reloc/reloc.c -lcapstone -o ./bin/reloc 44 | ./bin/reloc ./bin/crackme 0x13370000 ./bin/crackme_rebased 45 | 46 | layer2: layer2_embed layer2_module 47 | layer2_embed: 48 | $(CC) layer2/src/embed.c -o bin/layer2_embed.bin 49 | layer2_module: 50 | $(AS) $(ASFLAGS) layer2/src/launcher.asm -o layer2.o 51 | $(CC) $(CFLAGS) layer2/src/huffman.c -o huffman.o 52 | $(CC) $(CFLAGS) layer2/src/rc4.c -o rc4.o 53 | $(CC) $(CFLAGS) layer2/src/layer2_sigaction.c -o sigaction.o 54 | $(CC) $(CFLAGS) layer2/src/ul_exec.c -o ul_exec.o 55 | $(CC) $(CFLAGS) layer2/src/load.c -o load.o 56 | $(CC) $(CFLAGS) layer2/src/save.c -o save.o 57 | $(LD) $(LDFLAGS) layer2/src/layer2.ld \ 58 | layer2.o \ 59 | rc4.o \ 60 | huffman.o \ 61 | ul_exec.o \ 62 | load.o \ 63 | save.o \ 64 | sigaction.o \ 65 | layer2/src/libc.a -o bin/layer2.bin 66 | bin/layer2_embed.bin bin/layer2.bin ./bin/crackme bin/layer2_test.bin True 67 | #bin/layer2_embed.bin bin/layer2.bin ./crackme bin/layer2_test.bin True 68 | chmod 777 bin/layer2_test.bin 69 | #bin/layer2_test.bin 70 | 71 | final: 72 | bin/layer2_embed.bin bin/layer2.bin bin/layer1_test.bin bin/crackme.elflocked 73 | chmod 777 bin/crackme.elflocked 74 | bin/crackme.elflocked 75 | 76 | clean: 77 | -rm ./*.o 78 | cleanall: clean 79 | -rm bin/* 80 | 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ElfLocked 2 | PoC multi-layer Protector for ELF32 binaries 3 | 4 | This protector was an old project standing as a private repository for various years now in my github account, and based that encountering ELF32 ET_EXEC binaries are currently outdated in a sense, I decided to make it public. 5 | 6 | This protector contains two layers of abstraction implementing various anti-debugging/anti-analysis techniques ranging from: 7 | * Anti Ptrace 8 | * Breakpoint traps 9 | * Self modifying code 10 | * Anti LD_PRELOAD 11 | * Parent process checks 12 | * Various Control-Flow obfuscation techniques applied on different sections: 13 | * Exception manipulation 14 | * Hardware Breakpoint manipulation 15 | * Control-Flow flattening 16 | 17 | The embedded binary is also subject to a base-relocation to make the unpacking process a bit harder. This today is a default for PIE binaries, but at the time it was not trivial to rebase an ET_EXEC ELF binary. 18 | Leaving this project here for historic purposes and hopefully to bring some light into ELF Packers/Protectors. 19 | SPOILER: This project is from 2016! coding style is terrible as it was a very old project, you have been warned :D 20 | -------------------------------------------------------------------------------- /bin/crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/bin/crackme -------------------------------------------------------------------------------- /build_and_run.sh: -------------------------------------------------------------------------------- 1 | docker build -t elflock . 2 | docker run elflock /bin/bash -c "sh docker-entrypoint.sh; /bin/bash" 3 | sudo docker cp $(sudo docker ps -l | awk -F 'elflock' '{print $1}' | awk -F 'CONTAINER' '{print $1}' | awk -F ' ' '{print $1}'):/elflock/bin/crackme.elflocked . 4 | sudo docker stop $(sudo docker ps -l | awk -F 'elflock' '{print $1}' | awk -F 'CONTAINER' '{print $1}' | awk -F ' ' '{print $1}') 5 | 6 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | make 4 | -------------------------------------------------------------------------------- /layer1/include/anti_debugging.h: -------------------------------------------------------------------------------- 1 | 2 | int crc32(char * str, int size); 3 | char *get_proc_name(char *buff); 4 | void check_parent(); 5 | void check_ld_preload(); 6 | -------------------------------------------------------------------------------- /layer1/include/anti_debugging.h.gch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer1/include/anti_debugging.h.gch -------------------------------------------------------------------------------- /layer1/include/block_cipher.h: -------------------------------------------------------------------------------- 1 | void get_num_of_chunks(int text_size, int *nchunks, int *align); 2 | void encrypt_decrypt_block(char *chunk, int chunk_size, char *key, void (*f)(char*, char*, int)); 3 | void get_next_key(char *data, int size, char *key); 4 | int get_function_for_encrypting(char* crc); 5 | void encrypt_data(int total_size, char *plain_data); 6 | void decrypt_data(int nchunks, int align, char *encrypted_data); 7 | int encrypt_buff(char *data, int size); 8 | void decrypt_buff(char *data, int size); -------------------------------------------------------------------------------- /layer1/include/compile_time_obfuscation.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define PUSH 0x50 6 | #define POP 0x58 7 | #define MOV 0xB8 8 | #define NOP 0x90 9 | #define ADD 0x01 10 | #define AND 0x21 11 | #define XOR 0x31 12 | #define OR 0x09 13 | #define SBB 0x19 14 | #define SUB 0x29 15 | #define JMP 0xeb 16 | 17 | #define weird __COUNTER__ + __LINE__ 18 | #define xstrt(...) xstr(__VA_ARGS__) 19 | #define xstr(...) str(__VA_ARGS__) 20 | #define str(...) #__VA_ARGS__ 21 | #define op(...) ".byte " __VA_ARGS__ 22 | #define junk(x) asm volatile (x); 23 | 24 | #define STOP_TRACE \ 25 | if(!fork()) { \ 26 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) \ 27 | kill(0, SIGKILL); \ 28 | ptrace(PTRACE_DETACH, 0, 0, 0); \ 29 | exit(0); \ 30 | } 31 | 32 | #define ops(...) ".byte " xstr(__VA_ARGS__) 33 | #define pre \ 34 | asm volatile( "cpuid; \n\t" \ 35 | "test %eax, %eax; \n\t" \ 36 | "call 1f+1; \n\t" \ 37 | "1:; \n\t" \ 38 | ".byte 0x31; \n\t" \ 39 | "pop %eax; \n\t" \ 40 | "je 1f+14; \n\t" \ 41 | "xadd %eax, 0x1023; \n\t" \ 42 | "jmp *%eax; \n\t"); \ 43 | junk(op(xstr(XOR+weird, ADD+weird))) \ 44 | asm volatile("1:; \n\t"); \ 45 | junk(op(xstr(SBB+weird, ADD+weird))) \ 46 | junk(op(xstr(XOR+weird, SUB+weird, NOP+weird, XOR+weird, SBB+weird, ADD+weird))) \ 47 | junk(op(xstr(XOR+weird, SUB+weird, NOP+weird, XOR+weird, SBB+weird, ADD+weird))) 48 | 49 | 50 | #define post \ 51 | asm volatile("jmp 1f; \n\t"); \ 52 | junk(op(xstr(ADD))) \ 53 | asm volatile("1:; \n\t"); 54 | 55 | #define obf(x) pre; x; post; 56 | 57 | 58 | -------------------------------------------------------------------------------- /layer1/include/crc32_test.h: -------------------------------------------------------------------------------- 1 | unsigned int xcrc32 (char *buf, int len); -------------------------------------------------------------------------------- /layer1/include/huffman.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define QSIZE 0xff + 1 4 | 5 | typedef struct __node_t { 6 | int freq; 7 | char key; 8 | bool leaf; 9 | struct __node_t *left, *right; 10 | } Node; 11 | 12 | int decode_bin(Node *root, Node *original, char *bytes, int len, uint8_t *decoded); 13 | void qinsert(Node **nodes, Node *node); 14 | void insert_node(Node **nodes, Node *left, Node *right, int freq, int key); 15 | void qdelete(Node **nodes, int idx); 16 | int get_map_len(int *freqs); 17 | void encode(Node *root, int len, char *code, int nleaf_nodes); 18 | void decode(Node *root, Node *original, char *bits, int len); 19 | void insert_leaf_nodes(int *freqs, Node **nodes); 20 | Node *create_btree(int *freqs, Node **nodes); 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /layer1/include/huffman_encoding.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define QSIZE 0x100 17 | 18 | static int qtail = -1; 19 | static char *encoding[QSIZE] = {0}, *decoding, *compressed; 20 | 21 | typedef struct __node_t { 22 | int freq; 23 | char key; 24 | bool leaf; 25 | struct __node_t *left, *right; 26 | } Node; 27 | 28 | 29 | int decode_bin(Node *root, Node *original, char *bytes, int len) { 30 | int nbyte = 0, n = 0, nbit = 7; 31 | char byte = bytes[0]; 32 | 33 | while( nbyte < len ) { 34 | while (nbit >= 0) { 35 | if(root->leaf){ 36 | *(decoding + n++) = root->key; 37 | root = original; 38 | } 39 | root = (byte & (0x1 << nbit--)) ? root = root->right : root->left; 40 | } 41 | nbit = 7; 42 | byte = bytes[++nbyte]; 43 | } 44 | return n; 45 | 46 | } 47 | 48 | int str2bin(char* bin) { 49 | char* start = &bin[0]; 50 | int total = 0; 51 | 52 | while (*start){ 53 | total <<= 1; 54 | if (*start++ == '1') total ^= 1; 55 | } 56 | return total; 57 | } 58 | 59 | char * generate_elf_ordered_bitstream(uint8_t *elf, int size) { 60 | char *ord_bitstream = (char*)calloc(sizeof(char), size*30); 61 | int i, j = 0; 62 | 63 | for( i = 0; i < size; i++) { 64 | char *buf = strdup(encoding[elf[i]]); 65 | memcpy(ord_bitstream + j, buf, strlen(buf)); 66 | j += strlen(buf); 67 | 68 | free(buf); 69 | } 70 | ord_bitstream[j] = '\0'; 71 | 72 | return ord_bitstream; 73 | } 74 | 75 | void init_elf_hash_map(uint8_t *elf, int size, int *freqs) { 76 | int i; 77 | 78 | 79 | for (i = 0; i < size; i++) { 80 | if(elf[i] == 0) { 81 | freqs[0] += 1; 82 | } else { 83 | freqs[elf[i]] += 1; 84 | } 85 | } 86 | } 87 | 88 | unsigned char *binary2hex(char *ord_bitstream, int rsize, int *size){ 89 | unsigned char *hexstr = calloc(1, strlen(ord_bitstream)); 90 | unsigned char four[8]; 91 | int i, j = 0; 92 | 93 | 94 | for(i = 0; i < rsize / 8; ++i){ 95 | int hexnum = 0; 96 | memcpy(four, ord_bitstream + (i * 8), 8); 97 | 98 | hexnum = (int)str2bin(four); 99 | hexstr[j] = hexnum & 0xff; 100 | j+=1; 101 | } 102 | *size = j; 103 | return hexstr; 104 | } 105 | 106 | unsigned char * dc_bin2hex(char *ord_bitstream, int *size) { 107 | 108 | int half = strlen(ord_bitstream) / 2; 109 | int rsize, lsize; 110 | 111 | char * str1 = binary2hex(ord_bitstream, strlen(ord_bitstream), &rsize); 112 | char * hexstr = calloc(1, rsize); 113 | 114 | 115 | memcpy(hexstr, str1, rsize); 116 | *size = rsize; 117 | 118 | free(str1); 119 | return hexstr; 120 | 121 | } 122 | 123 | void qinsert(Node **nodes, Node *node){ 124 | int i = 0, j = 0; 125 | 126 | if(qtail == -1) { 127 | nodes[++qtail] = node; 128 | return; 129 | }else{ 130 | j = qtail+1; 131 | for(i = qtail; i >= 0; i--){ 132 | if(node->freq <= nodes[i]->freq) { 133 | nodes[j--] = nodes[i]; 134 | nodes[i] = node; 135 | }else{ 136 | nodes[j] = node; 137 | break; 138 | } 139 | 140 | } 141 | qtail += 1; 142 | return; 143 | } 144 | } 145 | 146 | void insert_node(Node **nodes, Node *left, Node *right, int freq, int key) { 147 | Node *node = (Node*) calloc(1, sizeof(Node)); 148 | 149 | if(!freq && !key) { 150 | node->freq = left->freq + right->freq; 151 | node->key = 0; 152 | node->leaf = false; 153 | node->left = left; 154 | node->right = right; 155 | }else{ 156 | node->freq = freq; 157 | node->key = key; 158 | node->leaf = true; 159 | node->left = NULL; 160 | node->right = NULL; 161 | } 162 | qinsert(nodes, node); 163 | } 164 | 165 | void qdelete(Node **nodes, int idx) { 166 | int i; 167 | 168 | for (i = idx; i < qtail; i++) { 169 | nodes[i] = nodes[i+1]; 170 | } 171 | qtail--; 172 | } 173 | 174 | int get_map_len(int *freqs) { 175 | int num = 0; 176 | 177 | 178 | for(int i = 0; i < QSIZE; i++) 179 | if(freqs[i] != 0) num++; 180 | return num; 181 | } 182 | 183 | void encode(Node *root, int len, char *code, int nleaf_nodes) { 184 | 185 | if(root->leaf) { 186 | *(code + len) = '\0'; 187 | char * cpy = strdup(code); 188 | // printf("%02x: %s\n", root->key & 0xff, cpy); 189 | encoding[root->key & 0xff] = cpy; 190 | return; 191 | }else{ 192 | code[len] = '1'; 193 | encode(root->right, len + 1, code, nleaf_nodes); 194 | 195 | code[len] = '0'; 196 | encode(root->left, len + 1, code, nleaf_nodes); 197 | } 198 | } 199 | 200 | void insert_leaf_nodes(int *freqs, Node **nodes) { 201 | int i = 0; 202 | 203 | while(i < QSIZE) { 204 | if (freqs[i] != 0) { 205 | insert_node(nodes, NULL, NULL, freqs[i], i); 206 | } 207 | i++; 208 | } 209 | } 210 | 211 | Node *create_btree(int *freqs, Node **nodes) { 212 | insert_leaf_nodes(freqs, nodes); 213 | 214 | while(qtail > 0){ 215 | Node *left = *nodes; 216 | Node *right = *(nodes + 1); 217 | 218 | qdelete(nodes, 0); 219 | insert_node(nodes, left, right, 0, 0); 220 | qdelete(nodes, 0); 221 | } 222 | return nodes[0]; 223 | } 224 | 225 | char * generate_ordered_bitstream(int sect_sz, int sect_off, uint8_t *elf) { 226 | int i; 227 | char *ord_bitstream = (char*) calloc(1, (sect_sz*30)*sizeof(char)); 228 | 229 | for( i = 0; i < sect_sz; i++) { 230 | char *buf = strdup(encoding[elf[sect_off+i]]); 231 | strcat(ord_bitstream, buf); 232 | free(buf); 233 | } 234 | 235 | return ord_bitstream; 236 | } 237 | 238 | 239 | void check_parent() { 240 | char buff[32]; 241 | int fd; 242 | 243 | snprintf(buff, 24, "/proc/%d/status", getppid()); 244 | 245 | if((fd = open(buff, O_RDONLY)) < 0) { 246 | return; 247 | } 248 | read(fd, buff, 16); 249 | close(fd); 250 | 251 | if(strstr(buff, "r2") || strstr(buff, "radare2") || strstr(buff, "gdb") || strstr(buff, "ida") || strstr(buff, "trace")) { 252 | kill(0, SIGTERM); 253 | } 254 | } 255 | 256 | void check_ld_preload() { 257 | int k = 0; 258 | 259 | char *str = getenv("LD_PRELOAD"); 260 | 261 | if(str == NULL) { 262 | putenv("LD_PRELOAD=Fasces"); 263 | if (strcmp(getenv("LD_PRELOAD"), "Fasces")){ 264 | kill(0, SIGTERM); 265 | } 266 | }else{ 267 | kill(0, SIGTERM); 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /layer1/include/huffman_old.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #define QSIZE 0x100 16 | #define PAGE_SIZE 0x1000 17 | #define PAGE_ROUND_UP(x) ( (((unsigned int)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1)) ) 18 | 19 | typedef struct __node_t { 20 | int freq; 21 | char key; 22 | bool leaf; 23 | struct __node_t *left, *right; 24 | } Node; 25 | 26 | extern int freqs[QSIZE]; 27 | extern char *decoding; 28 | extern void ul_exec(char *progname, void *ELF_buf, size_t elf_buf_size, int argc, char **argv, char **envp); 29 | //extern int decode_bin(Node *root, Node *original, char *bytes, int len); 30 | int decode_bin(Node *root, Node *original, char *bytes, int len, uint8_t *decoded); 31 | extern int str2bin(char* bin); 32 | extern char * generate_elf_ordered_bitstream(uint8_t *elf, int size); 33 | extern void init_elf_hash_map(uint8_t *elf, int size, int *freqs); 34 | extern unsigned char *binary2hex(char *ord_bitstream, int rsize, int *size); 35 | extern unsigned char * dc_bin2hex(char *ord_bitstream, int *size); 36 | extern void qinsert(Node **nodes, Node *node); 37 | extern void insert_node(Node **nodes, Node *left, Node *right, int freq, int key); 38 | extern void qdelete(Node **nodes, int idx); 39 | extern int get_map_len(int *freqs); 40 | extern void encode(Node *root, int len, char *code, int nleaf_nodes); 41 | extern void insert_leaf_nodes(int *freqs, Node **nodes); 42 | extern Node *create_btree(int *freqs, Node **nodes); 43 | extern char * generate_ordered_bitstream(int sect_sz, int sect_off, uint8_t *elf); 44 | 45 | -------------------------------------------------------------------------------- /layer1/include/rc4_test.h: -------------------------------------------------------------------------------- 1 | void swap(unsigned char *a, unsigned char *b); 2 | int KSA(char *key, unsigned char *S); 3 | int PRGA(unsigned char *S, char *plaintext, int size); 4 | int RC4(char *key, char *plaintext, int size); -------------------------------------------------------------------------------- /layer1/include/ul_exec.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef USERLAND_EXEC_H_ 3 | #define USERLAND_EXEC_H_ 1 4 | 5 | void ul_exec(char *progname, void *ELF_buf, size_t elf_buf_size, int argc, char **argv, char **envp); 6 | 7 | #endif /* USERLAND_EXEC_H_ */ 8 | -------------------------------------------------------------------------------- /layer1/include/ul_execP.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #ifndef USERLAND_EXEC_PRIV_H_ 6 | #define USERLAND_EXEC_PRIV_H_ 1 7 | 8 | typedef struct ul_args ul_args_t; 9 | 10 | 11 | extern ul_args_t *ul_save_args(int argc, char **argv); 12 | extern ul_args_t *ul_save_elfauxv(char **envp); 13 | extern void ul_release_args(ul_args_t *args); 14 | extern void * ul_setup_stack(ul_args_t *args, ul_args_t *envp, ul_args_t *auxvp, Elf32_Ehdr *elf,Elf32_Ehdr *interp); 15 | extern int ul_load_elf(uint8_t *ELF_buf, Elf32_Ehdr **elf, Elf32_Ehdr **interp); 16 | void *memcopy(void *dest, const void *src, size_t n); 17 | void unmap(char *progname, int set_signal_handler); 18 | void print_maps(void); 19 | 20 | #define ROUNDUP(x, y) ( ( ( x + ( y - 1 ) ) / y ) * y ) 21 | #define ALLOCATE(size) \ 22 | mmap(0, (size), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 23 | #define ALIGN(k, v) (((k)+((v)-1))&(~((v)-1))) 24 | #define ALIGNDOWN(k, v) ((unsigned int)(k)&(~((unsigned int)(v)-1))) 25 | 26 | /* Default VM page size in bytes. Hopefully, ul_save_elfauxv() will find 27 | * the page size in the ELF auxilliary vector and use that value instead. */ 28 | #define PAGESIZE 0x1000 29 | 30 | #endif /* USERLAND_EXEC_PRIV_H_ */ 31 | -------------------------------------------------------------------------------- /layer1/src/.launcher.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer1/src/.launcher.c.swp -------------------------------------------------------------------------------- /layer1/src/anti_debugging.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../include/anti_debugging.h" 12 | 13 | int crc32(char * str, int size){ 14 | int aux; 15 | unsigned int kk; 16 | char current_char; 17 | 18 | kk = 0xFFFFFFFF; 19 | size = strlen(str); 20 | 21 | for (int i = 0; i < size; i++){ 22 | current_char = str[i]; 23 | for (int k = 0; k < 8; k++){ 24 | aux = kk ^ current_char; 25 | kk = kk >> 1; 26 | if (aux & 0x1) 27 | kk ^= 0xEDB88320; 28 | 29 | current_char = current_char >> 1; 30 | } 31 | } 32 | return kk; 33 | } 34 | 35 | char *get_proc_name(char *buff){ 36 | char *init, *end, *name; 37 | 38 | init = strstr(buff, "\t"); 39 | end = strstr(init, "\n"); 40 | 41 | name = (char *) calloc(sizeof(char), end - init); 42 | memcpy(name, init + 1, end - init); 43 | name[end - init - 1] = 0x00; 44 | return name; 45 | } 46 | 47 | void check_parent() { 48 | char buff[24]; 49 | char *proc_name; 50 | int fd, crc; 51 | 52 | snprintf(buff, 24, "/proc/%d/status", getppid()); 53 | if((fd = open(buff, O_RDONLY)) < 0) { 54 | return; 55 | } 56 | memset(buff, '\0', 24); 57 | read(fd, buff, 24); 58 | close(fd); 59 | 60 | proc_name = get_proc_name(buff); 61 | crc = crc32(proc_name, strlen(proc_name)); 62 | 63 | // r2 - radare2 - gdb - idaq - idaq64 - strace - linux_server - linux_serverx64 64 | if (!(crc - 0x6bf8a7f4) || 65 | !(crc - 0xb2cc0ecb) || 66 | !(crc - 0xef0b559f) || 67 | !(crc - 0x8cafe0da) || 68 | !(crc - 0x73752682) || 69 | !(crc - 0x34f2038f) || 70 | !(crc - 0xb67665d3) || 71 | !(crc - 0xdc699c1c)) 72 | kill(0, SIGTERM); 73 | free(proc_name); 74 | } 75 | 76 | void check_ld_preload() { 77 | char *str = getenv("LD_PRELOAD"); 78 | 79 | if(str == NULL) { 80 | putenv("LD_PRELOAD=ELFlock"); 81 | if (strcmp(getenv("LD_PRELOAD"), "ELFlock")) 82 | kill(0, SIGTERM); 83 | } else { 84 | kill(0, SIGTERM); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /layer1/src/block_cipher.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../include/anti_debugging.h" 5 | #include "../include/rc4_test.h" 6 | #include "../include/crc32_test.h" 7 | 8 | #define BLOCKSIZE (16 * 1112) 9 | #define A_RC4 0x0 10 | #define A_RC5 0x1 11 | #define A_AES 0x2 12 | #define A_3DES 0x3 13 | #define A_SERPENT 0x4 14 | 15 | typedef void (*generic_encrypt_decrypt)(char *, char *, int); 16 | 17 | //char str[] = "Rnremitting scientific effort over the past 400 years has yielded an astonishing amount of information about the world we inhabit. By rights we ought to be very impressed and extremely interested. Unfortunately many of us simply aren't. Far from attracting the best candidates, science is proving a less and less popular subject in schools. And, with a few notable exceptions, popular books on scientific topics are a rare bird in the bestseller lists. Bill Bryson, the travel-writing phenomenon, thinks he knows what has gone wrong."; 18 | 19 | void get_num_of_chunks(int text_size, int *nchunks, int *align){ 20 | *nchunks = text_size/BLOCKSIZE; 21 | *align = text_size - BLOCKSIZE * *nchunks; 22 | } 23 | 24 | /* 25 | ALGORITHM TABLE: 26 | 0000 RC4 27 | 0001 RC5 28 | 0010 3DES 29 | 0011 AES 30 | 0100 SERPENT 31 | */ 32 | 33 | generic_encrypt_decrypt *ENCRYPTION_ARRAY[5] = { 34 | (generic_encrypt_decrypt*)RC4, // 0000 35 | (generic_encrypt_decrypt*)RC4, // 0001 36 | (generic_encrypt_decrypt*)RC4, // 0010 37 | (generic_encrypt_decrypt*)RC4, // 0011 38 | (generic_encrypt_decrypt*)RC4 // 0100 39 | }; 40 | 41 | void encrypt_decrypt_block(char *chunk, int chunk_size, char *key, void (*f)(char*, char*, int)){ 42 | (*f)(key, chunk, chunk_size); 43 | } 44 | 45 | void get_next_key(char *data, int size, char *key){ 46 | for(int i = 0; i < 4; i++) { 47 | int crc = xcrc32(data, size); 48 | memcpy(key + i * 4, &crc, sizeof(int)); 49 | } 50 | 51 | } 52 | 53 | /* 54 | Returns a constant that represents a encryption algorithm 55 | The returned algorithm depends on the last crc byte value 56 | */ 57 | 58 | int get_function_for_encrypting(char* crc){ 59 | switch (*crc & 0xF) { 60 | case A_RC4: 61 | return A_RC4; 62 | case A_RC5: 63 | return A_RC5; 64 | case A_AES: 65 | return A_AES; 66 | case A_3DES: 67 | return A_3DES; 68 | case A_SERPENT: 69 | return A_SERPENT; 70 | default: 71 | return A_RC4; 72 | }; 73 | } 74 | 75 | void encrypt_data(int total_size, char *plain_data){ 76 | int nchunks, align; 77 | int i; 78 | char key[] = "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"; 79 | get_num_of_chunks(total_size, &nchunks, &align); 80 | 81 | 82 | for (i = 0; i < nchunks; i++) { 83 | // Encrpt chunk with selected encrypt algorithm and gotten key 84 | encrypt_decrypt_block(plain_data + i * BLOCKSIZE, 85 | BLOCKSIZE, 86 | key, 87 | (void (*)(char *, char *, int))ENCRYPTION_ARRAY[get_function_for_encrypting(key)]); 88 | /* 89 | Get key from the last encrypted chunk. 90 | This key will be used to encrypt the next chunk. 91 | key = crc(encrypted-chunk).crc(encrypted-chunk) 92 | */ 93 | get_next_key(plain_data + i * BLOCKSIZE, BLOCKSIZE, key); 94 | } 95 | 96 | /* 97 | In this case, we are going to use always an encryption algorithm which encrypts in stream mode, 98 | because when there is align means the block is not multiple of BLOCKSIZE so (not in all cases) it is not 99 | valid to be encrypted with encryption algorithms which uses blocks for encryption. 100 | RC4, RC5, SERPENT... are possible candidates. 101 | */ 102 | if (align) { 103 | 104 | encrypt_decrypt_block(plain_data + i * BLOCKSIZE, 105 | align, 106 | key, 107 | (void (*)(char *, char *, int))ENCRYPTION_ARRAY[get_function_for_encrypting(key)]); 108 | } 109 | } 110 | 111 | 112 | void decrypt_data(int nchunks, int align, char *encrypted_data){ 113 | char key[16]; 114 | int last_chunk_size = align; 115 | 116 | 117 | if (align && nchunks) { 118 | get_next_key(encrypted_data + (nchunks - 1) * BLOCKSIZE, BLOCKSIZE, key); 119 | encrypt_decrypt_block(encrypted_data + nchunks * BLOCKSIZE, 120 | align, 121 | key, 122 | (void (*)(char *, char *, int))ENCRYPTION_ARRAY[get_function_for_encrypting(key)]); 123 | last_chunk_size = BLOCKSIZE; 124 | } 125 | 126 | for (int i = nchunks - 1 ; i >= 1; i--) { 127 | get_next_key(encrypted_data + (i - 1) * BLOCKSIZE, BLOCKSIZE, key); 128 | encrypt_decrypt_block(encrypted_data + i * BLOCKSIZE, 129 | BLOCKSIZE, 130 | key, 131 | (void (*)(char *, char *, int))ENCRYPTION_ARRAY[get_function_for_encrypting(key)]); 132 | } 133 | 134 | 135 | char key1[16] = "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"; 136 | encrypt_decrypt_block(encrypted_data + 0 * BLOCKSIZE, 137 | last_chunk_size, 138 | key1, 139 | (void (*)(char *, char *, int))ENCRYPTION_ARRAY[get_function_for_encrypting(key1)]); 140 | 141 | 142 | } 143 | 144 | 145 | int encrypt_buff(char *data, int size){ 146 | 147 | encrypt_data(size, data); 148 | return 1; 149 | } 150 | 151 | 152 | void decrypt_buff(char *data, int size){ 153 | int nchunks = 0; 154 | int align = 0; 155 | 156 | get_num_of_chunks(size, &nchunks, &align); 157 | decrypt_data(nchunks, align, data); 158 | } 159 | 160 | /* 161 | int main( int argc, char *argv[]) { 162 | int num_chunks = 0; 163 | int align = 0; 164 | int size; 165 | //int i; 166 | 167 | size = strlen(str); // Viene dado por el size del header 168 | get_num_of_chunks(size, &num_chunks, &align); 169 | 170 | printf("[+] PLAIN TEXT:\n%s\n\n", str); 171 | printf("\t[*] BLOCKSIZE: %d, BLOCKS: %d, ALIGN: %d DATALEN: %d\n\n", BLOCKSIZE, num_chunks, align, size); 172 | encrypt(str, size); 173 | //printf("\n"); 174 | //printf("[+] CRYPTED TEXT(HEX): \n"); 175 | //for (i = 0; i < size; i++) { 176 | // printf("%02hhX ", str[i]); 177 | //} 178 | decrypt(str, size); 179 | //printf("\n"); 180 | printf("[+] DECRYPTED TEXT:\n%s\n", str); 181 | return 0; 182 | } */ 183 | 184 | -------------------------------------------------------------------------------- /layer1/src/crc32_test.c: -------------------------------------------------------------------------------- 1 | /* crc32.c 2 | Copyright (C) 2009-2017 Free Software Foundation, Inc. 3 | This file is part of the libiberty library. 4 | This file is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | In addition to the permissions in the GNU General Public License, the 9 | Free Software Foundation gives you unlimited permission to link the 10 | compiled version of this file into combinations with other programs, 11 | and to distribute those combinations without any restriction coming 12 | from the use of this file. (The General Public License restrictions 13 | do apply in other respects; for example, they cover modification of 14 | the file, and distribution when not linked into a combined 15 | executable.) 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 23 | */ 24 | 25 | 26 | /* This table was generated by the following program. 27 | #include 28 | int 29 | main () 30 | { 31 | unsigned int i, j; 32 | unsigned int c; 33 | int table[256]; 34 | for (i = 0; i < 256; i++) 35 | { 36 | for (c = i << 24, j = 8; j > 0; --j) 37 | c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); 38 | table[i] = c; 39 | } 40 | printf ("static const unsigned int crc32_table[] =\n{\n"); 41 | for (i = 0; i < 256; i += 4) 42 | { 43 | printf (" 0x%08x, 0x%08x, 0x%08x, 0x%08x", 44 | table[i + 0], table[i + 1], table[i + 2], table[i + 3]); 45 | if (i + 4 < 256) 46 | putchar (','); 47 | putchar ('\n'); 48 | } 49 | printf ("};\n"); 50 | return 0; 51 | } 52 | For more information on CRC, see, e.g., 53 | http://www.ross.net/crc/download/crc_v3.txt. */ 54 | 55 | static const unsigned int crc32_table[] = 56 | { 57 | 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 58 | 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 59 | 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 60 | 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 61 | 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 62 | 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 63 | 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 64 | 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 65 | 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 66 | 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 67 | 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 68 | 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 69 | 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 70 | 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 71 | 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 72 | 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 73 | 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 74 | 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 75 | 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 76 | 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 77 | 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 78 | 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 79 | 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 80 | 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 81 | 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 82 | 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 83 | 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 84 | 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 85 | 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 86 | 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 87 | 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 88 | 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 89 | 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 90 | 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 91 | 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 92 | 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 93 | 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 94 | 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 95 | 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 96 | 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 97 | 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 98 | 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 99 | 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 100 | 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 101 | 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 102 | 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 103 | 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 104 | 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 105 | 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 106 | 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 107 | 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 108 | 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 109 | 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 110 | 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 111 | 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 112 | 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 113 | 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 114 | 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 115 | 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 116 | 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 117 | 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 118 | 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 119 | 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 120 | 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 121 | }; 122 | 123 | /* 124 | @deftypefn Extension {unsigned int} crc32 (const unsigned char *@var{buf}, @ 125 | int @var{len}, unsigned int @var{init}) 126 | Compute the 32-bit CRC of @var{buf} which has length @var{len}. The 127 | starting value is @var{init}; this may be used to compute the CRC of 128 | data split across multiple buffers by passing the return value of each 129 | call as the @var{init} parameter of the next. 130 | This is used by the @command{gdb} remote protocol for the @samp{qCRC} 131 | command. In order to get the same results as gdb for a block of data, 132 | you must pass the first CRC parameter as @code{0xffffffff}. 133 | This CRC can be specified as: 134 | Width : 32 135 | Poly : 0x04c11db7 136 | Init : parameter, typically 0xffffffff 137 | RefIn : false 138 | RefOut : false 139 | XorOut : 0 140 | This differs from the "standard" CRC-32 algorithm in that the values 141 | are not reflected, and there is no final XOR value. These differences 142 | make it easy to compose the values of multiple blocks. 143 | @end deftypefn 144 | */ 145 | 146 | unsigned int 147 | xcrc32 (char *buf, int len) 148 | { 149 | unsigned int crc = -1; 150 | while (len--) 151 | { 152 | crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255]; 153 | buf++; 154 | } 155 | return crc; 156 | } -------------------------------------------------------------------------------- /layer1/src/embed.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "../include/huffman_encoding.h" 13 | #include "../include/block_cipher.h" 14 | 15 | void file_export(uint8_t *elf, int size, char* name) { 16 | int fd; 17 | 18 | fd = open(name , O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); 19 | write(fd, elf, size); 20 | close(fd); 21 | 22 | return; 23 | } 24 | 25 | uint8_t* alloc_file(int *fd, struct stat *st, const char *filename) { 26 | uint8_t *elf; 27 | 28 | if((*fd = open(filename, O_RDWR)) < 0) { 29 | perror("exit"); 30 | exit(-1); 31 | } 32 | 33 | if(fstat(*fd, st) < 0) { 34 | perror("fstat"); 35 | exit(-1); 36 | } 37 | 38 | if((elf = mmap(NULL, st->st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) { 39 | perror("mmap"); 40 | exit(-1); 41 | } 42 | 43 | return elf; 44 | } 45 | 46 | int encrypt_text(uint8_t *elf, int *addr) { 47 | int i, j, size = 0, offset = 0; 48 | uint8_t *off, *strtab; 49 | Elf32_Shdr *shdr; 50 | 51 | Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf; 52 | shdr = (Elf32_Shdr*)&elf[ehdr->e_shoff]; 53 | strtab = (char*)(&elf[shdr[ehdr->e_shstrndx].sh_offset]); 54 | 55 | for(i = 1; i < ehdr->e_shnum; i++){ 56 | if (strstr(&strtab[shdr[i].sh_name], ".text")) { 57 | size = shdr[i].sh_size; 58 | offset = shdr[i].sh_offset; 59 | *addr = shdr[i].sh_addr; 60 | } 61 | } 62 | off = (uint8_t*)((char*)elf + offset); 63 | 64 | encrypt_buff(off, size); 65 | return size; 66 | } 67 | 68 | int encript_lookup(uint8_t *elf, unsigned int *addr) { 69 | int i, j, size = 0, offset = 0; 70 | uint8_t *off, *strtab; 71 | Elf32_Shdr *shdr; 72 | 73 | Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf; 74 | shdr = (Elf32_Shdr*)&elf[ehdr->e_shoff]; 75 | strtab = (char*)(&elf[shdr[ehdr->e_shstrndx].sh_offset]); 76 | 77 | for(i = 1; i < ehdr->e_shnum; i++){ 78 | if (strstr(&strtab[shdr[i].sh_name], ".switch_main")) { 79 | size = shdr[i].sh_size; 80 | offset = shdr[i].sh_offset; 81 | *addr = shdr[i].sh_addr; 82 | } 83 | } 84 | off = (uint8_t*)((char*)elf + offset); 85 | 86 | encrypt_buff(off, size); 87 | return size; 88 | } 89 | 90 | int encript_case9(uint8_t *elf, unsigned int *addr) { 91 | int i, j, size = 0, offset = 0; 92 | uint8_t *off, *strtab; 93 | Elf32_Shdr *shdr; 94 | 95 | Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf; 96 | shdr = (Elf32_Shdr*)&elf[ehdr->e_shoff]; 97 | strtab = (char*)(&elf[shdr[ehdr->e_shstrndx].sh_offset]); 98 | 99 | for(i = 1; i < ehdr->e_shnum; i++){ 100 | if (strstr(&strtab[shdr[i].sh_name], ".case9")) { 101 | size = shdr[i].sh_size; 102 | offset = shdr[i].sh_offset; 103 | *addr = shdr[i].sh_addr; 104 | } 105 | } 106 | off = (uint8_t*)((char*)elf + offset); 107 | 108 | for (int i = 0; i < size; i++) { 109 | *(uint8_t*)(off + i) ^= 0xff; 110 | } 111 | return size; 112 | } 113 | 114 | int main (int argc, char **argv) { 115 | uint8_t *elf1, *elf2, *f; 116 | struct stat st1, st2; 117 | int fd1, fd2, i, stub_size, 118 | nleaf_nodes, freqs[0x100] = {0}, 119 | elf_offset, elf_align, text_size, text_addr, prev_code; 120 | char *ord_bitstream, *c, *hexstr; 121 | Elf32_Ehdr *ehdr1, *ehdr2, *ehdr3; 122 | Elf32_Phdr *phdr, *code; 123 | Elf32_Shdr *shdr; 124 | Node **nodes; 125 | 126 | if(argc != 4) { 127 | fprintf(stderr, "Usage %s \n", argv[0]); 128 | exit(0); 129 | } 130 | 131 | if((f = mmap(NULL, 0x10000000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED) { 132 | perror("mmap"); 133 | exit(-1); 134 | } 135 | 136 | elf1 = alloc_file(&fd1, &st1, argv[1]); 137 | elf2 = alloc_file(&fd2, &st2, argv[2]); 138 | 139 | if(elf1[0] != 0x7f && strcmp((char*)&elf1[1], "ELF")){ 140 | fprintf(stderr, "[!] File 1 is not an elf file\n"); 141 | exit(-1); 142 | } 143 | 144 | if(elf2[0] != 0x7f && strcmp((char*)&elf2[1], "ELF")){ 145 | fprintf(stderr, "[!] File 2 is not an elf file\n"); 146 | exit(-1); 147 | } 148 | 149 | ehdr1 = (Elf32_Ehdr*)elf1; 150 | ehdr2 = (Elf32_Ehdr*)elf2; 151 | 152 | if(ehdr2->e_machine != EM_386) { 153 | printf("[-] Nodus does not support Binaries that isn't x86.\n"); 154 | exit(EXIT_FAILURE); 155 | } 156 | 157 | if(ehdr2->e_type != ET_EXEC) { 158 | printf("[-] Nodus does not support ET_DYN\n"); 159 | exit(EXIT_FAILURE); 160 | } 161 | 162 | if(ehdr2->e_version != EV_CURRENT) { 163 | printf("[-] Not a \"current\" ELF file.\n"); 164 | return -1; 165 | } 166 | 167 | if(ehdr2->e_ehsize != sizeof(Elf32_Ehdr) || ehdr2->e_phentsize != sizeof(Elf32_Phdr) || 168 | ehdr2->e_phnum > 20) { 169 | printf("[-] Instubid ELF header sizes\n"); 170 | return -1; 171 | } 172 | memset(elf2, 0, 4); // deleating magic header from blob 173 | printf("[+] ELF magic deleated from stub: (%s)\n", elf2); 174 | printf("[*] Packing file %s\n", argv[2]); 175 | phdr = (Elf32_Phdr*)&elf1[ehdr1->e_phoff]; 176 | 177 | for (i = 0; i < ehdr1->e_phnum; i++) { 178 | if (phdr[i].p_type == PT_LOAD && !phdr[i].p_offset) { 179 | code = &phdr[i]; 180 | break; 181 | } 182 | } 183 | 184 | 185 | unsigned int case9_addr, case9_size; 186 | if(!(case9_size = encript_case9(elf1, &case9_addr))) { 187 | printf("[-] section .switch_main not found\n"); 188 | exit(EXIT_FAILURE); 189 | } 190 | printf("[*] Target binary switch_main section @ 0x%x of size : %d encrypted\n", case9_addr, case9_size); 191 | 192 | if(!(text_size = encrypt_text(elf2, &text_addr))){ 193 | printf("[-] Text section target binary was not found\n"); 194 | exit(EXIT_FAILURE); 195 | } 196 | printf("[*] Target binary text section @ 0x%x of size : %d encrypted\n",text_addr, text_size); 197 | 198 | 199 | unsigned int lookup_addr, lookup_size; 200 | if(!(lookup_size = encript_lookup(elf1, &lookup_addr))) { 201 | printf("[-] section .switch_main not found\n"); 202 | exit(EXIT_FAILURE); 203 | } 204 | printf("[*] Target binary switch_main section @ 0x%x of size : %d encrypted\n",lookup_addr, lookup_size); 205 | 206 | 207 | printf("[*] compressing target binary via huffman encoding\n"); 208 | decoding = (char*)calloc(sizeof(char), st2.st_size); 209 | c = (char*)calloc(sizeof(char), (st2.st_size*10)); 210 | 211 | printf("[+] Initialization of frequency table\n"); 212 | init_elf_hash_map(elf2, st2.st_size, freqs); 213 | nleaf_nodes = get_map_len(freqs); 214 | 215 | printf("[+] Length of frequency dictionary: %d\n", nleaf_nodes); 216 | nodes = (Node**)calloc(1, nleaf_nodes*sizeof(Node)); 217 | 218 | printf("[+] Creating binary tree\n"); 219 | Node *btree = create_btree(freqs, nodes); 220 | 221 | printf("[+] Generating master tree\n"); 222 | encode(btree, 0, c, nleaf_nodes); 223 | 224 | printf("[*] Generating bitstream of target file\n"); 225 | ord_bitstream = generate_elf_ordered_bitstream(elf2, st2.st_size); 226 | 227 | printf("[*] Converting bitstream into hex\n"); 228 | unsigned char *stub = dc_bin2hex(ord_bitstream, &stub_size); 229 | memset(ord_bitstream, '\0', strlen(ord_bitstream)); 230 | printf("[*] Compression ratio: %.2f%%\n", (float)stub_size / st2.st_size * 100); 231 | 232 | prev_code = code->p_filesz; 233 | code->p_filesz = code->p_memsz + stub_size + sizeof(freqs); 234 | code->p_memsz = code->p_filesz; 235 | 236 | code->p_flags = PF_X | PF_W | PF_R; 237 | elf_offset = prev_code; 238 | 239 | memmove(f + code->p_offset, elf1 + code->p_offset, prev_code); 240 | memmove(f + elf_offset, freqs, sizeof(freqs)); 241 | memmove(f + elf_offset + sizeof(freqs), stub, stub_size); 242 | 243 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 244 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 245 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 246 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 247 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 248 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 249 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 250 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 251 | encrypt_buff((char*)f + elf_offset + sizeof(freqs), stub_size ); 252 | 253 | ehdr3 = (Elf32_Ehdr*)f; 254 | *(uint32_t*)&ehdr3->e_ident[8] = elf_offset; 255 | *(uint32_t*)&ehdr3->e_ident[12] = (uint32_t)(stub_size); 256 | *(uint8_t*)&ehdr3->e_ident[5]='\x02'; 257 | *(uint32_t*)&ehdr3->e_shoff = (uint32_t)(text_addr); 258 | *(uint32_t*)&ehdr3->e_flags = (uint32_t)(text_size); 259 | 260 | ehdr3->e_phnum = 1; 261 | ehdr3->e_shnum = 0; 262 | ehdr3->e_shstrndx = 0; 263 | ehdr3->e_shentsize = 0; 264 | 265 | file_export(f, code->p_filesz, argv[3]); 266 | printf("[*] File exported with name %s\n", argv[3]); 267 | } 268 | -------------------------------------------------------------------------------- /layer1/src/hbreaks.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | extern void sigHandler(); 18 | extern void case9(void); 19 | extern void case9_end(void); 20 | enum { EXECUTE=0, WRITE=1, READ_WRITE=3 }; 21 | 22 | 23 | void my_delta1(void) { 24 | size_t size = case9_end - case9; 25 | unsigned char *case9_bytes = (unsigned char*)case9; 26 | int i; 27 | 28 | for(i = 0; i < size; i++) { 29 | *(unsigned char*)(case9_bytes + i) ^= 0xff; 30 | } 31 | 32 | puts(""); 33 | 34 | return; 35 | } 36 | 37 | void my_delta0(void) { 38 | set_hbreak(0, 0, 0); 39 | set_hbreak(0, 0, 1); 40 | set_hbreak(0, 0, 2); 41 | set_hbreak(0, 0, 3); 42 | 43 | unset_hbreak_handler(); 44 | case9(); 45 | return; 46 | } 47 | 48 | int safe_ptrace(int request, int pid, unsigned int* addr, void * data){ 49 | int result; 50 | errno = 0; 51 | result = ptrace(request, pid, addr, data); 52 | if(errno){ 53 | kill(0, SIGBUS); 54 | } 55 | return result; 56 | } 57 | 58 | static int debug_reg(int pid, int regnum){ 59 | return safe_ptrace( 60 | PTRACE_PEEKUSER, pid, 61 | (unsigned int*)offsetof(struct user, u_debugreg[regnum]), 0 62 | ); 63 | } 64 | 65 | static int set_debug_reg(int pid, int regnum, unsigned int value){ 66 | return safe_ptrace( 67 | PTRACE_POKEUSER, pid, 68 | (unsigned int*)offsetof(struct user, u_debugreg[regnum]), (void*)value 69 | ); 70 | } 71 | 72 | static int bit_replace(int old_val, int lsb, int size, int new_val){ 73 | int mask = (-1 << (size+lsb)) | ((1 << lsb) - 1); 74 | return (old_val & mask) | (new_val << lsb); 75 | } 76 | 77 | static void setup_control_reg(int pid, int regnum, int len, int when){ 78 | int dr7 = debug_reg(pid, 7); 79 | 80 | dr7 = bit_replace(dr7, 18 + 4*regnum, 2, len-1); 81 | dr7 = bit_replace(dr7, 16 + 4*regnum, 2, when); 82 | dr7 |= 3 << (2*regnum); 83 | set_debug_reg(pid, 7, dr7); 84 | } 85 | 86 | 87 | static void sig_handler(int nsig, siginfo_t *siginfo, void *ptr_context) { 88 | int val; 89 | switch(nsig){ 90 | case SIGTRAP: 91 | { 92 | int reg_esi; 93 | unsigned int delta; 94 | 95 | asm volatile ("movl %%esi, %0;" : "=g" (reg_esi)); 96 | ucontext_t *context = (ucontext_t *)ptr_context; 97 | if(reg_esi == 1) 98 | my_delta0(); 99 | else 100 | my_delta1(); 101 | } 102 | break; 103 | } 104 | return; 105 | } 106 | 107 | void set_hbreak_handler(void) { 108 | struct sigaction s; 109 | 110 | s.sa_sigaction = sig_handler; 111 | s.sa_flags = SA_SIGINFO; 112 | sigaction(SIGTRAP, &s, NULL); 113 | return; 114 | } 115 | 116 | void set_hbreak(unsigned long *target, int type, int n) { 117 | pid_t child, parent; 118 | int returned_pid, status; 119 | parent = getpid(); 120 | //prctl (PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); // Allowing several ptrace tracers 121 | 122 | if (!fork()) { // Creating child thread; 123 | safe_ptrace(PTRACE_ATTACH, parent, NULL, NULL); // Child 124 | 125 | returned_pid = waitpid(parent, &status, WUNTRACED); // synchonization between threads 126 | //assert(returned_pid == parent); 127 | 128 | set_debug_reg(parent, n, (unsigned int)target); // setting EXECUTE watchpoint at function var 'my_test' on dr0 129 | setup_control_reg(parent, n, sizeof(char), type); // updating dr7 with attributes of dr0 130 | 131 | safe_ptrace(PTRACE_CONT, parent, NULL, NULL); // resuming execution of parent 132 | exit(0); 133 | } else { // Parent 134 | wait(NULL); // suspending parent temporarely 135 | } 136 | return; 137 | } 138 | 139 | int check_hbreaks_if_modified(void) { 140 | pid_t child, parent; 141 | long ptrace_result; 142 | int returned_pid, status, return_value = 0; 143 | 144 | parent = getpid(); 145 | 146 | if (!fork()) { 147 | int dr0, dr1, dr2, dr3; // Creating child thread; 148 | safe_ptrace(PTRACE_ATTACH, parent, NULL, NULL); // Child 149 | 150 | returned_pid = waitpid(parent, &status, WUNTRACED); // synchonization between threads 151 | 152 | dr0 = debug_reg(parent, 0); 153 | dr1 = debug_reg(parent, 1); 154 | dr2 = debug_reg(parent, 2); 155 | dr3 = debug_reg(parent, 3); 156 | 157 | if ( dr0 || dr1 || dr2 || dr3){ 158 | kill(0, SIGBUS); 159 | } 160 | set_debug_reg(parent, 0, (unsigned int)&return_value); // setting EXECUTE watchpoint at function var 'my_test' on dr0 161 | setup_control_reg(parent, 0, sizeof(char), WRITE); 162 | safe_ptrace(PTRACE_CONT, parent, NULL, NULL); // resuming execution of parent 163 | exit(0); 164 | } else { 165 | wait(NULL); 166 | return_value = 0; 167 | my_delta0(); 168 | } 169 | my_delta0(); 170 | return 0; 171 | } 172 | 173 | void unset_hbreak_handler(void) { 174 | struct sigaction s; 175 | 176 | memset(&s, 0, sizeof(s)); 177 | s.sa_flags = SA_SIGINFO; 178 | sigemptyset(&s.sa_mask); 179 | s.sa_handler = sigHandler; 180 | sigaction(SIGTRAP, &s, NULL); 181 | } 182 | 183 | void check_hbreaks() { 184 | int val; 185 | 186 | prctl (PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); // Allowing several ptrace tracers 187 | set_hbreak_handler(); 188 | check_hbreaks_if_modified(); 189 | return; 190 | } -------------------------------------------------------------------------------- /layer1/src/huffman.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "../include/huffman.h" 14 | 15 | static unsigned int qtail = -1; 16 | 17 | int decode_bin(Node *root, Node *original, char *bytes, int len, uint8_t * decoded) { 18 | int nbyte = 0, n = 0, nbit = 7; 19 | char byte = bytes[0]; 20 | 21 | while( nbyte < len ) { 22 | while (nbit >= 0) { 23 | if(root->leaf){ 24 | *(decoded + n++) = root->key; 25 | root = original; 26 | } 27 | root = (byte & (0x1 << nbit--)) ? root->right : root->left; 28 | } 29 | nbit = 7; 30 | byte = bytes[++nbyte]; 31 | } 32 | return n; 33 | 34 | } 35 | 36 | void qinsert(Node **nodes, Node *node){ 37 | int i = 0, j = 0; 38 | 39 | if(qtail == -1) { 40 | nodes[++qtail] = node; 41 | return; 42 | }else{ 43 | j = qtail+1; 44 | for(i = qtail; i >= 0; i--){ 45 | if(node->freq <= nodes[i]->freq) { 46 | nodes[j--] = nodes[i]; 47 | nodes[i] = node; 48 | }else{ 49 | nodes[j] = node; 50 | break; 51 | } 52 | 53 | } 54 | qtail += 1; 55 | return; 56 | } 57 | } 58 | 59 | void insert_node(Node **nodes, Node *left, Node *right, int freq, int key) { 60 | Node *node = (Node*) malloc(sizeof(Node)); 61 | 62 | if(!freq && !key) { 63 | node->freq = left->freq + right->freq; 64 | node->key = 0; 65 | node->leaf = false; 66 | node->left = left; 67 | node->right = right; 68 | }else{ 69 | node->freq = freq; 70 | node->key = key; 71 | node->leaf = true; 72 | node->left = NULL; 73 | node->right = NULL; 74 | } 75 | qinsert(nodes, node); 76 | } 77 | 78 | void qdelete(Node **nodes, int idx) { 79 | int i; 80 | 81 | for (i = idx; i < qtail; i++) { 82 | nodes[i] = nodes[i+1]; 83 | } 84 | qtail--; 85 | } 86 | 87 | int get_map_len(int *freqs) { 88 | int i, num = 0; 89 | 90 | for(i = 0; i < QSIZE; i++) 91 | if(freqs[i] != 0) num++; 92 | return num; 93 | } 94 | 95 | void init_hash_map(int sect_sz, int sect_off, int *freqs, uint8_t *elf) { 96 | int i; 97 | 98 | for( i = 0; i < sect_sz; i++) { 99 | if(elf[sect_off+i] == 0){ 100 | freqs[0]+=1; 101 | }else{ 102 | freqs[elf[sect_off+i]&0xff]+=1; 103 | } 104 | } 105 | } 106 | 107 | void insert_leaf_nodes(int *freqs, Node **nodes) { 108 | int i = 0; 109 | 110 | while(i < QSIZE) { 111 | if (freqs[i] != 0) { 112 | insert_node(nodes, NULL, NULL, freqs[i], i); 113 | } 114 | i++; 115 | } 116 | } 117 | 118 | Node *create_btree(int *freqs, Node **nodes) { 119 | qtail = -1; 120 | insert_leaf_nodes(freqs, nodes); 121 | 122 | while(qtail > 0){ 123 | Node *left = *nodes; 124 | Node *right = *(nodes + 1); 125 | 126 | qdelete(nodes, 0); 127 | insert_node(nodes, left, right, 0, 0); 128 | qdelete(nodes, 0); 129 | } 130 | return nodes[0]; 131 | } 132 | 133 | 134 | -------------------------------------------------------------------------------- /layer1/src/launcher.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include /* strtoul() */ 5 | #include /* stat(), open() */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "../include/ul_exec.h" 14 | #include "../include/ul_execP.h" 15 | #include "../include/huffman.h" 16 | #include "../include/compile_time_obfuscation.h" 17 | #include "../include/anti_debugging.h" 18 | #include "../include/block_cipher.h" 19 | 20 | extern void switch_main(); 21 | extern int switch_main_size; 22 | 23 | unsigned int text_addr; 24 | extern uint32_t etext; 25 | unsigned text_size; 26 | uint32_t *image_base, offset, size; 27 | Elf32_Ehdr *ehdr; 28 | struct sigaction s1; 29 | 30 | 31 | void sigHandler(int nsig, siginfo_t *siginfo, void *context) { 32 | switch(nsig){ 33 | case SIGTRAP: 34 | { 35 | int ret; 36 | uint32_t *image_base = (uint32_t*)((text_addr >> 16) << 16); 37 | Elf32_Ehdr *ehdr = (Elf32_Ehdr*)image_base; 38 | 39 | ret = mprotect(ehdr, sizeof(Elf32_Ehdr), PROT_WRITE); 40 | if(ret == -1) { 41 | //perror("mprotect"); 42 | exit(-1); 43 | } 44 | 45 | memset(ehdr, '\0', sizeof(Elf32_Ehdr)); 46 | ret = mprotect(image_base, 4069, PROT_NONE); 47 | if (ret == -1) { 48 | //perror("mprotect\n"); 49 | exit(-1); 50 | } 51 | } 52 | break; 53 | 54 | case SIGSEGV: 55 | { 56 | int i; 57 | uint8_t *addy = (uint8_t*)(((uint32_t)(siginfo->si_addr)) & ~4095); 58 | 59 | if(mprotect(addy, 4096, PROT_READ | PROT_EXEC |PROT_WRITE) == -1) { 60 | //perror("mprotect"); 61 | exit(-1); 62 | } 63 | addy = (uint8_t*)text_addr; 64 | decrypt_buff(addy, text_size); 65 | text_addr = 0; 66 | } 67 | break; 68 | } 69 | return; 70 | } 71 | 72 | void sigill_handler(int nsig, siginfo_t *siginfo, void *context) { 73 | switch(nsig){ 74 | case SIGILL: 75 | { 76 | ucontext_t *lcontext = (ucontext_t*)context; 77 | uint8_t *badinst = siginfo->si_addr; 78 | *(uint8_t*)badinst = '\x90'; 79 | 80 | image_base = (uint32_t*)(((unsigned int)&etext >> 16) << 16); 81 | ehdr = (Elf32_Ehdr*)image_base; 82 | size = *(uint32_t*)&ehdr->e_ident[12]; 83 | *(uint8_t*)(badinst + 1) = '\x90'; 84 | 85 | offset = *(uint32_t*)&ehdr->e_ident[8]; 86 | text_addr = ehdr->e_shoff; 87 | text_size = ehdr->e_flags; 88 | 89 | s1.sa_sigaction = sigHandler; 90 | s1.sa_flags = SA_SIGINFO; 91 | *(uint8_t*)(badinst + 2) = '\x90'; 92 | } 93 | break; 94 | } 95 | return; 96 | } 97 | 98 | int main(int argc, char **argv, char **envp) { 99 | struct sigaction s2; 100 | 101 | s2.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; 102 | s2.sa_sigaction = sigill_handler; 103 | if((sigaction(SIGILL, &s2, NULL)) < 0) { 104 | exit(-1); 105 | } 106 | asm volatile(".byte 0x0F, 0x0B, 0xc3"); // UD2, ret 107 | switch_main(argc, argv, envp); 108 | } 109 | 110 | 111 | // 1 - crc de segmento text. 112 | // 2 - hacer que nose intuitivo saber si el crc es correcto o incorrecto 113 | // 3 - numero de cases es flexible 114 | -------------------------------------------------------------------------------- /layer1/src/layer1.ld: -------------------------------------------------------------------------------- 1 | /* Script for -z combreloc: combine and sort reloc sections */ 2 | /* Copyright (C) 2014-2015 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("elf32-i386", "elf32-i386", 7 | "elf32-i386") 8 | OUTPUT_ARCH(i386) 9 | ENTRY(_start) 10 | SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/i686-linux-gnu/lib32"); SEARCH_DIR("=/usr/i686-linux-gnu/lib"); 11 | 12 | PHDRS 13 | { 14 | /* interp PT_INTERP ;*/ 15 | text PT_LOAD FILEHDR PHDRS; 16 | /*tls PT_TLS;*/ 17 | /* dump PT_LOAD AT(0x8000000) FLAGS(7); 18 | stub PT_LOAD AT(0x9000000) FLAGS(7);*/ 19 | /*dynamic PT_DYNAMIC ;*/ 20 | } 21 | 22 | SECTIONS 23 | { 24 | 25 | /* Read-only sections, merged into text segment: */ 26 | PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0a000000)); . = SEGMENT_START("text-segment", 0x0a000000) + SIZEOF_HEADERS; 27 | .interp : { *(.interp) } 28 | .note.gnu.build-id : { *(.note.gnu.build-id) } 29 | .hash : { *(.hash) } 30 | .gnu.hash : { *(.gnu.hash) } 31 | .dynsym : { *(.dynsym) } 32 | .dynstr : { *(.dynstr) } 33 | .gnu.version : { *(.gnu.version) } 34 | .gnu.version_d : { *(.gnu.version_d) } 35 | .gnu.version_r : { *(.gnu.version_r) } 36 | .rel.dyn : 37 | { 38 | *(.rel.init) 39 | *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) 40 | *(.rel.fini) 41 | *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) 42 | *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) 43 | *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) 44 | *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) 45 | *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) 46 | *(.rel.ctors) 47 | *(.rel.dtors) 48 | *(.rel.got) 49 | *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) 50 | *(.rel.ifunc) 51 | } 52 | 53 | .rel.plt : 54 | { 55 | *(.rel.plt) 56 | PROVIDE_HIDDEN (__rel_iplt_start = .); 57 | *(.rel.iplt) 58 | PROVIDE_HIDDEN (__rel_iplt_end = .); 59 | } 60 | 61 | .init : 62 | { 63 | KEEP (*(SORT_NONE(.init))) 64 | } 65 | 66 | .plt : { *(.plt) *(.iplt) } 67 | .plt.got : { *(.plt.got) } 68 | .text : 69 | { 70 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 71 | *(.text.exit .text.exit.*) 72 | *(.text.startup .text.startup.*) 73 | *(.text.hot .text.hot.*) 74 | *(.text .stub .text.* .gnu.linkonce.t.*) 75 | /* .gnu.warning sections are handled specially by elf32.em. */ 76 | *(.gnu.warning) 77 | } 78 | 79 | .fini : 80 | { 81 | KEEP (*(SORT_NONE(.fini))) 82 | } 83 | PROVIDE (__etext = .); 84 | PROVIDE (_etext = .); 85 | PROVIDE (etext = .); 86 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 87 | .rodata1 : { *(.rodata1) } 88 | .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } 89 | .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } :text 90 | .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table 91 | .gcc_except_table.*) } 92 | .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } 93 | /* These sections are generated by the Sun/Oracle C++ compiler. */ 94 | .exception_ranges : ONLY_IF_RO { *(.exception_ranges 95 | .exception_ranges*) } 96 | /* Adjust the address for the data segment. We want to adjust up to 97 | the same address within the page on the next page up. */ 98 | /* Exception handling */ 99 | .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } 100 | .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } 101 | .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } 102 | .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } 103 | /* Thread Local Storage sections */ 104 | .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } 105 | .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } 106 | .preinit_array : 107 | { 108 | PROVIDE_HIDDEN (__preinit_array_start = .); 109 | KEEP (*(.preinit_array)) 110 | PROVIDE_HIDDEN (__preinit_array_end = .); 111 | } 112 | .init_array : 113 | { 114 | PROVIDE_HIDDEN (__init_array_start = .); 115 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 116 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 117 | PROVIDE_HIDDEN (__init_array_end = .); 118 | } :text 119 | .fini_array : 120 | { 121 | PROVIDE_HIDDEN (__fini_array_start = .); 122 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 123 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 124 | PROVIDE_HIDDEN (__fini_array_end = .); 125 | } :text 126 | .ctors : 127 | { 128 | /* gcc uses crtbegin.o to find the start of 129 | the constructors, so we make sure it is 130 | first. Because this is a wildcard, it 131 | doesn't matter if the user does not 132 | actually link against crtbegin.o; the 133 | linker won't look for a file to match a 134 | wildcard. The wildcard also means that it 135 | doesn't matter which directory crtbegin.o 136 | is in. */ 137 | KEEP (*crtbegin.o(.ctors)) 138 | KEEP (*crtbegin?.o(.ctors)) 139 | /* We don't want to include the .ctor section from 140 | the crtend.o file until after the sorted ctors. 141 | The .ctor section from the crtend file contains the 142 | end of ctors marker and it must be last */ 143 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 144 | KEEP (*(SORT(.ctors.*))) 145 | KEEP (*(.ctors)) 146 | } 147 | .dtors : 148 | { 149 | KEEP (*crtbegin.o(.dtors)) 150 | KEEP (*crtbegin?.o(.dtors)) 151 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 152 | KEEP (*(SORT(.dtors.*))) 153 | KEEP (*(.dtors)) 154 | } 155 | .jcr : { KEEP (*(.jcr)) } 156 | .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } 157 | .dynamic : { *(.dynamic) } 158 | .got : { *(.got) *(.igot) } 159 | .got.plt : { *(.got.plt) *(.igot.plt) } 160 | .data : 161 | { 162 | *(.data .data.* .gnu.linkonce.d.*) 163 | SORT(CONSTRUCTORS) 164 | } 165 | .data1 : { *(.data1) } 166 | _edata = .; PROVIDE (edata = .); 167 | . = .; 168 | _end = .; PROVIDE (end = .); 169 | /* Stabs debugging sections. */ 170 | .stab 0 : { *(.stab) } 171 | .stabstr 0 : { *(.stabstr) } 172 | .stab.excl 0 : { *(.stab.excl) } 173 | .stab.exclstr 0 : { *(.stab.exclstr) } 174 | .stab.index 0 : { *(.stab.index) } 175 | .stab.indexstr 0 : { *(.stab.indexstr) } 176 | .comment 0 : { *(.comment) } 177 | /* DWARF debug sections. 178 | Symbols in the DWARF debugging sections are relative to the beginning 179 | of the section so we begin them at 0. */ 180 | /* DWARF 1 */ 181 | .debug 0 : { *(.debug) } 182 | .line 0 : { *(.line) } 183 | /* GNU DWARF 1 extensions */ 184 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 185 | .debug_sfnames 0 : { *(.debug_sfnames) } 186 | /* DWARF 1.1 and DWARF 2 */ 187 | .debug_aranges 0 : { *(.debug_aranges) } 188 | .debug_pubnames 0 : { *(.debug_pubnames) } 189 | /* DWARF 2 */ 190 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } 191 | .debug_abbrev 0 : { *(.debug_abbrev) } 192 | .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } 193 | .debug_frame 0 : { *(.debug_frame) } 194 | .debug_str 0 : { *(.debug_str) } 195 | .debug_loc 0 : { *(.debug_loc) } 196 | .debug_macinfo 0 : { *(.debug_macinfo) } 197 | /* SGI/MIPS DWARF 2 extensions */ 198 | .debug_weaknames 0 : { *(.debug_weaknames) } 199 | .debug_funcnames 0 : { *(.debug_funcnames) } 200 | .debug_typenames 0 : { *(.debug_typenames) } 201 | .debug_varnames 0 : { *(.debug_varnames) } 202 | /* DWARF 3 */ 203 | .debug_pubtypes 0 : { *(.debug_pubtypes) } 204 | .debug_ranges 0 : { *(.debug_ranges) } 205 | /* DWARF Extension. */ 206 | .debug_macro 0 : { *(.debug_macro) } 207 | .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } 208 | /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } 209 | /* 210 | .UX1 0x8000000 : AT(0x8000000) { 211 | SQUAD(0); 212 | . += 0x1000000-8; 213 | } :dump 214 | 215 | .UX2 0x9000000 : AT(0x9000000) { 216 | SQUAD(0); 217 | . += 0x1000000-8; 218 | } :stub 219 | */ 220 | . = SIZEOF_HEADERS; 221 | .interp : { *(.interp) } :text :interp 222 | .text : { *(.text) } :text 223 | .rodata : { *(.rodata) } /* defaults to :text */ 224 | .data : { *(.data) } :text 225 | .dynamic : { *(.dynamic) } :text :dynamic 226 | 227 | } 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /layer1/src/libc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer1/src/libc.a -------------------------------------------------------------------------------- /layer1/src/load.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../include/ul_execP.h" 12 | 13 | 14 | 15 | #define is_loaded(p) ((p)->p_type == PT_LOAD ? 1 : 0) 16 | #define is_txt_segt(p) ((is_loaded(p)) && (p)->p_flags == (PF_X|PF_R)) 17 | #define is_data_segt(p) ((is_loaded(p)) && (p)->p_flags == (PF_W|PF_R)) 18 | #define segt_size(p) ((size_t)((p)->p_vaddr + (p)->p_memsz)) 19 | #define load_addr(e) ((char *)(((e)->e_type == ET_DYN) ? (e) : NULL)) 20 | 21 | #define FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) 22 | 23 | static Elf32_Ehdr *load_linker_buf(void *linker_buf); 24 | 25 | /* 26 | * Argument elf_buf points to a read-in or mapped-in ELF format 27 | * executable. load_elf_buf() creates all the various discrete 28 | * pieces of memory, at the correct addresses, with the correct 29 | * parts of elf_buf copied in to them, for the executable to run. 30 | */ 31 | static Elf32_Ehdr * load_elf_buf(void *elf_buf) { 32 | Elf32_Ehdr *r = NULL, *e = (Elf32_Ehdr *)elf_buf; 33 | Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned int)elf_buf + e->e_phoff); 34 | Elf32_Phdr *p; 35 | int i; 36 | unsigned int highest_mapped_addr = 0; 37 | 38 | for (i = 0, p = phdr; i < e->e_phnum; i++, p++) { 39 | char *ptr; 40 | unsigned int elf_prot = 0; 41 | unsigned int map_flags = 0; 42 | void *map_addr; 43 | size_t rounded_len; 44 | unsigned int x; 45 | 46 | 47 | if (p->p_type != PT_LOAD) 48 | continue; 49 | 50 | map_flags = FLAGS|MAP_FIXED; 51 | 52 | map_addr = (void *)ALIGNDOWN(p->p_vaddr, p->p_align); 53 | rounded_len = ROUNDUP(p->p_memsz, p->p_align); 54 | 55 | while ((x = (unsigned int)map_addr + rounded_len) <= p->p_vaddr + p->p_memsz) 56 | rounded_len += p->p_align; /* rounded_len stays a multiple of p->p_align */ 57 | 58 | if (x >= highest_mapped_addr) 59 | { 60 | if (MAP_FAILED == (ptr = mmap(map_addr, rounded_len, PROT_NONE, map_flags, -1, 0))) 61 | return NULL; 62 | 63 | /* Mark newly allocated memory so we can write to it */ 64 | if (mprotect(ptr, rounded_len, PROT_WRITE)) 65 | return NULL; 66 | 67 | highest_mapped_addr = x; 68 | 69 | if (!r) r = (Elf32_Ehdr *)ptr; 70 | } 71 | 72 | /* We need the exact load address, not the rounded down 73 | * version. Otherwis we copy to a garbage location.. */ 74 | memcopy( 75 | (void *)p->p_vaddr, 76 | (char *)elf_buf + p->p_offset, 77 | p->p_filesz 78 | ); 79 | 80 | if (p->p_offset) { 81 | if (mprotect(map_addr, rounded_len, PROT_WRITE | PROT_READ)) 82 | return NULL; 83 | } else { 84 | if (mprotect(map_addr, rounded_len, PROT_READ | PROT_WRITE| PROT_EXEC)) 85 | return NULL; 86 | 87 | } 88 | } 89 | 90 | return (Elf32_Ehdr *)r; 91 | } 92 | 93 | /* It appears that most kernels use 0x1000 byte pages. 94 | * But this global-scope variable also gets set in 95 | * ul_save_elfauxv(), from the ELF auxilliary headers. 96 | */ 97 | size_t pgsz = PAGESIZE; 98 | 99 | /* 100 | * Loading ld.so, "ld-linux.so.2" or what have you, takes a slightly 101 | * different approach than load_elf_buf() uses. If you mmap() a few 102 | * pages for the .text segment of ld-linux.so.2, it's likely that 103 | * the kernel will map those pages in too close to something else. 104 | * The next mmap(), for the .bss segment of ld-linux.so.2, will overlap 105 | * that "something else". At least some Linux 3.x kernels put MAP_ANONYMOUS 106 | * pages as high as possible, causing the probable overlap. 107 | */ 108 | static Elf32_Ehdr * load_linker_buf(void *linker_buf) { 109 | Elf32_Ehdr *e = (Elf32_Ehdr *)linker_buf; 110 | Elf32_Phdr *p, *phdr = (Elf32_Phdr *)((unsigned int)linker_buf + e->e_phoff); 111 | int i; 112 | void *base_addr = NULL; 113 | unsigned int max_addr = 0; 114 | 115 | /* Find how many bytes to allocate for ld-linux.so.2 in a single 116 | * chunk. First, find the "high address" for it, based on 117 | * p->p_vaddr + p->p_memsz for each loadable Phdr. */ 118 | for (i = 0, p = phdr; i < e->e_phnum; i++, p++) 119 | { 120 | unsigned int addr; 121 | if (p->p_type != PT_LOAD) 122 | continue; 123 | addr = p->p_vaddr + p->p_memsz; 124 | if (addr > max_addr) max_addr = addr; 125 | } 126 | 127 | /* Round up the high address to a page-size multiple. */ 128 | max_addr = ROUNDUP(max_addr, pgsz); 129 | 130 | /* ld.so contains position independent code, so the "max address" 131 | * actually constitutes size in bytes. */ 132 | if (MAP_FAILED == (base_addr = mmap(0, max_addr, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0))) 133 | return NULL; 134 | 135 | /* Go over the Phdrs again, marking pages writeable, copying appropriate 136 | * pieces of linnker_buf into the right (relative) address, and then putting 137 | * the ELF protections on the page(s) as specified in the Phdr. */ 138 | for (i = 0, p = phdr; i < e->e_phnum; i++, p++) 139 | { 140 | unsigned int elf_prot = 0; 141 | void *prot_addr; 142 | size_t rounded_len; 143 | 144 | if (p->p_type != PT_LOAD) 145 | continue; 146 | 147 | prot_addr = (void *)ALIGNDOWN(base_addr + p->p_vaddr, pgsz); 148 | rounded_len = ROUNDUP((base_addr + p->p_vaddr + p->p_filesz - prot_addr), pgsz); 149 | /* Does a situation ever exist where p->p_vaddr + p->p_filesz > prot_addr + rounded_len? 150 | * It certainly happens in load_elf_buf(), but because we just do one 151 | * allocation for all of ld-linux.so.2, I don't think it can happen here. 152 | */ 153 | 154 | /* Mark mmapped memory so we can write to it */ 155 | if (mprotect(prot_addr, rounded_len, PROT_WRITE)) 156 | return NULL; 157 | 158 | /* Copy from linker_buf to the right (relative) 159 | * address in the allocation. */ 160 | memcopy( 161 | (void *)(base_addr + p->p_vaddr), 162 | (char *)linker_buf + p->p_offset, 163 | p->p_filesz 164 | ); 165 | 166 | /* Protect it as specified. */ 167 | if (p->p_flags & PF_R) 168 | elf_prot |= PROT_READ; 169 | if (p->p_flags & PF_W) 170 | elf_prot |= PROT_WRITE; 171 | if (p->p_flags & PF_X) 172 | elf_prot |= PROT_EXEC; 173 | 174 | if (mprotect(prot_addr, rounded_len, elf_prot)) 175 | return NULL; 176 | } 177 | 178 | return (Elf32_Ehdr *)base_addr; 179 | } 180 | 181 | /* Based on a filename, load any ELF run-time linker. */ 182 | static Elf32_Ehdr * load_linker(const char *fname) { 183 | Elf32_Ehdr *e; 184 | struct stat st; 185 | char *buf; 186 | int fd, sz; 187 | 188 | if (0 > (fd = open(fname, O_RDONLY))) 189 | return NULL; 190 | 191 | buf = mmap(NULL, 0x30000, PROT_READ, MAP_PRIVATE, fd, 0); 192 | if (buf == MAP_FAILED) 193 | { 194 | close(fd); 195 | return NULL; 196 | } 197 | 198 | e = load_linker_buf(buf); 199 | 200 | //munmap(buf, st.st_size); 201 | close(fd); 202 | 203 | return e; 204 | } 205 | 206 | /* 207 | * Assuming that ELF_buf points to an in-memory image of 208 | * an ELF file, create blocks of memory at correct addresses 209 | * specified by Phdrs of the ELF file. Copy appropriate sections 210 | * of ELF_buf into those blocks of memory, and give them protections 211 | * as specified in the Phdrs. 212 | */ 213 | int ul_load_elf(uint8_t *ELF_buf, Elf32_Ehdr **elf, Elf32_Ehdr **interp) { 214 | Elf32_Ehdr *e, *ei = NULL; 215 | Elf32_Phdr *p, *ptab; 216 | int i; 217 | 218 | e = (Elf32_Ehdr *)ELF_buf; 219 | ptab = (Elf32_Phdr*)&ELF_buf[e->e_phoff]; 220 | 221 | /* check for a dynamic linker, and if there is one, load it */ 222 | for (i = 0, p = ptab; i < e->e_phnum; i++, p++) 223 | { 224 | if (p->p_type == PT_INTERP) 225 | { 226 | if (NULL == (ei = load_linker((char *)((unsigned int)ELF_buf+p->p_offset)))) 227 | return -1; 228 | break; 229 | } 230 | } 231 | 232 | if ((e = load_elf_buf(ELF_buf)) == NULL) { 233 | return -1; 234 | 235 | } 236 | 237 | /* initialize the heap for later use. */ 238 | for (i = 0, p = ptab; i < e->e_phnum; i++, p++) 239 | if (is_data_segt(p)) 240 | brk(load_addr(e) + segt_size(p)); 241 | 242 | if (elf) 243 | *elf = e; 244 | if (interp) 245 | *interp = ei; 246 | 247 | return 0; 248 | } 249 | 250 | /* 251 | * Our own private memcpy() - this exists to help debug. 252 | * Getting an mprotect() address off some bytes can cause 253 | * a SIGSEGV. This one at least lets us see where the 254 | * actually faulting address lies. 255 | */ 256 | void * memcopy(void *dest, const void *src, size_t n) { 257 | unsigned int i; 258 | unsigned char *d = (unsigned char *)dest; 259 | unsigned char *s = (unsigned char *)src; 260 | 261 | /* 262 | printf("Copying %d bytes from %p to %p, last address %p\n", 263 | n, s, d, (void *)((unsigned int)d + n)); 264 | */ 265 | 266 | for (i = 0; i < n; ++i) 267 | d[i] = s[i]; 268 | 269 | return dest; 270 | } 271 | -------------------------------------------------------------------------------- /layer1/src/lz77.c: -------------------------------------------------------------------------------- 1 | /* PROG2.C */ 2 | /* Simple Hashing LZ77 Sliding Dictionary Compression Program */ 3 | /* By Rich Geldreich, Jr. October, 1993 */ 4 | /* Originally compiled with QuickC v2.5 in the small model. */ 5 | /* This program uses more efficient code to delete strings from */ 6 | /* the sliding dictionary compared to PROG1.C, at the expense of */ 7 | /* greater memory requirements. See the HashData and DeleteData */ 8 | /* subroutines. */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /* set this to 1 for a greedy encoder */ 16 | #define GREEDY 0 17 | 18 | /* ratio vs. speed constant */ 19 | /* the larger this constant, the better the compression */ 20 | #define MAXCOMPARES 75 21 | 22 | /* unused entry flag */ 23 | #define NIL 0xFFFF 24 | 25 | /* bits per symbol- normally 8 for general purpose compression */ 26 | #define CHARBITS 8 27 | 28 | /* minimum match length & maximum match length */ 29 | #define THRESHOLD 2 30 | #define MATCHBITS 4 31 | #define MAXMATCH ((1 << MATCHBITS) + THRESHOLD - 1) 32 | 33 | /* sliding dictionary size and hash table's size */ 34 | /* some combinations of HASHBITS and THRESHOLD values will not work 35 | correctly because of the way this program hashes strings */ 36 | #define DICTBITS 13 37 | #define HASHBITS 10 38 | #define DICTSIZE (1 << DICTBITS) 39 | #define HASHSIZE (1 << HASHBITS) 40 | 41 | /* # bits to shift after each XOR hash */ 42 | /* this constant must be high enough so that only THRESHOLD + 1 43 | characters are in the hash accumulator at one time */ 44 | #define SHIFTBITS ((HASHBITS + THRESHOLD) / (THRESHOLD + 1)) 45 | 46 | /* sector size constants */ 47 | #define SECTORBIT 10 48 | #define SECTORLEN (1 << SECTORBIT) 49 | 50 | #define HASHFLAG1 0x8000 51 | #define HASHFLAG2 0x7FFF 52 | 53 | /* dictionary plus MAXMATCH extra chars for string comparisions */ 54 | unsigned char 55 | dict[DICTSIZE + MAXMATCH]; 56 | 57 | /* hashtable & link list tables */ 58 | unsigned int 59 | hash[HASHSIZE], 60 | nextlink[DICTSIZE], 61 | lastlink[DICTSIZE]; 62 | 63 | /* misc. global variables */ 64 | unsigned int 65 | matchlength, 66 | matchpos, 67 | bitbuf, 68 | bitsin, 69 | masks[17] = {0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; 70 | 71 | FILE *infile, *outfile; 72 | 73 | /* writes multiple bit codes to the output stream */ 74 | void SendBits(unsigned int bits, unsigned int numbits) 75 | { 76 | 77 | bitbuf |= (bits << bitsin); 78 | 79 | bitsin += numbits; 80 | 81 | if (bitsin > 16) /* special case when # bits in buffer exceeds 16 */ 82 | { 83 | if (putc(bitbuf & 0xFF, outfile) == EOF) 84 | { 85 | //printf("\nerror writing to output file"); 86 | exit(EXIT_FAILURE); 87 | } 88 | bitbuf = bits >> (8 - (bitsin - numbits)); 89 | bitsin -= 8; 90 | } 91 | 92 | while (bitsin >= 8) 93 | { 94 | if (putc(bitbuf & 0xFF, outfile) == EOF) 95 | { 96 | //printf("\nerror writing to output file"); 97 | exit(EXIT_FAILURE); 98 | } 99 | bitbuf >>= 8; 100 | bitsin -= 8; 101 | } 102 | 103 | } 104 | 105 | /* reads multiple bit codes from the input stream */ 106 | unsigned int ReadBits(unsigned int numbits) 107 | { 108 | 109 | register unsigned int i; 110 | 111 | i = bitbuf >> (8 - bitsin); 112 | 113 | while (numbits > bitsin) 114 | { 115 | if ((bitbuf = getc(infile)) == EOF) 116 | { 117 | printf("\nerror reading from input file"); 118 | exit(EXIT_FAILURE); 119 | } 120 | i |= (bitbuf << bitsin); 121 | bitsin += 8; 122 | } 123 | 124 | bitsin -= numbits; 125 | 126 | return (i & masks[numbits]); 127 | 128 | } 129 | 130 | /* sends a match to the output stream */ 131 | void SendMatch(unsigned int matchlen, unsigned int matchdistance) 132 | { 133 | SendBits(1, 1); 134 | 135 | SendBits(matchlen - (THRESHOLD + 1), MATCHBITS); 136 | 137 | SendBits(matchdistance, DICTBITS); 138 | } 139 | 140 | /* sends one character (or literal) to the output stream */ 141 | void SendChar(unsigned int character) 142 | { 143 | SendBits(0, 1); 144 | 145 | SendBits(character, CHARBITS); 146 | } 147 | 148 | /* initializes the search structures needed for compression */ 149 | void InitEncode(void) 150 | { 151 | register unsigned int i; 152 | 153 | for (i = 0; i < HASHSIZE; i++) hash[i] = NIL; 154 | 155 | nextlink[DICTSIZE] = NIL; 156 | 157 | } 158 | 159 | /* loads dictionary with characters from the input stream */ 160 | unsigned int LoadDict(unsigned int dictpos) 161 | { 162 | register unsigned int i, j; 163 | 164 | if ((i = fread(&dict[dictpos], sizeof (char), SECTORLEN, infile)) == EOF) 165 | { 166 | printf("\nerror reading from input file"); 167 | exit(EXIT_FAILURE); 168 | } 169 | 170 | /* since the dictionary is a ring buffer, copy the characters at 171 | the very start of the dictionary to the end */ 172 | if (dictpos == 0) 173 | { 174 | for (j = 0; j < MAXMATCH; j++) dict[j + DICTSIZE] = dict[j]; 175 | } 176 | 177 | return i; 178 | } 179 | 180 | /* deletes data from the dictionary search structures */ 181 | /* this is only done when the number of bytes to be */ 182 | /* compressed exceeds the dictionary's size */ 183 | void DeleteData(unsigned int dictpos) 184 | { 185 | 186 | register unsigned int i, j, k; 187 | 188 | /* delete all references to the sector being deleted */ 189 | 190 | k = dictpos + SECTORLEN; 191 | 192 | for (i = dictpos; i < k; i++) 193 | { 194 | if ((j = lastlink[i]) & HASHFLAG1) 195 | { 196 | if (j != NIL) hash[j & HASHFLAG2] = NIL; 197 | } 198 | else 199 | nextlink[j] = NIL; 200 | } 201 | 202 | } 203 | 204 | /* hash data just entered into dictionary */ 205 | /* XOR hashing is used here, but practically any hash function will work */ 206 | void HashData(unsigned int dictpos, unsigned int bytestodo) 207 | { 208 | register unsigned int i, j, k; 209 | 210 | if (bytestodo <= THRESHOLD) /* not enough bytes in sector for match? */ 211 | for (i = 0; i < bytestodo; i++) 212 | nextlink[dictpos + i] = lastlink[dictpos + i] = NIL; 213 | else 214 | { 215 | /* matches can't cross sector boundries */ 216 | for (i = bytestodo - THRESHOLD; i < bytestodo; i++) 217 | nextlink[dictpos + i] = lastlink[dictpos + i] = NIL; 218 | 219 | j = (((unsigned int)dict[dictpos]) << SHIFTBITS) ^ dict[dictpos + 1]; 220 | 221 | k = dictpos + bytestodo - THRESHOLD; /* calculate end of sector */ 222 | 223 | for (i = dictpos; i < k; i++) 224 | { 225 | lastlink[i] = (j = (((j << SHIFTBITS) & (HASHSIZE - 1)) ^ dict[i + THRESHOLD])) | HASHFLAG1; 226 | if ((nextlink[i] = hash[j]) != NIL) lastlink[nextlink[i]] = i; 227 | hash[j] = i; 228 | } 229 | } 230 | } 231 | 232 | /* finds match for string at position dictpos */ 233 | /* this search code finds the longest AND closest */ 234 | /* match for the string at dictpos */ 235 | void FindMatch(unsigned int dictpos, unsigned int startlen) 236 | { 237 | register unsigned int i, j, k; 238 | unsigned char l; 239 | 240 | i = dictpos; matchlength = startlen; k = MAXCOMPARES; 241 | l = dict[dictpos + matchlength]; 242 | 243 | do 244 | { 245 | if ((i = nextlink[i]) == NIL) return; /* get next string in list */ 246 | 247 | if (dict[i + matchlength] == l) /* possible larger match? */ 248 | { 249 | for (j = 0; j < MAXMATCH; j++) /* compare strings */ 250 | if (dict[dictpos + j] != dict[i + j]) break; 251 | 252 | if (j > matchlength) /* found larger match? */ 253 | { 254 | matchlength = j; 255 | matchpos = i; 256 | if (matchlength == MAXMATCH) return; /* exit if largest possible match */ 257 | l = dict[dictpos + matchlength]; 258 | } 259 | } 260 | } 261 | while (--k); /* keep on trying until we run out of chances */ 262 | 263 | } 264 | 265 | /* finds dictionary matches for characters in current sector */ 266 | void DictSearch(unsigned int dictpos, unsigned int bytestodo) 267 | { 268 | 269 | register unsigned int i, j; 270 | 271 | #if (GREEDY == 0) 272 | 273 | unsigned int matchlen1, matchpos1; 274 | 275 | /* non-greedy search loop (slow) */ 276 | 277 | i = dictpos; j = bytestodo; 278 | 279 | while (j) /* loop while there are still characters left to be compressed */ 280 | { 281 | FindMatch(i, THRESHOLD); 282 | 283 | if (matchlength > THRESHOLD) 284 | { 285 | matchlen1 = matchlength; 286 | matchpos1 = matchpos; 287 | 288 | for ( ; ; ) 289 | { 290 | FindMatch(i + 1, matchlen1); 291 | 292 | if (matchlength > matchlen1) 293 | { 294 | matchlen1 = matchlength; 295 | matchpos1 = matchpos; 296 | SendChar(dict[i++]); 297 | j--; 298 | } 299 | else 300 | { 301 | if (matchlen1 > j) 302 | { 303 | matchlen1 = j; 304 | if (matchlen1 <= THRESHOLD) { SendChar(dict[i++]); j--; break; } 305 | } 306 | 307 | SendMatch(matchlen1, (i - matchpos1) & (DICTSIZE - 1)); 308 | i += matchlen1; 309 | j -= matchlen1; 310 | break; 311 | } 312 | } 313 | } 314 | else 315 | { 316 | SendChar(dict[i++]); 317 | j--; 318 | } 319 | } 320 | 321 | #else 322 | 323 | /* greedy search loop (fast) */ 324 | 325 | i = dictpos; j = bytestodo; 326 | 327 | while (j) /* loop while there are still characters left to be compressed */ 328 | { 329 | FindMatch(i, THRESHOLD); 330 | 331 | if (matchlength > j) matchlength = j; /* clamp matchlength */ 332 | 333 | if (matchlength > THRESHOLD) /* valid match? */ 334 | { 335 | SendMatch(matchlength, (i - matchpos) & (DICTSIZE - 1)); 336 | i += matchlength; 337 | j -= matchlength; 338 | } 339 | else 340 | { 341 | SendChar(dict[i++]); 342 | j--; 343 | } 344 | } 345 | 346 | #endif 347 | 348 | } 349 | 350 | /* main encoder */ 351 | void Encode (void) 352 | { 353 | unsigned int dictpos, deleteflag, sectorlen; 354 | unsigned long bytescompressed; 355 | 356 | InitEncode(); 357 | 358 | dictpos = deleteflag = 0; 359 | 360 | bytescompressed = 0; 361 | 362 | while (1) 363 | { 364 | /* delete old data from dictionary */ 365 | if (deleteflag) DeleteData(dictpos); 366 | 367 | /* grab more data to compress */ 368 | if ((sectorlen = LoadDict(dictpos)) == 0) break; 369 | 370 | /* hash the data */ 371 | HashData(dictpos, sectorlen); 372 | 373 | /* find dictionary matches */ 374 | DictSearch(dictpos, sectorlen); 375 | 376 | bytescompressed += sectorlen; 377 | 378 | printf("\r%ld", bytescompressed); 379 | 380 | dictpos += SECTORLEN; 381 | 382 | /* wrap back to beginning of dictionary when its full */ 383 | if (dictpos == DICTSIZE) 384 | { 385 | dictpos = 0; 386 | deleteflag = 1; /* ok to delete now */ 387 | } 388 | } 389 | 390 | /* Send EOF flag */ 391 | SendMatch(MAXMATCH + 1, 0); 392 | 393 | /* Flush bit buffer */ 394 | if (bitsin) SendBits(0, 8 - bitsin); 395 | 396 | return; 397 | } 398 | 399 | /* main decoder */ 400 | void Decode (void) 401 | { 402 | 403 | register unsigned int i, j, k; 404 | unsigned long bytesdecompressed; 405 | 406 | i = 0; 407 | bytesdecompressed = 0; 408 | 409 | for ( ; ; ) 410 | { 411 | if (ReadBits(1) == 0) /* character or match? */ 412 | { 413 | dict[i++] = ReadBits(CHARBITS); 414 | if (i == DICTSIZE) 415 | { 416 | if (fwrite(&dict, sizeof (char), DICTSIZE, outfile) == EOF) 417 | { 418 | printf("\nerror writing to output file"); 419 | exit(EXIT_FAILURE); 420 | } 421 | i = 0; 422 | bytesdecompressed += DICTSIZE; 423 | printf("\r%ld", bytesdecompressed); 424 | } 425 | } 426 | else 427 | { 428 | /* get match length from input stream */ 429 | k = (THRESHOLD + 1) + ReadBits(MATCHBITS); 430 | 431 | if (k == (MAXMATCH + 1)) /* Check for EOF flag */ 432 | { 433 | if (fwrite(&dict, sizeof (char), i, outfile) == EOF) 434 | { 435 | printf("\nerror writing to output file"); 436 | exit(EXIT_FAILURE); 437 | } 438 | bytesdecompressed += i; 439 | printf("\r%ld", bytesdecompressed); 440 | return; 441 | } 442 | 443 | /* get match position from input stream */ 444 | j = ((i - ReadBits(DICTBITS)) & (DICTSIZE - 1)); 445 | 446 | if ((i + k) >= DICTSIZE) 447 | { 448 | do 449 | { 450 | dict[i++] = dict[j++]; 451 | j &= (DICTSIZE - 1); 452 | if (i == DICTSIZE) 453 | { 454 | if (fwrite(&dict, sizeof (char), DICTSIZE, outfile) == EOF) 455 | { 456 | printf("\nerror writing to output file"); 457 | exit(EXIT_FAILURE); 458 | } 459 | i = 0; 460 | bytesdecompressed += DICTSIZE; 461 | printf("\r%ld", bytesdecompressed); 462 | } 463 | } 464 | while (--k); 465 | } 466 | else 467 | { 468 | if ((j + k) >= DICTSIZE) 469 | { 470 | do 471 | { 472 | dict[i++] = dict[j++]; 473 | j &= (DICTSIZE - 1); 474 | } 475 | while (--k); 476 | } 477 | else 478 | { 479 | do 480 | { 481 | dict[i++] = dict[j++]; 482 | } 483 | while (--k); 484 | } 485 | } 486 | } 487 | } 488 | } 489 | 490 | int main(int argc, char *argv[]) 491 | { 492 | char *s; 493 | 494 | if (argc != 4) 495 | { 496 | printf("\n'prog2 e file1 file2' encodes file1 into file2.\n" 497 | "'prog2 d file2 file1' decodes file2 into file1.\n"); 498 | return EXIT_FAILURE; 499 | } 500 | if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL) 501 | || (s = argv[2], (infile = fopen(s, "rb")) == NULL) 502 | || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) { 503 | printf("??? %s\n", s); return EXIT_FAILURE; 504 | } 505 | 506 | /* allocate 4k I/O buffers */ 507 | setvbuf( infile, NULL, _IOFBF, 4096); 508 | setvbuf( outfile, NULL, _IOFBF, 4096); 509 | 510 | if (toupper(*argv[1]) == 'E') 511 | { 512 | printf("Compressing %s to %s\n", argv[2], argv[3]); 513 | Encode(); 514 | } 515 | else 516 | { 517 | printf("Decompressing %s to %s\n", argv[2], argv[3]); 518 | Decode(); 519 | } 520 | 521 | fclose(infile); fclose(outfile); 522 | 523 | return EXIT_SUCCESS; 524 | } -------------------------------------------------------------------------------- /layer1/src/rc4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct __rc4 { 6 | int S[256]; 7 | int K[256]; 8 | int i; 9 | int j; 10 | }RC4; 11 | 12 | void rc4_stream_setup(char *key, RC4 *rc4) { 13 | int keysz = strlen(key); 14 | int i = 0, j = 0, tmp = 0; 15 | 16 | for (i = 0; i < 255; i++) { 17 | rc4->S[i] = i; 18 | rc4->K[i] = key[j++ % keysz]; 19 | } 20 | 21 | for (i = 0; i < 255; i++) { 22 | j = (j + rc4->S[i] + (int)rc4->K[i]) % 256; 23 | 24 | tmp = rc4->S[i]; 25 | rc4->S[i] = rc4->S[j]; 26 | rc4->S[j] = tmp; 27 | } 28 | } 29 | 30 | char rc4_get_byte_stream(RC4 *rc4) { 31 | int tmp = 0; 32 | 33 | rc4->i = (rc4->i +1) % 256; 34 | rc4->j = (rc4->j + rc4->S[rc4->i]) % 256; 35 | 36 | tmp = rc4->S[rc4->i]; 37 | rc4->S[rc4->i] = rc4->S[rc4->j]; 38 | rc4->S[rc4->j] = tmp; 39 | 40 | int t = (rc4->S[rc4->i] + rc4->S[rc4->j]) % 256; 41 | char *sbyte = (char*)(&rc4->S[t]); 42 | 43 | return sbyte[0]; 44 | } 45 | 46 | 47 | char *rc4_crypt(char *data, RC4 *rc4) { 48 | char xor_byte; 49 | int i, data_len = strlen(data); 50 | 51 | for (i=0; i < data_len; i++) { 52 | xor_byte = rc4_get_byte_stream(rc4); 53 | data[i] ^= xor_byte; 54 | } 55 | return data; 56 | } 57 | 58 | /* 59 | int main() { 60 | char key[] = "abcdefg"; 61 | char data[] = "hello_world"; 62 | 63 | RC4 *rc4_encrypt = (RC4*)calloc(1, sizeof(RC4)); 64 | RC4 *rc4_decrypt = (RC4*)calloc(1, sizeof(RC4)); 65 | 66 | rc4_stream_setup(key, rc4_encrypt); 67 | rc4_stream_setup(key, rc4_decrypt); 68 | 69 | printf ("Original data is %s\n", data); 70 | 71 | char *data_encrypted = rc4_crypt (data, rc4_encrypt); 72 | printf("The encrypted data is %s\n", data_encrypted); 73 | 74 | char *data_decrypted = rc4_crypt (data, rc4_decrypt); 75 | printf ("The decrypted data is %s\n", data_decrypted); 76 | 77 | free(rc4_encrypt); 78 | free(rc4_decrypt); 79 | 80 | return 0; 81 | 82 | } 83 | */ 84 | -------------------------------------------------------------------------------- /layer1/src/rc4_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define N 256 // 2^8 6 | 7 | void swap(unsigned char *a, unsigned char *b) { 8 | int tmp = *a; 9 | *a = *b; 10 | *b = tmp; 11 | } 12 | 13 | int KSA(char *key, unsigned char *S) { 14 | 15 | int len = 16; 16 | unsigned int j = 0; 17 | 18 | for(int i = 0; i < N; i++) 19 | S[i] = i; 20 | 21 | for(int i = 0; i < N; i++) { 22 | j = (j + S[i] + key[i % len]) % N; 23 | 24 | swap(&S[i], &S[j]); 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | int PRGA(unsigned char *S, char *plaintext, int size) { 31 | 32 | int i = 0; 33 | int j = 0; 34 | 35 | for(size_t n = 0, len = size; n < len; n++) { 36 | i = (i + 1) % N; 37 | j = (j + S[i]) % N; 38 | 39 | swap(&S[i], &S[j]); 40 | int rnd = S[(S[i] + S[j]) % N]; 41 | 42 | plaintext[n] = rnd ^ plaintext[n]; 43 | 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | int RC4(char *key, char *plaintext, int size) { 50 | 51 | unsigned char S[N]; 52 | KSA(key, S); 53 | 54 | PRGA(S, plaintext, size); 55 | 56 | return 0; 57 | } 58 | 59 | //int main(int argc, char *argv[]) { 60 | 61 | // if(argc < 3) { 62 | // printf("Usage: %s ", argv[0]); 63 | // return -1; 64 | // } 65 | 66 | 67 | // RC4(argv[1], argv[2], strlen(argv[2])); 68 | 69 | // for(size_t i = 0, len = strlen(argv[2]); i < len; i++) 70 | // printf("%02hhX", argv[2][i]); 71 | // printf("\n"); 72 | // return 0; 73 | //} 74 | -------------------------------------------------------------------------------- /layer1/src/save.c: -------------------------------------------------------------------------------- 1 | #include <stdlib.h> 2 | #include <string.h> 3 | #include <unistd.h> 4 | #include <sys/mman.h> 5 | #include <elf.h> 6 | #include "../include/ul_execP.h" 7 | 8 | extern unsigned int pgsz; /* set in ul_save_elfauxv() */ 9 | 10 | struct ul_args { 11 | size_t size; 12 | int cnt; 13 | char *block; 14 | }; 15 | 16 | ul_args_t * ul_save_args(int argc, char **argv) { 17 | ul_args_t *args; 18 | size_t len; 19 | int i; 20 | char *str; 21 | 22 | 23 | if (argc > 0) 24 | for (i = 0, len = 0; i < argc; i++) 25 | len += strlen(argv[i]) + 1; 26 | else { 27 | /* Count them ourselves - env doesn't have envc. */ 28 | argc = 0; 29 | char **p = argv; 30 | while (*p) 31 | { 32 | len += strlen(*p) + 1; 33 | ++p; /* move past ASCII Nul */ 34 | ++argc; 35 | } 36 | } 37 | 38 | args = ALLOCATE(sizeof(*args)); 39 | 40 | args->size = len; 41 | args->cnt = argc; 42 | args->block = ALLOCATE(args->size); 43 | 44 | /* Do it this way because the values of argv[] or env[] may not actually 45 | * exist as contiguous strings. We will make them contiguous. */ 46 | for (i = 0, str = args->block; i < argc; i++, str += strlen(str) + 1) 47 | strcat(str, argv[i]); 48 | 49 | return args; 50 | } 51 | 52 | void * ul_setup_stack( ul_args_t *args, ul_args_t *envp, ul_args_t *auxvp, Elf32_Ehdr *elf, Elf32_Ehdr *interp){ 53 | Elf32_auxv_t *aux, *excfn = NULL; 54 | char **av, **ev; 55 | char *addr, *str, *esp; 56 | unsigned int *ptr; 57 | int argsize, i, j; 58 | 59 | /* Count bytes needed for new stack */ 60 | argsize = 4 + strlen(args->block) + 1; /* NULL at top of stack, executable file name */ 61 | argsize += envp->size; /* environment strings */ 62 | argsize += args->size; /* argument strings size */ 63 | argsize += 4; /* Do we really need a NULL word here? */ 64 | argsize += auxvp->cnt * sizeof(Elf32_auxv_t); /* Elf aux vector table */ 65 | argsize += 4; /* NULL that ends envp[] */ 66 | argsize += envp->cnt * sizeof(char *); /* table of pointers to env strings */ 67 | argsize += 4; /* NULL that ends argv[] */ 68 | argsize += args->cnt * sizeof(char *); /* table of pointers to argv strings */ 69 | argsize += 4; /* argc */ 70 | 71 | 72 | /* Allocate and align a new stack. */ 73 | esp = (char *)ALIGN((unsigned int)alloca(ROUNDUP(argsize, pgsz)), 16); 74 | 75 | /* NOTE: The new stack for the userland-execed process lives 76 | * *below* the bottom of the stack RIGHT NOW. After returning from 77 | * ul_setup_stack(), don't call anything that uses the call stack: that 78 | * will roach this newly-constructed stack. In fact, the code below 79 | * does its own strcpy() and memcpy() equivalents, to the detriment of 80 | * code quality. 81 | */ 82 | 83 | ptr = (unsigned int *)esp; 84 | 85 | *ptr++ = args->cnt; 86 | av = (char **)ptr; 87 | ptr += args->cnt; /* skip over argv[] */ 88 | *ptr++ = 0; 89 | 90 | ev = (char **)ptr; 91 | ptr += envp->cnt; /* skip over envp[] */ 92 | *ptr++ = 0; 93 | 94 | aux = (Elf32_auxv_t *)ptr; 95 | 96 | ptr = (unsigned int *)ROUNDUP((unsigned long)ptr + auxvp->size, sizeof(unsigned int)); 97 | 98 | /* Copy ELF auxilliary vector table onto fake stack. */ 99 | addr = (char *)aux; 100 | for (j = 0; j < auxvp->size; ++j) 101 | addr[j] = auxvp->block[j]; 102 | 103 | /* Fix up a few entries: kernel will have set up the AUXV 104 | * for the user-land exec program, mapped in at a low address. 105 | * need to fix up a few AUXV entries for the "real" program. */ 106 | for (i = 0; i < auxvp->cnt; ++i) 107 | { 108 | switch (aux[i].a_type) 109 | { 110 | case AT_PHDR: aux[i].a_un.a_val = (unsigned int)((char *)elf + elf->e_phoff); break; 111 | case AT_PHNUM: aux[i].a_un.a_val = elf->e_phnum; break; 112 | /* Some kernels give AT_BASE a zero value. */ 113 | case AT_BASE: aux[i].a_un.a_val = (unsigned int)interp; break; 114 | case AT_ENTRY: aux[i].a_un.a_val = (unsigned int)elf->e_entry; break; 115 | /* Not all glibc specify this, apparently. */ 116 | #ifdef AT_EXECFN 117 | case AT_EXECFN: excfn = &(aux[i]); break; 118 | #endif 119 | } 120 | } 121 | 122 | *ptr++ = 0; 123 | 124 | /* Copy argv strings onto stack */ 125 | addr = (char *)ptr; 126 | str = args->block; 127 | 128 | for (i = 0; i < args->cnt; ++i) 129 | { 130 | av[i] = addr; 131 | for (j = 0; *str; ++j) 132 | *addr++ = *str++; 133 | *addr++ = *str++; /* ASCII Nul */ 134 | } 135 | 136 | ptr = (unsigned int *)ROUNDUP((unsigned int)addr, sizeof(unsigned int)); 137 | *ptr = 0; 138 | 139 | /* Copy envp strings onto stack */ 140 | addr = (char *)ptr; 141 | str = envp->block; 142 | 143 | for (i = 0; i < envp->cnt; ++i) 144 | { 145 | ev[i] = addr; 146 | for (j = 0; *str; ++j) 147 | *addr++ = *str++; 148 | *addr++ = *str++; /* ASCII Nul */ 149 | } 150 | 151 | ptr = (unsigned int *)ROUNDUP((unsigned int)addr, sizeof(unsigned int)); 152 | *ptr = 0; 153 | 154 | /* Executable name at top of stack. 155 | * Not all kernels put the name at the top of the stack. 156 | * RHEL old 2.6.18 kernels don't. 157 | */ 158 | if (excfn) 159 | { 160 | addr = (char *)ptr; 161 | str = args->block; 162 | excfn->a_un.a_val = (unsigned int)addr; 163 | for (j = 0; *str; ++j) 164 | *addr++ = *str++; 165 | *addr++ = *str++; /* ASCII Nul */ 166 | 167 | ptr = (unsigned int *)ROUNDUP((unsigned int)addr, sizeof(unsigned int)); 168 | } 169 | 170 | munmap(args->block, args->size); 171 | munmap(args, sizeof(*args)); 172 | munmap(auxvp->block, auxvp->size); 173 | munmap(auxvp, sizeof(*auxvp)); 174 | munmap(envp->block, envp->size); 175 | munmap(envp, sizeof(*envp)); 176 | 177 | *ptr = 0; 178 | 179 | return ((void *)esp); 180 | } 181 | 182 | /* Get a copy of ELF auxilliary vector table. */ 183 | ul_args_t * ul_save_elfauxv(char **envp) { 184 | int cnt; 185 | ul_args_t *r = NULL; 186 | Elf32_auxv_t *q; 187 | unsigned int *p; 188 | 189 | /* Grope up the stack for Elf auxilliary vectors. 190 | * Find NULL word (32-bit) after env string pointers. 191 | */ 192 | p = (unsigned int *)envp; 193 | while (*p != 0) 194 | ++p; 195 | 196 | ++p; /* skip the null word */ 197 | 198 | for (cnt = 0, q = (Elf32_auxv_t *)p; q->a_type != AT_NULL; ++q) 199 | { 200 | /* Why get pagesize from the ELF aux vector? Because dietlibc 201 | * doesn't have a totally static version of getpagesize(), which 202 | * means glibc gets used via a weak symbol in dietlibc. */ 203 | if (AT_PAGESZ == q->a_type) 204 | pgsz = q->a_un.a_val; 205 | ++cnt; 206 | } 207 | 208 | ++cnt; /* The AT_NULL final entry */ 209 | 210 | r = ALLOCATE(sizeof(*r)); 211 | r->size = sizeof(*q) * cnt; 212 | r->cnt = cnt; 213 | r->block = ALLOCATE(r->size); 214 | memcopy((void *)r->block, (void *)p, r->size); 215 | 216 | return r; 217 | } 218 | -------------------------------------------------------------------------------- /layer1/src/switch32.asm: -------------------------------------------------------------------------------- 1 | [BITS 32] 2 | 3 | global switch_main:function 4 | global switch_main_size:data 5 | global case9:function 6 | global case9_end:function 7 | extern image_base 8 | extern ehdr 9 | extern size 10 | extern offset 11 | 12 | extern check_hbreaks 13 | extern check_parent 14 | extern decrypt_buff 15 | extern ul_exec 16 | extern free 17 | extern create_btree 18 | extern sigaction 19 | extern decode_bin 20 | extern memset 21 | extern check_ld_preload 22 | extern get_map_len 23 | extern calloc 24 | extern s1 25 | extern sigHandler 26 | 27 | 28 | SA_SIGINFO equ 0x00000040 29 | SIGSEGV equ 11 30 | SIGTRAP equ 5 31 | 32 | struc Node 33 | .freq resd 1 34 | .key resb 1 35 | .leaf resb 1 36 | .left resd 1 37 | .right resd 1 38 | endstruc 39 | 40 | 41 | struc Elf32_Ehdr 42 | .e_ident resb 16 43 | .e_type resw 1 44 | .e_machine resw 1 45 | .e_version resd 1 46 | .e_entry resd 1 47 | .e_phoff resd 1 48 | .e_shoff resd 1 49 | .e_flags resd 1 50 | .e_ehsize resw 1 51 | .e_phentsize resw 1 52 | .e_phnum resw 1 53 | .e_shentsize resw 1 54 | .e_shnum resw 1 55 | .e_shstrndx resw 1 56 | endstruc 57 | 58 | struc sigaction32 59 | .sa_handler resd 1 60 | .sa_sigaction resd 1 61 | .sa_mask resd 1 62 | .sa_flags resd 1 63 | .sa_restorer resd 1 64 | endstruc 65 | 66 | section .decrypter write alloc exec 67 | 68 | switch_main: 69 | mov eax, esp 70 | add eax, 4 71 | mov ebx, [eax] 72 | mov [argc], ebx 73 | add eax, 4 74 | mov ebx, [eax] 75 | mov [argv], ebx 76 | mov ecx, [ebx] 77 | mov [argv0], ecx 78 | add eax, 4 79 | mov eax, [eax] 80 | mov [envp], eax 81 | 82 | xor eax, eax 83 | mov [count], eax 84 | 85 | mov eax, switch_main_size 86 | mov eax, [eax] 87 | push eax 88 | push while 89 | call decrypt_buff 90 | jmp while 91 | 92 | section .switch_main write alloc exec 93 | while: 94 | mov eax, [count] 95 | test eax, eax 96 | jl return 97 | 98 | mov ecx, switch_cases 99 | mov ebx, switch_lookout 100 | xlatb 101 | xlatb 102 | xlatb 103 | xlatb 104 | shl al, 2 105 | add ecx, eax 106 | jmp [ecx] 107 | 108 | 109 | 110 | case1: 111 | mov eax, [image_base] 112 | add eax, [offset] 113 | mov ebx, [size] 114 | mov ecx, 0x100 115 | shl ecx, 2 116 | add eax, ecx 117 | push ebx 118 | push eax 119 | call decrypt_buff 120 | jmp iterate 121 | 122 | case0: 123 | ;call check_parent 124 | 125 | mov eax, [image_base] 126 | add eax, [offset] 127 | mov ebx, [size] 128 | mov ecx, 0x100 129 | shl ecx, 2 130 | add eax, ecx 131 | push ebx 132 | push eax 133 | call decrypt_buff 134 | jmp iterate 135 | 136 | 137 | 138 | case3: 139 | mov eax, [load_addr] 140 | mov [freqs], eax 141 | 142 | mov eax, size 143 | shl eax, 1 144 | push eax 145 | push 1 146 | call calloc 147 | mov [decoded], eax 148 | 149 | mov eax, [image_base] 150 | add eax, [offset] 151 | mov ebx, [size] 152 | mov ecx, 0x100 153 | shl ecx, 2 154 | add eax, ecx 155 | push ebx 156 | push eax 157 | call decrypt_buff 158 | 159 | jmp iterate 160 | 161 | case4: 162 | ;call check_ld_preload 163 | 164 | mov eax, [image_base] 165 | add eax, [offset] 166 | mov ebx, [size] 167 | mov ecx, 0x100 168 | shl ecx, 2 169 | add eax, ecx 170 | push ebx 171 | push eax 172 | call decrypt_buff 173 | 174 | jmp iterate 175 | 176 | case2: 177 | mov eax, [image_base] 178 | add eax, [offset] 179 | mov [load_addr], eax 180 | 181 | mov ebx, 0x100 182 | shl ebx, 2 183 | add eax, ebx 184 | mov [compressed_buf], eax 185 | 186 | mov eax, [image_base] 187 | add eax, [offset] 188 | mov ebx, [size] 189 | mov ecx, 0x100 190 | shl ecx, 2 191 | add eax, ecx 192 | push ebx 193 | push eax 194 | call decrypt_buff 195 | 196 | jmp iterate 197 | 198 | case7: 199 | push 0 200 | lea eax, [s1] 201 | push eax 202 | push SIGTRAP 203 | call sigaction 204 | test eax, eax 205 | jl exit 206 | 207 | mov eax, [image_base] 208 | add eax, [offset] 209 | mov ebx, [size] 210 | mov ecx, 0x100 211 | shl ecx, 2 212 | add eax, ecx 213 | push ebx 214 | push eax 215 | call decrypt_buff 216 | 217 | jmp iterate 218 | 219 | case5: 220 | mov eax, [freqs] 221 | push eax 222 | call get_map_len 223 | 224 | mov [nleaf_nodes], eax 225 | mov ebx, 0x10 226 | push eax 227 | push ebx 228 | call calloc 229 | mov [nodes], eax 230 | 231 | mov eax, [image_base] 232 | add eax, [offset] 233 | mov ebx, [size] 234 | mov ecx, 0x100 235 | shl ecx, 2 236 | add eax, ecx 237 | push ebx 238 | push eax 239 | call decrypt_buff 240 | 241 | jmp iterate 242 | 243 | case6: 244 | mov eax, [image_base] 245 | add eax, [offset] 246 | mov ebx, [size] 247 | mov ecx, 0x100 248 | shl ecx, 2 249 | add eax, ecx 250 | push ebx 251 | push eax 252 | call decrypt_buff 253 | 254 | mov eax, [nodes] 255 | mov ebx, [freqs] 256 | push eax 257 | push ebx 258 | call create_btree 259 | mov [btree], eax 260 | 261 | jmp iterate 262 | 263 | case8: 264 | mov eax, [image_base] 265 | add eax, [offset] 266 | mov ebx, [size] 267 | mov ecx, 0x100 268 | shl ecx, 2 269 | add eax, ecx 270 | push ebx 271 | push eax 272 | call decrypt_buff 273 | 274 | mov eax, [decoded] 275 | push eax 276 | mov eax, [size] 277 | push eax 278 | mov eax, [compressed_buf] 279 | push eax 280 | mov eax, [btree] 281 | push eax 282 | push eax 283 | call decode_bin 284 | mov [dsize], eax 285 | call check_hbreaks 286 | 287 | case10: 288 | xor eax, eax 289 | xor ebx, ebx 290 | idiv ebx 291 | 292 | 293 | iterate: 294 | add dword [count], 1 295 | jmp while 296 | 297 | exit: 298 | xor eax, eax 299 | inc ebx 300 | int 0x80 301 | 302 | return: 303 | ret 304 | 305 | switch_cases: 306 | .case6 dd case6 307 | .case9 dd case9 308 | .case4 dd case4 309 | .case8 dd case8 310 | .case2 dd case2 311 | .case5 dd case5 312 | .case0 dd case0 313 | .case7 dd case7 314 | .case3 dd case3 315 | .case1 dd case1 316 | 317 | .case10 dd case6+15 318 | .case11 dd case9+30 319 | .case12 dd case4+32 320 | .case13 dd case8+120 321 | .case14 dd case2+45 322 | .case15 dd case5+34 323 | .case16 dd case0+322 324 | .case17 dd case7+655 325 | .case18 dd case3+321 326 | .case19 dd case1+123 327 | 328 | switch_lookout db 4, 6, 8, 1, 3, 5, 2, 7, 9, 0, 10, 19, 18, 11, 12, 17, 16, 13, 15, 14 329 | end: 330 | 331 | section .text 332 | dsize dd 0 333 | btree dd 0 334 | nodes dd 0 335 | nleaf_nodes dd 0 336 | freqs dd 0 337 | compressed_buf dd 0 338 | load_addr dd 0 339 | count dd 0 340 | envp dd 0 341 | argv dd 0 342 | argv0 dd 0 343 | argc dd 0 344 | decoded dd 0 345 | switch_main_size dd end - while 346 | 347 | section .case9 348 | case9: 349 | push 0 350 | lea eax, [s1] 351 | push eax 352 | push SIGSEGV 353 | call sigaction 354 | test eax, eax 355 | jl exit 356 | 357 | mov eax, [envp] 358 | push eax 359 | mov eax, [argv] 360 | push eax 361 | mov eax, [argc] 362 | push eax 363 | mov eax, [dsize] 364 | push eax 365 | mov eax, [decoded] 366 | push eax 367 | mov eax, [argv0] 368 | push eax 369 | call ul_exec 370 | 371 | jmp iterate 372 | case9_end: 373 | nop 374 | nop 375 | nop 376 | 377 | 378 | 379 | -------------------------------------------------------------------------------- /layer1/src/ul_exec.c: -------------------------------------------------------------------------------- 1 | #include <unistd.h> 2 | #include <stdlib.h> 3 | #include <alloca.h> 4 | #include <elf.h> 5 | #include <signal.h> 6 | #include <errno.h> 7 | #include <string.h> 8 | #include <sys/types.h> 9 | #include <sys/stat.h> 10 | #include <fcntl.h> 11 | #include <sys/mman.h> 12 | #include <sys/prctl.h> 13 | #include "../include/ul_execP.h" 14 | 15 | #define SET_STACK(esp) asm("\tmovl %0, %%esp\n" :: "r"(esp)) 16 | #define JMP_ADDR(addr) asm("\tjmp *%0\n" :: "r" (addr)) 17 | 18 | static void ul_exec_common(void *ELF_buf, size_t elf_buf_size, ul_args_t *argv, ul_args_t *envp, ul_args_t *auxvp); 19 | 20 | void ul_exec(char *progname, void *elf_buf, size_t elf_buf_sz, int argc, char **argv, char **env) { 21 | ul_args_t *argvp, *envp, *auxvp; 22 | if ((argvp = ul_save_args(argc, argv)) == NULL) 23 | return; 24 | 25 | if ((envp = ul_save_args(0, env)) == NULL) 26 | return; 27 | 28 | if ((auxvp = ul_save_elfauxv(env)) == NULL) 29 | return; 30 | 31 | ul_exec_common(elf_buf, elf_buf_sz, argvp, envp, auxvp); 32 | } 33 | 34 | static void ul_exec_common( void *elf_buf, size_t elf_buf_sz, ul_args_t *argv, ul_args_t *envp, ul_args_t *auxvp) { 35 | Elf32_Ehdr *elf, *interp; 36 | void (*entry)(); 37 | void *esp; 38 | 39 | prctl(PR_SET_DUMPABLE, 0); 40 | 41 | if (ul_load_elf(elf_buf, &elf, &interp)) 42 | return; 43 | 44 | entry = interp ? (void(*)())(((char *)interp) + interp->e_entry) : 45 | (void(*)())elf->e_entry; 46 | esp = ul_setup_stack(argv, envp, auxvp, elf, interp); 47 | 48 | if (NULL == esp) return; 49 | 50 | asm volatile(".byte 0xf1"); // icebp 51 | SET_STACK(esp); 52 | JMP_ADDR(entry); 53 | } 54 | -------------------------------------------------------------------------------- /layer1/src/unmap.c: -------------------------------------------------------------------------------- 1 | /* $Id: unmap.c,v 1.6 2012/07/12 23:33:31 bediger Exp $ */ 2 | #include <stdio.h> /* BUFSIZ, snprintf(), fopen(), fread(), etc */ 3 | #include <stdlib.h> /* strtoul() */ 4 | #include <errno.h> 5 | #include <string.h> 6 | #include <unistd.h> /* getpid() */ 7 | #include <sys/mman.h> 8 | #include <signal.h> 9 | #include <elf.h> 10 | #include "../include/ul_execP.h" 11 | 12 | #ifdef SIGNAL_HANDLER 13 | /* signal handler function in .so, so that it doesn't get 14 | * munmapped along with the .text segment. If something in 15 | * unmap() segfaults, this will let us know. */ 16 | void 17 | handler(int signo, siginfo_t *info, void *p) { 18 | ucontext_t *ctxt = p; 19 | fprintf(stderr, "enter handler(%d)\n", signo); 20 | fprintf(stderr, "siginfo_t at %p, ucontext_t at %p\n", info, ctxt); 21 | fprintf(stderr, "si_signo %d\n", info->si_signo); 22 | fprintf(stderr, "si_errno %d\n", info->si_errno); 23 | fprintf(stderr, "si_code %d\n", info->si_code); 24 | if (signo == SIGSEGV) 25 | { 26 | switch (info->si_code) 27 | { 28 | case SEGV_MAPERR: fprintf(stderr, "Address not mapped to object.\n"); break; 29 | case SEGV_ACCERR: fprintf(stderr, "Invalid permissions for mapped object.\n"); break; 30 | } 31 | 32 | fprintf(stderr, "Faulting instruction/memory ref: %p\n", 33 | info->si_addr); 34 | } 35 | exit(99); 36 | } 37 | #endif 38 | 39 | void 40 | unmap(char *progname, int set_handler) { 41 | char buf[BUFSIZ], *p; 42 | int c; 43 | FILE *fin; 44 | #ifdef SIGNAL_HANDLER 45 | struct sigaction act, oact; 46 | 47 | if (set_handler) 48 | { 49 | act.sa_flags = SA_SIGINFO; 50 | act.sa_sigaction = handler; 51 | 52 | if (sigaction(SIGSEGV, &act, &oact)) 53 | fprintf(stderr, "Problem setting handler for SIGSEGV: %s\n", 54 | strerror(errno)); 55 | } 56 | #endif 57 | 58 | fin = fopen("/proc/self/maps", "r"); 59 | 60 | p = &buf[0]; 61 | 62 | /* Read contents of /proc/self/maps into buf, one byte at 63 | * a time. When we hit a newline-valuded byte, we know we've 64 | * read an entire line of text, and we can now act on it. */ 65 | while (EOF != (c = fgetc(fin))) 66 | { 67 | if ('\n' != c) 68 | *p++ = c; 69 | else { 70 | *p = '\0'; 71 | /* When a line from /proc/self/maps shows up as having been 72 | * mapped in from this running program, ld.so or libc, unmap it. 73 | * This will keep the exec'd program's address space a lot 74 | * cleaner. But even a 32-bit address space can hold 2 copies 75 | * of glibc without ill effects, so you don't really have to 76 | * munmap() anything other than the program calling ul_exec() */ 77 | if (strstr(buf, progname) || strstr(buf, "libdl") 78 | || strstr(buf, "/lib/ld-") || strstr(buf, "libc")) 79 | { 80 | char *u; 81 | char *first, *second; 82 | unsigned int low, high; 83 | 84 | u = strchr(buf, ' '); 85 | *u = '\0'; 86 | 87 | first = buf; 88 | 89 | second = strchr(first, '-'); 90 | *second = '\0'; 91 | ++second; 92 | 93 | low = strtoul(first, NULL, 0x10); 94 | high = strtoul(second, NULL, 0x10); 95 | 96 | if (munmap((void *)low, high-low)) 97 | fprintf(stderr, "munmap 0x%x (%d) bytes at 0x%x failed: %s\n", 98 | high-low, high-low, low, strerror(errno)); 99 | 100 | } 101 | 102 | p = &buf[0]; 103 | } 104 | } 105 | 106 | fclose(fin); 107 | } 108 | 109 | #ifdef NEEDITNOW 110 | /* A function useful in debugging, but nowhere else. */ 111 | void print_maps(void) { 112 | char buf[BUFSIZ]; 113 | int cc; 114 | FILE *fin; 115 | 116 | fin = fopen("/proc/self/maps", "r"); 117 | 118 | while (0 < (cc = fread(buf, 1, sizeof(buf), fin))) 119 | fwrite(buf, 1, cc, stdout); 120 | 121 | fclose(fin); 122 | } 123 | #endif 124 | -------------------------------------------------------------------------------- /layer2/include/c_primitives.h: -------------------------------------------------------------------------------- 1 | #include <signal.h> 2 | 3 | static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6); 4 | static inline long syscall3(long syscall, long arg1, long arg2, long arg3); 5 | static inline long syscall2(long syscall, long arg1, long arg2); 6 | static inline long syscall1(long syscall, long arg1); 7 | 8 | 9 | int __exit(int exit_code); 10 | int _write(int fd, const void* buf, int count); 11 | void * _mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 12 | void * _malloc(size_t length); 13 | int _mprotect(void *addr, size_t len, int prot); 14 | void _memset(void *addr, size_t len); 15 | int _sigaction(int signum, const struct sigaction *act,struct sigaction *oldact); 16 | size_t _strlen(const uint8_t *s); 17 | int _munmap(void *addr, size_t length); 18 | void *_memcpy(uint8_t *dest, const uint8_t *src, size_t n); 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /layer2/include/huffman.h: -------------------------------------------------------------------------------- 1 | 2 | #define QSIZE 0xff + 1 3 | 4 | typedef struct __node_t { 5 | int freq; 6 | char key; 7 | bool leaf; 8 | struct __node_t *left, *right; 9 | } Node; 10 | 11 | int decode_bin(Node *root, Node *original, char *bytes, int len, uint8_t *decoded); 12 | void qinsert(Node **nodes, Node *node); 13 | void insert_node(Node **nodes, Node *left, Node *right, int freq, int key); 14 | void qdelete(Node **nodes, int idx); 15 | int get_map_len(int *freqs); 16 | void encode(Node *root, int len, char *code, int nleaf_nodes); 17 | void decode(Node *root, Node *original, char *bits, int len); 18 | void insert_leaf_nodes(int *freqs, Node **nodes); 19 | Node *create_btree(int *freqs, Node **nodes); 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /layer2/include/huffman_encoding.h: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <stdlib.h> 3 | #include <string.h> 4 | #include <unistd.h> 5 | #include <limits.h> 6 | #include <errno.h> 7 | #include <sys/mman.h> 8 | #include <sys/stat.h> 9 | #include <fcntl.h> 10 | #include <stdbool.h> 11 | #include <elf.h> 12 | #include <ctype.h> 13 | #include <signal.h> 14 | #include <sys/ptrace.h> 15 | 16 | #define QSIZE 0x100 17 | 18 | static int qtail = -1; 19 | static char *encoding[QSIZE] = {0}, *decoding, *compressed; 20 | 21 | typedef struct __node_t { 22 | int freq; 23 | char key; 24 | bool leaf; 25 | struct __node_t *left, *right; 26 | } Node; 27 | 28 | 29 | int decode_bin(Node *root, Node *original, char *bytes, int len) { 30 | int nbyte = 0, n = 0, nbit = 7; 31 | char byte = bytes[0]; 32 | 33 | while( nbyte < len ) { 34 | while (nbit >= 0) { 35 | if(root->leaf){ 36 | *(decoding + n++) = root->key; 37 | root = original; 38 | } 39 | root = (byte & (0x1 << nbit--)) ? root = root->right : root->left; 40 | } 41 | nbit = 7; 42 | byte = bytes[++nbyte]; 43 | } 44 | return n; 45 | 46 | } 47 | 48 | int str2bin(char* bin) { 49 | char* start = &bin[0]; 50 | int total = 0; 51 | 52 | while (*start){ 53 | total <<= 1; 54 | if (*start++ == '1') total ^= 1; 55 | } 56 | return total; 57 | } 58 | 59 | char * generate_elf_ordered_bitstream(uint8_t *elf, int size) { 60 | char *ord_bitstream = (char*)calloc(sizeof(char), size*30); 61 | int i, j = 0; 62 | 63 | for( i = 0; i < size; i++) { 64 | char *buf = strdup(encoding[elf[i]]); 65 | memcpy(ord_bitstream + j, buf, strlen(buf)); 66 | j += strlen(buf); 67 | 68 | free(buf); 69 | } 70 | ord_bitstream[j] = '\0'; 71 | 72 | return ord_bitstream; 73 | } 74 | 75 | void init_elf_hash_map(uint8_t *elf, int size, int *freqs) { 76 | int i; 77 | 78 | 79 | for (i = 0; i < size; i++) { 80 | if(elf[i] == 0) { 81 | freqs[0] += 1; 82 | } else { 83 | freqs[elf[i]] += 1; 84 | } 85 | } 86 | } 87 | 88 | unsigned char *binary2hex(char *ord_bitstream, int rsize, int *size){ 89 | unsigned char *hexstr = calloc(1, strlen(ord_bitstream)); 90 | unsigned char four[8]; 91 | int i, j = 0; 92 | 93 | 94 | for(i = 0; i < rsize / 8; ++i){ 95 | int hexnum = 0; 96 | memcpy(four, ord_bitstream + (i * 8), 8); 97 | 98 | hexnum = (int)str2bin(four); 99 | hexstr[j] = hexnum & 0xff; 100 | j+=1; 101 | } 102 | *size = j; 103 | return hexstr; 104 | } 105 | 106 | unsigned char * dc_bin2hex(char *ord_bitstream, int *size) { 107 | 108 | int half = strlen(ord_bitstream) / 2; 109 | int rsize, lsize; 110 | 111 | char * str1 = binary2hex(ord_bitstream, strlen(ord_bitstream), &rsize); 112 | char * hexstr = calloc(1, rsize); 113 | 114 | 115 | memcpy(hexstr, str1, rsize); 116 | *size = rsize; 117 | 118 | free(str1); 119 | return hexstr; 120 | 121 | } 122 | 123 | void qinsert(Node **nodes, Node *node){ 124 | int i = 0, j = 0; 125 | 126 | if(qtail == -1) { 127 | nodes[++qtail] = node; 128 | return; 129 | }else{ 130 | j = qtail+1; 131 | for(i = qtail; i >= 0; i--){ 132 | if(node->freq <= nodes[i]->freq) { 133 | nodes[j--] = nodes[i]; 134 | nodes[i] = node; 135 | }else{ 136 | nodes[j] = node; 137 | break; 138 | } 139 | 140 | } 141 | qtail += 1; 142 | return; 143 | } 144 | } 145 | 146 | void insert_node(Node **nodes, Node *left, Node *right, int freq, int key) { 147 | Node *node = (Node*) calloc(1, sizeof(Node)); 148 | 149 | if(!freq && !key) { 150 | node->freq = left->freq + right->freq; 151 | node->key = 0; 152 | node->leaf = false; 153 | node->left = left; 154 | node->right = right; 155 | }else{ 156 | node->freq = freq; 157 | node->key = key; 158 | node->leaf = true; 159 | node->left = NULL; 160 | node->right = NULL; 161 | } 162 | qinsert(nodes, node); 163 | } 164 | 165 | void qdelete(Node **nodes, int idx) { 166 | int i; 167 | 168 | for (i = idx; i < qtail; i++) { 169 | nodes[i] = nodes[i+1]; 170 | } 171 | qtail--; 172 | } 173 | 174 | int get_map_len(int *freqs) { 175 | int num = 0; 176 | 177 | 178 | for(int i = 0; i < QSIZE; i++) 179 | if(freqs[i] != 0) num++; 180 | return num; 181 | } 182 | 183 | void encode(Node *root, int len, char *code, int nleaf_nodes) { 184 | 185 | if(root->leaf) { 186 | *(code + len) = '\0'; 187 | char * cpy = strdup(code); 188 | // printf("%02x: %s\n", root->key & 0xff, cpy); 189 | encoding[root->key & 0xff] = cpy; 190 | return; 191 | }else{ 192 | code[len] = '1'; 193 | encode(root->right, len + 1, code, nleaf_nodes); 194 | 195 | code[len] = '0'; 196 | encode(root->left, len + 1, code, nleaf_nodes); 197 | } 198 | } 199 | 200 | void insert_leaf_nodes(int *freqs, Node **nodes) { 201 | int i = 0; 202 | 203 | while(i < QSIZE) { 204 | if (freqs[i] != 0) { 205 | insert_node(nodes, NULL, NULL, freqs[i], i); 206 | } 207 | i++; 208 | } 209 | } 210 | 211 | Node *create_btree(int *freqs, Node **nodes) { 212 | insert_leaf_nodes(freqs, nodes); 213 | 214 | while(qtail > 0){ 215 | Node *left = *nodes; 216 | Node *right = *(nodes + 1); 217 | 218 | qdelete(nodes, 0); 219 | insert_node(nodes, left, right, 0, 0); 220 | qdelete(nodes, 0); 221 | } 222 | return nodes[0]; 223 | } 224 | 225 | char * generate_ordered_bitstream(int sect_sz, int sect_off, uint8_t *elf) { 226 | int i; 227 | char *ord_bitstream = (char*) calloc(1, (sect_sz*30)*sizeof(char)); 228 | 229 | for( i = 0; i < sect_sz; i++) { 230 | char *buf = strdup(encoding[elf[sect_off+i]]); 231 | strcat(ord_bitstream, buf); 232 | free(buf); 233 | } 234 | 235 | return ord_bitstream; 236 | } 237 | 238 | 239 | void check_parent() { 240 | char buff[32]; 241 | int fd; 242 | 243 | snprintf(buff, 24, "/proc/%d/status", getppid()); 244 | 245 | if((fd = open(buff, O_RDONLY)) < 0) { 246 | return; 247 | } 248 | read(fd, buff, 16); 249 | close(fd); 250 | 251 | if(strstr(buff, "r2") || strstr(buff, "radare2") || strstr(buff, "gdb") || strstr(buff, "ida") || strstr(buff, "trace")) { 252 | kill(0, SIGTERM); 253 | } 254 | } 255 | 256 | void check_ld_preload() { 257 | int k = 0; 258 | 259 | char *str = getenv("LD_PRELOAD"); 260 | 261 | if(str == NULL) { 262 | putenv("LD_PRELOAD=Fasces"); 263 | if (strcmp(getenv("LD_PRELOAD"), "Fasces")){ 264 | kill(0, SIGTERM); 265 | } 266 | }else{ 267 | kill(0, SIGTERM); 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /layer2/include/ul_exec.h: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #ifndef USERLAND_EXEC_H_ 3 | #define USERLAND_EXEC_H_ 1 4 | 5 | void ul_exec(char *progname, void *ELF_buf, size_t elf_buf_size, int argc, char **argv, char **envp); 6 | 7 | #endif /* USERLAND_EXEC_H_ */ 8 | -------------------------------------------------------------------------------- /layer2/include/ul_execP.h: -------------------------------------------------------------------------------- 1 | 2 | #include <elf.h> 3 | #include <stdio.h> 4 | #include <stdlib.h> 5 | #include <stddef.h> 6 | #ifndef USERLAND_EXEC_PRIV_H_ 7 | #define USERLAND_EXEC_PRIV_H_ 1 8 | 9 | typedef struct ul_args ul_args_t; 10 | 11 | 12 | extern ul_args_t *ul_save_args(int argc, char **argv); 13 | extern ul_args_t *ul_save_elfauxv(char **envp); 14 | extern void ul_release_args(ul_args_t *args); 15 | extern void * ul_setup_stack(ul_args_t *args, ul_args_t *envp, ul_args_t *auxvp, Elf32_Ehdr *elf,Elf32_Ehdr *interp); 16 | extern int ul_load_elf(void *ELF_buf, Elf32_Ehdr **elf, Elf32_Ehdr **interp); 17 | void *memcopy(void *dest, const void *src, size_t n); 18 | void unmap(char *progname, int set_signal_handler); 19 | void print_maps(void); 20 | 21 | #define ROUNDUP(x, y) ( ( ( x + ( y - 1 ) ) / y ) * y ) 22 | #define ALLOCATE(size) \ 23 | mmap(0, (size), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 24 | #define ALIGN(k, v) (((k)+((v)-1))&(~((v)-1))) 25 | #define ALIGNDOWN(k, v) ((unsigned int)(k)&(~((unsigned int)(v)-1))) 26 | 27 | /* Default VM page size in bytes. Hopefully, ul_save_elfauxv() will find 28 | * the page size in the ELF auxilliary vector and use that value instead. */ 29 | #define PAGESIZE 0x1000 30 | 31 | #endif /* USERLAND_EXEC_PRIV_H_ */ 32 | -------------------------------------------------------------------------------- /layer2/src/.c_primitives.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer2/src/.c_primitives.c.swp -------------------------------------------------------------------------------- /layer2/src/.embed.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer2/src/.embed.c.swp -------------------------------------------------------------------------------- /layer2/src/.launcher.asm.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer2/src/.launcher.asm.swp -------------------------------------------------------------------------------- /layer2/src/.rc4.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer2/src/.rc4.c.swp -------------------------------------------------------------------------------- /layer2/src/c_primitives.c: -------------------------------------------------------------------------------- 1 | #include <stdint.h> 2 | #include <unistd.h> 3 | #include <sys/mman.h> 4 | #include <signal.h> 5 | 6 | static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) { 7 | long ret; 8 | 9 | asm volatile("movl %1, %%eax;\n" 10 | "movl %2, %%ebx;\n" 11 | "movl %3, %%ecx;\n" 12 | "movl %4, %%edx;\n" 13 | "movl %5, %%esi;\n" 14 | "movl %6, %%edi;\n" 15 | "movl %7, %%ebp;\n" 16 | "int $0x80;\n" 17 | : "=a" (ret) 18 | : "g" (syscall) ,"g" (arg1), "g" (arg2), "g" (arg3), "g" (arg4), "g" (arg5), "g" (arg6)); 19 | return ret; 20 | } 21 | 22 | static inline long syscall3(long syscall, long arg1, long arg2, long arg3) { 23 | long ret; 24 | asm volatile("int $0x80;" : "=a" (ret) 25 | : "a" (syscall) 26 | , "b" (arg1) 27 | , "c" (arg2) 28 | , "d" (arg3) 29 | : "memory"); 30 | return ret; 31 | } 32 | 33 | static inline long syscall2(long syscall, long arg1, long arg2) { 34 | long ret; 35 | asm volatile("int $0x80;" : "=a" (ret) 36 | : "a" (syscall) 37 | , "b" (arg1) 38 | , "c" (arg2) 39 | : "memory"); 40 | return ret; 41 | } 42 | 43 | static inline long syscall1(unsigned long syscall, long arg1) { 44 | long ret; 45 | 46 | asm volatile("int $0x80;" : "=a" (ret) 47 | : "a" (syscall) 48 | , "b" (arg1) 49 | : "memory"); 50 | return ret; 51 | } 52 | 53 | int __exit(int exit_code) { 54 | return syscall1(1, exit_code); 55 | } 56 | 57 | int _write(int fd, const void* buf, int count) { 58 | return syscall3(4, fd, (long)buf, count); 59 | } 60 | 61 | void * _mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset){ 62 | return (void *)syscall6(192, (unsigned long)addr, length, prot, flags, fd, offset); 63 | } 64 | 65 | void * _malloc(size_t length){ 66 | length = (length <= 4096) ? 4096 : 4096 * ((length / 2096) + 1); 67 | void *mem = _mmap(NULL, length, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0); 68 | return mem; 69 | } 70 | 71 | int _mprotect(void *addr, size_t len, int prot) { 72 | return syscall3(125, (long)addr, len, prot); 73 | } 74 | 75 | void _memset(void *addr, size_t len) { 76 | asm volatile( 77 | "movl %0, %%ecx;\n" 78 | "movl %1, %%edi;\n" 79 | "xorb %%al, %%al;\n" 80 | "rep stosb;\n" 81 | : : "g" (len), "g" (addr)); 82 | } 83 | 84 | int _sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { 85 | return syscall3(67, signum, (long)act, (long)oldact); 86 | } 87 | 88 | int _munmap(void *addr, size_t length) { 89 | return syscall2(11, (long)addr, length); 90 | } 91 | 92 | void *_memcpy(uint8_t *dest, const uint8_t *src, size_t n) { 93 | int i = 0; 94 | while(i++ != n) dest[i] = src[i]; 95 | return dest; 96 | } 97 | 98 | size_t _strlen(const uint8_t *s) { 99 | int ret = 0; 100 | while(s[ret] != 0) ret++; 101 | return ret; 102 | } 103 | 104 | int _open(const char *pathname, int flags) { 105 | return syscall2(2, pathname, flags); 106 | } 107 | 108 | int _fstat(int fd, struct stat *buf) { 109 | return syscall2(5, fd, buf); 110 | } 111 | 112 | int _close(int fd) { 113 | return syscall1(3, fd); 114 | } 115 | 116 | char * _strcat(char *dest, const char *src) { 117 | char *rdest = dest; 118 | 119 | while (*dest) 120 | dest++; 121 | while (*dest++ = *src++); 122 | return rdest; 123 | } 124 | -------------------------------------------------------------------------------- /layer2/src/embed.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <stdlib.h> 3 | #include <string.h> 4 | #include <unistd.h> 5 | #include <limits.h> 6 | #include <errno.h> 7 | #include <sys/mman.h> 8 | #include <sys/stat.h> 9 | #include <fcntl.h> 10 | #include <stdbool.h> 11 | #include <elf.h> 12 | #include <time.h> 13 | #include "../include/huffman_encoding.h" 14 | #include "rc4_embed.c" 15 | 16 | #define PAGE_SIZE 0x1000 17 | #define PAGE_ROUND_UP(x) ( (((unsigned int)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1)) ) 18 | 19 | 20 | void file_export(uint8_t *elf, int size, char* name) { 21 | int fd; 22 | fd = open(name , O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); 23 | write(fd, elf, size); 24 | close(fd); 25 | 26 | return; 27 | } 28 | 29 | 30 | uint8_t* alloc_file(int *fd, struct stat *st, const char *filename) { 31 | uint8_t *elf; 32 | if((*fd = open(filename, O_RDWR)) < 0) { 33 | perror("exit"); 34 | exit(-1); 35 | } 36 | if(fstat(*fd, st) < 0) { 37 | perror("fstat"); 38 | exit(-1); 39 | } 40 | if((elf = mmap(NULL, st->st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) { 41 | perror("mmap"); 42 | exit(-1); 43 | } 44 | return elf; 45 | } 46 | 47 | int get_section(uint8_t *elf, uint32_t *offset, uint8_t *name) { 48 | int i, size = 0; 49 | uint8_t *strtab; 50 | Elf32_Shdr *shdr; 51 | 52 | Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf; 53 | shdr = (Elf32_Shdr*)&elf[ehdr->e_shoff]; 54 | strtab = (uint8_t*)(&elf[shdr[ehdr->e_shstrndx].sh_offset]); 55 | 56 | for(i = 1; i < ehdr->e_shnum; i++){ 57 | if (strstr(&strtab[shdr[i].sh_name], name)) { 58 | size = shdr[i].sh_size; 59 | *offset = shdr[i].sh_offset; 60 | break; 61 | } 62 | } 63 | return size; 64 | } 65 | 66 | int main (int argc, char **argv) { 67 | uint8_t *elf1, *elf2, *f; 68 | struct stat st1, st2; 69 | int fd1, fd2, i, size_hstr, rc4_blob_size, 70 | nleaf_nodes, freqs[0x100] = {0}, 71 | elf_offset, elf_align, text_size, text_addr, prev_code, rc4_off; 72 | char *ord_bitstream, *c, *hexstr; 73 | Elf32_Ehdr *ehdr1, *ehdr2, *ehdr3; 74 | Elf32_Phdr *phdr, *code; 75 | Elf32_Shdr *shdr; 76 | Node **nodes; 77 | 78 | if(argc < 4) { 79 | fprintf(stderr, "Usage %s <ux laucher> <file to compress> <output filename>\n", argv[0]); 80 | exit(0); 81 | } 82 | if((f = mmap(NULL, 0x10000000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED) { 83 | perror("mmap"); 84 | exit(-1); 85 | } 86 | 87 | elf1 = alloc_file(&fd1, &st1, argv[1]); 88 | elf2 = alloc_file(&fd2, &st2, argv[2]); 89 | 90 | if(elf1[0] != 0x7f && strcmp((char*)&elf1[1], "ELF")){ 91 | fprintf(stderr, "[!] File 1 is not an elf file\n"); 92 | exit(-1); 93 | } 94 | if(elf2[0] != 0x7f && strcmp((char*)&elf2[1], "ELF")){ 95 | fprintf(stderr, "[!] File 2 is not an elf file\n"); 96 | exit(-1); 97 | } 98 | 99 | ehdr1 = (Elf32_Ehdr*)elf1; 100 | ehdr2 = (Elf32_Ehdr*)elf2; 101 | 102 | if(ehdr2->e_machine != EM_386) { 103 | printf("[-] ELFMaze does not support Binaries that isn't x86.\n"); 104 | exit(EXIT_FAILURE); 105 | } 106 | if(ehdr2->e_type != ET_EXEC) { 107 | printf("[-] ELFMaze does not support ET_DYN\n"); 108 | exit(EXIT_FAILURE); 109 | } 110 | 111 | if(ehdr2->e_version != EV_CURRENT) { 112 | printf("[-] Not a \"current\" ELF file.\n"); 113 | return -1; 114 | } 115 | if(ehdr2->e_ehsize != sizeof(Elf32_Ehdr) || ehdr2->e_phentsize != sizeof(Elf32_Phdr) || 116 | ehdr2->e_phnum > 20) { 117 | printf("[-] Invalid ELF header sizes\n"); 118 | return -1; 119 | } 120 | memset(elf2, 0, 4); // deleating magic header from blob 121 | printf("[+] ELF magic deleated from stub: (%s)\n", elf2); 122 | printf("[*] Packing file %s\n", argv[2]); 123 | phdr = (Elf32_Phdr*)&elf1[ehdr1->e_phoff]; 124 | 125 | for (i = 0; i < ehdr1->e_phnum; i++) { 126 | if (phdr[i].p_type == PT_LOAD && !phdr[i].p_offset) { 127 | code = &phdr[i]; 128 | break; 129 | } 130 | } 131 | 132 | printf("[*] compressing target binary via huffman encoding\n"); 133 | decoding = (char*)calloc(sizeof(char), st2.st_size); 134 | c = (char*)calloc(sizeof(char), (st2.st_size*10)); 135 | 136 | printf("[+] Initialization of frequency table\n"); 137 | init_elf_hash_map(elf2, st2.st_size, freqs); 138 | nleaf_nodes = get_map_len(freqs); 139 | 140 | printf("[+] Length of frequency dictionary: %d\n", nleaf_nodes); 141 | nodes = (Node**)calloc(1, nleaf_nodes*sizeof(Node)); 142 | 143 | printf("[+] Creating binary tree\n"); 144 | Node *btree = create_btree(freqs, nodes); 145 | 146 | printf("[+] Generating master tree\n"); 147 | encode(btree, 0, c, nleaf_nodes); 148 | 149 | printf("[*] Generating bitstream of target file\n"); 150 | ord_bitstream = generate_elf_ordered_bitstream(elf2, st2.st_size); 151 | 152 | printf("[*] Converting bitstream into hex\n"); 153 | uint8_t *val = dc_bin2hex(ord_bitstream, &size_hstr); 154 | memset(ord_bitstream, '\0', strlen(ord_bitstream)); 155 | printf("[*] Compression ratio: %.2f%%\n", (float)size_hstr / st2.st_size * 100); 156 | 157 | rc4_blob_size = get_section(elf1, &rc4_off, ".text"); 158 | printf("[+] Encripting .text section using RC4 at offset 0x%x of size 0x%x\n", rc4_off, rc4_blob_size); 159 | int seed = 0x1337 + clock(); 160 | srand(seed); 161 | uint8_t randstr[16] = {0}; 162 | for (i = 0; i < 16; i++) { 163 | randstr[i] = rand() % (0x7f + 1 - 0x20) + 5 ; 164 | } 165 | printf("[+] Generated seed 0x%x\n", seed); 166 | printf("[+] Using key %s\n", randstr); 167 | 168 | rc4_crypt_blob(elf1 + rc4_off, rc4_blob_size, randstr, 16); 169 | printf("[+] .text Section encrypted successfully\n"); 170 | 171 | prev_code = code->p_filesz; 172 | code->p_filesz = code->p_memsz + size_hstr + sizeof(freqs) + 16; 173 | code->p_memsz = code->p_filesz; 174 | //code->p_flags = PF_X | PF_W | PF_R; 175 | code->p_flags = PF_R | PF_W; //LOL 176 | elf_offset = prev_code; 177 | 178 | memmove(f + code->p_offset, elf1 + code->p_offset, prev_code); 179 | memmove(f + elf_offset, freqs, sizeof(freqs)); 180 | memmove(f + elf_offset + sizeof(freqs), val, size_hstr); 181 | memcpy(f + elf_offset + sizeof(freqs) + size_hstr, randstr, 16); 182 | 183 | ehdr3 = (Elf32_Ehdr*)f; 184 | *(uint32_t*)&ehdr3->e_shoff = (uint32_t)(rc4_blob_size); 185 | printf("[+] Embedding blob_size: 0x%x\n", rc4_blob_size); 186 | 187 | int rc4_key_off = elf_offset + sizeof(freqs) + size_hstr; 188 | *(uint32_t*)&ehdr3->e_flags = (uint32_t)(rc4_key_off); 189 | printf("[+] Embedding key_offset: 0x%x\n", rc4_key_off); 190 | 191 | *(uint8_t*)&ehdr3->e_ident[5]='\x02'; 192 | *(uint32_t*)&ehdr3->e_ident[8] = (uint32_t)elf_offset; 193 | *(uint32_t*)&ehdr3->e_ident[12] = (uint32_t)size_hstr; 194 | 195 | ehdr3->e_phnum = 1; 196 | ehdr3->e_shnum = 0; 197 | ehdr3->e_shstrndx = 0; 198 | ehdr3->e_shentsize = 0; 199 | 200 | file_export(f, code->p_filesz, argv[3]); 201 | printf("[*] File exported with name %s\n", argv[3]); 202 | } 203 | -------------------------------------------------------------------------------- /layer2/src/huffman.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <stdlib.h> 3 | #include <string.h> 4 | #include <unistd.h> 5 | #include <limits.h> 6 | #include <errno.h> 7 | #include <sys/mman.h> 8 | #include <sys/stat.h> 9 | #include <fcntl.h> 10 | #include <stdbool.h> 11 | #include <elf.h> 12 | #include <ctype.h> 13 | #include "../include/huffman.h" 14 | 15 | static unsigned int qtail = -1; 16 | 17 | int decode_bin(Node *root, Node *original, char *bytes, int len, uint8_t * decoded) { 18 | int nbyte = 0, n = 0, nbit = 7; 19 | char byte = bytes[0]; 20 | 21 | while( nbyte < len ) { 22 | while (nbit >= 0) { 23 | if(root->leaf){ 24 | *(decoded + n++) = root->key; 25 | root = original; 26 | } 27 | root = (byte & (0x1 << nbit--)) ? root->right : root->left; 28 | } 29 | nbit = 7; 30 | byte = bytes[++nbyte]; 31 | } 32 | return n; 33 | 34 | } 35 | 36 | void qinsert(Node **nodes, Node *node){ 37 | int i = 0, j = 0; 38 | 39 | if(qtail == -1) { 40 | nodes[++qtail] = node; 41 | return; 42 | }else{ 43 | j = qtail+1; 44 | for(i = qtail; i >= 0; i--){ 45 | if(node->freq <= nodes[i]->freq) { 46 | nodes[j--] = nodes[i]; 47 | nodes[i] = node; 48 | }else{ 49 | nodes[j] = node; 50 | break; 51 | } 52 | 53 | } 54 | qtail += 1; 55 | return; 56 | } 57 | } 58 | 59 | void insert_node(Node **nodes, Node *left, Node *right, int freq, int key) { 60 | Node *node = (Node*) malloc(sizeof(Node)); 61 | 62 | if(!freq && !key) { 63 | node->freq = left->freq + right->freq; 64 | node->key = 0; 65 | node->leaf = false; 66 | node->left = left; 67 | node->right = right; 68 | }else{ 69 | node->freq = freq; 70 | node->key = key; 71 | node->leaf = true; 72 | node->left = NULL; 73 | node->right = NULL; 74 | } 75 | qinsert(nodes, node); 76 | } 77 | 78 | void qdelete(Node **nodes, int idx) { 79 | int i; 80 | 81 | for (i = idx; i < qtail; i++) { 82 | nodes[i] = nodes[i+1]; 83 | } 84 | qtail--; 85 | } 86 | 87 | int get_map_len(int *freqs) { 88 | int i, num = 0; 89 | 90 | for(i = 0; i < QSIZE; i++) 91 | if(freqs[i] != 0) num++; 92 | return num; 93 | } 94 | 95 | void init_hash_map(int sect_sz, int sect_off, int *freqs, uint8_t *elf) { 96 | int i; 97 | 98 | for( i = 0; i < sect_sz; i++) { 99 | if(elf[sect_off+i] == 0){ 100 | freqs[0]+=1; 101 | }else{ 102 | freqs[elf[sect_off+i]&0xff]+=1; 103 | } 104 | } 105 | } 106 | 107 | void insert_leaf_nodes(int *freqs, Node **nodes) { 108 | int i = 0; 109 | 110 | while(i < QSIZE) { 111 | if (freqs[i] != 0) { 112 | insert_node(nodes, NULL, NULL, freqs[i], i); 113 | } 114 | i++; 115 | } 116 | } 117 | 118 | Node *create_btree(int *freqs, Node **nodes) { 119 | qtail = -1; 120 | insert_leaf_nodes(freqs, nodes); 121 | 122 | while(qtail > 0){ 123 | Node *left = *nodes; 124 | Node *right = *(nodes + 1); 125 | 126 | qdelete(nodes, 0); 127 | insert_node(nodes, left, right, 0, 0); 128 | qdelete(nodes, 0); 129 | } 130 | return nodes[0]; 131 | } 132 | 133 | 134 | -------------------------------------------------------------------------------- /layer2/src/launcher.asm: -------------------------------------------------------------------------------- 1 | 2 | [bits 32] 3 | 4 | global rc4_key:data 5 | global rc4_size:data 6 | global start_rc4:data 7 | 8 | extern check_hardware_breakpoints 9 | extern sigfpe_handler 10 | extern fork 11 | extern exit 12 | extern kill 13 | extern waitpid 14 | extern sleep 15 | extern ptrace 16 | extern malloc 17 | extern munmap 18 | extern ul_exec 19 | extern getpid 20 | extern anti_attach 21 | extern decode_bin 22 | extern create_btree 23 | extern get_map_len 24 | extern set_sigfpe 25 | extern _etext,_edata, _end 26 | extern puts 27 | 28 | %define WUNTRACED 2 29 | %define SIGKILL 9 30 | %define SIGTERM 15 31 | %define SYS_mmap2 192 32 | %define SYS_clone 120 33 | %define MAX_THREADS 20 ;number of threads 34 | %define STACK_SIZE (4096) ; stack size for each thread 35 | %define PTRACE_ATTACH 0x00000010 36 | %define PTRACE_TRACEME 0x00000000 37 | %define PTRACE_CONT 0x00000007 38 | %define CLONE_VM 0x00000100 39 | %define CLONE_FS 0x00000200 40 | %define CLONE_FILES 0x00000400 41 | %define CLONE_SIGHAND 0x00000800 42 | %define CLONE_PARENT 0x00008000 43 | %define CLONE_THREAD 0x00010000 44 | %define CLONE_IO 0x80000000 45 | %define MAP_GROWSDOWN 0x0100 46 | %define MAP_ANONYMOUS 0x0020 47 | %define MAP_PRIVATE 0x0002 48 | %define MAP_SHARED 0x0001 49 | %define PROT_READ 0x1 50 | %define PROT_WRITE 0x2 51 | %define PROT_EXEC 0x4 52 | %define THREAD_FLAGS \ 53 | CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD 54 | 55 | section .crypter progbits exec 56 | global _start 57 | _start: 58 | lea edi, [imageBase] 59 | lea eax, [_etext] 60 | xor edx, edx 61 | dec edx 62 | shr edx, 52 63 | shl edx, 52 64 | and eax, edx 65 | stosd ; storing image base 66 | lea esi, [eax + 8] 67 | mov ecx, 2 68 | 69 | .mini_init: ; initialising next 2 global variables from elf header 70 | lodsd ; retrieving fields from header 71 | cmp ecx, 1 72 | jz .first 73 | add eax, [imageBase] 74 | .first: 75 | stosd 76 | loop .mini_init 77 | 78 | mov edi, [imageBase] 79 | add edi, 0x20 80 | mov esi, [edi] 81 | mov [rc4_size], esi 82 | add edi, 4 83 | mov esi, [edi] 84 | add esi, [imageBase] 85 | mov [rc4_key], esi 86 | mov eax, after_rc4 87 | mov [start_rc4], eax 88 | xor eax, eax 89 | inc eax 90 | shl eax, 10 91 | mov [dict_size], eax 92 | add eax, [dict_addr] ; calculating address of frequency table 93 | mov [blob_addr], eax 94 | mov eax, [esp] 95 | mov [argc], eax 96 | mov eax, esp 97 | add eax, 4 98 | mov [argv], eax 99 | mov eax, [eax] 100 | mov [appname], eax 101 | mov eax, esp 102 | add eax, 12 103 | mov [envp], eax 104 | call sigfpe_handler 105 | 106 | xor esi, esi 107 | idiv esi 108 | call after_rc4 109 | ret 110 | 111 | section .text progbits exec 112 | 113 | after_rc4: 114 | call check_hardware_breakpoints 115 | call alloc_shareable_chunk ; creating shareble chunk for threads to check checksum 116 | mov [shared], eax 117 | call compute_checksum 118 | mov ebx, [shared] 119 | mov [ebx], eax 120 | push decompression-0x200 121 | call deploy_threads 122 | ret 123 | _exit: 124 | push 0x0 125 | call exit 126 | 127 | killpid: 128 | push SIGTERM 129 | push 0x0 130 | call kill 131 | ret 132 | 133 | deploy_threads: 134 | pop eax 135 | pop eax 136 | mov [pivot], eax 137 | or ebp, MAX_THREADS 138 | .create: 139 | mov ebx, threadfn 140 | call thread_create 141 | dec ebp 142 | test ebp, ebp 143 | jnz .create 144 | mov eax, [pivot] 145 | add eax, 0x200 146 | jmp eax 147 | 148 | threadfn: 149 | call compute_checksum 150 | mov ebx, [shared] 151 | mov ebx, [ebx] 152 | cmp ebx, eax 153 | jnz .notequal 154 | jmp threadfn 155 | .notequal: 156 | push SIGKILL 157 | xor eax, eax 158 | push eax 159 | call kill 160 | ret 161 | 162 | thread_create: 163 | push ebx 164 | call stack_create 165 | lea ecx, [eax + STACK_SIZE - 8] 166 | pop dword [ecx] 167 | mov ebx, THREAD_FLAGS 168 | mov eax, SYS_clone 169 | int 0x80 170 | ret 171 | 172 | stack_create: 173 | mov ebx, 0 174 | mov ecx, STACK_SIZE 175 | mov edx, PROT_WRITE | PROT_READ 176 | mov esi, MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN 177 | mov eax, SYS_mmap2 178 | int 0x80 179 | ret 180 | 181 | alloc_shareable_chunk: 182 | mov ebx, 0 183 | mov ecx, 0x1000 184 | mov edx, PROT_WRITE | PROT_READ 185 | mov esi, MAP_ANONYMOUS | MAP_SHARED 186 | mov eax, SYS_mmap2 187 | int 0x80 188 | ret 189 | 190 | compute_checksum: 191 | xor edx, edx 192 | xor eax, eax 193 | mov ecx, _etext 194 | mov esi, after_rc4 195 | sub ecx, esi 196 | .compute: 197 | lodsb 198 | add edx, eax 199 | loop .compute 200 | mov eax, edx 201 | ret 202 | 203 | decompression: ; decompression routines 204 | mov ebx, [blob_addr] 205 | push ebx 206 | mov ebx, [blob_size] 207 | push ebx 208 | mov ebx, [dict_addr] 209 | push ebx 210 | call decompress ; calling to decompress buff 211 | mov eax, [envp] 212 | push eax 213 | mov eax, [argv] 214 | push eax 215 | mov eax, [argc] 216 | push eax 217 | mov eax, [decoded_size] 218 | push eax 219 | mov eax, [decoded] 220 | push eax 221 | mov eax, [argv] 222 | push eax 223 | call check_hardware_breakpoints 224 | call ul_exec 225 | call _exit 226 | 227 | decompress: 228 | mov [pivot], esp 229 | mov ecx, [esp + 8] 230 | shl ecx, 2 231 | push ecx 232 | call malloc 233 | test eax, eax 234 | jz _exit 235 | mov [decoded], eax 236 | 237 | mov ecx, [esp + 4] ;dict_addr 238 | push ecx 239 | call get_map_len 240 | 241 | push eax 242 | call malloc 243 | test eax, eax 244 | jz _exit 245 | mov [nodes], eax ; allocating memory for node structure 246 | 247 | push eax 248 | mov ecx, [dict_addr] 249 | push ecx 250 | call create_btree 251 | 252 | mov ebx, [decoded] 253 | push ebx 254 | mov ebx, [blob_size] 255 | add ebx, 100 256 | push ebx 257 | mov ebx, [blob_addr] 258 | push ebx 259 | push eax 260 | push eax 261 | call check_hardware_breakpoints 262 | call decode_bin 263 | mov [decoded_size], eax 264 | 265 | mov esp, [pivot] 266 | ret 267 | 268 | section .data progbits write 269 | imageBase: dd 0x0 270 | dict_addr: dd 0x0 271 | blob_size: dd 0x0 272 | dict_size: dd 0x0 273 | blob_addr: dd 0x0 274 | nodes: dd 0x0 275 | decoded: dd 0x0 276 | decoded_size: dd 0x0 277 | argc: dd 0x0 278 | argv: dd 0x0 279 | envp: dd 0x0 280 | appname: dd 0x0 281 | pivot: dd 0x0 282 | ppid: dd 0x0 283 | checksum: dd 0x0 284 | shared: dd 0x0 285 | rc4_key: dd 0x0 286 | rc4_size: dd 0x0 287 | start_rc4 dd 0x0 288 | 289 | -------------------------------------------------------------------------------- /layer2/src/layer2.ld: -------------------------------------------------------------------------------- 1 | /* Script for -z combreloc: combine and sort reloc sections */ 2 | /* Copyright (C) 2014-2015 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("elf32-i386", "elf32-i386", 7 | "elf32-i386") 8 | OUTPUT_ARCH(i386) 9 | ENTRY(_start) 10 | SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/i686-linux-gnu/lib32"); SEARCH_DIR("=/usr/i686-linux-gnu/lib"); 11 | 12 | PHDRS 13 | { 14 | /* interp PT_INTERP ;*/ 15 | text PT_LOAD FILEHDR PHDRS; 16 | /*tls PT_TLS;*/ 17 | /* dump PT_LOAD AT(0x8000000) FLAGS(7); 18 | stub PT_LOAD AT(0x9000000) FLAGS(7);*/ 19 | /*dynamic PT_DYNAMIC ;*/ 20 | } 21 | 22 | SECTIONS 23 | { 24 | 25 | /* Read-only sections, merged into text segment: */ 26 | PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0c000000)); . = SEGMENT_START("text-segment", 0x0c000000) + SIZEOF_HEADERS; 27 | .interp : { *(.interp) } 28 | .note.gnu.build-id : { *(.note.gnu.build-id) } 29 | .hash : { *(.hash) } 30 | .gnu.hash : { *(.gnu.hash) } 31 | .dynsym : { *(.dynsym) } 32 | .dynstr : { *(.dynstr) } 33 | .gnu.version : { *(.gnu.version) } 34 | .gnu.version_d : { *(.gnu.version_d) } 35 | .gnu.version_r : { *(.gnu.version_r) } 36 | .rel.dyn : 37 | { 38 | *(.rel.init) 39 | *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) 40 | *(.rel.fini) 41 | *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) 42 | *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) 43 | *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) 44 | *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) 45 | *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) 46 | *(.rel.ctors) 47 | *(.rel.dtors) 48 | *(.rel.got) 49 | *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) 50 | *(.rel.ifunc) 51 | } 52 | 53 | .rel.plt : 54 | { 55 | *(.rel.plt) 56 | PROVIDE_HIDDEN (__rel_iplt_start = .); 57 | *(.rel.iplt) 58 | PROVIDE_HIDDEN (__rel_iplt_end = .); 59 | } 60 | 61 | .init : 62 | { 63 | KEEP (*(SORT_NONE(.init))) 64 | } 65 | 66 | .plt : { *(.plt) *(.iplt) } 67 | .plt.got : { *(.plt.got) } 68 | .text : 69 | { 70 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 71 | *(.text.exit .text.exit.*) 72 | *(.text.startup .text.startup.*) 73 | *(.text.hot .text.hot.*) 74 | *(.text .stub .text.* .gnu.linkonce.t.*) 75 | /* .gnu.warning sections are handled specially by elf32.em. */ 76 | *(.gnu.warning) 77 | } 78 | 79 | .fini : 80 | { 81 | KEEP (*(SORT_NONE(.fini))) 82 | } 83 | PROVIDE (__etext = .); 84 | PROVIDE (_etext = .); 85 | PROVIDE (etext = .); 86 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 87 | .rodata1 : { *(.rodata1) } 88 | .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } 89 | .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } :text 90 | .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table 91 | .gcc_except_table.*) } 92 | .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } 93 | /* These sections are generated by the Sun/Oracle C++ compiler. */ 94 | .exception_ranges : ONLY_IF_RO { *(.exception_ranges 95 | .exception_ranges*) } 96 | /* Adjust the address for the data segment. We want to adjust up to 97 | the same address within the page on the next page up. */ 98 | /* Exception handling */ 99 | .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } 100 | .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } 101 | .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } 102 | .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } 103 | /* Thread Local Storage sections */ 104 | .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } 105 | .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } 106 | .preinit_array : 107 | { 108 | PROVIDE_HIDDEN (__preinit_array_start = .); 109 | KEEP (*(.preinit_array)) 110 | PROVIDE_HIDDEN (__preinit_array_end = .); 111 | } 112 | .init_array : 113 | { 114 | PROVIDE_HIDDEN (__init_array_start = .); 115 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) 116 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) 117 | PROVIDE_HIDDEN (__init_array_end = .); 118 | } :text 119 | .fini_array : 120 | { 121 | PROVIDE_HIDDEN (__fini_array_start = .); 122 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) 123 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) 124 | PROVIDE_HIDDEN (__fini_array_end = .); 125 | } :text 126 | .ctors : 127 | { 128 | /* gcc uses crtbegin.o to find the start of 129 | the constructors, so we make sure it is 130 | first. Because this is a wildcard, it 131 | doesn't matter if the user does not 132 | actually link against crtbegin.o; the 133 | linker won't look for a file to match a 134 | wildcard. The wildcard also means that it 135 | doesn't matter which directory crtbegin.o 136 | is in. */ 137 | KEEP (*crtbegin.o(.ctors)) 138 | KEEP (*crtbegin?.o(.ctors)) 139 | /* We don't want to include the .ctor section from 140 | the crtend.o file until after the sorted ctors. 141 | The .ctor section from the crtend file contains the 142 | end of ctors marker and it must be last */ 143 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) 144 | KEEP (*(SORT(.ctors.*))) 145 | KEEP (*(.ctors)) 146 | } 147 | .dtors : 148 | { 149 | KEEP (*crtbegin.o(.dtors)) 150 | KEEP (*crtbegin?.o(.dtors)) 151 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) 152 | KEEP (*(SORT(.dtors.*))) 153 | KEEP (*(.dtors)) 154 | } 155 | .jcr : { KEEP (*(.jcr)) } 156 | .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } 157 | .dynamic : { *(.dynamic) } 158 | .got : { *(.got) *(.igot) } 159 | .got.plt : { *(.got.plt) *(.igot.plt) } 160 | .data : 161 | { 162 | *(.data .data.* .gnu.linkonce.d.*) 163 | SORT(CONSTRUCTORS) 164 | } 165 | .data1 : { *(.data1) } 166 | _edata = .; PROVIDE (edata = .); 167 | . = .; 168 | _end = .; PROVIDE (end = .); 169 | /* Stabs debugging sections. */ 170 | .stab 0 : { *(.stab) } 171 | .stabstr 0 : { *(.stabstr) } 172 | .stab.excl 0 : { *(.stab.excl) } 173 | .stab.exclstr 0 : { *(.stab.exclstr) } 174 | .stab.index 0 : { *(.stab.index) } 175 | .stab.indexstr 0 : { *(.stab.indexstr) } 176 | .comment 0 : { *(.comment) } 177 | /* DWARF debug sections. 178 | Symbols in the DWARF debugging sections are relative to the beginning 179 | of the section so we begin them at 0. */ 180 | /* DWARF 1 */ 181 | .debug 0 : { *(.debug) } 182 | .line 0 : { *(.line) } 183 | /* GNU DWARF 1 extensions */ 184 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 185 | .debug_sfnames 0 : { *(.debug_sfnames) } 186 | /* DWARF 1.1 and DWARF 2 */ 187 | .debug_aranges 0 : { *(.debug_aranges) } 188 | .debug_pubnames 0 : { *(.debug_pubnames) } 189 | /* DWARF 2 */ 190 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } 191 | .debug_abbrev 0 : { *(.debug_abbrev) } 192 | .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } 193 | .debug_frame 0 : { *(.debug_frame) } 194 | .debug_str 0 : { *(.debug_str) } 195 | .debug_loc 0 : { *(.debug_loc) } 196 | .debug_macinfo 0 : { *(.debug_macinfo) } 197 | /* SGI/MIPS DWARF 2 extensions */ 198 | .debug_weaknames 0 : { *(.debug_weaknames) } 199 | .debug_funcnames 0 : { *(.debug_funcnames) } 200 | .debug_typenames 0 : { *(.debug_typenames) } 201 | .debug_varnames 0 : { *(.debug_varnames) } 202 | /* DWARF 3 */ 203 | .debug_pubtypes 0 : { *(.debug_pubtypes) } 204 | .debug_ranges 0 : { *(.debug_ranges) } 205 | /* DWARF Extension. */ 206 | .debug_macro 0 : { *(.debug_macro) } 207 | .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } 208 | /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } 209 | /* 210 | .UX1 0x8000000 : AT(0x8000000) { 211 | SQUAD(0); 212 | . += 0x1000000-8; 213 | } :dump 214 | 215 | .UX2 0x9000000 : AT(0x9000000) { 216 | SQUAD(0); 217 | . += 0x1000000-8; 218 | } :stub 219 | */ 220 | . = SIZEOF_HEADERS; 221 | .interp : { *(.interp) } :text :interp 222 | .text : { *(.text) } :text 223 | .rodata : { *(.rodata) } /* defaults to :text */ 224 | .data : { *(.data) } :text 225 | .dynamic : { *(.dynamic) } :text :dynamic 226 | 227 | } 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /layer2/src/layer2_sigaction.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include <unistd.h> 3 | #include <stdio.h> 4 | #include <stdlib.h> 5 | #include <pthread.h> 6 | #include <sys/ptrace.h> 7 | #include <sys/prctl.h> 8 | #include <sys/user.h> 9 | #include <stddef.h> 10 | #include <errno.h> 11 | #include <assert.h> 12 | #include <wait.h> 13 | #include<signal.h> 14 | #include<ucontext.h> 15 | 16 | int safe_ptrace(int request, int pid, unsigned int* addr, void * data){ 17 | int result; 18 | errno = 0; 19 | result = ptrace(request, pid, addr, data); 20 | if(errno){ 21 | kill(0, SIGILL); 22 | } 23 | return result; 24 | } 25 | 26 | static int debug_reg(int pid, int regnum){ 27 | return safe_ptrace( 28 | PTRACE_PEEKUSER, pid, 29 | (unsigned int*)offsetof(struct user, u_debugreg[regnum]), 0 30 | ); 31 | } 32 | 33 | static int set_debug_reg(int pid, int regnum, unsigned int value){ 34 | return safe_ptrace( 35 | PTRACE_POKEUSER, pid, 36 | (unsigned int*)offsetof(struct user, u_debugreg[regnum]), (void*)value 37 | ); 38 | } 39 | 40 | static int bit_replace(int old_val, int lsb, int size, int new_val){ 41 | int mask = (-1 << (size+lsb)) | ((1 << lsb) - 1); 42 | return (old_val & mask) | (new_val << lsb); 43 | } 44 | 45 | static void setup_control_reg(int pid, int regnum, int len, int when){ 46 | int dr7 = debug_reg(pid, 7); 47 | 48 | dr7 = bit_replace(dr7, 18 + 4*regnum, 2, len-1); 49 | dr7 = bit_replace(dr7, 16 + 4*regnum, 2, when); 50 | dr7 |= 3 << (2*regnum); 51 | set_debug_reg(pid, 7, dr7); 52 | } 53 | 54 | 55 | int check_hardware_breakpoints(void) { 56 | pid_t child, parent; 57 | long ptrace_result; 58 | int returned_pid, status; 59 | struct sigaction s; 60 | 61 | parent = getpid(); 62 | prctl (PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); // Allowing several ptrace tracers 63 | 64 | if (!fork()) { 65 | int dr0, dr1, dr2, dr3; // Creating child thread; 66 | safe_ptrace(PTRACE_ATTACH, parent, NULL, NULL); // Child 67 | 68 | returned_pid = waitpid(parent, &status, WUNTRACED); // synchonization between threads 69 | assert(returned_pid == parent); 70 | 71 | dr0 = debug_reg(parent, 0); 72 | dr1 = debug_reg(parent, 1); 73 | dr2 = debug_reg(parent, 2); 74 | dr3 = debug_reg(parent, 3); 75 | 76 | if ( dr0 || dr1 || dr2 || dr3){ 77 | kill(0, SIGBUS); 78 | } 79 | safe_ptrace(PTRACE_CONT, parent, NULL, NULL); // resuming execution of parent 80 | exit(0); 81 | } else { // Parent 82 | wait(NULL); // suspending parent temporarely 83 | } 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /layer2/src/libc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulexec/ElfLocker/1bb5973cd08ca40f308dd92a8a0d4f7bb0bbd897/layer2/src/libc.a -------------------------------------------------------------------------------- /layer2/src/load.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <unistd.h> 3 | #include <string.h> 4 | #include <errno.h> 5 | #include <unistd.h> 6 | #include <fcntl.h> 7 | #include <sys/types.h> 8 | #include <sys/mman.h> 9 | #include <sys/stat.h> 10 | #include <elf.h> 11 | #include <alloca.h> 12 | #include "../include/ul_execP.h" 13 | 14 | 15 | #define is_loaded(p) ((p)->p_type == PT_LOAD ? 1 : 0) 16 | #define is_txt_segt(p) ((is_loaded(p)) && (p)->p_flags == (PF_X|PF_R)) 17 | #define is_data_segt(p) ((is_loaded(p)) && (p)->p_flags == (PF_W|PF_R)) 18 | #define segt_size(p) ((size_t)((p)->p_vaddr + (p)->p_memsz)) 19 | #define load_addr(e) ((char *)(((e)->e_type == ET_DYN) ? (e) : NULL)) 20 | 21 | #define FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) 22 | 23 | static Elf32_Ehdr *load_linker_buf(void *linker_buf); 24 | 25 | /* 26 | * Argument elf_buf points to a read-in or mapped-in ELF format 27 | * executable. load_elf_buf() creates all the various discrete 28 | * pieces of memory, at the correct addresses, with the correct 29 | * parts of elf_buf copied in to them, for the executable to run. 30 | */ 31 | static Elf32_Ehdr * load_elf_buf(void *elf_buf) { 32 | Elf32_Ehdr *r = NULL, *e = (Elf32_Ehdr *)elf_buf; 33 | Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned int)elf_buf + e->e_phoff); 34 | Elf32_Phdr *p; 35 | int i; 36 | unsigned int highest_mapped_addr = 0; 37 | 38 | for (i = 0, p = phdr; i < e->e_phnum; i++, p++) { 39 | char *ptr; 40 | unsigned int elf_prot = 0; 41 | unsigned int map_flags = 0; 42 | void *map_addr; 43 | size_t rounded_len; 44 | unsigned int x; 45 | 46 | 47 | if (p->p_type != PT_LOAD) 48 | continue; 49 | 50 | map_flags = FLAGS|MAP_FIXED; 51 | 52 | map_addr = (void *)ALIGNDOWN(p->p_vaddr, p->p_align); 53 | rounded_len = ROUNDUP(p->p_memsz, p->p_align); 54 | 55 | while ((x = (unsigned int)map_addr + rounded_len) <= p->p_vaddr + p->p_memsz) 56 | rounded_len += p->p_align; /* rounded_len stays a multiple of p->p_align */ 57 | 58 | if (x >= highest_mapped_addr) 59 | { 60 | if (MAP_FAILED == (ptr = mmap(map_addr, rounded_len, PROT_NONE, map_flags, -1, 0))) 61 | return NULL; 62 | 63 | /* Mark newly allocated memory so we can write to it */ 64 | if (mprotect(ptr, rounded_len, PROT_WRITE)) 65 | return NULL; 66 | 67 | highest_mapped_addr = x; 68 | 69 | if (!r) r = (Elf32_Ehdr *)ptr; 70 | } 71 | 72 | /* We need the exact load address, not the rounded down 73 | * version. Otherwis we copy to a garbage location.. */ 74 | memcopy( 75 | (void *)p->p_vaddr, 76 | (char *)elf_buf + p->p_offset, 77 | p->p_filesz 78 | ); 79 | 80 | if (p->p_offset) { 81 | if (mprotect(map_addr, rounded_len, PROT_WRITE | PROT_READ)) 82 | return NULL; 83 | } else { 84 | if (mprotect(map_addr, rounded_len, PROT_READ | PROT_WRITE| PROT_EXEC)) 85 | return NULL; 86 | 87 | } 88 | } 89 | 90 | return (Elf32_Ehdr *)r; 91 | } 92 | 93 | /* It appears that most kernels use 0x1000 byte pages. 94 | * But this global-scope variable also gets set in 95 | * ul_save_elfauxv(), from the ELF auxilliary headers. 96 | */ 97 | size_t pgsz = PAGESIZE; 98 | 99 | /* 100 | * Loading ld.so, "ld-linux.so.2" or what have you, takes a slightly 101 | * different approach than load_elf_buf() uses. If you mmap() a few 102 | * pages for the .text segment of ld-linux.so.2, it's likely that 103 | * the kernel will map those pages in too close to something else. 104 | * The next mmap(), for the .bss segment of ld-linux.so.2, will overlap 105 | * that "something else". At least some Linux 3.x kernels put MAP_ANONYMOUS 106 | * pages as high as possible, causing the probable overlap. 107 | */ 108 | static Elf32_Ehdr * load_linker_buf(void *linker_buf) { 109 | Elf32_Ehdr *e = (Elf32_Ehdr *)linker_buf; 110 | Elf32_Phdr *p, *phdr = (Elf32_Phdr *)((unsigned int)linker_buf + e->e_phoff); 111 | int i; 112 | void *base_addr = NULL; 113 | unsigned int max_addr = 0; 114 | 115 | /* Find how many bytes to allocate for ld-linux.so.2 in a single 116 | * chunk. First, find the "high address" for it, based on 117 | * p->p_vaddr + p->p_memsz for each loadable Phdr. */ 118 | for (i = 0, p = phdr; i < e->e_phnum; i++, p++) 119 | { 120 | unsigned int addr; 121 | if (p->p_type != PT_LOAD) 122 | continue; 123 | addr = p->p_vaddr + p->p_memsz; 124 | if (addr > max_addr) max_addr = addr; 125 | } 126 | 127 | /* Round up the high address to a page-size multiple. */ 128 | max_addr = ROUNDUP(max_addr, pgsz); 129 | 130 | /* ld.so contains position independent code, so the "max address" 131 | * actually constitutes size in bytes. */ 132 | if (MAP_FAILED == (base_addr = mmap(0, max_addr, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0))) 133 | return NULL; 134 | 135 | /* Go over the Phdrs again, marking pages writeable, copying appropriate 136 | * pieces of linnker_buf into the right (relative) address, and then putting 137 | * the ELF protections on the page(s) as specified in the Phdr. */ 138 | for (i = 0, p = phdr; i < e->e_phnum; i++, p++) 139 | { 140 | unsigned int elf_prot = 0; 141 | void *prot_addr; 142 | size_t rounded_len; 143 | 144 | if (p->p_type != PT_LOAD) 145 | continue; 146 | 147 | prot_addr = (void *)ALIGNDOWN(base_addr + p->p_vaddr, pgsz); 148 | rounded_len = ROUNDUP((base_addr + p->p_vaddr + p->p_filesz - prot_addr), pgsz); 149 | /* Does a situation ever exist where p->p_vaddr + p->p_filesz > prot_addr + rounded_len? 150 | * It certainly happens in load_elf_buf(), but because we just do one 151 | * allocation for all of ld-linux.so.2, I don't think it can happen here. 152 | */ 153 | 154 | /* Mark mmapped memory so we can write to it */ 155 | if (mprotect(prot_addr, rounded_len, PROT_WRITE)) 156 | return NULL; 157 | 158 | /* Copy from linker_buf to the right (relative) 159 | * address in the allocation. */ 160 | memcopy( 161 | (void *)(base_addr + p->p_vaddr), 162 | (char *)linker_buf + p->p_offset, 163 | p->p_filesz 164 | ); 165 | 166 | /* Protect it as specified. */ 167 | if (p->p_flags & PF_R) 168 | elf_prot |= PROT_READ; 169 | if (p->p_flags & PF_W) 170 | elf_prot |= PROT_WRITE; 171 | if (p->p_flags & PF_X) 172 | elf_prot |= PROT_EXEC; 173 | 174 | if (mprotect(prot_addr, rounded_len, elf_prot)) 175 | return NULL; 176 | } 177 | 178 | return (Elf32_Ehdr *)base_addr; 179 | } 180 | 181 | /* Based on a filename, load any ELF run-time linker. */ 182 | static Elf32_Ehdr * load_linker(const char *fname) { 183 | Elf32_Ehdr *e; 184 | struct stat st; 185 | char *buf; 186 | int fd; 187 | 188 | if (0 > (fd = open(fname, O_RDONLY))) 189 | return NULL; 190 | 191 | if (stat(fname, &st)) 192 | { 193 | close(fd); 194 | return NULL; 195 | } 196 | buf = mmap(NULL, 0x30000, PROT_READ, MAP_PRIVATE, fd, 0); 197 | if (buf == MAP_FAILED) 198 | { 199 | close(fd); 200 | return NULL; 201 | } 202 | 203 | e = load_linker_buf(buf); 204 | 205 | munmap(buf, st.st_size); 206 | close(fd); 207 | 208 | return e; 209 | } 210 | 211 | /* 212 | * Assuming that ELF_buf points to an in-memory image of 213 | * an ELF file, create blocks of memory at correct addresses 214 | * specified by Phdrs of the ELF file. Copy appropriate sections 215 | * of ELF_buf into those blocks of memory, and give them protections 216 | * as specified in the Phdrs. 217 | */ 218 | int ul_load_elf(void *ELF_buf, Elf32_Ehdr **elf, Elf32_Ehdr **interp) { 219 | Elf32_Ehdr *e, *ei = NULL; 220 | Elf32_Phdr *p, *ptab; 221 | int i; 222 | 223 | e = (Elf32_Ehdr *)ELF_buf; 224 | ptab = (Elf32_Phdr*)&ELF_buf[e->e_phoff]; 225 | 226 | /* check for a dynamic linker, and if there is one, load it */ 227 | for (i = 0, p = ptab; i < e->e_phnum; i++, p++) 228 | { 229 | if (p->p_type == PT_INTERP) 230 | { 231 | if (NULL == (ei = load_linker((char *)((unsigned int)ELF_buf+p->p_offset)))) 232 | return -1; 233 | break; 234 | } 235 | } 236 | 237 | if ((e = load_elf_buf(ELF_buf)) == NULL) { 238 | return -1; 239 | 240 | } 241 | 242 | if (elf) 243 | *elf = e; 244 | if (interp) 245 | *interp = ei; 246 | 247 | return 0; 248 | } 249 | 250 | /* 251 | * Our own private memcpy() - this exists to help debug. 252 | * Getting an mprotect() address off some bytes can cause 253 | * a SIGSEGV. This one at least lets us see where the 254 | * actually faulting address lies. 255 | */ 256 | void * memcopy(void *dest, const void *src, size_t n) { 257 | unsigned int i; 258 | unsigned char *d = (unsigned char *)dest; 259 | unsigned char *s = (unsigned char *)src; 260 | 261 | /* 262 | printf("Copying %d bytes from %p to %p, last address %p\n", 263 | n, s, d, (void *)((unsigned int)d + n)); 264 | */ 265 | 266 | for (i = 0; i < n; ++i) 267 | d[i] = s[i]; 268 | 269 | return dest; 270 | } 271 | -------------------------------------------------------------------------------- /layer2/src/rc4.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <string.h> 3 | #include <stdlib.h> 4 | #include <stdint.h> 5 | #include <time.h> 6 | #include <sys/ptrace.h> 7 | #include <signal.h> 8 | #define __USE_GNU 9 | #include <unistd.h> 10 | #include <fcntl.h> 11 | #include <ucontext.h> 12 | #define N 256 // 2^8 13 | 14 | extern uint8_t *rc4_key; 15 | extern uint32_t rc4_size; 16 | extern uint8_t *start_rc4; 17 | 18 | void __attribute__((section(".crypter"))) swap(unsigned char *a, unsigned char *b) { 19 | int tmp = *a; 20 | *a = *b; 21 | *b = tmp; 22 | } 23 | 24 | int __attribute__((section(".crypter"))) KSA(char *key, int len, unsigned char *S) { 25 | int j = 0; 26 | 27 | for(int i = 0; i < N; i++) 28 | S[i] = i; 29 | 30 | for(int i = 0; i < N; i++) { 31 | j = (j + S[i] + key[i % len]) % N; 32 | 33 | swap(&S[i], &S[j]); 34 | } 35 | return 0; 36 | } 37 | 38 | int __attribute__((section(".crypter"))) PRGA(unsigned char *S, char *data, int len) { 39 | 40 | int i = 0; 41 | int j = 0; 42 | 43 | for(size_t n = 0; n < len; n++) { 44 | i = (i + 1) % N; 45 | j = (j + S[i]) % N; 46 | 47 | swap(&S[i], &S[j]); 48 | int rnd = S[(S[i] + S[j]) % N]; 49 | 50 | data[n] ^= rnd; 51 | } 52 | return 0; 53 | } 54 | 55 | int __attribute__((section(".crypter"))) rc4_crypt_blob(uint8_t *data, int data_size, char *key, int key_size) { 56 | 57 | unsigned char S[N]; 58 | KSA(key, key_size, S); 59 | PRGA(S, data, data_size); 60 | 61 | return 0; 62 | } 63 | 64 | void __attribute__((section(".crypter"))) sigHandler(int nsig, siginfo_t *siginfo, void *context) { 65 | asm volatile( 66 | "push $0x10; \n" 67 | "push %%eax; \n" 68 | "push %%ebx; \n" 69 | "push %%ecx; \n" 70 | "call %%edx; \n" 71 | "mov %2, %%eax; \n" 72 | "push %%eax; \n" 73 | : : 74 | "a"(rc4_key), 75 | "b"(rc4_size), 76 | "c"(start_rc4), 77 | "d" (rc4_crypt_blob)); 78 | } 79 | 80 | 81 | int __attribute__((section(".crypter"))) sigfpe_handler(unsigned char *S, char *data, int len) { 82 | struct sigaction s; 83 | s.sa_sigaction = sigHandler; 84 | s.sa_flags = SA_SIGINFO; 85 | 86 | long ret; 87 | asm volatile("int $0x80;" : "=a" (ret) 88 | : "a" (67) 89 | , "b" (8) 90 | , "c" (&s) 91 | , "d" (0) 92 | : "memory"); 93 | if (ret != 0) 94 | goto exit; 95 | 96 | return 0; 97 | 98 | exit: 99 | asm volatile ("int $0x80;" : : "a" (1), "b" (0)); 100 | 101 | } 102 | -------------------------------------------------------------------------------- /layer2/src/rc4_embed.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <string.h> 3 | #include <stdlib.h> 4 | #include <stdint.h> 5 | #include <time.h> 6 | #include <sys/ptrace.h> 7 | #include <signal.h> 8 | #define __USE_GNU 9 | #include <ucontext.h> 10 | #define N 256 // 2^8 11 | 12 | void __attribute__((section(".crypter"))) swap(unsigned char *a, unsigned char *b) { 13 | int tmp = *a; 14 | *a = *b; 15 | *b = tmp; 16 | } 17 | 18 | int __attribute__((section(".crypter"))) KSA(char *key, int len, unsigned char *S) { 19 | int j = 0; 20 | 21 | for(int i = 0; i < N; i++) 22 | S[i] = i; 23 | 24 | for(int i = 0; i < N; i++) { 25 | j = (j + S[i] + key[i % len]) % N; 26 | 27 | swap(&S[i], &S[j]); 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | int __attribute__((section(".crypter"))) PRGA(unsigned char *S, char *data, int len) { 34 | 35 | int i = 0; 36 | int j = 0; 37 | 38 | for(size_t n = 0; n < len; n++) { 39 | i = (i + 1) % N; 40 | j = (j + S[i]) % N; 41 | 42 | swap(&S[i], &S[j]); 43 | int rnd = S[(S[i] + S[j]) % N]; 44 | 45 | data[n] ^= rnd; 46 | } 47 | return 0; 48 | } 49 | 50 | int __attribute__((section(".crypter"))) rc4_crypt_blob(uint8_t *data, int data_size, char *key, int key_size) { 51 | 52 | unsigned char S[N]; 53 | KSA(key, key_size, S); 54 | PRGA(S, data, data_size); 55 | 56 | return 0; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /layer2/src/save.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <stdlib.h> 3 | #include <string.h> 4 | #include <unistd.h> 5 | #include <sys/mman.h> 6 | #include <elf.h> 7 | #include "../include/ul_execP.h" 8 | 9 | extern unsigned int pgsz; /* set in ul_save_elfauxv() */ 10 | 11 | struct ul_args { 12 | size_t size; 13 | int cnt; 14 | char *block; 15 | }; 16 | 17 | ul_args_t * ul_save_args(int argc, char **argv) { 18 | ul_args_t *args; 19 | size_t len; 20 | int i; 21 | char *str; 22 | 23 | 24 | if (argc > 0) 25 | for (i = 0, len = 0; i < argc; i++) 26 | len += strlen(argv[i]) + 1; 27 | else { 28 | /* Count them ourselves - env doesn't have envc. */ 29 | argc = 0; 30 | char **p = argv; 31 | while (*p) 32 | { 33 | len += strlen(*p) + 1; 34 | ++p; /* move past ASCII Nul */ 35 | ++argc; 36 | } 37 | } 38 | 39 | args = ALLOCATE(sizeof(*args)); 40 | 41 | args->size = len; 42 | args->cnt = argc; 43 | args->block = ALLOCATE(args->size); 44 | 45 | /* Do it this way because the values of argv[] or env[] may not actually 46 | * exist as contiguous strings. We will make them contiguous. */ 47 | for (i = 0, str = args->block; i < argc; i++, str += strlen(str) + 1) 48 | strcat(str, argv[i]); 49 | 50 | return args; 51 | } 52 | 53 | void * ul_setup_stack( ul_args_t *args, ul_args_t *envp, ul_args_t *auxvp, Elf32_Ehdr *elf, Elf32_Ehdr *interp){ 54 | Elf32_auxv_t *aux, *excfn = NULL; 55 | char **av, **ev; 56 | char *addr, *str, *esp; 57 | unsigned int *ptr; 58 | int argsize, i, j; 59 | 60 | /* Count bytes needed for new stack */ 61 | argsize = 4 + strlen(args->block) + 1; /* NULL at top of stack, executable file name */ 62 | argsize += envp->size; /* environment strings */ 63 | argsize += args->size; /* argument strings size */ 64 | argsize += 4; /* Do we really need a NULL word here? */ 65 | argsize += auxvp->cnt * sizeof(Elf32_auxv_t); /* Elf aux vector table */ 66 | argsize += 4; /* NULL that ends envp[] */ 67 | argsize += envp->cnt * sizeof(char *); /* table of pointers to env strings */ 68 | argsize += 4; /* NULL that ends argv[] */ 69 | argsize += args->cnt * sizeof(char *); /* table of pointers to argv strings */ 70 | argsize += 4; /* argc */ 71 | 72 | 73 | /* Allocate and align a new stack. */ 74 | esp = (char *)ALIGN((unsigned int)alloca(ROUNDUP(argsize, pgsz)), 16); 75 | 76 | /* NOTE: The new stack for the userland-execed process lives 77 | * *below* the bottom of the stack RIGHT NOW. After returning from 78 | * ul_setup_stack(), don't call anything that uses the call stack: that 79 | * will roach this newly-constructed stack. In fact, the code below 80 | * does its own strcpy() and memcpy() equivalents, to the detriment of 81 | * code quality. 82 | */ 83 | 84 | ptr = (unsigned int *)esp; 85 | 86 | *ptr++ = args->cnt; 87 | av = (char **)ptr; 88 | ptr += args->cnt; /* skip over argv[] */ 89 | *ptr++ = 0; 90 | 91 | ev = (char **)ptr; 92 | ptr += envp->cnt; /* skip over envp[] */ 93 | *ptr++ = 0; 94 | 95 | aux = (Elf32_auxv_t *)ptr; 96 | 97 | ptr = (unsigned int *)ROUNDUP((unsigned long)ptr + auxvp->size, sizeof(unsigned int)); 98 | 99 | /* Copy ELF auxilliary vector table onto fake stack. */ 100 | addr = (char *)aux; 101 | for (j = 0; j < auxvp->size; ++j) 102 | addr[j] = auxvp->block[j]; 103 | 104 | /* Fix up a few entries: kernel will have set up the AUXV 105 | * for the user-land exec program, mapped in at a low address. 106 | * need to fix up a few AUXV entries for the "real" program. */ 107 | for (i = 0; i < auxvp->cnt; ++i) 108 | { 109 | switch (aux[i].a_type) 110 | { 111 | case AT_PHDR: aux[i].a_un.a_val = (unsigned int)((char *)elf + elf->e_phoff); break; 112 | case AT_PHNUM: aux[i].a_un.a_val = elf->e_phnum; break; 113 | /* Some kernels give AT_BASE a zero value. */ 114 | case AT_BASE: aux[i].a_un.a_val = (unsigned int)interp; break; 115 | case AT_ENTRY: aux[i].a_un.a_val = (unsigned int)elf->e_entry; break; 116 | /* Not all glibc specify this, apparently. */ 117 | #ifdef AT_EXECFN 118 | case AT_EXECFN: excfn = &(aux[i]); break; 119 | #endif 120 | } 121 | } 122 | 123 | *ptr++ = 0; 124 | 125 | /* Copy argv strings onto stack */ 126 | addr = (char *)ptr; 127 | str = args->block; 128 | 129 | for (i = 0; i < args->cnt; ++i) 130 | { 131 | av[i] = addr; 132 | for (j = 0; *str; ++j) 133 | *addr++ = *str++; 134 | *addr++ = *str++; /* ASCII Nul */ 135 | } 136 | 137 | ptr = (unsigned int *)ROUNDUP((unsigned int)addr, sizeof(unsigned int)); 138 | *ptr = 0; 139 | 140 | /* Copy envp strings onto stack */ 141 | addr = (char *)ptr; 142 | str = envp->block; 143 | 144 | for (i = 0; i < envp->cnt; ++i) 145 | { 146 | ev[i] = addr; 147 | for (j = 0; *str; ++j) 148 | *addr++ = *str++; 149 | *addr++ = *str++; /* ASCII Nul */ 150 | } 151 | 152 | ptr = (unsigned int *)ROUNDUP((unsigned int)addr, sizeof(unsigned int)); 153 | *ptr = 0; 154 | 155 | /* Executable name at top of stack. 156 | * Not all kernels put the name at the top of the stack. 157 | * RHEL old 2.6.18 kernels don't. 158 | */ 159 | if (excfn) 160 | { 161 | addr = (char *)ptr; 162 | str = args->block; 163 | excfn->a_un.a_val = (unsigned int)addr; 164 | for (j = 0; *str; ++j) 165 | *addr++ = *str++; 166 | *addr++ = *str++; /* ASCII Nul */ 167 | 168 | ptr = (unsigned int *)ROUNDUP((unsigned int)addr, sizeof(unsigned int)); 169 | } 170 | 171 | munmap(args->block, args->size); 172 | munmap(args, sizeof(*args)); 173 | munmap(auxvp->block, auxvp->size); 174 | munmap(auxvp, sizeof(*auxvp)); 175 | munmap(envp->block, envp->size); 176 | munmap(envp, sizeof(*envp)); 177 | 178 | *ptr = 0; 179 | 180 | return ((void *)esp); 181 | } 182 | 183 | /* Get a copy of ELF auxilliary vector table. */ 184 | ul_args_t * ul_save_elfauxv(char **envp) { 185 | int cnt; 186 | ul_args_t *r = NULL; 187 | Elf32_auxv_t *q; 188 | unsigned int *p; 189 | 190 | /* Grope up the stack for Elf auxilliary vectors. 191 | * Find NULL word (32-bit) after env string pointers. 192 | */ 193 | p = (unsigned int *)envp; 194 | while (*p != 0) 195 | ++p; 196 | 197 | ++p; /* skip the null word */ 198 | 199 | for (cnt = 0, q = (Elf32_auxv_t *)p; q->a_type != AT_NULL; ++q) 200 | { 201 | /* Why get pagesize from the ELF aux vector? Because dietlibc 202 | * doesn't have a totally static version of getpagesize(), which 203 | * means glibc gets used via a weak symbol in dietlibc. */ 204 | if (AT_PAGESZ == q->a_type) 205 | pgsz = q->a_un.a_val; 206 | ++cnt; 207 | } 208 | 209 | ++cnt; /* The AT_NULL final entry */ 210 | 211 | r = ALLOCATE(sizeof(*r)); 212 | r->size = sizeof(*q) * cnt; 213 | r->cnt = cnt; 214 | r->block = ALLOCATE(r->size); 215 | memcopy((void *)r->block, (void *)p, r->size); 216 | 217 | return r; 218 | } 219 | -------------------------------------------------------------------------------- /layer2/src/ul_exec.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <unistd.h> 3 | #include <stdlib.h> 4 | #include <alloca.h> 5 | #include <elf.h> 6 | #include <signal.h> 7 | #include <errno.h> 8 | #include <string.h> 9 | #include <sys/types.h> 10 | #include <sys/stat.h> 11 | #include <fcntl.h> 12 | #include <sys/mman.h> 13 | #include "../include/ul_execP.h" 14 | 15 | #define SET_STACK(esp) asm("\tmovl %0, %%esp\n" :: "r"(esp)) 16 | #define JMP_ADDR(addr) asm("\tjmp *%0\n" :: "r" (addr)) 17 | 18 | static void ul_exec_common(void *ELF_buf, size_t elf_buf_size, ul_args_t *argv, ul_args_t *envp, ul_args_t *auxvp); 19 | 20 | void ul_exec(char *progname, void *elf_buf, size_t elf_buf_sz, int argc, char **argv, char **env) { 21 | ul_args_t *argvp, *envp, *auxvp; 22 | if ((argvp = ul_save_args(argc, argv)) == NULL) 23 | return; 24 | 25 | if ((envp = ul_save_args(0, env)) == NULL) 26 | return; 27 | 28 | if ((auxvp = ul_save_elfauxv(env)) == NULL) 29 | return; 30 | 31 | ul_exec_common(elf_buf, elf_buf_sz, argvp, envp, auxvp); 32 | } 33 | 34 | static void (*entry)() = (void(*)())-1; 35 | 36 | static void ul_exec_common( void *elf_buf, size_t elf_buf_sz, ul_args_t *argv, ul_args_t *envp, ul_args_t *auxvp) { 37 | Elf32_Ehdr *elf, *interp; 38 | 39 | void *esp; 40 | /* load the main binary, and if required the dynamic linker */ 41 | if (ul_load_elf(elf_buf, &elf, &interp)) 42 | return; 43 | 44 | entry = interp ? (void(*)())(((char *)interp) + interp->e_entry) : 45 | (void(*)())elf->e_entry; 46 | 47 | esp = ul_setup_stack(argv, envp, auxvp, elf, interp); 48 | 49 | 50 | if (NULL == esp) 51 | return; 52 | /* 53 | mprotect(elf, sizeof(Elf32_Ehdr), PROT_WRITE); 54 | mprotect(interp, sizeof(Elf32_Ehdr), PROT_WRITE); 55 | memset(elf, '\0', sizeof(Elf32_Ehdr)); 56 | memset(interp, '\0', 4); 57 | mprotect(elf, sizeof(Elf32_Ehdr), PROT_EXEC); 58 | mprotect(interp, sizeof(Elf32_Ehdr), PROT_EXEC); 59 | printf("%p\n", elf); 60 | printf("%p\n", interp); 61 | */ 62 | /* No longer need the memory area pointed to by elf_buf */ 63 | //munmap(elf_buf, elf_buf_sz); 64 | 65 | /* initialize the stack. */ 66 | /* Take care adding code here: the fake stack is *below* 67 | * (at a smaller address) the current stack frame. If you 68 | * call anything that uses the stack, you stand a good chance 69 | * of overwriting the fake stack that ul_setup_stack() took 70 | * such care to construct. */ 71 | /* set the %esp */ 72 | 73 | // asm volatile("int3"); 74 | 75 | SET_STACK(esp); 76 | 77 | /* transfer control to the new image */ 78 | JMP_ADDR(entry); 79 | 80 | /* if we get here, there are massive fucking problems, for a start 81 | * our stack is fucked up, and we can't return(). Just crash out. */ 82 | } 83 | -------------------------------------------------------------------------------- /reloc/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc reloc.c -lcapstone -o reloc 3 | -------------------------------------------------------------------------------- /reloc/reloc.c: -------------------------------------------------------------------------------- 1 | #include <stdio.h> 2 | #include <stdlib.h> 3 | #include <string.h> 4 | #include <unistd.h> 5 | #include <stdint.h> 6 | #include <limits.h> 7 | #include <errno.h> 8 | #include <sys/mman.h> 9 | #include <sys/stat.h> 10 | #include <fcntl.h> 11 | #include <stdbool.h> 12 | #include <elf.h> 13 | 14 | #include <capstone/capstone.h> 15 | 16 | #define DEBUG 1 17 | #define PDBG(fmt, ...) \ 18 | do { \ 19 | if (DEBUG) \ 20 | fprintf(stderr, "%s:%d:%s()\t:" fmt, __FILE__, \ 21 | __LINE__, __func__, __VA_ARGS__); \ 22 | } while (0); 23 | 24 | void export_file(uint8_t *elf, int size, char* name) { 25 | int fd; 26 | 27 | fd = open(name , O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG); 28 | write(fd, elf, size); 29 | close(fd); 30 | 31 | return; 32 | } 33 | 34 | uint8_t* alloc_file(int *fd, struct stat *st, uint8_t *filename) { 35 | uint8_t *elf; 36 | 37 | if((*fd = open(filename, O_RDWR)) < 0) { 38 | perror("open"); 39 | exit(-1); 40 | } 41 | if(fstat(*fd, st) < 0) { 42 | perror("fstat"); 43 | exit(-1); 44 | } 45 | if((elf = mmap(NULL, st->st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) { 46 | perror("mmap"); 47 | exit(-1); 48 | } 49 | 50 | return elf; 51 | } 52 | 53 | typedef struct { 54 | Elf32_Ehdr *ehdr; 55 | Elf32_Shdr *shdr; 56 | Elf32_Phdr *phdr; 57 | Elf32_Phdr *code; 58 | Elf32_Phdr *data; 59 | Elf32_Phdr *dynamic; 60 | uint8_t *elf; 61 | uint8_t *filename; 62 | uint32_t oimage_base; 63 | uint32_t timage_base; 64 | uint32_t palign; 65 | uint32_t delta; 66 | uint32_t text_offset; 67 | int fd; 68 | struct stat st; 69 | csh handle; 70 | cs_insn *insn; 71 | } Elf32_Obj; 72 | 73 | static int get_operand_offset(uint32_t operand_value, uint8_t *instr_bytes, size_t instr_size) { 74 | int count = 0, nbytes = 0; 75 | 76 | for( int i = 0; i < instr_size; i++) { 77 | if(operand_value == *(uint32_t*)&instr_bytes[i]) { 78 | return i; 79 | } 80 | } 81 | return 0; 82 | } 83 | 84 | static void patch_code_absolute_operands(Elf32_Obj *obj, cs_mode mode, cs_insn *ins) { 85 | int count, i, instruction_offset; 86 | uint32_t section_offset, operand_offset; 87 | cs_x86 *x86; 88 | csh ud = obj->handle; 89 | 90 | // detail can be NULL on "data" instruction if SKIPDATA option is turned ON 91 | if (ins->detail == NULL) 92 | return; 93 | 94 | x86 = &(ins->detail->x86); 95 | instruction_offset = ins->address - obj->timage_base; 96 | 97 | for (i = 0; i < x86->op_count; i++) { 98 | cs_x86_op *op = &(x86->operands[i]); 99 | switch((int)op->type) { 100 | case X86_OP_IMM: 101 | if ((op->imm & 0xfff00000) == (obj->oimage_base & 0xfff00000)) { 102 | //printf("0x%"PRIx64":\t%s\t\t%s\nsize: %d\n", ins->address, ins->mnemonic, ins->op_str, ins->size); 103 | //printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm); 104 | operand_offset = get_operand_offset(op->imm, ins->bytes, ins->size); 105 | *(uint32_t*)(obj->elf + instruction_offset + operand_offset) = op->imm + obj->delta; 106 | //printf("%lx\n", *(uint32_t*)(obj->elf + opcode_offset -1)); 107 | //printf("\t\toperand patched: 0x%lx\n", *(uint32_t*)(obj->elf + instruction_offset + operand_offset)); 108 | } 109 | break; 110 | case X86_OP_MEM: 111 | if (op->mem.disp) 112 | if ((op->mem.disp & 0xfff00000) == (obj->oimage_base & 0xfff00000)){ 113 | //printf("0x%"PRIx64":\t%s\t\t%s\nsize: %d\n", ins->address, ins->mnemonic, ins->op_str, ins->size); 114 | //printf("\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp); 115 | operand_offset = get_operand_offset(op->mem.disp, ins->bytes, ins->size); 116 | *(uint32_t*)(obj->elf + instruction_offset + operand_offset) = op->mem.disp + obj->delta; 117 | //printf("\t\toperand patched: 0x%lx\n", *(uint32_t*)(obj->elf + instruction_offset + operand_offset)); 118 | } 119 | break; 120 | } 121 | 122 | } 123 | } 124 | 125 | 126 | int reloc_code_section(Elf32_Obj *obj, Elf32_Shdr *shdr) { 127 | int count, i, j; 128 | cs_x86 *x86; 129 | 130 | count = cs_disasm(obj->handle, obj->elf + shdr->sh_offset, shdr->sh_size, obj->timage_base + shdr->sh_offset, 0, &obj->insn); 131 | if (count > 0) { 132 | for (j = 0; j < count; j++) { 133 | patch_code_absolute_operands(obj, CS_MODE_32, &obj->insn[j]); 134 | } 135 | cs_free(obj->insn, count); 136 | } else { 137 | printf("ERROR: Failed to disassemble given code!\n"); 138 | return -1; 139 | } 140 | return 0; 141 | } 142 | 143 | static void reloc_data_section(Elf32_Obj *obj, Elf32_Shdr *shdr) { 144 | uint8_t *current_val; 145 | int increment = 0; 146 | 147 | for (int i = 0; i < shdr->sh_size; i +=2 ) { 148 | current_val = obj->elf + shdr->sh_offset + i; 149 | if ((*(uint32_t*)current_val & 0xfff00000) == (obj->oimage_base & 0xfff00000)){ 150 | //printf("[+] Pointer found: %llx\n", *(uint32_t*)current_val); 151 | *(uint32_t*)current_val += obj->delta; 152 | //printf("[+] Pointer relocated: %llx\n", *(uint32_t*)current_val); 153 | } 154 | } 155 | 156 | } 157 | 158 | int reloc_code_segment(Elf32_Obj *obj) { 159 | uint8_t *shstrtab; 160 | int i; 161 | printf("[*] Relocating CODE segment\n"); 162 | 163 | shstrtab = (uint8_t*)(&obj->elf[obj->shdr[obj->ehdr->e_shstrndx].sh_offset]); 164 | for (i = 0; i < obj->ehdr->e_shnum; i++) { 165 | if (obj->shdr[i].sh_flags & SHF_EXECINSTR) { 166 | printf ("\t[+] Relocating section %s\n", &shstrtab[obj->shdr[i].sh_name]); 167 | reloc_code_section(obj, &obj->shdr[i]); 168 | } 169 | } 170 | 171 | return 0; 172 | } 173 | 174 | static void reloc_data_segment(Elf32_Obj *obj) { 175 | Elf32_Phdr *phdr = obj->data; 176 | uint8_t *current_val; 177 | uint8_t *shstrtab; 178 | int i; 179 | 180 | printf("\n[*] Relocating Data segment\n"); 181 | 182 | shstrtab = (uint8_t*)(&obj->elf[obj->shdr[obj->ehdr->e_shstrndx].sh_offset]); 183 | for (i = 0; i < obj->ehdr->e_shnum; i++) { 184 | if (obj->shdr[i].sh_flags & SHF_EXECINSTR) { 185 | continue; 186 | } else { 187 | printf ("\t[+] Relocating section %s\n", &shstrtab[obj->shdr[i].sh_name]); 188 | reloc_data_section(obj, &obj->shdr[i]); 189 | } 190 | } 191 | } 192 | 193 | 194 | 195 | int relocate(uint8_t *filename, int32_t timage_base, uint8_t *output_file) { 196 | Elf32_Obj *obj = (Elf32_Obj*)calloc (1, sizeof(Elf32_Obj)); 197 | Elf32_Phdr *phdr; 198 | Elf32_Shdr *shdr; 199 | uint8_t *shstrtab; 200 | int i, j; 201 | 202 | PDBG ("[*] Mapping %s\n", filename); 203 | 204 | obj->filename = filename; 205 | obj->elf = alloc_file(&obj->fd, &obj->st, obj->filename); 206 | obj->ehdr = (Elf32_Ehdr*)obj->elf; 207 | obj->shdr = (Elf32_Shdr*)(obj->elf + obj->ehdr->e_shoff); 208 | obj->phdr = (Elf32_Phdr*)(obj->elf + obj->ehdr->e_phoff); 209 | obj->timage_base = timage_base; 210 | 211 | for (i = 0; i < obj->ehdr->e_phnum; i++) { 212 | phdr = (Elf32_Phdr*)&obj->phdr[i]; 213 | switch(phdr->p_type) { 214 | case PT_LOAD: 215 | if (!phdr->p_offset) { 216 | obj->oimage_base = phdr->p_vaddr; 217 | obj->code = phdr; 218 | obj->palign = phdr->p_align; 219 | } else { 220 | obj->data = phdr; 221 | } 222 | break; 223 | } 224 | } 225 | 226 | PDBG ("[+] Original ImageBase mapped at 0x%x\n", obj->oimage_base); 227 | obj->delta = (obj->oimage_base > timage_base) ? (obj->oimage_base - timage_base) * -1 228 | : timage_base - obj->oimage_base; 229 | PDBG ("[*] Relocation delta: %x -- %x\n", obj->delta, obj->oimage_base + obj->delta); 230 | 231 | if (cs_open(CS_ARCH_X86, CS_MODE_32, &obj->handle) != CS_ERR_OK) { 232 | return -1; 233 | } 234 | cs_option(obj->handle, CS_OPT_DETAIL, CS_OPT_ON); 235 | 236 | reloc_code_segment(obj); 237 | reloc_data_segment(obj); 238 | 239 | for (i = 0; i < obj->ehdr->e_phnum; i++) { 240 | phdr = (Elf32_Phdr*)&obj->phdr[i]; 241 | switch(phdr->p_type) { 242 | case PT_LOAD: 243 | if (!phdr->p_offset) { 244 | *(uint32_t*)&phdr->p_vaddr = obj->timage_base; 245 | *(uint32_t*)&phdr->p_paddr = obj->timage_base; 246 | } else { 247 | *(uint32_t*)&phdr->p_vaddr += obj->delta; 248 | *(uint32_t*)&phdr->p_paddr += obj->delta; 249 | } 250 | break; 251 | case PT_GNU_STACK: 252 | break; 253 | default: 254 | *(uint32_t*)&phdr->p_vaddr += obj->delta; 255 | *(uint32_t*)&phdr->p_paddr += obj->delta; 256 | break; 257 | } 258 | } 259 | 260 | for (i = 0; i < obj->ehdr->e_shnum; i++) { 261 | shdr = (Elf32_Phdr*)&obj->shdr[i]; 262 | if (shdr->sh_addr) { 263 | *(uint32_t*)&shdr->sh_addr += obj->delta; 264 | } 265 | } 266 | 267 | *(uint32_t*)&obj->ehdr->e_entry += obj->delta; 268 | export_file(obj->elf, obj->st.st_size, output_file); 269 | 270 | cs_close(&obj->handle); 271 | free (obj); 272 | 273 | return 0; 274 | } 275 | 276 | int main(int argc, char **argv) { 277 | uint8_t *elf; 278 | uint8_t *filename, *output_file; 279 | int32_t target_image_base; 280 | if (argc != 4) { 281 | printf("[*] Usage: %s <elf to rebase> <target image_base> <output filename>\n", argv[0]); 282 | return 0; 283 | } 284 | 285 | filename = strdup (argv[1]); 286 | output_file = strdup(argv[3]); 287 | target_image_base = strstr (argv[2], "0x") ? strtoll (argv[2], NULL, 0) 288 | : strtoll (argv[2], NULL, 16); 289 | target_image_base &= 0xfffff000; 290 | 291 | if (target_image_base > 0xc0000000) { 292 | printf ("[-] ImageBase is too big. it overlaps with kernel space (0xc0000000)\n"); 293 | free (filename); 294 | return -1; 295 | } 296 | 297 | /*if (target_image_base < 0x10000000) { 298 | printf ("[-] ImageBase is too small. (0x00100000)\n"); 299 | free (filename); 300 | return -1; 301 | }*/ 302 | 303 | 304 | PDBG ("[+] relocating: %s to imagebase 0x%lx\n", filename, (void*)target_image_base); 305 | relocate (filename, target_image_base, output_file); 306 | 307 | free (filename); 308 | free (output_file); 309 | } 310 | --------------------------------------------------------------------------------