From 1c9ce758736ee22c8cc1ef4b9a0e493eee198c13 Mon Sep 17 00:00:00 2001 From: pbonilla Date: Wed, 19 Jun 2024 15:21:28 +0200 Subject: [PATCH] 32 bits management --- Makefile | 4 +- includes/woody.h | 39 +++++++++---- print.s | 2 +- srcs/encrypt.c | 6 +- srcs/main.c | 56 +++++++++++++++---- srcs/payload.c | 61 ++++++++++++++++++++ srcs/utils.c | 12 ++-- srcs/woody.c | 143 ----------------------------------------------- srcs/woody32.c | 80 ++++++++++++++++++++++++++ srcs/woody64.c | 80 ++++++++++++++++++++++++++ 10 files changed, 304 insertions(+), 179 deletions(-) create mode 100644 srcs/payload.c delete mode 100644 srcs/woody.c create mode 100644 srcs/woody32.c create mode 100644 srcs/woody64.c diff --git a/Makefile b/Makefile index c6b661f..faa514a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,9 @@ SRCS_PATH = srcs/ SRCS = $(SRCS_PATH)main.c \ $(SRCS_PATH)utils.c \ - $(SRCS_PATH)woody.c \ + $(SRCS_PATH)payload.c \ + $(SRCS_PATH)woody32.c \ + $(SRCS_PATH)woody64.c \ $(SRCS_PATH)encrypt.c diff --git a/includes/woody.h b/includes/woody.h index b7b02f4..540ce44 100644 --- a/includes/woody.h +++ b/includes/woody.h @@ -28,19 +28,27 @@ typedef struct payload int len; } t_payload; +typedef struct elf32 +{ + Elf32_Ehdr *Ehdr; + Elf32_Phdr *Phdr; + Elf32_Shdr *Shdr; +} t_elf32; + +typedef struct elf64 +{ + Elf64_Ehdr *Ehdr; + Elf64_Phdr *Phdr; + Elf64_Shdr *Shdr; +} t_elf64; + typedef struct elf_content { long unsigned int file_size; char *file_path; char *file; - Elf64_Ehdr *Ehdr; - Elf64_Phdr *Phdr; - Elf64_Shdr *Shdr; - Elf64_Shdr *symbols_table; - int num_symbols; - Elf64_Shdr *text_section; - Elf64_Sym *symbols; - char *Sshstrtab; + t_elf32 *elf32; + t_elf64 *elf64; } t_elf_content; // utils.c @@ -49,10 +57,19 @@ int ft_put_error(char *str); char *get_string(char *str, char *end_file); int get_symbols_count(int sh_size, int sh_entsize); char *get_section_name(t_elf_content *woody, int section_index); +int elf_magic_numbers(char *str); -// woody.c -int inject(t_elf_content *woody); -int get_elf_sections(t_elf_content *woody); +// payload.c +t_payload *get_payload(); +int insert_payload(t_elf_content *woody, t_payload *payload, size_t payload_position, unsigned int e_entry, unsigned int p_offset, unsigned int p_memsz); + +// woody32.c +int get_elf_sections32(t_elf_content *woody); +int inject32(t_elf_content *woody); + +// woody64.c +int get_elf_sections64(t_elf_content *woody); +int inject64(t_elf_content *woody); // encrypt.c diff --git a/print.s b/print.s index 9347f3e..0b5475f 100644 --- a/print.s +++ b/print.s @@ -18,7 +18,7 @@ _start: cmp r8, r9 je end_encrypt movzx r10, byte[rax + r9] - ;inc r10b ;rot + 1 + inc r10b ;rot + 1 mov byte[rax + r9], r10b inc r9 jmp encrypt diff --git a/srcs/encrypt.c b/srcs/encrypt.c index f5b5f58..f7866d7 100644 --- a/srcs/encrypt.c +++ b/srcs/encrypt.c @@ -5,11 +5,7 @@ void encrypt(char *file, unsigned long int offset, unsigned long int size) size_t i = 0; while (i < size) { - file[offset + i] = file[offset + i];// - 1; + file[offset + i] = file[offset + i] - 1; ++i; } - printf("\nENCRYPTION : \n"); - printf(" File encrypted from %ld (%lx) to %ld (%lx)\n", offset, offset, offset + size, offset + size); - printf(" Size of encryption = %ld (%lx)\n", size, size); - printf("\n"); } \ No newline at end of file diff --git a/srcs/main.c b/srcs/main.c index 87ac802..b41b121 100644 --- a/srcs/main.c +++ b/srcs/main.c @@ -1,5 +1,12 @@ #include "../includes/woody.h" +void free_elf_content(t_elf_content *woody) +{ + if (woody->elf32) + free(woody->elf32); + else if (woody->elf64) + free(woody->elf64); +} int get_elf_file(t_elf_content *woody) { int fd; @@ -34,13 +41,13 @@ int save_file(char *path, char *file, unsigned long int size) { int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0755); if (fd == -1) { - printf("Error: Failed to create new file \'%s\'\n", path); + ft_printf("Error: Failed to create new file \'%s\'\n", path); return EXIT_FAILURE; } if (write(fd, file, size) == -1) { close(fd); - printf("Error: Failed to write new file \'%s\'\n", path); + ft_printf("Error: Failed to write new file \'%s\'\n", path); return EXIT_FAILURE; } close(fd); @@ -66,7 +73,7 @@ int save_woody(t_elf_content *woody) int main(int ac, char **av) { - t_elf_content woody; + t_elf_content woody = {0}; if (ac != 2) { return ft_put_error("Woody_woodpacker take 1 argument\n"); @@ -75,15 +82,42 @@ int main(int ac, char **av) int elf_error = get_elf_file(&woody); if (elf_error) return elf_error; - elf_error = get_elf_sections(&woody); + if (woody.file_size < sizeof(Elf32_Ehdr) || !elf_magic_numbers(woody.file)) + { + ft_printf("Error: \'%s\' is not a valid ELF file\n", woody.file_path); + return EXIT_FAILURE; + } + int elfclass = woody.file[4]; + if (elfclass == ELFCLASS32) + { + if (!(woody.elf32 = malloc(sizeof(t_elf32)))) + return ft_put_error("Allocation error"); + elf_error = get_elf_sections32(&woody); + } + else if (elfclass == ELFCLASS64) + { + if (!(woody.elf64 = malloc(sizeof(t_elf64)))) + return ft_put_error("Allocation error"); + elf_error = get_elf_sections64(&woody); + } + else + { + elf_error = EXIT_FAILURE; + ft_printf("Error: \'%s\' is not a valid ELF file\n", woody.file_path); + } if (elf_error) return elf_error; - - int inject_error = inject(&woody); - if (!inject_error) + int inject_error = -1; + if (elfclass == ELFCLASS32) + inject_error = inject32(&woody); + else if (elfclass == ELFCLASS64) + inject_error = inject64(&woody); + if (inject_error) { - return save_woody(&woody); + free_elf_content(&woody); + return inject_error; } - return EXIT_SUCCESS; -} - + int save_error = save_woody(&woody); + free_elf_content(&woody); + return save_error; +} \ No newline at end of file diff --git a/srcs/payload.c b/srcs/payload.c new file mode 100644 index 0000000..aca3fdf --- /dev/null +++ b/srcs/payload.c @@ -0,0 +1,61 @@ + +#include "../includes/woody.h" + +t_payload *get_payload() +{ + t_payload *payload = malloc(sizeof(t_payload)); + if (!payload) + return NULL; + char buffer[1024]; + int fd = open("payload", O_RDONLY); + if (fd == -1) { + ft_put_error("Failed to open payload"); + free(payload); + return NULL; + } + payload->len = read(fd, buffer, 1024); + if (payload->len == -1) + { + ft_put_error("Failed to read payload"); + free(payload); + close(fd); + return NULL; + } + close(fd); + payload->payload = malloc(sizeof(char) * payload->len); + if (!payload->payload) + { + ft_put_error("Allocation error"); + free(payload); + return NULL; + } + ft_memcpy(payload->payload, buffer, payload->len); + return payload; +} + +int insert_payload(t_elf_content *woody, t_payload *payload, size_t payload_position, unsigned int e_entry, unsigned int p_offset, unsigned int p_memsz) +{ + char *ptr_jmp_value = ft_strnstr_nullterminated(payload->payload, JUMP_VALUE, payload->len); + char *ptr_woody = ft_strnstr_nullterminated(payload->payload, WOODY, payload->len); + char *ptr_text_section = ft_strnstr_nullterminated(payload->payload, TEXT_OFFSET, payload->len); + char *ptr_section_size = ft_strnstr_nullterminated(payload->payload, SECTION_SIZE, payload->len); + if (ptr_jmp_value && ptr_woody && ptr_text_section && ptr_section_size) + { + int32_t woody_index = ptr_woody - payload->payload; + int32_t jmp_index = ptr_jmp_value - sizeof(JUMP) - payload->payload; + int32_t jump_value = ((payload_position + jmp_index + 5) - e_entry) * -1; // 5 = JUMP SIZE (OPCODE + 4 bytes operand) + ft_memcpy(&payload->payload[jmp_index + 1], &jump_value, sizeof(jump_value)); + + int64_t text_index = ptr_text_section - payload->payload; + int64_t text_value = payload_position - p_offset + woody_index; + ft_memcpy(&payload->payload[text_index], &text_value, sizeof(text_value)); + + int64_t section_index = ptr_section_size - payload->payload; + int64_t section_value = p_memsz; + ft_memcpy(&payload->payload[section_index], §ion_value, sizeof(section_value)); + + ft_memcpy(woody->file + payload_position, payload->payload, payload->len); + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} \ No newline at end of file diff --git a/srcs/utils.c b/srcs/utils.c index 6355bfa..92c3fca 100644 --- a/srcs/utils.c +++ b/srcs/utils.c @@ -7,6 +7,11 @@ void *fetch(char *file, unsigned long file_size, unsigned long offset_to_data, u return NULL; } +int elf_magic_numbers(char *str) +{ + return (!ft_strncmp(str, ELFMAG, SELFMAG)); +} + int get_symbols_count(int sh_size, int sh_entsize) { if (sh_size <= 0 || sh_entsize <= 0) @@ -22,17 +27,10 @@ char *get_string(char *str, char *end_file) if (*search_end == 0) return str; ++search_end; - } return NULL; } -char *get_section_name(t_elf_content *woody, int section_index) -{ - unsigned int shstrtabndx = woody->Shdr[section_index].sh_name; - return get_string(&woody->Sshstrtab[shstrtabndx], woody->file + woody->file_size); -} - int ft_put_error(char *str) { ft_putstr_fd("Error: ", STDERR_FILENO); diff --git a/srcs/woody.c b/srcs/woody.c deleted file mode 100644 index c9d8fbe..0000000 --- a/srcs/woody.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "../includes/woody.h" - -int elf_magic_numbers(char *str) -{ - return (!ft_strncmp(str, ELFMAG, SELFMAG)); -} - -int get_load_segment(t_elf_content *woody, int start, bool executable) -{ - for (int i = start; i < woody->Ehdr->e_phnum; i++) - { - if (woody->Phdr[i].p_type == PT_LOAD) - { - if (executable) - { - if (woody->Phdr[i].p_flags & PF_X) - return i; - } - else - return i; - } - } - return -1; -} - -t_payload *get_payload() -{ - t_payload *payload = malloc(sizeof(t_payload)); - if (!payload) - return NULL; - char buffer[1024]; - int fd = open("payload", O_RDONLY); - if (fd == -1) { - ft_put_error("Failed to open payload"); - free(payload); - close(fd); - return NULL; - } - payload->len = read(fd, buffer, 1024); - if (payload->len == -1) - { - ft_put_error("Failed to read payload"); - free(payload); - close(fd); - return NULL; - } - close(fd); - payload->payload = malloc(sizeof(char) * payload->len); - if (!payload->payload) - { - ft_put_error("Allocation error"); - free(payload); - return NULL; - } - ft_memcpy(payload->payload, buffer, payload->len); - return payload; -} - -int insert_payload(t_elf_content *woody, t_payload *payload, size_t payload_position, int load_segment_index) -{ - char *ptr_jmp_value = ft_strnstr_nullterminated(payload->payload, JUMP_VALUE, payload->len); - char *ptr_woody = ft_strnstr_nullterminated(payload->payload, WOODY, payload->len); - char *ptr_text_section = ft_strnstr_nullterminated(payload->payload, TEXT_OFFSET, payload->len); - char *ptr_section_size = ft_strnstr_nullterminated(payload->payload, SECTION_SIZE, payload->len); - if (ptr_jmp_value && ptr_woody && ptr_text_section && ptr_section_size) - { - int32_t woody_index = ptr_woody - payload->payload; - int32_t jmp_index = ptr_jmp_value - sizeof(JUMP) - payload->payload; - int32_t jump_value = ((payload_position + jmp_index + 5) - woody->Ehdr->e_entry) * -1; // 5 = JUMP SIZE (OPCODE + 4 bytes operand) - ft_memcpy(&payload->payload[jmp_index + 1], &jump_value, sizeof(jump_value)); - - int64_t text_index = ptr_text_section - payload->payload; - int64_t text_value = payload_position - woody->Phdr[load_segment_index].p_offset + woody_index; - ft_memcpy(&payload->payload[text_index], &text_value, sizeof(text_value)); - - int64_t section_index = ptr_section_size - payload->payload; - int64_t section_value = woody->Phdr[load_segment_index].p_memsz; - ft_memcpy(&payload->payload[section_index], §ion_value, sizeof(section_value)); - - ft_memcpy(woody->file + payload_position, payload->payload, payload->len); - return EXIT_SUCCESS; - } - return EXIT_FAILURE; -} - -int inject(t_elf_content *woody) -{ - t_payload *payload = get_payload(); - if (!payload) - return EXIT_FAILURE; - - int i = get_load_segment(woody, 0, true); - int j = get_load_segment(woody, i + 1, false); - - if (i == -1 || j != i + 1) - { - free(payload->payload); - free(payload); - return ft_put_error("PT_LOAD segment missing"); - } - - size_t code_cave_size = woody->Phdr[j].p_offset - (woody->Phdr[i].p_offset + woody->Phdr[i].p_filesz); - size_t payload_position = woody->Phdr[i].p_offset + woody->Phdr[i].p_filesz; - - if (code_cave_size < (size_t)payload->len) - { - free(payload->payload); - free(payload); - return ft_put_error("Unable to insert payload, not enough space for code cave"); - } - - woody->Phdr[i].p_filesz += payload->len; - woody->Phdr[i].p_memsz += payload->len; - - if (insert_payload(woody, payload, payload_position, i)) - { - free(payload->payload); - free(payload); - return ft_put_error("Unable to insert payload, please regenerate it"); - } - - woody->Ehdr->e_entry = payload_position; - woody->Phdr[i].p_flags = PF_X | PF_W | PF_R; - free(payload->payload); - free(payload); - return EXIT_SUCCESS; -} - -int get_elf_sections(t_elf_content *woody) -{ - woody->Ehdr = (Elf64_Ehdr *)fetch(woody->file, woody->file_size, 0, sizeof(Elf64_Ehdr)); - if (!woody->Ehdr || !elf_magic_numbers(woody->file) || woody->Ehdr->e_ident[EI_CLASS] != ELFCLASS64) - { - printf("Error: \'%s\' is not a valid 64-bit ELF file\n", woody->file_path); - return EXIT_FAILURE; - } - woody->Phdr = (Elf64_Phdr *)fetch(woody->file, woody->file_size, woody->Ehdr->e_phoff, sizeof(Elf64_Phdr)); - - woody->Shdr = (Elf64_Shdr *)fetch(woody->file, woody->file_size, woody->Ehdr->e_shoff, sizeof(Elf64_Shdr)); - if (!woody->Shdr|| !fetch(woody->file, woody->file_size, woody->Ehdr->e_shoff, woody->Ehdr->e_shnum * sizeof(Elf64_Shdr))) - return EXIT_FAILURE; - return EXIT_SUCCESS; -} diff --git a/srcs/woody32.c b/srcs/woody32.c new file mode 100644 index 0000000..29b3e4a --- /dev/null +++ b/srcs/woody32.c @@ -0,0 +1,80 @@ +#include "../includes/woody.h" + +int get_load_segment32(t_elf_content *woody, int start, bool executable) +{ + t_elf32 *elf = woody->elf32; + for (int i = start; i < elf->Ehdr->e_phnum; i++) + { + if (elf->Phdr[i].p_type == PT_LOAD) + { + if (executable) + { + if (elf->Phdr[i].p_flags & PF_X) + return i; + } + else + return i; + } + } + return -1; +} + +int inject32(t_elf_content *woody) +{ + t_elf32 *elf = woody->elf32; + t_payload *payload = get_payload(); + if (!payload) + return EXIT_FAILURE; + + int i = get_load_segment32(woody, 0, true); + int j = get_load_segment32(woody, i + 1, false); + + if (i == -1 || j != i + 1) + { + free(payload->payload); + free(payload); + return ft_put_error("PT_LOAD segment missing"); + } + + size_t code_cave_size = elf->Phdr[j].p_offset - (elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz); + size_t payload_position = elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz; + + if (code_cave_size < (size_t)payload->len) + { + free(payload->payload); + free(payload); + return ft_put_error("Unable to insert payload, not enough space for code cave"); + } + + elf->Phdr[i].p_filesz += payload->len; + elf->Phdr[i].p_memsz += payload->len; + + if (insert_payload(woody, payload, payload_position, elf->Ehdr->e_entry, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz)) + { + free(payload->payload); + free(payload); + return ft_put_error("Unable to insert payload, please regenerate it"); + } + + elf->Ehdr->e_entry = payload_position; + elf->Phdr[i].p_flags = PF_X | PF_W | PF_R; + free(payload->payload); + free(payload); + return EXIT_SUCCESS; +} + +int get_elf_sections32(t_elf_content *woody) +{ + woody->elf32->Ehdr = (Elf32_Ehdr *)fetch(woody->file, woody->file_size, 0, sizeof(Elf32_Ehdr)); + if (!woody->elf32->Ehdr) + return EXIT_FAILURE; + + woody->elf32->Phdr = (Elf32_Phdr *)fetch(woody->file, woody->file_size, woody->elf32->Ehdr->e_phoff, sizeof(Elf32_Phdr)); + if (!woody->elf32->Phdr) + return EXIT_FAILURE; + + woody->elf32->Shdr = (Elf32_Shdr *)fetch(woody->file, woody->file_size, woody->elf32->Ehdr->e_shoff, sizeof(Elf32_Shdr)); + if (!woody->elf32->Shdr || !fetch(woody->file, woody->file_size, woody->elf32->Ehdr->e_shoff, woody->elf32->Ehdr->e_shnum * sizeof(Elf32_Shdr))) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/srcs/woody64.c b/srcs/woody64.c new file mode 100644 index 0000000..f18f7b7 --- /dev/null +++ b/srcs/woody64.c @@ -0,0 +1,80 @@ +#include "../includes/woody.h" + +int get_load_segment64(t_elf_content *woody, int start, bool executable) +{ + t_elf64 *elf = woody->elf64; + for (int i = start; i < elf->Ehdr->e_phnum; i++) + { + if (elf->Phdr[i].p_type == PT_LOAD) + { + if (executable) + { + if (elf->Phdr[i].p_flags & PF_X) + return i; + } + else + return i; + } + } + return -1; +} + +int inject64(t_elf_content *woody) +{ + t_elf64 *elf = woody->elf64; + t_payload *payload = get_payload(); + if (!payload) + return EXIT_FAILURE; + + int i = get_load_segment64(woody, 0, true); + int j = get_load_segment64(woody, i + 1, false); + + if (i == -1 || j != i + 1) + { + free(payload->payload); + free(payload); + return ft_put_error("PT_LOAD segment missing"); + } + + size_t code_cave_size = elf->Phdr[j].p_offset - (elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz); + size_t payload_position = elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz; + + if (code_cave_size < (size_t)payload->len) + { + free(payload->payload); + free(payload); + return ft_put_error("Unable to insert payload, not enough space for code cave"); + } + + elf->Phdr[i].p_filesz += payload->len; + elf->Phdr[i].p_memsz += payload->len; + + if (insert_payload(woody, payload, payload_position, elf->Ehdr->e_entry, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz)) + { + free(payload->payload); + free(payload); + return ft_put_error("Unable to insert payload, please regenerate it"); + } + + elf->Ehdr->e_entry = payload_position; + elf->Phdr[i].p_flags = PF_X | PF_W | PF_R; + free(payload->payload); + free(payload); + return EXIT_SUCCESS; +} + +int get_elf_sections64(t_elf_content *woody) +{ + woody->elf64->Ehdr = (Elf64_Ehdr *)fetch(woody->file, woody->file_size, 0, sizeof(Elf64_Ehdr)); + if (!woody->elf64->Ehdr) + return EXIT_FAILURE; + + woody->elf64->Phdr = (Elf64_Phdr *)fetch(woody->file, woody->file_size, woody->elf64->Ehdr->e_phoff, sizeof(Elf64_Phdr)); + if (!woody->elf64->Phdr) + return EXIT_FAILURE; + + woody->elf64->Shdr = (Elf64_Shdr *)fetch(woody->file, woody->file_size, woody->elf64->Ehdr->e_shoff, sizeof(Elf64_Shdr)); + if (!woody->elf64->Shdr || !fetch(woody->file, woody->file_size, woody->elf64->Ehdr->e_shoff, woody->elf64->Ehdr->e_shnum * sizeof(Elf64_Shdr))) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} \ No newline at end of file