Created
March 18, 2023 21:51
-
-
Save eramax/587d123924d105c33d2c51757744e02c to your computer and use it in GitHub Desktop.
elf64
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <sys/mman.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <sys/stat.h> | |
#include <sys/mman.h> | |
#include <elf.h> | |
const char *r64_str[] = { | |
"rax", | |
"rcx", | |
"rdx", | |
"rbx", | |
"rsp", | |
"rbp", | |
"rsi", | |
"rdi", | |
"r8", | |
"r9", | |
"r10", | |
"r11", | |
"r12", | |
"r13", | |
"r14", | |
"r15"}; | |
typedef enum | |
{ | |
RAX = 0, | |
RCX = 1, | |
RDX = 2, | |
RBX = 3, | |
RSP = 4, | |
RBP = 5, | |
RSI = 6, | |
RDI = 7, | |
R8 = 8, | |
R9 = 9, | |
R10 = 10, | |
R11 = 11, | |
R12 = 12, | |
R13 = 13, | |
R14 = 14, | |
R15 = 15 | |
} RG64; | |
typedef enum | |
{ | |
EAX = 0, | |
ECX = 1, | |
EDX = 2, | |
EBX = 3, | |
ESP = 4, | |
EBP = 5, | |
ESI = 6, | |
EDI = 7 | |
} RG32; | |
typedef enum | |
{ | |
AX = 0, | |
CX = 1, | |
DX = 2, | |
BX = 3, | |
SP = 4, | |
BP = 5, | |
SI = 6, | |
DI = 7 | |
} RG16; | |
typedef enum | |
{ | |
AL = 0, | |
CL = 1, | |
DL = 2, | |
BL = 3, | |
AH = 4, | |
CH = 5, | |
DH = 6, | |
BH = 7 | |
} RG8; | |
void mov_r64_imm64(RG64 register_id, uint64_t value, uint8_t **machine_code) | |
{ | |
**machine_code = 0x48 + (register_id >= RSP); | |
(*machine_code)[1] = 0xb8 + (register_id % 8); | |
*((uint64_t *)(*machine_code + 2)) = value; | |
*machine_code += 10; | |
} | |
void mov_r32_imm32(RG32 register_id, uint32_t value, uint8_t **machine_code) | |
{ | |
**machine_code = 0xb8 + register_id; | |
*((uint32_t *)(*machine_code + 1)) = value; | |
*machine_code += 5; | |
} | |
void end_app(uint32_t exit_code, uint8_t **machine_code) | |
{ | |
mov_r32_imm32(EAX, 0x3c, machine_code); | |
(*machine_code)[0] = 0x48; // xor ebx, ebx | |
(*machine_code)[1] = 0x31; | |
(*machine_code)[2] = 0xff; | |
(*machine_code)[3] = 0x0f; // int 0x80 | |
(*machine_code)[4] = 0x05; | |
*machine_code += 4; | |
} | |
void generate_elf64_file(uint8_t *program, size_t program_size, const char *filename, Elf64_Addr entry_point) | |
{ | |
size_t padding_size = entry_point - (sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr)); | |
uint8_t padding[padding_size]; | |
for (size_t i = 0; i < padding_size; ++i) padding[i] = 0; | |
Elf64_Ehdr elf_hdr = { | |
.e_ident = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV}, | |
.e_type = ET_EXEC, | |
.e_machine = EM_X86_64, | |
.e_version = EV_CURRENT, | |
.e_entry = entry_point, | |
.e_phoff = sizeof(Elf64_Ehdr), | |
.e_ehsize = sizeof(Elf64_Ehdr), | |
.e_phentsize = sizeof(Elf64_Phdr), | |
.e_phnum = 1, | |
.e_shentsize = 0x40}; | |
Elf64_Phdr program_hdr = { | |
.p_type = PT_LOAD, | |
.p_flags = PF_X | PF_R, | |
.p_offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) + padding_size, | |
.p_vaddr = entry_point, | |
.p_filesz = program_size, | |
.p_memsz = program_size, | |
.p_align = 0x1000, | |
}; | |
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); | |
if (fd == -1) | |
{ | |
perror("open"); | |
exit(EXIT_FAILURE); | |
} | |
write(fd, &elf_hdr, sizeof(Elf64_Ehdr)); | |
write(fd, &program_hdr, sizeof(Elf64_Phdr)); | |
write(fd, padding, padding_size); | |
write(fd, program, program_size); | |
close(fd); | |
printf("program_size = 0x%lx\n", program_size); | |
} | |
int main() | |
{ | |
size_t code_size = 1024; | |
uint8_t *mem_ptr; | |
mem_ptr = mmap(NULL, code_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
if (mem_ptr == MAP_FAILED) | |
printf("mmap failed"); | |
uint8_t *mem_start = mem_ptr; | |
mov_r64_imm64(RAX, 0xFFFF, &mem_ptr); | |
mov_r64_imm64(RBX, 0x1234567890ABCDEF, &mem_ptr); | |
mov_r64_imm64(RCX, 0xCCCCCCCCCCCCCCC, &mem_ptr); | |
mov_r32_imm32(EAX, 0x123456, &mem_ptr); | |
mov_r32_imm32(EDX, 0x222222, &mem_ptr); | |
mov_r32_imm32(ECX, 0x12345678, &mem_ptr); | |
end_app(0, &mem_ptr); | |
// Add a 'ret' instruction | |
//*mem_ptr = 0xC3; | |
code_size = mem_ptr - mem_start + 1; | |
printf("Generated machine code, size = %d B", code_size); | |
uint8_t i = 0; | |
for (uint8_t *ptr = mem_start; ptr <= mem_ptr; ptr++, i++) | |
{ | |
if (*ptr == 0x48 || *ptr == 0x49 || *ptr == 0xC3 || i % 10 == 0) | |
printf("\n%p: %02X ", ptr, *ptr); | |
else | |
printf("%02X ", *ptr); | |
} | |
printf("\n"); | |
generate_elf64_file(mem_start, code_size, "f2", 0x10080); | |
// Create a function pointer and execute the code | |
// uint64_t (*func)() = (uint64_t (*)()) mem_ptr; | |
// func(); | |
// Cleanup | |
munmap(mem_ptr, code_size); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment