poke-devel
[Top][All Lists]
Advanced

[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);
```



reply via email to

[Prev in Thread] Current Thread [Next in Thread]