Kto widział moją binarkę?

SEConference 2013 - Maciej Kotowicz / @maciekkotowicz

Samolans

  • Student ii@Uwr
  • Wykladowca ii@Uwr
  • Bezpiecznik @ WCSS
  • oper @ CERT Polska
  • DragonSector CTF Team
  • Reverse Engineer/Exploit dev etc..etc..

Plan zajec

  • Wstep
  • Wprowadzenie
  • egzekucja - zajrzyjmy pod maske
  • ELF - male pokraczne stworzonka
  • SELF - demon z przeszlosci
  • pySELF - lepsze jutro ;]
  • Zakonczenie

Motywacja

Daive Aitel:

Occasionally, or "all the time", depending on how often you hack and what you hack, you'll run into a system or situation where you can't upload and execute your kernel exploit! Selinux? Non-exec mounts? This is very frustrating! You pound the table, gnash your teeth, and curse in the little Mandarin you know.

sys_execve

  1. open_exec
  2. prepare_binprm
  3. copy_strings
  4. search_binary_handler
  5. load_elf_binary

Executable Linkable Format

EHdr


typedef struct
{
  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
  Elf32_Half	e_type;			/* Object file type */
  Elf32_Half	e_machine;		/* Architecture */
  Elf32_Word	e_version;		/* Object file version */
  Elf32_Addr	e_entry;		/* Entry point virtual address */
  Elf32_Off	e_phoff;		/* Program header table file offset */
  Elf32_Off	e_shoff;		/* Section header table file offset */
  Elf32_Word	e_flags;		/* Processor-specific flags */
  Elf32_Half	e_ehsize;		/* ELF header size in bytes */
  Elf32_Half	e_phentsize;		/* Program header table entry size */
  Elf32_Half	e_phnum;		/* Program header table entry count */
  Elf32_Half	e_shentsize;		/* Section header table entry size */
  Elf32_Half	e_shnum;		/* Section header table entry count */
  Elf32_Half	e_shstrndx;		/* Section header string table index */
} Elf32_Ehdr;

				  
[mak@asdf pyload]$ readelf -h foo-64 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400e30
  Start of program headers:          64 (bytes into file)
  Start of section headers:          768280 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         5
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 28

				  

PHdr


typedef struct
{
  Elf32_Word	p_type;			/* Segment type */
  Elf32_Off	p_offset;		/* Segment file offset */
  Elf32_Addr	p_vaddr;		/* Segment virtual address */
  Elf32_Addr	p_paddr;		/* Segment physical address */
  Elf32_Word	p_filesz;		/* Segment size in file */
  Elf32_Word	p_memsz;		/* Segment size in memory */
  Elf32_Word	p_flags;		/* Segment flags */
  Elf32_Word	p_align;		/* Segment alignment */
} Elf32_Phdr;

				  

PT_TYPE



#define	PT_NULL		0		/* Program header table entry unused */
#define PT_LOAD		1		/* Loadable program segment */
#define PT_DYNAMIC	2		/* Dynamic linking information */
#define PT_INTERP	3		/* Program interpreter */
#define PT_NOTE		4		/* Auxiliary information */
#define PT_SHLIB	5		/* Reserved */
#define PT_PHDR		6		/* Entry for header table itself */
#define PT_TLS		7		/* Thread-local storage segment */
#define	PT_NUM		8		/* Number of defined types */
#define PT_LOOS		0x60000000	/* Start of OS-specific */
#define PT_GNU_EH_FRAME	0x6474e550	/* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK	0x6474e551	/* Indicates stack executability */
#define PT_GNU_RELRO	0x6474e552	/* Read-only after relocation */
				  
[mak@asdf pyload]$ readelf -l foo-64 

Elf file type is EXEC (Executable file)
Entry point 0x400e30
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000b9ee8 0x00000000000b9ee8  R E    200000
  LOAD           0x00000000000ba000 0x00000000006ba000 0x00000000006ba000
                 0x0000000000001790 0x0000000000003f98  RW     200000
  NOTE           0x0000000000000158 0x0000000000400158 0x0000000000400158
                 0x0000000000000044 0x0000000000000044  R      4
  TLS            0x00000000000ba000 0x00000000006ba000 0x00000000006ba000
                 0x0000000000000020 0x0000000000000050  R      8
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     8
				  
[mak@asdf pyload]$ readelf -l /usr/bin/id

Elf file type is EXEC (Executable file)
Entry point 0x40204c
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000006e3c 0x0000000000006e3c  R E    200000
  LOAD           0x0000000000007e08 0x0000000000607e08 0x0000000000607e08
                 0x0000000000000498 0x00000000000006c0  RW     200000
  DYNAMIC        0x0000000000007e20 0x0000000000607e20 0x0000000000607e20
                 0x00000000000001d0 0x00000000000001d0  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000061cc 0x00000000004061cc 0x00000000004061cc
                 0x000000000000026c 0x000000000000026c  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     8
  GNU_RELRO      0x0000000000007e08 0x0000000000607e08 0x0000000000607e08
                 0x00000000000001f8 0x00000000000001f8  R      1
				  

RTFS - /usr/include/elf.h
ABI V - www.sco.com/developers/gabi/

ul_exec

the_grugq

http://grugq.github.io/docs/ul_exec.txt

SELF

Pluf & Ripe

phrack-0x3f-0x0b

SELF

  [ Autoloadable and Autoexecutable Object ]
