The elf in ELF
use 0-day to cheat all disassemblers
@ CyberSEC 2019 david942j
1 . 1
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
@ CyberSEC 2019 david942j
1 . 1
2 . 1
2 . 2
2 . 3
3 . 1
3 . 2
3 . 3
3 . 4
3 . 5
3 . 6
3 . 7
3 . 8
#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
3 . 10
3 . 11
4 . 1
4 . 2
4 . 3
4 . 4
ELF header program header many tables.. executable code .eh_frame .init_array/.fini_array .data/.bss ... .rodata executable data
0x400000 0x600000 0xe08 0x600e08
.dynamic
0x400e08 0x0
ELF file In memory
4 . 5
4 . 6
4 . 7
4 . 8
execve("a.out", ...)
load_libraries elf_dynamic_do_rela (relocation)
kernel space load_elf_binary
load_elf_interp (ld.so) mmap(PT_LOADs) create_elf_tables (AUXV) *phdr, phnum, *entry, *auxv
ld.so#dl_main
4 . 9
4 . 10
4 . 11
4 . 12
4 . 13
ELF header program header many tables.. executable code .eh_frame .init_array/.fini_array .data/.bss ... .rodata executable data
0x400000 0x600000 0xe08 0x600e08
.dynamic
0x400e08 0x0
ELF file In memory
4 . 14
4 . 15
4 . 16
ELF header program header many tables.. executable code .eh_frame .init_array/.fini_array .data ...
0x400000 0x604000 0x0
ELF file In memory fake program header
0x204000 0x4000 0x804000 program header
.data
fake prog. hdr e_phoff
load_addr 4 . 17
4 . 18
4 . 19
4 . 20
4 . 21
4 . 22
4 . 23
4 . 24
4 . 25
lea rdi,[rip+0xba] mov eax,0x0
call 5f0 <scanf@plt> lea rdx,[rbp0xe0] lea rax,[rbp0x70]
int ret = scanf(args);
if(trigger(args)) backdoor(); return ret;
4 . 26
4 . 27
5 . 1
5 . 2
ELF header program header ELF file PT_PHDR ... PT_LOAD PT_LOAD
5 . 3
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
5 . 5
5 . 6
5 . 7
main_map->l_addr = phdr - ph->p_vaddr
main_map->l_ld = main_map->l_addr + ph->p_vaddr
5 . 8
5 . 9
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
main_map->l_addr = phdr - ph->p_vaddr
main_map->l_ld = main_map->l_addr + ph->p_vaddr
main_map->l_addr = phdr - ph->p_vaddr
5 . 11
5 . 12
5 . 13
6 . 1
6 . 2
6 . 3
6 . 4
7 . 1