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 \
fetch.c \
check_ident.c \
xor_mode.c \
debug_mode.c \
OBJ_FILE = $(SRC_FILE:.c=.o)

View File

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

View File

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

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;
}
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) {

View File

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

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