From f163f8f81ae4c0392b6c08cd1a47c5dbc9be96bb Mon Sep 17 00:00:00 2001 From: gbrochar Date: Fri, 6 Sep 2024 15:02:02 +0200 Subject: [PATCH] diverse fixes and polish --- Makefile | 2 + assets/xor.s | 34 ++++++--------- inc/woody.h | 9 +++- src/debug_mode.c | 17 ++++++++ src/main.c | 4 +- src/woody_woodpacker.c | 94 +++++++++--------------------------------- src/xor_mode.c | 78 +++++++++++++++++++++++++++++++++++ 7 files changed, 140 insertions(+), 98 deletions(-) create mode 100644 src/debug_mode.c create mode 100644 src/xor_mode.c diff --git a/Makefile b/Makefile index f2a1044..02e4984 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,8 @@ SRC_FILE = main.c \ error.c \ fetch.c \ check_ident.c \ + xor_mode.c \ + debug_mode.c \ OBJ_FILE = $(SRC_FILE:.c=.o) diff --git a/assets/xor.s b/assets/xor.s index 21e2f45..e45be13 100644 --- a/assets/xor.s +++ b/assets/xor.s @@ -2,28 +2,23 @@ bits 64 global _start _start: - push rbp - push rsp - push rbx push rax push rcx push rdx push rsi push rdi - push r8 - lea rsi, [rel msg] - mov rbx, rsi - sub rbx, qword [rel text_section] ;text_section address because of this and that - mov r8, qword [rel section_size] ;text_section size + lea rdi, [rel _start] + sub rdi, qword [rel load_ptr] + mov rsi, qword [rel load_size] mov rdx, qword [rel private_key] decrypt_last_block: - ; rcx = 8 * (8 - section_size % 8) + ; rcx = 8 * (8 - load_size % 8) ; Then crop the private key by rcx bits ; That's to decrypt the end of the section in case the section size ; isn't a multiple of 64 bits - mov rcx, r8 + mov rcx, rsi not rcx and rcx, 7 inc rcx @@ -32,34 +27,31 @@ _start: shl rax, cl shr rax, cl ; make section size a multiple of 64bits with this and - and r8, 0xfffffffffffffff8 - xor [rbx + r8], rax + and rsi, 0xfffffffffffffff8 + xor [rdi + rsi], rax decrypt_whole_blocks: - sub r8, 8 - cmp r8, -8 + sub rsi, 8 + cmp rsi, -8 je end_decrypt - xor [rbx + r8], rdx + xor [rdi + rsi], rdx jmp decrypt_whole_blocks end_decrypt: + lea rsi, [rel msg] mov rdi, 1 mov rdx, 14 mov rax, 1 syscall - pop r8 pop rdi pop rsi pop rdx pop rcx pop rax - pop rbx - pop rsp - pop rbp jmp 0xdadadada ; this needs to be just before that msg db "....WOODY....",10 ; that needs to be just after this - text_section dq 0xbabababababababa - section_size dq 0xcacacacacacacaca + load_ptr dq 0xbabababababababa + load_size dq 0xcacacacacacacaca private_key dq 0xabcdefabcdefabcd diff --git a/inc/woody.h b/inc/woody.h index 4ac7983..1be701a 100644 --- a/inc/woody.h +++ b/inc/woody.h @@ -20,7 +20,8 @@ typedef struct s_map { } t_map; typedef struct s_payload64 { - int (*encrypt)(t_map, Elf64_Phdr); + int (*encrypt)(t_map, void *, Elf64_Phdr); + int (*gen_key)(void **); size_t jump_offset; size_t woody_offset; size_t load_ptr_offset; @@ -40,4 +41,10 @@ int wdy_perror(char *path); int check_ident(t_map file); +t_payload64 get_debug_payload64(void); + +int gen_key_xor(void **key); +int encrypt_xor(t_map file, void *key_ptr, Elf64_Phdr load_segment); +t_payload64 get_xor_payload64(void); + #endif diff --git a/src/debug_mode.c b/src/debug_mode.c new file mode 100644 index 0000000..17360db --- /dev/null +++ b/src/debug_mode.c @@ -0,0 +1,17 @@ +#include "woody.h" + +t_payload64 get_debug_payload64(void) { + t_payload64 payload; + + payload.len = 55; + payload.jump_offset = 37; + payload.encrypt = NULL; + payload.data = malloc(payload.len * sizeof(unsigned char)); + ft_memcpy(payload.data, + "\x55\x54\x50\x52\x56\x57\xbf\x01\x00\x00\x00\x48\x8d\x35\x17\x00" + "\x00\x00\xba\x0e\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\x5f\x5e" + "\x5a\x58\x5c\x5d\xe9\xb1\xda\xda\xda\x2e\x2e\x2e\x2e\x57\x4f\x4f" + "\x44\x59\x2e\x2e\x2e\x2e\x0a", + payload.len); + return payload; +} diff --git a/src/main.c b/src/main.c index d2ad045..66ff840 100644 --- a/src/main.c +++ b/src/main.c @@ -7,8 +7,8 @@ void banner(void) { return; } char buffer[13149]; - read(fd, buffer, 13149); - write(1, buffer, 13149); + ssize_t len = read(fd, buffer, 13149); + write(1, buffer, len); } int main(int ac, char **av) { diff --git a/src/woody_woodpacker.c b/src/woody_woodpacker.c index 4d7598b..2ec830a 100644 --- a/src/woody_woodpacker.c +++ b/src/woody_woodpacker.c @@ -52,8 +52,8 @@ int get_load_segment64( // TODO refacto t_map get_code_cave(t_map file, Elf64_Phdr load_segment) { size_t page_size = load_segment.p_align; - size_t len = load_segment.p_filesz + page_size - load_segment.p_filesz % page_size; - size_t offset = load_segment.p_offset; + size_t len = page_size - load_segment.p_filesz % page_size; + size_t offset = load_segment.p_offset + load_segment.p_filesz; unsigned char *seg = fetch(file, offset, len); if (!seg) { printf("fallback to weird code cave finder\n"); @@ -91,71 +91,6 @@ t_map get_code_cave(t_map file, Elf64_Phdr load_segment) { return code_cave; } -int encrypt_default( - __attribute__((unused)) t_map file, - __attribute__((unused)) Elf64_Phdr load_segment) { - return RET_OK; -} - -int encrypt_xor(t_map file, Elf64_Phdr load_segment) { - uint64_t key = 0xabcdefabcdefabcd; - printf("xor begin\n"); - size_t i = 0; - while (i < load_segment.p_filesz >> 3) { - ((uint64_t *)file.data)[i + (load_segment.p_offset >> 3)] ^= key; - i++; - } - key <<= (8 - (load_segment.p_filesz % 8)) * 8; - key >>= (8 - (load_segment.p_filesz % 8)) * 8; - ((uint64_t *)file.data)[i + (load_segment.p_offset >> 3)] ^= key; - // TODO end encrypt and fix asm - printf("xor ok\n"); - return RET_OK; -} - -t_payload64 get_xor_payload64(void) { - t_payload64 payload; - - size_t diff = 30; - - payload.len = 191 - diff; - payload.jump_offset = 149 - diff; - payload.load_ptr_offset = 167 - diff; - payload.load_size_offset = 175 - diff; - payload.encrypt = &encrypt_xor; - payload.data = malloc(payload.len * sizeof(unsigned char)); - ft_memcpy(payload.data, - "\x55\x54\x53\x50\x51\x52\x56\x57\x41\x50\x48\x8d\x35\x6a\x00\x00" - "\x00\x48\x89\xf3\x48\x2b\x1d\x6e\x00\x00\x00\x4c\x8b\x05\x6f\x00" - "\x00\x00\x48\x8b\x15\x70\x00\x00\x00\x4c\x89\xc1\x48\xf7\xd1\x48" - "\x83\xe1\x07\x48\xff\xc1\x48\xc1\xe1\x03\x48\x89\xd0\x48\xd3\xe0" - "\x48\xd3\xe8\x49\x83\xe0\xf8\x4a\x31\x04\x03\x49\x83\xe8\x08\x49" - "\x83\xf8\xf8\x74\x06\x4a\x31\x14\x03\xeb\xf0\xbf\x01\x00\x00\x00" - "\xba\x0e\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\x41\x58\x5f\x5e" - "\x5a\x59\x58\x5b\x5c\x5d\xe9\x5f\xda\xda\xda\x2e\x2e\x2e\x2e\x57" - "\x4f\x4f\x44\x59\x2e\x2e\x2e\x2e\x0a\xba\xba\xba\xba\xba\xba\xba" - "\xba\xca\xca\xca\xca\xca\xca\xca\xca\xcd\xab\xef\xcd\xab\xef\xcd" - "\xab", - payload.len); - return payload; -} - -t_payload64 get_debug_payload64(void) { - t_payload64 payload; - - payload.len = 55; - payload.jump_offset = 37; - payload.encrypt = &encrypt_default; - payload.data = malloc(payload.len * sizeof(unsigned char)); - ft_memcpy(payload.data, - "\x55\x54\x50\x52\x56\x57\xbf\x01\x00\x00\x00\x48\x8d\x35\x17\x00" - "\x00\x00\xba\x0e\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\x5f\x5e" - "\x5a\x58\x5c\x5d\xe9\xb1\xda\xda\xda\x2e\x2e\x2e\x2e\x57\x4f\x4f" - "\x44\x59\x2e\x2e\x2e\x2e\x0a", - payload.len); - return payload; -} - int pack_elf64(t_map file) { Elf64_Ehdr *elf_header = (Elf64_Ehdr *)fetch(file, 0, sizeof(Elf64_Ehdr)); if (!elf_header) { @@ -189,7 +124,6 @@ int pack_elf64(t_map file) { t_map code_cave = get_code_cave(file, *load_segment); t_payload64 payload = get_xor_payload64(); - // This should fallback to compression algorithm, or smaller payload (eg rsa->xor) if (payload.len > (size_t)code_cave.size) { printf("code cave size: %ld (0x%lx) bytes\n", code_cave.size, code_cave.size); @@ -202,14 +136,20 @@ int pack_elf64(t_map file) { // 4 because jump has a 4 byte operand) size_t code_cave_start = code_cave.data - file.data; int jump_value = elf_header->e_entry - code_cave_start - payload.jump_offset - 4; - ft_memcpy(payload.data + payload.jump_offset, &jump_value, sizeof(jump_value)); - uint64_t load_ptr_value = code_cave_start - load_segment->p_offset + payload.jump_offset + 4; - ft_memcpy(payload.data + payload.load_ptr_offset, &load_ptr_value, sizeof(load_ptr_value)); + if (payload.encrypt != NULL) { + uint64_t load_ptr_value = code_cave_start - load_segment->p_offset; + ft_memcpy(payload.data + payload.load_ptr_offset, &load_ptr_value, sizeof(load_ptr_value)); + ft_memcpy(payload.data + payload.load_size_offset, &load_segment->p_filesz, sizeof(load_segment->p_memsz)); + void *key = NULL; + if (payload.gen_key(&key) != RET_OK) { + return wdy_error("key generation failed"); + } + ft_memcpy(payload.data + payload.private_key_offset, key, sizeof(uint64_t)); + payload.encrypt(file, key, *load_segment); + } - ft_memcpy(payload.data + payload.load_size_offset, &load_segment->p_memsz, sizeof(load_segment->p_memsz)); - payload.encrypt(file, *load_segment); elf_header->e_entry = code_cave.data - file.data; load_segment->p_filesz += payload.len; load_segment->p_memsz += payload.len; @@ -243,5 +183,11 @@ int woody_woodpacker(char *path) { if (check_ident(file) == RET_ERR) { return RET_ERR; } - return pack_elf(file); + int ret = pack_elf(file); + if (ret == RET_OK) { + ft_printf("successfully woody woodpacked %s\n", path); + } else { + ft_printf("error: can't woody woodpack %s\n", path); + } + return ret; } diff --git a/src/xor_mode.c b/src/xor_mode.c new file mode 100644 index 0000000..1c00407 --- /dev/null +++ b/src/xor_mode.c @@ -0,0 +1,78 @@ +#include "woody.h" + +int gen_key_xor(void **key) { + int fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) { + return wdy_perror("/dev/urandom"); + } + *key = malloc(sizeof(uint64_t)); + if (!key) { + return wdy_perror("malloc"); + } + if (read(fd, *key, sizeof(uint64_t)) != 8) { + return wdy_perror("/dev/urandom"); + } + close(fd); + return RET_OK; +} + +void print_key(uint64_t key) { + uint64_t mask = 0xf000000000000000; + ft_printf("info: private_key: 0x"); + for (int i = 60; i >= 0; i -= 4) { + uint64_t print = (key & mask) >> i; + if (print < 10) { + print += '0'; + write(1, &print, 1); + } + else { + print += 'a' - 10; + write(1, &print, 1); + } + mask >>= 4; + } + write (1, "\n", 1); +} + +int encrypt_xor(t_map file, void *key_ptr, Elf64_Phdr load_segment) { + // TODO try oneliner + uint64_t *tmp = key_ptr; + uint64_t key = *tmp; + + print_key(key); + size_t i = 0; + while (i < load_segment.p_filesz >> 3) { + ((uint64_t *)file.data)[i + (load_segment.p_offset >> 3)] ^= key; + i++; + } + key <<= (8 - (load_segment.p_filesz % 8)) * 8; + key >>= (8 - (load_segment.p_filesz % 8)) * 8; + ((uint64_t *)file.data)[i + (load_segment.p_offset >> 3)] ^= key; + return RET_OK; +} + +t_payload64 get_xor_payload64(void) { + t_payload64 payload; + + payload.len = 155; + payload.jump_offset = 113; + payload.load_ptr_offset = 131; + payload.load_size_offset = 139; + payload.private_key_offset = 147; + payload.encrypt = &encrypt_xor; + payload.gen_key = &gen_key_xor; + payload.data = malloc(payload.len * sizeof(unsigned char)); + ft_memcpy(payload.data, + "\x50\x51\x52\x56\x57\x48\x8d\x3d\xf4\xff\xff\xff\x48\x2b\x3d\x70" + "\x00\x00\x00\x48\x8b\x35\x71\x00\x00\x00\x48\x8b\x15\x72\x00\x00" + "\x00\x48\x89\xf1\x48\xf7\xd1\x48\x83\xe1\x07\x48\xff\xc1\x48\xc1" + "\xe1\x03\x48\x89\xd0\x48\xd3\xe0\x48\xd3\xe8\x48\x83\xe6\xf8\x48" + "\x31\x04\x37\x48\x83\xee\x08\x48\x83\xfe\xf8\x74\x06\x48\x31\x14" + "\x37\xeb\xf0\x48\x8d\x35\x1b\x00\x00\x00\xbf\x01\x00\x00\x00\xba" + "\x0e\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05\x5f\x5e\x5a\x59\x58" + "\xe9\x65\xda\xda\xda\x2e\x2e\x2e\x2e\x57\x4f\x4f\x44\x59\x2e\x2e" + "\x2e\x2e\x0a\xba\xba\xba\xba\xba\xba\xba\xba\xca\xca\xca\xca\xca" + "\xca\xca\xca\xcd\xab\xef\xcd\xab\xef\xcd\xab", + payload.len); + return payload; +}