Skip to content

Instantly share code, notes, and snippets.

@eramax
Created March 18, 2023 21:51
Show Gist options
  • Save eramax/587d123924d105c33d2c51757744e02c to your computer and use it in GitHub Desktop.
Save eramax/587d123924d105c33d2c51757744e02c to your computer and use it in GitHub Desktop.
elf64
#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