diverse fixes and polish
This commit is contained in:
parent
839f1395a3
commit
f163f8f81a
2
Makefile
2
Makefile
|
@ -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)
|
||||||
|
|
||||||
|
|
34
assets/xor.s
34
assets/xor.s
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue