feat: xor payload
This commit is contained in:
parent
7d93440bd1
commit
77b90650b1
|
@ -0,0 +1,76 @@
|
||||||
|
bits 64
|
||||||
|
global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
push rbp
|
||||||
|
push rsp
|
||||||
|
push rbx
|
||||||
|
push r13
|
||||||
|
push rax
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
|
||||||
|
mov rdi, 1
|
||||||
|
lea rsi, [rel msg]
|
||||||
|
mov rbx, rsi
|
||||||
|
;mov rbx, qword [rel text_section]
|
||||||
|
sub rbx, qword [rel text_section] ;text_section address because of this and that
|
||||||
|
mov r8, qword [rel section_size] ;text_section size
|
||||||
|
mov r9, 0 ;increment register
|
||||||
|
xor r13, r13
|
||||||
|
mov r13, qword [rel private_key]
|
||||||
|
|
||||||
|
decrypt_whole_blocks:
|
||||||
|
; check left to decrypt < block_size
|
||||||
|
mov rcx, r8
|
||||||
|
sub rcx, r9
|
||||||
|
cmp rcx, 8
|
||||||
|
jle decrypt_last_block
|
||||||
|
; xor section with private_key
|
||||||
|
mov rdx, rbx
|
||||||
|
add rdx, r9
|
||||||
|
xor [rdx], r13
|
||||||
|
; increase section address
|
||||||
|
; increase counter
|
||||||
|
add r9, 8
|
||||||
|
jmp decrypt_whole_blocks
|
||||||
|
|
||||||
|
decrypt_last_block:
|
||||||
|
mov rdx, 8
|
||||||
|
sub rdx, rcx
|
||||||
|
mov rcx, rdx
|
||||||
|
mov rax, 8
|
||||||
|
mul cl
|
||||||
|
mov rcx, rax
|
||||||
|
shl r13, cl
|
||||||
|
shr r13, cl
|
||||||
|
mov rdx, rbx
|
||||||
|
add rdx, r9
|
||||||
|
xor [rdx], r13
|
||||||
|
|
||||||
|
end_decrypt:
|
||||||
|
mov rdx, 14
|
||||||
|
mov rax, 1
|
||||||
|
syscall
|
||||||
|
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
|
pop rax
|
||||||
|
pop r13
|
||||||
|
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
|
||||||
|
private_key dq 0xabcdefabcdefabcd
|
15
inc/woody.h
15
inc/woody.h
|
@ -10,11 +10,26 @@
|
||||||
# define RET_ERR 1
|
# define RET_ERR 1
|
||||||
# define RET_OK 0
|
# define RET_OK 0
|
||||||
|
|
||||||
|
# define PL_XOR 0
|
||||||
|
# define PL_RSA 1
|
||||||
|
# define PL_DEBUG 2
|
||||||
|
|
||||||
typedef struct s_map {
|
typedef struct s_map {
|
||||||
void *data;
|
void *data;
|
||||||
off_t size;
|
off_t size;
|
||||||
} t_map;
|
} t_map;
|
||||||
|
|
||||||
|
typedef struct s_payload64 {
|
||||||
|
int (*encrypt)(t_map, Elf64_Phdr);
|
||||||
|
size_t jump_offset;
|
||||||
|
size_t woody_offset;
|
||||||
|
size_t load_ptr_offset;
|
||||||
|
size_t load_size_offset;
|
||||||
|
size_t private_key_offset;
|
||||||
|
size_t len;
|
||||||
|
unsigned char *data;
|
||||||
|
} t_payload64;
|
||||||
|
|
||||||
int woody_woodpacker(char *path);
|
int woody_woodpacker(char *path);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -86,11 +86,75 @@ t_map get_code_cave(t_map file, Elf64_Phdr load_segment) {
|
||||||
code_cave.data = fetch(file, longest_i + offset, longest);
|
code_cave.data = fetch(file, longest_i + offset, longest);
|
||||||
code_cave.size = longest;
|
code_cave.size = longest;
|
||||||
if (!code_cave.data) {
|
if (!code_cave.data) {
|
||||||
printf("unreachable !!!\n");
|
ft_printf("unreachable !!!\n");
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
|
||||||
|
payload.len = 191;
|
||||||
|
payload.jump_offset = 149;
|
||||||
|
payload.load_ptr_offset = 167;
|
||||||
|
payload.load_size_offset = 175;
|
||||||
|
payload.encrypt = &encrypt_xor;
|
||||||
|
payload.data = malloc(payload.len * sizeof(unsigned char));
|
||||||
|
ft_memcpy(payload.data,
|
||||||
|
"\x55\x54\x53\x41\x55\x50\x51\x52\x56\x57\x41\x50\x41\x51\xbf\x01"
|
||||||
|
"\x00\x00\x00\x48\x8d\x35\x7f\x00\x00\x00\x48\x89\xf3\x48\x2b\x1d"
|
||||||
|
"\x83\x00\x00\x00\x4c\x8b\x05\x84\x00\x00\x00\x41\xb9\x00\x00\x00"
|
||||||
|
"\x00\x4d\x31\xed\x4c\x8b\x2d\x7c\x00\x00\x00\x4c\x89\xc1\x4c\x29"
|
||||||
|
"\xc9\x48\x83\xf9\x08\x7e\x0f\x48\x89\xda\x4c\x01\xca\x4c\x31\x2a"
|
||||||
|
"\x49\x83\xc1\x08\xeb\xe5\xba\x08\x00\x00\x00\x48\x29\xca\x48\x89"
|
||||||
|
"\xd1\xb8\x08\x00\x00\x00\xf6\xe1\x48\x89\xc1\x49\xd3\xe5\x49\xd3"
|
||||||
|
"\xed\x48\x89\xda\x4c\x01\xca\x4c\x31\x2a\xba\x0e\x00\x00\x00\xb8"
|
||||||
|
"\x01\x00\x00\x00\x0f\x05\x41\x59\x41\x58\x5f\x5e\x5a\x59\x58\x41"
|
||||||
|
"\x5d\x5b\x5c\x5d\xe9\x41\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) {
|
||||||
|
@ -123,35 +187,33 @@ 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);
|
||||||
|
|
||||||
size_t payload_len = 55;
|
t_payload64 payload = get_xor_payload64();
|
||||||
unsigned char *payload = malloc(payload_len * sizeof(unsigned char));
|
|
||||||
ft_memcpy(payload, "\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);
|
|
||||||
// todo measure this, probably wc/4 in shell script output + hardcoded
|
|
||||||
// 55 bytes ^^^
|
|
||||||
|
|
||||||
// same, probably will hardcode it in functions like "get_debug_payload_info"
|
|
||||||
// or "get_rsa_payload_info" etc etc...
|
|
||||||
size_t jump_i = 36;
|
|
||||||
|
|
||||||
// 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);
|
||||||
return wdy_error("payload length exceed code cave size");
|
return wdy_error("payload length exceed code cave size");
|
||||||
}
|
}
|
||||||
|
|
||||||
// e_entry because relative to this (where we gonna go)
|
// e_entry because relative to this (where we gonna go)
|
||||||
// code cave start because thats the start of the code
|
// code cave start because thats the start of the code
|
||||||
// jump_i because thats the index of jump from code cave start
|
// jump_offset is the index of jump from code cave start
|
||||||
// 5 because jump_i is 5 bytes long operation (1 byte opcode + 4 byte operand)
|
// 4 because jump has a 4 byte operand)
|
||||||
int jump_value = elf_header->e_entry - (code_cave.data - file.data) - jump_i - 5;
|
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 + jump_i + 1, &jump_value, 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));
|
||||||
|
|
||||||
|
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;
|
||||||
load_segment->p_flags |= PF_W | PF_R;
|
load_segment->p_flags |= PF_W | PF_R;
|
||||||
ft_memcpy(code_cave.data, payload, payload_len);
|
ft_memcpy(code_cave.data, payload.data, payload.len);
|
||||||
|
|
||||||
int fd = open("woody", O_WRONLY | O_CREAT, 0755);
|
int fd = open("woody", O_WRONLY | O_CREAT, 0755);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
|
Loading…
Reference in New Issue