diverse fixes and polish

This commit is contained in:
gbrochar 2024-09-06 15:02:02 +02:00
parent 839f1395a3
commit f163f8f81a
7 changed files with 140 additions and 98 deletions

View File

@ -5,6 +5,8 @@ SRC_FILE = main.c \
error.c \ error.c \
fetch.c \ fetch.c \
check_ident.c \ check_ident.c \
xor_mode.c \
debug_mode.c \
OBJ_FILE = $(SRC_FILE:.c=.o) OBJ_FILE = $(SRC_FILE:.c=.o)

View File

@ -2,28 +2,23 @@ bits 64
global _start global _start
_start: _start:
push rbp
push rsp
push rbx
push rax push rax
push rcx push rcx
push rdx push rdx
push rsi push rsi
push rdi push rdi
push r8
lea rsi, [rel msg] lea rdi, [rel _start]
mov rbx, rsi sub rdi, qword [rel load_ptr]
sub rbx, qword [rel text_section] ;text_section address because of this and that mov rsi, qword [rel load_size]
mov r8, qword [rel section_size] ;text_section size
mov rdx, qword [rel private_key] mov rdx, qword [rel private_key]
decrypt_last_block: decrypt_last_block:
; rcx = 8 * (8 - section_size % 8) ; rcx = 8 * (8 - load_size % 8)
; Then crop the private key by rcx bits ; Then crop the private key by rcx bits
; That's to decrypt the end of the section in case the section size ; That's to decrypt the end of the section in case the section size
; isn't a multiple of 64 bits ; isn't a multiple of 64 bits
mov rcx, r8 mov rcx, rsi
not rcx not rcx
and rcx, 7 and rcx, 7
inc rcx inc rcx
@ -32,34 +27,31 @@ _start:
shl rax, cl shl rax, cl
shr rax, cl shr rax, cl
; make section size a multiple of 64bits with this and ; make section size a multiple of 64bits with this and
and r8, 0xfffffffffffffff8 and rsi, 0xfffffffffffffff8
xor [rbx + r8], rax xor [rdi + rsi], rax
decrypt_whole_blocks: decrypt_whole_blocks:
sub r8, 8 sub rsi, 8
cmp r8, -8 cmp rsi, -8
je end_decrypt je end_decrypt
xor [rbx + r8], rdx xor [rdi + rsi], rdx
jmp decrypt_whole_blocks jmp decrypt_whole_blocks
end_decrypt: end_decrypt:
lea rsi, [rel msg]
mov rdi, 1 mov rdi, 1
mov rdx, 14 mov rdx, 14
mov rax, 1 mov rax, 1
syscall syscall
pop r8
pop rdi pop rdi
pop rsi pop rsi
pop rdx pop rdx
pop rcx pop rcx
pop rax pop rax
pop rbx
pop rsp
pop rbp
jmp 0xdadadada ; this needs to be just before that jmp 0xdadadada ; this needs to be just before that
msg db "....WOODY....",10 ; that needs to be just after this msg db "....WOODY....",10 ; that needs to be just after this
text_section dq 0xbabababababababa load_ptr dq 0xbabababababababa
section_size dq 0xcacacacacacacaca load_size dq 0xcacacacacacacaca
private_key dq 0xabcdefabcdefabcd private_key dq 0xabcdefabcdefabcd

View File

@ -20,7 +20,8 @@ typedef struct s_map {
} t_map; } t_map;
typedef struct s_payload64 { 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 jump_offset;
size_t woody_offset; size_t woody_offset;
size_t load_ptr_offset; size_t load_ptr_offset;
@ -40,4 +41,10 @@ int wdy_perror(char *path);
int check_ident(t_map file); 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 #endif

17
src/debug_mode.c Normal file
View File

@ -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;
}

View File

@ -7,8 +7,8 @@ void banner(void) {
return; return;
} }
char buffer[13149]; char buffer[13149];
read(fd, buffer, 13149); ssize_t len = read(fd, buffer, 13149);
write(1, buffer, 13149); write(1, buffer, len);
} }
int main(int ac, char **av) { int main(int ac, char **av) {

View File

@ -52,8 +52,8 @@ int get_load_segment64(
// TODO refacto // TODO refacto
t_map get_code_cave(t_map file, Elf64_Phdr load_segment) { t_map get_code_cave(t_map file, Elf64_Phdr load_segment) {
size_t page_size = load_segment.p_align; 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 len = page_size - load_segment.p_filesz % page_size;
size_t offset = load_segment.p_offset; size_t offset = load_segment.p_offset + load_segment.p_filesz;
unsigned char *seg = fetch(file, offset, len); unsigned char *seg = fetch(file, offset, len);
if (!seg) { if (!seg) {
printf("fallback to weird code cave finder\n"); 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; 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) { int pack_elf64(t_map file) {
Elf64_Ehdr *elf_header = (Elf64_Ehdr *)fetch(file, 0, sizeof(Elf64_Ehdr)); Elf64_Ehdr *elf_header = (Elf64_Ehdr *)fetch(file, 0, sizeof(Elf64_Ehdr));
if (!elf_header) { if (!elf_header) {
@ -189,7 +124,6 @@ int pack_elf64(t_map file) {
t_map code_cave = get_code_cave(file, *load_segment); t_map code_cave = get_code_cave(file, *load_segment);
t_payload64 payload = get_xor_payload64(); t_payload64 payload = get_xor_payload64();
// This should fallback to compression algorithm, or smaller payload (eg rsa->xor) // This should fallback to compression algorithm, or smaller payload (eg rsa->xor)
if (payload.len > (size_t)code_cave.size) { if (payload.len > (size_t)code_cave.size) {
printf("code cave size: %ld (0x%lx) bytes\n", code_cave.size, 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) // 4 because jump has a 4 byte operand)
size_t code_cave_start = code_cave.data - file.data; size_t code_cave_start = code_cave.data - file.data;
int jump_value = elf_header->e_entry - code_cave_start - payload.jump_offset - 4; 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)); 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; 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_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; elf_header->e_entry = code_cave.data - file.data;
load_segment->p_filesz += payload.len; load_segment->p_filesz += payload.len;
load_segment->p_memsz += payload.len; load_segment->p_memsz += payload.len;
@ -243,5 +183,11 @@ int woody_woodpacker(char *path) {
if (check_ident(file) == RET_ERR) { if (check_ident(file) == RET_ERR) {
return 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;
} }

78
src/xor_mode.c Normal file
View File

@ -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;
}