the elf in elf
play

The elf in ELF use 0-day to cheat all disassemblers david942j @ - PowerPoint PPT Presentation

The elf in ELF use 0-day to cheat all disassemblers david942j @ CyberSEC 2019 1 . 1 This talk Tricks to cheat disassemblers objdump, readelf, IDA Pro, etc. 2 . 1 IDA Pro The best tool for reverse-engineering Take it as examples in this


  1. The elf in ELF use 0-day to cheat all disassemblers david942j @ CyberSEC 2019 1 . 1

  2. This talk Tricks to cheat disassemblers objdump, readelf, IDA Pro, etc. 2 . 1

  3. IDA Pro The best tool for reverse-engineering Take it as examples in this talk 2 . 2

  4. anti-reverse-engineering - What you see is NOT what it really is IDA Pro 2 . 3

  5. Introduction to ELF 3 . 1

  6. ELF Executable and Linkable Format Linux 3 . 2

  7. Header ELF header Section header (not important here) Program header 3 . 3

  8. 3 . 4

  9. ELF header ELF class: 32 / 64-bit arch: x86 / ARM / MIPS .. section / program header 3 . 5

  10. Section header (static linker) ELF .text , .rodata , etc. 3 . 6

  11. Program header Needed Libraries, Segment Permissions, etc. _DYNAMIC table 3 . 7

  12. _DYNAMIC 3 . 8

  13. Example #include <stdio.h> #include <iostream> using std::cout; int main() { char s[100] = {}; scanf("%99s", s); // libc.so.6#scanf cout << "Hello, " << s << "!\n"; // libstdc++.so.6#std::cout return 0; } 3 . 9

  14. _DYNAMIC Need libraries: libc.so.6, libstdc++.so.6 Need functions: scanf & std::cout ld.so _DYNAMIC function 3 . 10

  15. In this talk IDA Pro _DYNAMIC table e.g. IDA Pro printf system 0-day bug in Linux kernel Bug(?) in ld.so 3 . 11

  16. The Linux 0-day bug 4 . 1

  17. PT_LOAD 4 . 2

  18. PT_LOAD Program header PT_LOAD entry ELF memory 4 . 3

  19. PT_LOAD 4 . 4

  20. Memory mapping ELF file In memory 0x0 0x400000 ELF header program header many tables.. executable executable code .rodata .eh_frame 0x400e08 0xe08 ... .init_array/.fini_array 0x600000 .dynamic 0x600e08 .data/.bss data 4 . 5

  21. Linux#execve 4 . 6

  22. linux/fs/binfmt_elf.c#load_elf_binary Read and check ELF header Parse program header PT_INTERP PT_LOAD PT_GNU_STACK Setup AUXV 4 . 7

  23. AUXV AUXiliary Vector interpreter(ld.so) AT_PHDR AT_ENTRY AT_UID ... 4 . 8

  24. Flow of execve execve("a.out", ... ) load_elf_binary mmap(PT_LOADs) kernel space load_elf_interp (ld.so) create_elf_tables (AUXV) *phdr, phnum, *entry, *auxv ld.so#dl_main load_libraries elf_dynamic_do_rela (relocation) 4 . 9

  25. Bug Kernel AT_PHDR 4 . 10

  26. binfmt_elf.c#create_elf_tables 4 . 11

  27. Normally load_addr exec->e_phoff 0x400000 0x40 0x400040 4 . 12

  28. load_addr is The �rst LOADed address 4 . 13

  29. ELF file In memory 0x0 0x400000 ELF header program header many tables.. executable executable code .rodata .eh_frame 0x400e08 0xe08 ... .init_array/.fini_array 0x600000 .dynamic 0x600e08 .data/.bss data 4 . 14

  30. Nobody promises PHDR is located in the �rst PT_LOAD 4 . 15

  31. Put PHDR in the second PT_LOAD 4 . 16

  32. ELF file In memory 0x0 0x400000 ELF header load_addr many tables.. executable code .eh_frame ... .init_array/.fini_array 0x4000 fake program header 0x604000 fake prog. hdr e_phoff .data .data 0x204000 program header 0x804000 program header 4 . 17

  33. Effect Kernel loads binary correctly But kernel cheats ld.so the address of PHDR 4 . 18

  34. ld.so 4 . 19

  35. ld.so ? Load shared libraries Process dynamic relocation 4 . 20

  36. _DYNAMIC 4 . 21

  37. function e.g. printf -> system 4 . 22

  38. 4 . 23

  39. Relocation type 1: scanf scanf@got type 2: put backdoor on scanf@got 4 . 24

  40. relocation table IDA scanf relocate 4 . 25

  41. lea rdi,[rip+0xba] int ret = scanf(args); mov eax,0x0 if ( trigger (args)) call 5f0 <scanf@plt> backdoor (); lea rdx,[rbp­0xe0] return ret; lea rax,[rbp­0x70] 4 . 26

  42. Demo 4 . 27

  43. Let's play ld.so 5 . 1

  44. PT_PHDR in Program header 5 . 2

  45. PT_PHDR points to itself ELF file ELF header program header PT_PHDR PT_LOAD PT_LOAD ... 5 . 3

  46. glibc/elf/rtld.c#1147 for (ph = phdr; ph < &phdr[phnum]; ++ph) switch (ph->p_type) { case PT_PHDR: /* Find out the load address. */ main_map->l_addr = phdr - ph->p_vaddr; break; case PT_DYNAMIC: /* This tells us where to find the dynamic section, which tells us everything we need to do. */ main_map->l_ld = main_map->l_addr + ph->p_vaddr; break; 5 . 4

  47. PT_PHDR ld.so binary ! 5 . 5

  48. the Linux kernel bug Program header for kernel for ld.so 5 . 6

  49. ? ld.so binary 5 . 7

  50. program header PT_PHDR main_map->l_addr = phdr - ph->p_vaddr PT_LOAD PT_LOAD PT_DYNAMIC main_map->l_ld = main_map->l_addr + ph->p_vaddr ... 5 . 8

  51. Use two PT_PHDR s 5 . 9

  52. glibc/elf/rtld.c#1147 for (ph = phdr; ph < &phdr[phnum]; ++ph) switch (ph->p_type) { case PT_PHDR: /* Find out the load address. */ main_map->l_addr = phdr - ph->p_vaddr; break; case PT_DYNAMIC: /* This tells us where to find the dynamic section, which tells us everything we need to do. */ main_map->l_ld = main_map->l_addr + ph->p_vaddr; break; 5 . 10

  53. Two PT_PHDR s PT_PHDR main_map->l_addr = phdr - ph->p_vaddr PT_DYNAMIC main_map->l_ld = main_map->l_addr + ph->p_vaddr PT_PHDR main_map->l_addr = phdr - ph->p_vaddr PT_LOAD PT_LOAD ... 5 . 11

  54. _DYNAMIC relocation 5 . 12

  55. Demo Given two ELFs Looks like A in IDA Pro but actually B 5 . 13

  56. Conclusion 6 . 1

  57. The Linux kernel 0-day bug Kernel calculates PHDR incorrectly ld.so gets wrong address of program header 6 . 2

  58. ld.so ld.so using PT_PHDR for calculating base address Nobody checks correctness of PT_PHDR 6 . 3

  59. _DYNAMIC table 6 . 4

  60. david942j @ 7 . 1

Recommend


More recommend