\[ \definecolor{data}{RGB}{18,110,213} \definecolor{unknown}{RGB}{217,86,16} \definecolor{learned}{RGB}{175,114,176} \]

ELFie brudne sztuczki

Maciej Kotowicz

Intro

$ whois mak

Kwestionariusz

  • Google: elves dirty tricks

Kwestionariusz

  • Google: elves dirty tricks

Kwestionariusz

  • Google: elves dirty tricks
  • Kto analizowal jakiegos ELFa?

Kwestionariusz

  • Google: elves dirty tricks
  • Kto analizowal jakiegos ELFa?
  • Kto analizowal jakis ELFi malware?

Kwestionariusz

  • Google: elves dirty tricks
  • Kto analizowal jakiegos ELFa?
  • Kto analizowal jakis ELFi malware?
  • Kto napisał własny ELFi parser?

Kwestionariusz

  • Google: elves dirty tricks
  • Kto analizowal jakiegos ELFa?
  • Kto analizowal jakis ELFi malware?
  • Kto napisał własny ELFi parser?
  • Kto napisał własny loader dla ELFa

Executable Linkable Format

why?

jakas reklama - My attack are extremely powerful now – now average 700-800Gbps krebs - 665 Gigabits

Executable Linkable Format

Typy

/* Type for a 16-bit quantity.  */
typedef uint16_t Elf32_Half;
typedef uint16_t Elf64_Half;

/* Types for signed and unsigned 32-bit quantities.  */
typedef uint32_t Elf32_Word;
typedef int32_t  Elf32_Sword;
typedef uint32_t Elf64_Word;
typedef int32_t  Elf64_Sword;

/* Types for signed and unsigned 64-bit quantities.  */
typedef uint64_t Elf32_Xword;
typedef int64_t  Elf32_Sxword;
typedef uint64_t Elf64_Xword;
typedef int64_t  Elf64_Sxword;

Typy (cd.)


/* Type of addresses.  */
typedef uint32_t Elf32_Addr;
typedef uint64_t Elf64_Addr;

/* Type of file offsets.  */
typedef uint32_t Elf32_Off;
typedef uint64_t Elf64_Off;

EHDR32

#define EI_NIDENT (16)

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;

EHDR64

#define EI_NIDENT (16)

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

PHDR32

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;

PHDR64

typedef struct
{
  Elf64_Word    p_type;         /* Segment type */
  Elf64_Word    p_flags;        /* Segment flags */
  Elf64_Off     p_offset;       /* Segment file offset */
  Elf64_Addr    p_vaddr;        /* Segment virtual address */
  Elf64_Addr    p_paddr;        /* Segment physical address */
  Elf64_Xword   p_filesz;       /* Segment size in file */
  Elf64_Xword   p_memsz;        /* Segment size in memory */
  Elf64_Xword   p_align;        /* Segment alignment */
} Elf64_Phdr;

Typy Segemntów

#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

SHDR32

typedef struct
{
  Elf32_Word    sh_name;        /* Section name (string tbl index) */
  Elf32_Word    sh_type;        /* Section type */
  Elf32_Word    sh_flags;       /* Section flags */
  Elf32_Addr    sh_addr;        /* Section virtual addr at execution */
  Elf32_Off sh_offset;      /* Section file offset */
  Elf32_Word    sh_size;        /* Section size in bytes */
  Elf32_Word    sh_link;        /* Link to another section */
  Elf32_Word    sh_info;        /* Additional section information */
  Elf32_Word    sh_addralign;       /* Section alignment */
  Elf32_Word    sh_entsize;     /* Entry size if section holds table */
} Elf32_Shdr;

SHDR64

typedef struct
{
  Elf64_Word    sh_name;        /* Section name (string tbl index) */
  Elf64_Word    sh_type;        /* Section type */
  Elf64_Xword   sh_flags;       /* Section flags */
  Elf64_Addr    sh_addr;        /* Section virtual addr at execution */
  Elf64_Off sh_offset;      /* Section file offset */
  Elf64_Xword   sh_size;        /* Section size in bytes */
  Elf64_Word    sh_link;        /* Link to another section */
  Elf64_Word    sh_info;        /* Additional section information */
  Elf64_Xword   sh_addralign;       /* Section alignment */
  Elf64_Xword   sh_entsize;     /* Entry size if section holds table */
} Elf64_Shdr;

Typy Sekcji