.------------------------------------------------
|
|       [ Static Executable File (1) ]
|    .--------------------------------.
|    |                                |
|    |    .----------------------.    |
|    |    | ELF Header )---------|----|--.
|    |    |----------------------|    |  | Shellcode Elf loader (3)
|    |    | Program Header Table |    |  | hdr->e_ident[9]
|    |    |                      |    |  |
|    |    | + PT_LOAD0           |    |  |
|    |    | + PT_LOAD1           |    |  |
|    |    |     ...              |    |  |
|    |    |     ...              |    |  |
|    |    | + PT_STACK )---------|----|--|--.
|    |    |                      |    |  |  | Stack Context (2)
|    |    |----------------------|    |  |  |
|    |    | Sections (code/data) |    |  |  |
|    '--> |----------------------| <--'  |  |
|    .--> |######################| <-----'  |
|    |    |## SHELLCODE LOADER ##|          |
|  P |    |######################|          |
|  A |    |                      |          |
|  G |    |       .......        |          |
|  E |    |       .......        |          |
|    |    |                      |          |
|    |    |######################| <--------'
|    |    |#### STACK CONTEXT ###|
|    |    |######################|
|    '--> '----------------------'
|
'-----------------
				      

SELF

  1. sparsowac elfa
  2. zmmapowc ET_LOAD
  3. stworzyc stos - liste argumentow/srodowsko
  4. odalic _start

1. sparsowac elfa

2. zmmapowc ET_LOAD

3. stworzyc stos

4. opalic _start

Niespodzianka

ELF - AUXV

Auxiliary Vector


typedef struct
{
  uint32_t a_type;		/* Entry type */
  union
    {
      uint32_t a_val;		/* Integer value */
      /* We use to have pointer elements added here.  We cannot do that,
	 though, since it does not work when using 32-bit definitions
	 on 64-bit platforms and vice versa.  */
    } a_un;
} Elf32_auxv_t;
				  

.a_type: AT_SYSINFO_EHDR | .a_val: 0x7ffff7ffa000
.a_type: AT_HWCAP | .a_val: 0xbfebfbff
.a_type: AT_PAGESZ | .a_val: 0x1000
.a_type: AT_CLKTCK | .a_val: 0x64
.a_type: AT_PHDR | .a_val: 0x400040
.a_type: AT_PHENT | .a_val: 0x38
.a_type: AT_PHNUM | .a_val: 0x9
.a_type: AT_BASE | .a_val: 0x7ffff7ddb000
.a_type: AT_FLAGS | .a_val: 0x0
.a_type: AT_ENTRY | .a_val: 0x40204c
.a_type: AT_UID | .a_val: 0x3e8
.a_type: AT_EUID | .a_val: 0x3e8
.a_type: AT_GID | .a_val: 0x3e8
.a_type: AT_EGID | .a_val: 0x3e8
.a_type: AT_SECURE | .a_val: 0x0
.a_type: AT_RANDOM | .a_val: 0x7fffffffebf9
.a_type: AT_EXECFN | .a_val: 0x7fffffffefec
.a_type: AT_PLATFORM | .a_val: 0x7fffffffec09
				    

pySELF


import sys,os
from ctypes import *
libc = CDLL("libc.so.6")
CFUNC = CFUNCTYPE(c_int,c_void_p)
MYSELF = os.path.abspath(os.path.expanduser(__file__))
sys.path.append(os.path.dirname(MYSELF))
from builder import Builder
b = Builder('./foo'+sys.argv[1],['a','b','c'],["PATH=/tmp/",'EVIL=dupa'])
payload = b.payload()
lpayload = (len(payload) + 0x1000) & ~(0x1000-1)
libc.mmap.restype = c_void_p
addr = libc.mmap(0,lpayload,7,0x22,0,0)
addr = c_void_p(addr)
libc.memcpy(addr,payload,len(payload))
cfun = cast(addr,CFUNC)
cfun(addr)
exit()
				  

pySELF

+------------------------+
|                        |
|  SHELLCODE x86/x64     |
|                        |
+------------------------+
| +---------------+      |
| |  chunk0 type  |      |
| +---------------+      |
| |               |<--+  |
| | chunk0 data   |   |  |
| |               |chunk0|
| +---------------+      |
| | chunk1 type   |      |
| +---------------+      |
| |      +        |      |
| |      +        |      |
| |               |      |
| |      +        |      |
| |      +        |      |
| |               |      |
| |      +        |      |
| |      +       +|      |
| |+--------------+      |
| |  chunkN type  |      |
| +---------------+      |
| |               |<--+  |
| | chunkN data   |   |  |
| |               |chunkN|
| +---------------+      |
+-----------------------+
				      
 LOAD_TYPE  = 1
 STACK_TYPE = 2
 ENTRY_TYPE = 3

            +----------+
+---------+ |STACK_TYPE|
|LOAD_TYPE| +----------+
+---------+ |STACK_PROT|
|LOAD_PROT| +----------+
+---------+ |ARGV_SIZE | +----------+
|  SIZE   | +----------+ |ENTRY_TYPE|
+---------+ |ENVP_SIZE | +----------+
|  VADDR  | +----------+ | E_ENTRY  |
+---------+ | OFFSETS  | +----------+
|         | +----------+
|  DATA   | | AUXVEC   |
|         | |          |
|         | +----------+
+---------+ |          |
            |  ARGV    |
            |   +      |
            |  ENVP    |
            +----------+
 					

pySELF

DEMO

github.com/mak/pyself

Q & A

rekrutacja@nask.pl