Merge branch 'rsa-asm'

This commit is contained in:
gbrochar 2024-08-20 16:36:54 +02:00
commit 0ddaef8b12
12 changed files with 380 additions and 48 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
rsa/rsa
rsa64/rsa
*.swp
*.o *.o
*.a *.a
woody_woodpacker woody_woodpacker

View File

@ -3,11 +3,13 @@ NAME = woody_woodpacker
SRCS_PATH = srcs/ SRCS_PATH = srcs/
SRCS = $(SRCS_PATH)main.c \ SRCS = $(SRCS_PATH)main.c \
$(SRCS_PATH)utils.c \ $(SRCS_PATH)utils.c \
$(SRCS_PATH)payload.c \ $(SRCS_PATH)payload.c \
$(SRCS_PATH)woody32.c \ $(SRCS_PATH)woody32.c \
$(SRCS_PATH)woody64.c \ $(SRCS_PATH)woody64.c \
$(SRCS_PATH)encrypt.c $(SRCS_PATH)encrypt.c \
$(SRCS_PATH)rsa.c \
$(SRCS_PATH)primes.c
OBJS = ${SRCS:.c=.o} OBJS = ${SRCS:.c=.o}
@ -25,7 +27,7 @@ all: ${NAME}
.c.o: .c.o:
${CC} ${INCLUDES} ${DEFINES} ${CFLAGS} -c $< -o $@ ${CC} ${INCLUDES} ${DEFINES} ${CFLAGS} -c $< -o $@
$(NAME): ${OBJS} $(NAME): ${OBJS} includes/woody.h
make -C ft_printf make -C ft_printf
${CC} ${OBJS} ${LIBFT_FLAGS} -o ${NAME} ${CC} ${OBJS} ${LIBFT_FLAGS} -o ${NAME}
@ -33,7 +35,7 @@ clean:
make -C ft_printf clean make -C ft_printf clean
${RM} ${OBJS} ${RM} ${OBJS}
fclean: fclean: clean
make -C ft_printf fclean make -C ft_printf fclean
make clean make clean
${RM} ${NAME} ${RM} ${NAME}

29
includes/rsa.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef _RSA_H
#define _RSA_H 1
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define RSA_BLOCK_SIZE 128
typedef struct rsa_s {
uint64_t n;
uint64_t d;
} rsa_t;
void *protected_malloc(size_t size);
rsa_t rsa_generate_keys();
uint16_t generate_prime();
uint64_t pow_mod(uint64_t nn, uint64_t e, uint64_t mm);
uint16_t get_random_bytes(int fd);
#endif

View File

@ -1,6 +1,8 @@
#ifndef WOODY_H #ifndef WOODY_H
#define WOODY_H #define WOODY_H
#include "rsa.h"
#include "../ft_printf/includes/ft_printf.h" #include "../ft_printf/includes/ft_printf.h"
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h> #include <unistd.h>
@ -17,10 +19,11 @@
#define JUMP "\xe9" #define JUMP "\xe9"
#define WOODY "....WOODY...." #define WOODY "....WOODY...."
#define JUMP_VALUE "\xda\xda\xda" #define JUMP_VALUE "\xda\xda"
#define TEXT_OFFSET "\xba\xba\xba\xba\xba\xba\xba\xba" #define TEXT_OFFSET "\xba\xba\xba\xba\xba\xba\xba\xba"
#define SECTION_SIZE "\xca\xca\xca\xca\xca\xca\xca\xca" #define SECTION_SIZE "\xca\xca\xca\xca\xca\xca\xca\xca"
#define PRIVATE_KEY "\xcd\xab\xef\xcd\xab\xef\xcd\xab"
typedef struct payload typedef struct payload
{ {
@ -63,7 +66,7 @@ int elf_magic_numbers(char *str);
// payload.c // payload.c
t_payload *get_payload(); 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); 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_memszi, rsa_t rsa);
// woody32.c // woody32.c
int get_elf_sections32(t_elf_content *woody); int get_elf_sections32(t_elf_content *woody);
@ -75,7 +78,7 @@ int inject64(t_elf_content *woody);
// encrypt.c // encrypt.c
void encrypt(char *file, unsigned long int offset, unsigned long int size); unsigned long encrypt(char *file, unsigned long int offset, unsigned long int size, rsa_t rsa);
#endif #endif

152
print.s
View File