#define SHT_NULL      0     /* Section header table entry unused */
#define SHT_PROGBITS   1     /* Program data */
#define SHT_SYMTAB     2     /* Symbol table */
#define SHT_STRTAB     3     /* String table */
#define SHT_RELA      4     /* Relocation entries with addends */
#define SHT_HASH      5     /* Symbol hash table */
#define SHT_DYNAMIC    6     /* Dynamic linking information */
#define SHT_NOTE      7     /* Notes */
#define SHT_NOBITS    8     /* Program space with no data (bss) */
#define SHT_REL       9     /* Relocation entries, no addends */
#define SHT_SHLIB     10        /* Reserved */
#define SHT_DYNSYM     11        /* Dynamic linker symbol table */
#define SHT_INIT_ARRAY    14        /* Array of constructors */
#define SHT_FINI_ARRAY    15        /* Array of destructors */
#define SHT_PREINIT_ARRAY 16        /* Array of pre-constructors */
...
#define SHT_GNU_HASH   0x6ffffff6    /* GNU-style hash table.  */

DYN32

typedef struct
{
  Elf32_Sword   d_tag;          /* Dynamic entry type */
  union
    {
      Elf32_Word d_val;         /* Integer value */
      Elf32_Addr d_ptr;         /* Address value */
    } d_un;
} Elf32_Dyn;

DYN32


typedef struct
{
  Elf64_Sxword  d_tag;          /* Dynamic entry type */
  union
    {
      Elf64_Xword d_val;        /* Integer value */
      Elf64_Addr d_ptr;         /* Address value */
    } d_un;
} Elf64_Dyn;

DT_*

/* Legal values for d_tag (dynamic entry type).  */
#define DT_NULL     0       /* Marks end of dynamic section */
#define DT_NEEDED    1       /* Name of needed library */
#define DT_PLTRELSZ 2       /* Size in bytes of PLT relocs */
#define DT_PLTGOT    3       /* Processor defined value */
#define DT_HASH      4       /* Address of symbol hash table */
#define DT_STRTAB    5       /* Address of string table */
#define DT_SYMTAB    6       /* Address of symbol table */
...
#define DT_SONAME   14      /* Name of shared object */
#define DT_RPATH    15      /* Library search path (deprecated) */
...
#define DT_PLTREL   20      /* Type of reloc in PLT */
#define DT_DEBUG    21      /* For debugging; unspecified */
#define DT_TEXTREL  22      /* Reloc might modify .text */
#define DT_JMPREL    23      /* Address of PLT relocs */
...

SYM32

typedef struct
{
  Elf32_Word    st_name;        /* Symbol name (string tbl index) */
  Elf32_Addr    st_value;       /* Symbol value */
  Elf32_Word    st_size;        /* Symbol size */
  unsigned char st_info;        /* Symbol type and binding */
  unsigned char st_other;       /* Symbol visibility */
  Elf32_Section st_shndx;       /* Section index */
} Elf32_Sym;

SYM64

typedef struct
{
  Elf64_Word    st_name;        /* Symbol name (string tbl index) */
  unsigned char st_info;        /* Symbol type and binding */
  unsigned char st_other;       /* Symbol visibility */
  Elf64_Section st_shndx;       /* Section index */
  Elf64_Addr    st_value;       /* Symbol value */
  Elf64_Xword   st_size;        /* Symbol size */
} Elf64_Sym;

Jeden bajt by nimi rządzic

Słowo o importach

mak@phun> readelf -d x
Dynamic section at offset 0xbb340 contains 29 entries:
Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libgmp.so.10]
0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED)             Shared library: [libffi.so.6]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
[..]
0x0000000000000015 (DEBUG)              0x0
0x0000000000000003 (PLTGOT)             0x6bb568
0x0000000000000002 (PLTRELSZ)           2760 (bytes)
[..]
0x0000000000000000 (NULL)               0x0

Dynamic section at offset 0xbb340 contains 29 entries:
    Tag        Type                         Name/Value
    0x0000000000000001 (NEEDED)             Shared library: [libgmp.so.10]
    0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
    0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
    0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
    0x0000000000000001 (NEEDED)             Shared library: [libffi.so.6]
    0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
[..]

import sys, elf
from struct import unpack, pack
e = elf.Elf(sys.argv[1])
for p in e.phdrs:
    if p.type == 'PT_DYNAMIC':
        break
dyva = p.p_vaddr
strtab = e.dynamic['DT_STRTAB']
dstrtab_off = dyva + 0x10 * (e.dynamic.off - 1)
strtab_d = e.read(strtab,0x100)
x = e.dynamic['DT_DEBUG']
ddebug = dyva + 0x10 * ( e.dynamic.off - 1)
print 'your new lib', strtab_d[3:].split("\x00")[0]
e.write(ddebug, pack('QQ', 1, 3))
e.save(sys.argv[1] + '.l.bin')

