Skip to content

Instantly share code, notes, and snippets.

@ShinyaKato
Created May 5, 2019 17:09
Show Gist options
  • Save ShinyaKato/99cce502591919ae6e26fa4bf564b89d to your computer and use it in GitHub Desktop.
Save ShinyaKato/99cce502591919ae6e26fa4bf564b89d to your computer and use it in GitHub Desktop.
ELF (executable) generation example
// $ gcc gen_hello.c -o gen_hello
// $ ./gen_hello
// $ ./hello
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#define SEGMENTS 1
#define SEG_EXEC 0
Elf64_Ehdr ehdr;
Elf64_Phdr phdr[SEGMENTS];
uint8_t text[] = {
// hello
0x48, 0x89, 0xe5, // mov %rsp, %rbp
0xc6, 0x45, 0xf4, 0x48, // movb $72, -12(%rbp)
0xc6, 0x45, 0xf5, 0x65, // movb $101, -11(%rbp)
0xc6, 0x45, 0xf6, 0x6c, // movb $108, -10(%rbp)
0xc6, 0x45, 0xf7, 0x6c, // movb $108, -9(%rbp)
0xc6, 0x45, 0xf8, 0x6f, // movb $111, -8(%rbp)
0xc6, 0x45, 0xf9, 0x20, // movb $32, -7(%rbp)
0xc6, 0x45, 0xfa, 0x57, // movb $87, -6(%rbp)
0xc6, 0x45, 0xfb, 0x6f, // movb $111, -5(%rbp)
0xc6, 0x45, 0xfc, 0x72, // movb $114, -4(%rbp)
0xc6, 0x45, 0xfd, 0x6c, // movb $108, -3(%rbp)
0xc6, 0x45, 0xfe, 0x64, // movb $100, -2(%rbp)
0xc6, 0x45, 0xff, 0x0a, // movb $10, -1(%rbp)
0x48, 0xc7, 0xc2, 0x0c, 0x00, 0x00, 0x00, // mov $12, %rdx
0x48, 0x8d, 0x75, 0xf4, // lea -12(%rbp), %rsi
0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, // mov $1, %rdi
0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, // mov $1, %rax
0x0f, 0x05, // syscall
0x48, 0xc7, 0xc7, 0x00, 0x00, 0x00, 0x00, // mov $0, %rdi
0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, // mov $60, %rax
0x0f, 0x05, // syscall
};
int main(void) {
Elf64_Off offset_phdr = sizeof(ehdr);
Elf64_Off offset_text = sizeof(ehdr) + sizeof(phdr);
Elf64_Addr entry = 0x400000 + offset_text;
uint64_t align = 0x200000;
ehdr.e_ident[0] = ELFMAG0;
ehdr.e_ident[1] = ELFMAG1;
ehdr.e_ident[2] = ELFMAG2;
ehdr.e_ident[3] = ELFMAG3;
ehdr.e_ident[4] = ELFCLASS64;
ehdr.e_ident[5] = ELFDATA2LSB;
ehdr.e_ident[6] = EV_CURRENT;
ehdr.e_ident[7] = ELFOSABI_NONE;
ehdr.e_type = ET_EXEC;
ehdr.e_machine = EM_X86_64;
ehdr.e_version = EV_CURRENT;
ehdr.e_entry = entry;
ehdr.e_phoff = offset_phdr;
ehdr.e_ehsize = sizeof(Elf64_Ehdr);
ehdr.e_phentsize = sizeof(Elf64_Phdr);
ehdr.e_phnum = SEGMENTS;
phdr[SEG_EXEC].p_type = PT_LOAD;
phdr[SEG_EXEC].p_flags = PF_R | PF_X;
phdr[SEG_EXEC].p_offset = offset_text;
phdr[SEG_EXEC].p_vaddr = entry;
phdr[SEG_EXEC].p_paddr = entry;
phdr[SEG_EXEC].p_filesz = sizeof(text);
phdr[SEG_EXEC].p_memsz = sizeof(text);
phdr[SEG_EXEC].p_align = align;
FILE *out = fopen("hello", "wb");
fwrite(&ehdr, sizeof(ehdr), 1, out);
fwrite(&phdr, sizeof(phdr), 1, out);
fwrite(&text, sizeof(text), 1, out);
fclose(out);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment