[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Creating a minimal ELF file using poke
From: |
Mohammad-Reza Nabipoor |
Subject: |
Creating a minimal ELF file using poke |
Date: |
Sat, 16 Jul 2022 13:08:57 +0430 |
Hello people!
I've added a new entry to https://pokology.org/fun-with-elf.html article.
`3 Building "Hello, world" from scratch`
It is based on an interesting blog post: https://kevinboone.me/elfdemo.html?i=1
The idea here is to create a valid working ELF executable which runs
on a x86_64 Linux machine.
The following Poke script will create `fun-with-elf.exe` file in your
current directory. You can run in after `chmod +x fun-with-elf.exe`.
I'd be happy to hear your suggestions/reviews/improvements/... :)
BTW we soon don't need functions like `u32off_as_le_bytes` (when I
finished the cast from integers/offsets to byte arrays!)
Regards,
Mohammad-Reza
```poke
load elf;
/* Gives the bytes (little-endian) of a byte-offset of 32-bit width. */
fun u32off_as_le_bytes = (offset<uint32,B> helloworld_adr_num) byte[4]:
{
var helloworld_adr = byte[4] ();
/* Fill `helloworld_adr` array with bytes of `helloworld_adr_num`
in little-endian mode. */
with_temp_ios
:endian ENDIAN_LITTLE
:do lambda void:
{
offset<uint32,B> @ 0#B = helloworld_adr_num;
/* Disentangle the byte array from the temp IOS to make it
normal unmapped array. */
helloworld_adr = unmap (byte[4] @ 0#B);
}
;
return helloworld_adr;
}
set_endian(ENDIAN_LITTLE);
var load_adr = 0x400000UL#B,
epoint_off = 0x78UL#B,
prghdr_off = 0x40UL#B,
sechdr_off = 0xc0UL#B;
// Address of "Hello, World\n" string for the `mov` instruction
var str_adr_bytes = u32off_as_le_bytes (load_adr + 0xa2UL#B);
/* Building the ELF header. */
var ehdr =
Elf64_Ehdr
{
e_ident = Elf_Ident {
// ei_mag = [0x7fUB,'E', 'L', 'F'],
ei_class = 0x02UB, /* 64-bit */
ei_data = 0x01UB, /* little-endian */
ei_version = 0x01UB,
// ei_osabi = 0x0UB,
// ei_abiversion = 0x0UB,
// ei_pad = [0x0UB,0x0UB,0x0UB,0x0UB,0x0UB,0x0UB],
// ei_nident = 0x0UB#B
},
e_type = ET_EXEC,
e_machine = 0x3eUH, /* amd64 architecture */
e_version = 0x1U,
e_entry = load_adr + epoint_off,
e_phoff = prghdr_off,
e_shoff = sechdr_off,
// e_flags = 0x0U,
e_ehsize = Elf64_Ehdr {}'size,
e_phentsize = Elf64_Phdr {}'size,
e_phnum = 0x1UH,
e_shentsize = Elf64_Shdr {}'size,
e_shnum = 0x3UH,
e_shstrndx = 0x2UH
};
/* Constructing the program header. */
var phdr =
Elf64_Phdr
{
p_type = PT_LOAD,
p_flags = Elf_SegmentFlags { flags = PF_X | PF_R },
// p_offset = 0UL#B, // offset within file
p_vaddr = load_adr, // in virtual memory
p_paddr = load_adr, // in physical memory
p_filesz = 0xB0UL#B,
p_memsz = 0xB0UL#B,
p_align = 0x200000UL#B, // alignment boundary for sections
};
/* "Compiling" the program
(x86-64 machine code) */
var program_text = [
// mov 0x01, %rax ; sys_write
0x48UB, 0xc7UB, 0xc0UB, 0x01UB, 0x00UB, 0x00UB, 0x00UB,
// mov 0x01, %rdi ; file descriptor (stdout)
0x48UB, 0xc7UB, 0xc7UB, 0x01UB, 0x00UB, 0x00UB, 0x00UB,
// mov $helloworld_adr, %rsi ; location of string
0x48UB, 0xc7UB, 0xc6UB,
str_adr_bytes[0], str_adr_bytes[1], str_adr_bytes[2], str_adr_bytes[3],
// mov 0x0d,%rdx ; size of string, 13 bytes
0x48UB, 0xc7UB, 0xc2UB, 0x0dUB, 0x00UB, 0x00UB, 0x00UB,
// syscall
0x0fUB, 0x05UB,
// mov 0x3c,$rax ; exit program
0x48UB, 0xc7UB, 0xc0UB, 0x3cUB, 0x00UB, 0x00UB, 0x00UB,
// xor %rdi,%rdi ; exit code, 0
0x48UB, 0x31UB, 0xffUB,
// syscall
0x0fUB, 0x05UB,
// Text "Hello, world\n\0" -- total 14 bytes including the null
'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '\n', '\0',
];
/* Constructing the string table */
var string_table = [
".shstrtab",
".text",
];
/* Constructing the section header table */
var sections = [
Elf64_Shdr {},
Elf64_Shdr
{
sh_name = string_table[0]'size, // offset to the name of the section
sh_type = SHT_PROGBITS, // program data
sh_flags = Elf64_SectionFlags { flags = SHF_ALLOC | SHF_EXECINSTR },
sh_addr = load_adr + epoint_off,
sh_offset = epoint_off,
sh_size = Elf64_Shdr {}'size,
// sh_link = 0U,
// sh_info = 0U,
sh_addralign = 1UL,
// sh_entsize = 0UL#B,
},
Elf64_Shdr
{
sh_name = 0UL#B,
sh_type = SHT_STRTAB,
sh_flags = Elf64_SectionFlags {},
// sh_addr = 0,
sh_offset = 0xB0UL#B,
sh_size = 0x10UL#B,
// sh_link = 0U,
// sh_info = 0U,
sh_addralign = 1UL,
// sh_entsize = 0UL#B,
},
];
/* Putting it all together */
var fd = open ("*elf*");
var off = 0UL#B;
Elf64_Ehdr @ off = ehdr;
off += ehdr'size;
Elf64_Phdr @ off = phdr;
off += phdr'size;
byte[] @ off = program_text;
off += program_text'size;
string[] @ off = string_table;
off += string_table'size;
Elf64_Shdr[] @ off = sections;
off += sections'size;
save :ios fd
:file "fun-with-elf.exe"
:from 0#B
:size off
:append 0
;
close (fd);
```
- Creating a minimal ELF file using poke,
Mohammad-Reza Nabipoor <=