@ -2,36 +2,148 @@ bits 64
global _start global _start
_start: _start:
push rbp
push rsp
push rbx
push r12
push r13
push r14
push r15
push rax push rax
push rdi push rcx
push rsi
push rdx push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11
mov rdi, 1 mov rdi, 1
lea rsi, [rel msg] lea rsi, [rel msg]
mov rax, rsi mov rbx, rsi
sub rax, qword [rel text_section] ;text_section address sub rbx, qword [rel text_section] ;text_section address because of this and that
mov r8, qword [rel section_size] ;text_section size mov r8, qword [rel section_size] ;text_section size
shr r8, 2
inc r8
mov r9, 0 ;increment register mov r9, 0 ;increment register
mov r10, 0 ;increment register
xor r10, r10 xor r10, r10
encrypt: xor r13, r13
cmp r8, r9 mov r13d, dword [rel private_key]
je end_encrypt xor r12, r12
movzx r10, byte[rax + r9] mov r12d, dword [rel private_key + 4]
inc r10b ;rot + 1 ;shr r12, 32
mov byte[rax + r9], r10b push r13 ; push rsa.d
inc r9 push r12 ; push rsa.n
jmp encrypt jmp decrypt_loop
end_encrypt:
; rbx is adress of text(encrypted) section
; r8 is section size
; r9 is index
; rax is cypher that needs to be converted to message
; dword [rsp + 16] is rsa.d
; dword [rsp + 8] is rsa.n
; qword [rsp] is cypher backup
decrypt_once:
mov r11, 0x100000000
sq_mul_bit_index:
shr r11, 1
mov r12, r11
and r12, qword [rsp + 16]
jz sq_mul_bit_index
sq_mul_loop:
; check if pow is zero
shr r11, 1
cmp r11, 0
je decrypt_loop2
; square ...
mul rax,
; modulo n ...
mov r13, qword [rsp + 8]
xor rdx, rdx
div r13
mov rax, rdx
; ... and multiply
mov r12, r11
and r12, qword [rsp + 16]
cmp r12, 0
je sq_mul_loop
mov r13, qword [rsp]
mul r13
; modulo n ...
mov r13, qword [rsp + 8]
xor rdx, rdx
div r13
mov rax, rdx
; end of loop
jmp sq_mul_loop
decrypt_loop:
cmp r8, r10
je end_decrypt
xor rax, rax
mov eax, dword [rbx + r9]
push rax
;push r10
jmp decrypt_once
decrypt_loop2:
sub rax, 42 ; remove 42 of result (avoid 0 values)
sub rax, r10 ; remove index of result (caesar like cypher so 0/42 values are differents)
; unpadding and write back here
mov dword [rbx + r9], 0
mov r15, r10
shr r15, 5
shl r15, 2
mov rcx, r10
shl rcx, 59
shr rcx, 59
inc rcx
shl rax, cl
mov r14, r9
sub r14, r15
add [rbx + r14], eax
shr rax, 32
cmp r9, 0
je first_block_skip
add [rbx + r14 - 4], eax
first_block_skip:
; unpadding and write back here
pop rax
add r9, 4
inc r10
jmp decrypt_loop
end_decrypt:
mov rdx, 14 mov rdx, 14
mov rax, 1 mov rax, 1
syscall syscall
pop rdx
pop rsi
pop rdi
pop rax
jmp 0xdadadada pop r12 ; pop rsa.n
msg db "....WOODY....",10 pop r12 ; pop rsa.d
text_section dq 0xbabababababababa
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rdx
pop rcx
pop rax
pop r15
pop r14
pop r13
pop r12
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 section_size dq 0xcacacacacacacaca
private_key dq 0xabcdefabcdefabcd

View File

@ -1,11 +1,51 @@
#include "../includes/woody.h" #include "../includes/woody.h"
#include "../includes/rsa.h"
void encrypt(char *file, unsigned long int offset, unsigned long int size) unsigned long encrypt(char *file, unsigned long int offset, unsigned long int size, rsa_t rsa)
{ {
size_t padded_len = size * sizeof(char) * 33 / sizeof(uint32_t) / 32 + 1; // every 32 octet one padding octet, plus one for the remainder (uses too much memory for size % 128 == 0 but fuck you)
uint32_t *padded = (uint32_t *)malloc(sizeof(uint32_t) * padded_len);
for (size_t i = 0; i < padded_len; i++) {
padded[padded_len] = 0;
}
(void)rsa;
size_t i = 0; size_t i = 0;
while (i < size) while (i < (size + 4)) {
{ /*if (i < 8) {
file[offset + i] = file[offset + i] - 1; printf("%x\n", file[offset+i]);
}*/
size_t j = 0;
size_t tool = i % 4;
int tool2 = 0;
if (tool == 0) {
tool2 = 3;
} else if (tool == 1) {
tool2 = 1;
} else if (tool == 2) {
tool2 = -1;
} else {
tool2 = -3;
}
while (j < 8) {
size_t bit_index = i * 8 + j;
//printf("gonna encrypt index %lu\n", offset + bit_index / 8);
padded[bit_index / 31] += (1 & (file[offset + bit_index / 8 + tool2] >> (7 - j))) << (30 - bit_index % 31);
j++;
}
++i; ++i;
} }
for (size_t i = 0; i < padded_len; i++) {
printf("block : %x\n", padded[i]);
padded[i] = pow_mod(padded[i] + 42 + i, 11317, rsa.n);
printf("encrypted block : %x\n", padded[i]);
printf("decipher block : %lx\n\n", pow_mod(padded[i], rsa.d, rsa.n) - 42 - i);
}
memcpy(&file[offset], padded, padded_len * sizeof(uint32_t));
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(" Size of padded encryption = %ld (%lx)\n", padded_len * sizeof(uint32_t), padded_len * sizeof(uint32_t));
printf("\n");
return offset + padded_len * sizeof(uint32_t);
} }

View File

@ -33,18 +33,19 @@ t_payload *get_payload()
return payload; 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) 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, rsa_t rsa)
{ {
char *ptr_jmp_value = ft_strnstr_nullterminated(payload->payload, JUMP_VALUE, payload->len); 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_woody = ft_strnstr_nullterminated(payload->payload, WOODY, payload->len);
char *ptr_text_section = ft_strnstr_nullterminated(payload->payload, TEXT_OFFSET, payload->len); char *ptr_text_section = ft_strnstr_nullterminated(payload->payload, TEXT_OFFSET, payload->len);
char *ptr_private_key = ft_strnstr_nullterminated(payload->payload, PRIVATE_KEY, payload->len);
char *ptr_section_size = ft_strnstr_nullterminated(payload->payload, SECTION_SIZE, 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) if (ptr_jmp_value && ptr_woody && ptr_text_section && ptr_section_size)
{ {
int32_t woody_index = ptr_woody - payload->payload; int32_t woody_index = ptr_woody - payload->payload;
int32_t jmp_index = ptr_jmp_value - sizeof(JUMP) - 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) int32_t jump_value = ((payload_position + jmp_index + 5 - 1) - e_entry) * -1; // 5 = JUMP SIZE (OPCODE + 4 bytes operand)
ft_memcpy(&payload->payload[jmp_index + 1], &jump_value, sizeof(jump_value)); ft_memcpy(&payload->payload[jmp_index + 1 - 1], &jump_value, sizeof(jump_value));
printf("jump_value = %d (%x)\n", jump_value, jump_value); printf("jump_value = %d (%x)\n", jump_value, jump_value);
printf("jmp_index = %d (%x)\n", jmp_index, jmp_index); printf("jmp_index = %d (%x)\n", jmp_index, jmp_index);
@ -56,9 +57,13 @@ int insert_payload(t_elf_content *woody, t_payload *payload, size_t payload_posi
ft_memcpy(&payload->payload[text_index], &text_value, sizeof(text_value)); ft_memcpy(&payload->payload[text_index], &text_value, sizeof(text_value));
int64_t section_index = ptr_section_size - payload->payload; int64_t section_index = ptr_section_size - payload->payload;
int64_t section_value = p_memsz; int64_t section_value = p_memsz * 33/32 + 1; //woody->text_section->sh_size;
ft_memcpy(&payload->payload[section_index], &section_value, sizeof(section_value)); ft_memcpy(&payload->payload[section_index], &section_value, sizeof(section_value));
int64_t private_key_index = ptr_private_key - payload->payload;
int64_t private_key_value = (rsa.n << 32) + rsa.d;
ft_memcpy(&payload->payload[private_key_index], &private_key_value, sizeof(uint64_t));
ft_memcpy(woody->file + payload_position, payload->payload, payload->len); ft_memcpy(woody->file + payload_position, payload->payload, payload->len);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

74
srcs/primes.c Normal file
View File

@ -0,0 +1,74 @@
#include "../includes/rsa.h"
uint16_t get_random_bytes(int fd) {
uint16_t ret;
if (read(fd, &ret, sizeof(uint16_t)) == -1) {
exit(1);
}
return ret;
}
// n pow e mod m
uint64_t pow_mod(uint64_t n, uint64_t e, uint64_t m) {
uint64_t y = 1;
while (e > 1) {
if (e & 1) {
y = (y * n) % m;
}
n = (n * n) % m;
e = e >> 1;
}
return (n * y) % m;
}
bool is_prime(uint16_t n, size_t k_max, int fd) {
uint16_t a = get_random_bytes(fd);
uint16_t d = n - 1;
uint16_t s = 0;
while ((d & 1) == 0) {
s++;
d = d >> 1;
}
for (size_t k = 0; k < k_max; k++) {
a = 0;
while (a < 2 || a > (n - 2)) {
a = get_random_bytes(fd);
}
uint16_t x = pow_mod(a, d, n);
uint16_t y;
for (uint16_t i = 0; i < s; i++) {
y = pow_mod(x, 2, n);
if (y == 1 && x != 1 && x != n - 1)
return false;
x = y;
}
if (y != 1) {
return false;
}
}
return true;
}
uint16_t generate_prime_fd(int fd) {
uint16_t n = get_random_bytes(fd);
n |= 1 << 15;
n |= 1;
while (!is_prime(n, 16, fd)) {
n = get_random_bytes(fd);
n |= 1 << 15;
n |= 1;
}
return n;
}
uint16_t generate_prime() {
int fd = open("/dev/urandom", O_RDONLY);
uint16_t n = generate_prime_fd(fd);
close(fd);
return n;
}

58
srcs/rsa.c Normal file
View File

@ -0,0 +1,58 @@
#include "../includes/rsa.h"
int64_t euler(int64_t r0, int64_t r1) {
int64_t s0 = 1;
int64_t s1 = 0;
int64_t t0 = 0;
int64_t t1 = 1;
int64_t q0 = 0;
while (r1 != 0) {
q0 = r0 / r1;
int64_t tmp = r0 % r1;
r0 = r1;
r1 = tmp;
tmp = s0 - q0 * s1;
s0 = s1;
s1 = tmp;
tmp = t0 - q0 * t1;
t0 = t1;
t1 = tmp;
}
return s0;
}
rsa_t rsa_generate_keys(void) {
int64_t n = 0;
int64_t p = (uint64_t)generate_prime();
int64_t q = (uint64_t)generate_prime();
int64_t ln = (p - 1) * (q - 1);
int64_t e = 11317;
while (ln % e == 0 || p == q || !(n & (1 << 31))) {
p = generate_prime();
q = generate_prime();
ln = (p - 1) * (q - 1);
n = p * q;
}
if (q > p) {
uint64_t tmp = p;
p = q;
q = tmp;
}
int64_t d = euler(e, ln) + ln;
if (d > n) {
d -= ln;
}
rsa_t rsa;
rsa.d = d;
rsa.n = n;
//rsa.d = 104320933;
//rsa.n = 2959006679;
return rsa;
}

View File

@ -37,6 +37,8 @@ int inject32(t_elf_content *woody)
} }
size_t code_cave_size = elf->Phdr[j].p_offset - (elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz); 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; size_t payload_position = elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz;
rsa_t rsa = rsa_generate_keys();
printf("key n : %ld (%lx) key d %ld (%lx), key total : %ld (%lx)\n", rsa.n, rsa.n, rsa.d, rsa.d, (rsa.n << 32) + rsa.d, (rsa.n << 32) + rsa.d);
if (code_cave_size < (size_t)payload->len) if (code_cave_size < (size_t)payload->len)
{ {
@ -45,9 +47,9 @@ int inject32(t_elf_content *woody)
return ft_put_error("Unable to insert payload, not enough space for code cave"); return ft_put_error("Unable to insert payload, not enough space for code cave");
} }
encrypt(woody->file, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz); payload_position = encrypt(woody->file, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz, rsa);
if (insert_payload(woody, payload, payload_position, elf->text_section->sh_offset, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz)) if (insert_payload(woody, payload, payload_position, elf->text_section->sh_offset, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz, rsa))
{ {
free(payload->payload); free(payload->payload);
free(payload); free(payload);

View File

@ -38,6 +38,8 @@ int inject64(t_elf_content *woody)
size_t code_cave_size = elf->Phdr[j].p_offset - (elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz); 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; size_t payload_position = elf->Phdr[i].p_offset + elf->Phdr[i].p_filesz;
rsa_t rsa = rsa_generate_keys();
printf("key n : %ld (%lx) key d %ld (%lx), key total : %ld (%lx)\n", rsa.n, rsa.n, rsa.d, rsa.d, (rsa.n << 32) + rsa.d, (rsa.n << 32) + rsa.d);
if (code_cave_size < (size_t)payload->len) if (code_cave_size < (size_t)payload->len)
{ {
@ -45,9 +47,10 @@ int inject64(t_elf_content *woody)
free(payload); free(payload);
return ft_put_error("Unable to insert payload, not enough space for code cave"); return ft_put_error("Unable to insert payload, not enough space for code cave");
} }
encrypt(woody->file, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz); payload_position = encrypt(woody->file, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz, rsa);
if (insert_payload(woody, payload, payload_position, elf->Ehdr->e_entry, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz))
if (insert_payload(woody, payload, payload_position, elf->Ehdr->e_entry, elf->Phdr[i].p_offset, elf->Phdr[i].p_memsz, rsa))
{ {
free(payload->payload); free(payload->payload);
free(payload); free(payload);

1
zreset_woody.sh Executable file
View File

@ -0,0 +1 @@
./gen_payload.sh && rm -f woody && ./woody_woodpacker resources/sample64 > log && xxd woody > dump