Upgrade to Pro — share decks privately, control downloads, hide ads and more …

blinkroot - HITCON 2015 writeup

Dhaval Kapil
October 12, 2017

blinkroot - HITCON 2015 writeup

Dhaval Kapil

October 12, 2017
Tweet

More Decks by Dhaval Kapil

Other Decks in Education

Transcript

  1. blinkroot HITCON 2015

  2. Challenge overview • blinkroot (64 bit dynamically linked executable) •

    libc
  3. Challenge overview read(0, &global_arr, 0x400); // char global_arr[0x400]; close(0); close(1);

    close(2); int index = *(int64_t *)global_arr; global_arr[index] = *(int64_t *)(global_arr + 8); puts(global_arr[16]);
  4. ELF Symbols typedef struct { uint32_t st_name; /* Offset into

    the corresponding table's string table */ unsigned char st_info; /* Symbol type and binding attributes */ unsigned char st_other; /* Symbol visibility */ uint16_t st_shndx; /* Each symbol is defined for a particular section */ Elf64_Addr st_value; /* Either an address or offset */ uint64_t st_size; /* Size of the actual reference */ } Elf64_Sym; /* A single entry in any of the symbol table */
  5. ELF Symbols • .symtab - Used mainly for debugging and

    linking. Not needed for program execution, can be stripped. Each entry’s st_name is an offset in .strtab • .dynsym - Contains references to external sources (shared libraries). Used by the dynamic linker to resolve references at run time. Each entry’s st_name is an offset into .dynstr
  6. ELF Symbols

  7. ELF Relocations • Relocation entries help in patching binaries during

    dynamic linking typedef struct { Elf64_Addr r_offset; // The address that requires to be relocated uint64_t r_info; // Index into symbol table + type of relocation } Elf64_Rel;
  8. ELF Relocations

  9. Dynamic Section • Dynamic section entries list out the various

    dynamic sections entries present in ELF. typedef struct { Elf32_Sword d_tag; // What kind of section is this? STRTAB, SYMTAB, etc. union { Elf32_Word d_val; Elf32_Addr d_ptr; } d_un; } Elf32_Dyn;
  10. Dynamic Section

  11. Dynamic linking process • Dynamic linker is loaded • It

    handles it’s own relocation • Loads needed shared libraries (recursively) • For every ELF file loaded, it creates an array of ‘link_map’ structures. (The first entry being of the executable binary itself)
  12. link_map struct struct link_map { ElfW(Addr) l_addr; /* Base address

    shared object is loaded at. */ … struct link_map *l_next, *l_prev; /* Chain of loaded objects. */ ... ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM]; /* Holds pointers to dynamic section entries of string table(l_info[DT_STRTAB], symbol table (l_info[DT_SYMTAB]), relocation table (l_info[DT_JMPREL]), etc */ ... };
  13. Global Offset Table (Each entry is 8 byte) GOT[0] -

    points to the ‘dymanic section’ of the executable GOT[1] - points to the first element of link_map structure array GOT[2] - points to _dl_runtime_resolve() GOT[3] .. onwards relocation entries for external functions
  14. Dynamic linking of external function ‘func’ • Corresponding ‘func@plt’ is

    called • [func@plt] ‘func@plt’ jumps to GOT entry for func • [func@plt] Initially GOT entry points to next instruction in ‘func@plt’ • [func@plt] Pushes an offset (index of ‘func’ in .rel.plt) on stack • [func@plt] Jump to a common stub in ‘plt’ section • [common@plt] Pushes GOT[1] (ptr to link_map) on stack • [common@plt] Jump to GOT[2] (__dl_runtime_resolve()) Stack has the relocation entry offset and address of link_map structure array. __dl_runtime_resolve() calls _dl_fixup() with these two as parameters
  15. Dynamic linking of external function ‘func’

  16. _dl_fixup() • Retrieves symbol table, string table and relocation table

    from the first link map’s l->l_info. • Retrieves the particular relocation entry in the table using the relocation offset • Relocation entry gives symbol table entry, which gives offset into the string table for the name of the symbol • Computes the address to be patched as: l->l_addr (the load address for the ELF) + reloc->r_offset (the address within the ELF to be patched) • Search for the symbol by name in shared libraries and patch the corresponding address calculated. • Also return the address that has been resolved
  17. None
  18. Problem • No leak • Cannot make link map’s next

    pointer to libc library.
  19. Trick ……….

  20. Trick • Craft symbol entry such that flow goes into

    ‘else’ • The target value written is l->l_addr + sym->st_value • Make symbol entry point to some address already resolved by libc, say ‘read’ address in GOT (such that sym->st_value = address of read) • Make relocation entry point to appropriate index into symbol table containing ‘read’ • Setup l_addr with (offset_system - offset_read) so that instead of read’s address, system’s address is returned. • puts will be resolved to system!
  21. https://gist.github.com/DhavalKapil/4dbb49dd72e0ac1e5c4191d108b05ccc [Complete Exploit] https://www.usenix.org/node/190923 [Related reading]