Co dwie tablice to nie jedna

$ cat >>a.c<<\EOT
int main(int a, char **b) {
  printf(b[1]);
}
EOT
$ gcc -O0 -o a a.c
$ python2 rename.py a
$ chmod +x ./a.r.bin
$ objdump -d ./a.r.bin
00000000004004e6 <main>:
  4004e6:      55             push   %rbp
...
  400508:      e8 b3 fe ff ff callq  4003c0 <printf@plt>
  40050d:      b8 00 00 00 00 mov    $0x0,%eax
  400512:      c9             leaveq
  400513:      c3             retq
$ ./a.r.bin id
uid=1000(mak) gid=1000(mak) groups=1000(mak),78(kvm),92(audio),150(wireshark)

import sys, elf
from struct import unpack, pac
e = elf.Elf(sys.argv[1])
for p in e.phdrs:
    if p.type == 'PT_DYNAMIC':
        break
dyva = p.p_vaddr
strtab = e.dynamic['DT_STRTAB']
dstrtab_off = dyva + 0x10 * (e.dynamic.off-1)
strtab_d = e.read(strtab, 0x100).replace('printf', 'system')
e.insert_phdr(p_type = 1,
              p_flags = 6,
              p_vaddr = 0x500000,
              data = strtab_d
)
e.write(dstrtab_off + 8, pack('Q', 0x500000))
e.save(sys.argv[1] + '.r.bin')

Rozdwojenie jaźni

Ładowanie a Wykonanie

Ładowanie a Wykonanie

Ładowanie a Wykonanie

void good() { puts("good");}
int main() {
  good();
}
$ readelf -e a1
Section Headers:
    [Nr] Name              Type             Address           Offset
         Size              EntSize          Flags Link Info Align
...
    [14] .text             PROGBITS         00000000004003f0 000003f0
         0000000000000192  0000000000000000 AX         0     0     16
...
Program Headers:
    Type     Offset             VirtAddr           PhysAddr
             FileSiz            MemSiz              Flags Align
...
    LOAD     0x0000000000000000 0x0000000000400000 0x0000000000400000
             0x00000000000006ec 0x00000000000006ec R E     200000

[BITS 64]
jmp a
b:
  pop rsi
  push rdx
  mov rdx,4
  xor rax,rax
  inc rax
  mov rdi,rax
  syscall
  pop rdx
  push 0x4003f0
  ret
a:
call b
db "bad",0xa
nasm x.asm -o x.bin
dd if=x.bin of=a1 seek=$((0x880)) oflag=seek_bytes conv=notrunc
echo -ne "\x80\x08" | dd of=a1 seek=24 oflag=seek_bytes conv=notrunc

Down memory lane

  • SBSWAW 2013 microCTF

Down memory lane

  • SBSWAW 2013 microCTF
$ cat ~/sbs/web.py   | grep dual-elf
dual-elf    : sbs{98b18715f67b4091cbb85fda71f18cc3fe3a4009}
tasks_id = {1:'coq',2:'small-elf',3:'dual-elf',4:'hask-pwn',5:'green-stego'}
$ cat ~/sbs/tasks/3 
<br>
Get the flag!: <a href="/static/3">file

Down memory lane

  • SBSWAW 2013 microCTF
$ cat ~/sbs/web.py   | grep dual-elf
dual-elf    : sbs{98b18715f67b4091cbb85fda71f18cc3fe3a4009}
tasks_id = {1:'coq',2:'small-elf',3:'dual-elf',4:'hask-pwn',5:'green-stego'}
$ cat ~/sbs/tasks/3 
<br>
Get the flag!: <a href="/static/3">file
  • DragonSector CTF Finals 2015
    Just a simple crackme.
    File: [shiz]({{resource("re200")}})

The End.

Shameless plug

http://bit.do/PWN-Praktyczna-inzynieria-wsteczna

  • Tomasz Bukowski
  • Grzegorz Antoniak
  • Tomasz Kwiecień
  • Mateusz Krzywicki
  • Marcin Hartung
  • Gynvael Coldwind
  • Hasherezade
  • Maciej Kotowicz
  • Michał Kowalczyk
  • Robert Święcki
  • Piotr Bania
  • Mateusz Jurczyk

mak mak@cert.pl
mak mak@lokalhost.pl
mak @maciekkotowicz