slides

Transcript

slides
Università degli Studi di Milano
Facoltà di Scienze Matematiche, Fisiche e Naturali
Reverse engineering: executable file format
Alessandro Reina <[email protected]>
Aristide Fattori<[email protected]>
A.A. 2011–2012
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
1 / 60
Introduzione
Reverse engineering [1]
reverse engineering is the process of extracting the
knowledge or design blueprints from anything man-made
contesti differenti (e.g., elettronica, informatica, . . . )
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
2 / 60
Disassembly Theory
... a step backward ...
first-generation language: consistono di 0 e 1 spesso
rappresentati in forma esadicimale (machine language,
bytecode)
second-generation language: mapping di pattern specifici di
bit, opcode, in forma di caratteri facilmente memorizzabili
(mnemonics) rappresentanti istruzioni (assembly languages).
L’assembler è un tool utilizzato per la traduzione di
programmi assembly in linguaggio macchina.
third-generation language: introduzione di keyword e
costrutti utilizzati come building block per la scrittura di un
programma. Tali linguaggi, spesso, sono platform independent
(e.g. C, Fortran, Java, . . . ). I compilatori traducono tali
programmi in linguaggio assembly oppure fino al linguaggio
macchina.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
3 / 60
The What of Disassembly
Traditional model
Sviluppo del software, compilatori, assembler, e linker sono
utilizzati per la creazione di un programma eseguibile.
The way backwards: reverse engineering
(assebly)undo = disassembler(bin);
(high-level language)undo = decompiler(bin);
source-code recovery: hard
compilazione può perdere informazioni (e.g. nomi di variabili, nomi
di funzioni, . . . )
compilazione di file sorgente può essere tradotto in assembly, cosı̀
come da linguaggio macchina a sorgente, in modi differenti
decompilatori dipendenti dal linguaggio e dalle librerie utilizzate
necessità di un perfetto compilatore
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
4 / 60
The Why of Disassembly
Why?
Scopo dei disassembler è facilitare la comprensione di programmi
quando il codice sorgente non è disponibile.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
5 / 60
The Why of Disassembly
Why?
Scopo dei disassembler è facilitare la comprensione di programmi
quando il codice sorgente non è disponibile.
Casi:
analisi di malware (static/dynamic analysis)
analisi di closed-source software per vulnerabilità (vuln.
discovery → vuln. analysis → exploit dev.)
analisi di closed-source software per interoperabilità (driver,
plugin, WINE, ReactOS, samba, . . . )
analisi di codice generato dal compilatore per valutare
correttezza e performance
visualizzazione delle istruzioni assembly durante debugging
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
5 / 60
The Why of Disassembly
Why?
Scopo dei disassembler è facilitare la comprensione di programmi
quando il codice sorgente non è disponibile.
Casi:
analisi di malware (static/dynamic analysis)
analisi di closed-source software per vulnerabilità (vuln.
discovery → vuln. analysis → exploit dev.)
analisi di closed-source software per interoperabilità (driver,
plugin, WINE, ReactOS, samba, . . . )
analisi di codice generato dal compilatore per valutare
correttezza e performance
visualizzazione delle istruzioni assembly durante debugging
cracking :-)
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
5 / 60
The How of Disassembly
. . . and now?
Prossima lezione ;-)
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
6 / 60
. . . btw . . .
What is this thing?
OMG ... this is an unknown file, and so what?
l’estensione del file non determina necessariamente che file sia
realmente
le estensioni dei file sono inutili
un file, ASCII e non-ASCII, si identifica sulla base di specifici
campi al suo interno
magic numbers: uno speciale TAG, se richiesto dalle specifiche
di formato del file, che indentifica se il file è conforme a tali
specifiche (solitamente uniche per un determinato tipo di file)
Tool
file è una utility (*NIX) che permette di identificare il tipo di file
in base a particolari regole stabilite in un magic file (e.g
/usr/share/file/magic, /usr/share/misc/magic)
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
7 / 60
what’s inside a file?
Esempio
taryn:Downloads ale$ file ./secuinside/bin.exe && hexdump -C ./secuinside/bin.exe | head -n2
./secuinside/bin.exe: PE32 executable for MS Windows (console) Intel 80386 32-bit
00000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 |MZ..............|
00000010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......|
taryn:~ ale$ file /tmp/asd && hexdump -C /tmp/asd | head -n2
/tmp/asd: Mach-O 64-bit executable x86_64
00000000 cf fa ed fe 07 00 00 01 03 00 00 80 02 00 00 00 |................|
00000010 0d 00 00 00 20 06 00 00 85 00 20 00 00 00 00 00 |.... ..... .....
ale@iron3:~$ file /bin/ls && hexdump -C /bin/ls | head -n2
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked
(uses shared libs),
for GNU/Linux 2.6.18, BuildID[sha1]=0x5a659f89602a2a59f8ba3fafeb5d7a99ac2d9c39, stripped
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 3e 00 01 00 00 00 50 25 40 00 00 00 00 00 |..>.....P%@.....|
ale@iron3:~$ file asd
asd: JPEG image data,
00000000 ff d8 ff e0
00000010 00 60 00 00
&& hexdump -C asd | head -n2
JFIF standard 1.01
00 10 4a 46 49 46 00 01 01 01 00 60
ff e1 10 ee 45 78 69 66 00 00 4d 4d
|......JFIF.....‘|
|.‘......Exif..MM|
Tuttavia ... nella pratica del reverse engineering: mai fidarsi
completamente dell’output di qualsiasi tool finché non si è correlato
l’output con il risultato di diversi tool insieme ad analisi manuale
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
8 / 60
Software reverse engineering
Tecniche statiche
il programma non viene eseguito
documentazione
codice sorgente
analisi di stringhe, simboli, funzioni di libreria
disassembly e analisi codice assembly
Tecniche dinamiche
esecuzione (monitorata) dell’applicazione
interazioni con l’ambiente (e.g., file system, rete, registro)
interazioni con il sistema operativo (system call)
debugging
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
9 / 60
Analisi di codice binario
Tecniche statiche
1
analisi meta-informazioni dell’eseguibile
funzioni di libreria utilizzate
simboli
informazioni di debugging
...
2
disassembly
call graph
analisi codice assembly
...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
10 / 60
Struttura file eseguibili
file eseguibili “moderni” hanno una struttura complessa
Linux → Executable and Linkable Format (ELF)
Windows → Portable Executable (PE)
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
11 / 60
Struttura file eseguibili
file eseguibili “moderni” hanno una struttura complessa
Linux → Executable and Linkable Format (ELF)
Windows → Portable Executable (PE)
Un po’ di “storia”. . .
MS-DOS → formato COM
no header, no meta-data
solo codice e dati, in un unico segmento
problemi
max 0xff00 byte
non rilocabile
niente dynamic linking
...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
11 / 60
ELF: Executable and Linkable Format
Tipologie di file ELF [4]
1
relocatable
2
executable
3
shared object
Esempio
ale@iron3:/tmp$ gcc -c test.c -o test.o
ale@iron3:/tmp$ file test.o
test.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV) ...
ale@iron3:/tmp$ gcc test.c -o test
ale@iron3:/tmp$ file test
test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV) ...
ale@iron3:/tmp$ gcc -shared test.c -o test.so
ale@iron3:/tmp$ file test.so
test.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV) ...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
12 / 60
ELF: Executable and Linkable Format
Struttura file ELF
ELF header
Program header table
Section 1
...
Informazioni
sull’organizzazione del file
Section n
...
Section header table
ELF executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
13 / 60
ELF: Executable and Linkable Format
Struttura file ELF
ELF header
Program header table
Section 1
...
Dettagli su come creare
l’immagine in memoria
Section n
...
Section header table
ELF executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
13 / 60
ELF: Executable and Linkable Format
Struttura file ELF
ELF header
Program header table
Section 1
...
Contengono i dati “effettivi” (e.g., istruzioni,
dati, symbol table)
Section n
...
Section header table
ELF executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
13 / 60
ELF: Executable and Linkable Format
Struttura file ELF
ELF header
Program header table
Section 1
...
Informazioni relative alle sezioni
(e.g., nome, dimensione)
Section n
...
Section header table
ELF executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
13 / 60
ELF: Executable and Linkable Format
ELF header
Elf32 Ehdr in /usr/include/linux/elf.h
magic number (\x7fELF), ELF type & version
architettura & endianness
entry point (virtual address)
offset (nel file) di program & section header table
...
Esempio
ale@iron3:/tmp$ readelf -h test
ELF Header:
Magic:
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
...
Type:
EXEC (Executable file)
Machine:
Intel 80386
Version:
0x1
Entry point address:
0x80482f0
...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
14 / 60
ELF: Executable and Linkable Format
Section header table
Array di Elf32 Shdr in /usr/include/linux/elf.h
specifica, per ogni sezione
nome (i.e., indice nella section header string table)
posizione nel file e memoria
dimensione
...
Esempio
ale@iron3:/tmp$ objdump -h test
Idx Name
Size
VMA
LMA
File off
0 .interp
00000013 08048114 08048114 00000114
CONTENTS, ALLOC, LOAD, READONLY, DATA
...
12 .text
0000017c 080482f0 080482f0 000002f0
CONTENTS, ALLOC, LOAD, READONLY, CODE
...
22 .data
00000008 080495a4 080495a4 000005a4
CONTENTS, ALLOC, LOAD, DATA
23 .bss
00000008 080495ac 080495ac 000005ac
ALLOC
Alessandro Reina
Algn
2**0
2**4
2**2
2**2
Reverse engineering: executable file format
A.A. 2011–2012
15 / 60
ELF: Executable and Linkable Format
Program header table
Array di Elf32 Phdr in /usr/include/linux/elf.h
array di strutture, ciascuna delle quali definisce
un segmento (i.e., 1+ sezioni in memoria); oppure,
altre informazioni necessarie per organizzare l’immagine in memoria
Esempio
ale@iron3:/tmp$
Program Header:
PHDR off
filesz
INTERP off
filesz
LOAD off
filesz
LOAD off
filesz
DYNAMIC off
filesz
NOTE off
filesz
STACK off
filesz
Alessandro Reina
objdump -p test
0x00000034
0x000000e0
0x00000114
0x00000013
0x00000000
0x000004a4
0x000004a4
0x00000108
0x000004b8
0x000000d0
0x00000128
0x00000020
0x00000000
0x00000000
vaddr
memsz
vaddr
memsz
vaddr
memsz
vaddr
memsz
vaddr
memsz
vaddr
memsz
vaddr
memsz
0x08048034
0x000000e0
0x08048114
0x00000013
0x08048000
0x000004a4
0x080494a4
0x00000110
0x080494b8
0x000000d0
0x08048128
0x00000020
0x00000000
0x00000000
paddr
flags
paddr
flags
paddr
flags
paddr
flags
paddr
flags
paddr
flags
paddr
flags
0x08048034
r-x
0x08048114
r-0x08048000
r-x
0x080494a4
rw0x080494b8
rw0x08048128
r-0x00000000
rw-
align 2**2
align 2**0
align 2**12
align 2**12
align 2**2
align 2**2
align 2**2
Reverse engineering: executable file format
A.A. 2011–2012
16 / 60
ELF: Executable and Linkable Format
Symbol table
sezione con una entry per simbolo
debugging, dynamic linking, relocation, . . .
Esempio
ale@iron3:/tmp$ readelf -s test
Symbol table ’.dynsym’
Num:
Value Size
0: 00000000
0
...
3: 00000000
460
4: 0804848c
4
contains 5 entries:
Type
Bind
Vis
NOTYPE LOCAL DEFAULT
Ndx Name
UND
FUNC
OBJECT
UND puts@GLIBC_2.0 (2)
15 _IO_stdin_used
Symbol table ’.symtab’
Num:
Value Size
0: 00000000
0
1: 08048114
0
...
70: 080495ac
0
71: 0804843a
0
72: 080483a4
38
73: 08048274
0
contains 74 entries:
Type
Bind
Vis
NOTYPE LOCAL DEFAULT
SECTION LOCAL DEFAULT
Ndx Name
UND
1
NOTYPE
FUNC
FUNC
FUNC
ABS _edata
13 __i686.get_pc_thunk.bx
13 main
11 _init
Alessandro Reina
GLOBAL DEFAULT
GLOBAL DEFAULT
GLOBAL
GLOBAL
GLOBAL
GLOBAL
DEFAULT
HIDDEN
DEFAULT
DEFAULT
Reverse engineering: executable file format
A.A. 2011–2012
17 / 60
ELF: Executable and Linkable Format
Symbol table
sezione con una entry per simbolo
debugging, dynamic linking, relocation, . . .
Esempio
ale@iron3:/tmp$ readelf -S test | grep ’\.symtab’
[34] .symtab
SYMTAB
...
ale@iron3:/tmp$ strip test
ale@iron3:/tmp$ readelf -s test
Symbol table ’.dynsym’ contains 5 entries:
Num:
Value Size Type
Bind
Vis
Ndx Name
0: 00000000
0 NOTYPE LOCAL DEFAULT UND
...
3: 00000000
460 FUNC
GLOBAL DEFAULT UND puts@GLIBC_2.0 (2)
4: 0804848c
4 OBJECT GLOBAL DEFAULT
15 _IO_stdin_used
ale@iron3:/tmp$ readelf -S test | grep ’\.symtab’
ale@iron3:/tmp$
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
17 / 60
ELF: Executable and Linkable Format
What do linkers and loaders do?
Linker: combina più object file in un unico file
Loader: prende gli object file e li carica in memoria
Permettono di scrivere programmi utilizzando nomi astratti perché
la loro preoccupazione è associare nomi astratti a nomi concreti.
Linking vs. Loading
Efettuano operazioni correlate tra loro ma concettualmente separate.
program loading: copia di un programma dalla memoria secondaria alla
memoria principale configurando l’ambiente per l’esecuzione.
relocation: compilatori ed assembler generalmente creano object file con
indirizzi di programma a partire da 0. La rilocazione è il processo di
assegnamento degli indirizzi di caricamento alle varie parti che compongono il
programma modificando codice e dati per riflettere gli indirizzi assegnati. In
altre parole: determina il valore di X e mettilo nel binario all’offset Y .
symbol resolution: un programma è spesso composto da più oggetti, i
riferimenti ai nomi degli oggetti sono fatti mediante simboli. Il linker risolve i
simboli modificando il codice del chiamante in modo tale che la chiamata si
riferisca alla locazione a cui il simbolo fa riferimento (patch object code).
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
18 / 60
ELF: Executable and Linkable
Linker
two-pass linking
Linker prende in input un insieme di object file, librerie e produce in output un nuovo
object file o eseguibile.
ogni file contiene un insieme di segmenti ed almeno una symbol table (simboli
importati ed esportati).
il linker scansiona i file in input, determina la dimensione dei segmenti e
colleziona definizioni e riferimenti di tutti i simboli.
il linker assegna locazioni numeriche ai simboli, determina la dimensione e la
locazione dei segmenti nello spazio di indirizzamento di output e definisce dove
ogni parte deve risiedere nel file di output.
le informazioni collezionate sono utilizzate nel reale processo di linking. Il linker
legge e riloca il codice oggetto sostituendo simboli con indirizzi di memoria,
sistema codice e dati per riflettere i cambiamente dovuti alla rilocazione dei
segmenti.
se il programma utilizza dynmic linking la symbol table conterrà le informazioni
che il runtime linker avrà bisogno per risolvere i simboli dinamicamente.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
19 / 60
ELF: Executable and Linkable
Linker
Relocation entry
Le relocation entry sono utilizzate con una duplice funzionalità:
quando una sezione di codice è rilocata ad un differente base
address, le relocation entry marcano tale posizione nel codice
per essere modificata
in un file linkable le relocation entry marcano riferimenti a
simboli non definiti in modo tale che il linker/loader conosca
le posizioni da modificare quando viene fatta la risoluzione del
simbolo
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
20 / 60
ELF: Executable and Linkable
Compiling & Linking
Hello World
.data
msg:
.text
.global
# section containing initialized data
.string Hello World!
len=.-msg
_start
# linker needs it to find the entry point
_start:
## write to standard output
movl $4, %eax
# syscall write
movl $1, %ebx
# file descriptor stdout
movl $msg, %ecx
# offset of the message
movl $len, %edx
# len of the message
int $0x80
## exit gracefully :-)
movl $1,%eax
# syscall exit
movl $0,%ebx
# return value
int $0x80
...
ale@iron3:~/rev1/example1$ as hello.S -32 -o hello.out
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
21 / 60
ELF: Executable and Linkable
Compiling & Linking
Disassembly & Relocation
ale@iron3:~/rev1/example1$ objdump -D hello.out
...
00000000 <_start>:
0: b8 04 00 00 00
mov
$0x4,%eax
5: bb 01 00 00 00
mov
$0x1,%ebx
a: b9 00 00 00 00
mov
$0x0,%ecx # movl $msg, %ecx
f: ba 0e 00 00 00
mov
$0xe,%edx
14: cd 80
int
$0x80
16: b8 01 00 00 00
mov
$0x1,%eax
1b: bb 00 00 00 00
mov
$0x0,%ebx
20: cd 80
int
$0x80
...
ale@iron3:~/rev1/example1$ readelf hello.out -a
ELF Header:
Magic:
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
...
Relocation section ’.rel.text’ at offset 0x258 contains 1 entries:
Offset
Info
Type
Sym.Value Sym. Name
0000000b 00000201 R_386_32
00000000
.data
...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
22 / 60
ELF: Executable and Linkable
Loading & Running
Program Header
ale@iron3:~/rev1/example1$ ld -m elf_i386 -o hello hello.out
ale@iron3:~/rev1/example1$ readelf -l hello
Elf file type is EXEC (Executable file)
Entry point 0x8048074
There are 2 program headers, starting at offset 52
Program Headers:
Type
Offset
VirtAddr
PhysAddr
FileSiz MemSiz Flg Align
LOAD
0x000000 0x08048000 0x08048000 0x00096 0x00096 R E 0x1000
LOAD
0x000098 0x08049098 0x08049098 0x0000e 0x0000e RW 0x1000
Section to Segment mapping:
Segment Sections...
00
.text
01
.data
code segment sarà caricato dal file all’offset 0x000000 in una regione di
memoria (RE) mappata nell’address space del processo all’indirizzo 0x08048000
con dimensione pari a 0x00096 byte e page-aligned (0x1000).
data segment sarà caricato dal file all’offset 0x000098 . . .
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
23 / 60
ELF: Executable and Linkable
Shared Library
Why?
Una shared library (shared object) è un file che può essere
condiviso da file eseguibili o altri shared object
caricate a load time o run time piuttosto che essere copiate
dal linker all’interno di un file eseguibile
possono essere statically linked, riferimenti risolti a compile
time, oppure dynamically linked dove il linking è posticipato al
caricamento o la risoluzione degli indirizzi posticipata al
momento della prima chiamate (lazy linking )
Loading shared library
load-time relocation
position independet code (PIC)
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
24 / 60
ELF: Executable and Linkable
Loading shared library
reloc.c
int rel global = 0x1337C0D3;
int rel function(int a, int b)
{
rel global += a;
return b + rel global;
}
ale@iron3:˜/rev1/example2$ gcc −c reloc.c −o reloc.o −m32
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
25 / 60
ELF: Executable and Linkable
Load-time relocation
ale@iron3:~/rev1/example2$ gcc -shared -o libreloc.so reloc.o -m32
ale@iron3:~/rev1/example2$ readelf -h libreloc.so
ELF Header:
Magic:
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class:
ELF32
...
Type:
DYN (Shared object file)
Machine:
Intel 80386
Version:
0x1
Entry point address:
0x3b0
Il linker linka lo shared object a partire dall’indirizzo 0x00000000. La sezione .text
inizia all’indirizzo 0x3b0.
ale@iron3:~/rev1/example2$ readelf -t libreloc.so
[12] .text
PROGBITS
000003b0 0003b0 000118 00
[00000006]: ALLOC, EXEC
Alessandro Reina
Reverse engineering: executable file format
| grep -A2 .text
0
0 16
A.A. 2011–2012
26 / 60
ELF: Executable and Linkable
Load-time relocation
ale@iron3:~/rev1/example2$ objdump -d libreloc.so
libreloc.so:
file format elf32-i386
...
0000046c <rel_function>:
46c: 55
push
%ebp
46d: 89 e5
mov
%esp,%ebp
46f: a1 00 00 00 00
mov
0x0,%eax
474: 03 45 08
add
0x8(%ebp),%eax
477: a3 00 00 00 00
mov
%eax,0x0
47c: a1 00 00 00 00
mov
0x0,%eax
481: 03 45 0c
add
0xc(%ebp),%eax
484: 5d
pop
%ebp
485: c3
ret
486: 90
nop
...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
27 / 60
ELF: Executable and Linkable
Load-time relocation
ale@iron3:~/rev1/example2$ objdump -d libreloc.so
libreloc.so:
file format elf32-i386
...
0000046c <rel_function>:
46c: 55
push
%ebp
46d: 89 e5
mov
%esp,%ebp
46f: a1 00 00 00 00
mov
0x0,%eax
474: 03 45 08
add
0x8(%ebp),%eax
477: a3 00 00 00 00
mov
%eax,0x0
47c: a1 00 00 00 00
mov
0x0,%eax
481: 03 45 0c
add
0xc(%ebp),%eax
484: 5d
pop
%ebp
485: c3
ret
486: 90
nop
...
Dopo le prime due istruzioni che identificano il prologo troviamo l’istruzione
rel_global += a. Il valore di rel_global viene preso dalla memoria e salvato nel
registro %eax, quindi incrementato di a cioè 0x8(%ebp) e salvato nuovamente in
memoria.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
27 / 60
ELF: Executable and Linkable
Load-time relocation
ale@iron3:~/rev1/example2$ objdump -d libreloc.so
libreloc.so:
file format elf32-i386
...
0000046c <rel_function>:
46c: 55
push
%ebp
46d: 89 e5
mov
%esp,%ebp
46f: a1 00 00 00 00
mov
0x0,%eax
474: 03 45 08
add
0x8(%ebp),%eax
477: a3 00 00 00 00
mov
%eax,0x0
47c: a1 00 00 00 00
mov
0x0,%eax
481: 03 45 0c
add
0xc(%ebp),%eax
484: 5d
pop
%ebp
485: c3
ret
486: 90
nop
...
Dopo le prime due istruzioni che identificano il prologo troviamo l’istruzione
rel_global += a. Il valore di rel_global viene preso dalla memoria e salvato nel
registro %eax, quindi incrementato di a cioè 0x8(%ebp) e salvato nuovamente in
memoria.
?!?
Ma l’istruzione mov dove prende rel_global?
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
27 / 60
ELF: Executable and Linkable
Load-time relocation
:-)
Il valore dell’operando dell’istruzione mov è proprio 0x0... o meglio
questo è come funziona la rilocazione. L’assemblatore/linker
inserisce dei valori provvisori nel codice e per ognuno di essi crea
una relocation entry che si riferisce alle posizioni in cui sono stati
inseriti.
ale@iron3:~/rev1/example2$ readelf -r libreloc.so
Relocation section
Offset
Info
00001638 00000008
00000470 00000a01
00000478 00000a01
0000047d 00000a01
...
’.rel.dyn’ at offset 0x304 contains 7 entries:
Type
Sym.Value Sym. Name
R_386_RELATIVE
R_386_32
0000163c
rel_global
R_386_32
0000163c
rel_global
R_386_32
0000163c
rel_global
La sezione .rel.dyn di un ELF è riservata per le rilocazioni dinamiche (load-time) che
vengono utilizzate dal dynamic loader.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
28 / 60
ELF: Executable and Linkable
Load-time relocation
Rilocazione
La seconda entry nella relocation section indica: vai all’offset
0x470 nella shared library ed applica il tipo di rilocazione
R_386_32 (S + A) che signfica: prendi il valore del simbolo il cui
indice risiede nella relocation entry e somma l’addend usato per
calcolare il valore del relocation field ehm, what??!? :-(
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
29 / 60
ELF: Executable and Linkable
Load-time relocation
Rilocazione
La seconda entry nella relocation section indica: vai all’offset
0x470 nella shared library ed applica il tipo di rilocazione
R_386_32 (S + A) che signfica: prendi il valore del simbolo il cui
indice risiede nella relocation entry e somma l’addend usato per
calcolare il valore del relocation field ehm, what??!? :-(
46f: a1 00 00 00 00
mov
0x0,%eax
a1 rappresenta l’opcode dell’istruzione mov che inizia all’indirizzo 0x46f, mentre
l’operando risiede al byte successivo 0x470 con valore 0x0 (A = addend).
R_386_32 definisce la seguente operazione: somma l’indirizzo di rel_global (S
= symbol value, cioè base address + prev. sym val) all’operando
dell’istruzione mov, cioè 0x0. Questo dice al dynamic loader: quando effettui
l’assegnamento dell’indirizzo, salva l’indirizzo reale di rel_global all’offset
0x470 sostituendo il vecchio operando della mov con quello nuovo.
Sym. Value rappresenta l’offset di rel_global nell’immagine della memoria
virtuale della shared library.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
29 / 60
ELF: Executable and Linkable
Load-time relocation
run the binary...
ale@iron3:~/rev1/example2$ readelf --segment libreloc.so
Elf file type is DYN (Shared object file)
Entry point 0x3b0
There are 6 program headers, starting at offset 52
Program Headers:
Type
LOAD
LOAD
DYNAMIC
NOTE
GNU_EH_FRAME
GNU_STACK
Offset
0x000000
0x000534
0x000548
0x0000f4
0x0004e4
0x000000
VirtAddr
0x00000000
0x00001534
0x00001548
0x000000f4
0x000004e4
0x00000000
PhysAddr
0x00000000
0x00001534
0x00001548
0x000000f4
0x000004e4
0x00000000
FileSiz
0x00534
0x0010c
0x000d0
0x00024
0x00014
0x00000
MemSiz
0x00534
0x00114
0x000d0
0x00024
0x00014
0x00000
Flg
R E
RW
RW
R
R
RW
Align
0x1000
0x1000
0x4
0x4
0x4
0x4
Section to Segment mapping:
Segment Sections...
00
.note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version
.gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .eh_frame_hdr .eh_frame
01
.ctors .dtors .jcr .dynamic .got .got.plt .data .bss
02
.dynamic
03
.note.gnu.build-id
04
.eh_frame_hdr
05
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
30 / 60
ELF: Executable and Linkable
Load-time relocation
run the binary...
in Section to Segment mapping il segmento 01 contiene la
sezione .data dove risiede rel_global
VirtAddr specifica che il segmento 01 inizia a 0x00001534
con dimensione su file pari 0x0010c byte; include pertanto
rel_global che ha offset nell’immagine della memoria
virtuale della shared library 0x163c
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
31 / 60
ELF: Executable and Linkable
Load-time relocation
run the binary...
in Section to Segment mapping il segmento 01 contiene la
sezione .data dove risiede rel_global
VirtAddr specifica che il segmento 01 inizia a 0x00001534
con dimensione su file pari 0x0010c byte; include pertanto
rel_global che ha offset nell’immagine della memoria
virtuale della shared library 0x163c
?!?
C’è un bug in readelf, gcc, ld, . . . ? Come mai FileSiz e
MemSiz non coincidono?! In memoria il segmento è più grande
della dimensione su file!?
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
31 / 60
ELF: Executable and Linkable
Load-time relocation
walk through list of shared objects
#define GNU SOURCE
#include <link.h>
#include <stdlib.h>
#include <stdio.h>
static int callback(struct dl phdr info ∗info, size t size, void ∗data)
{
int j;
printf(”%s (%d segments) at address %p\n”,
info−>dlpi name, info−>dlpi phnum, (void∗)info−>dlpi addr);
for (j = 0; j < info−>dlpi phnum; j++) {
printf(”\t\t header %2d: start at address %10p\n”, j,
(void∗) (info−>dlpi addr + info−>dlpi phdr[j].p vaddr));
}
printf(”\n”);
return 0;
}
extern int rel functin(int, int);
int main(int argc, const char∗ argv[])
{
dl iterate phdr(callback, NULL);
int res = rel function(argc, argc);
return 0;
}
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
32 / 60
ELF: Executable and Linkable
Load-time relocation
ale@iron3:~/rev1/example2$ gdb -q driver
Reading symbols from /home/ale/rev1/example2/driver...(no debugging symbols found)...done.
(gdb) b rel_function
Breakpoint 1 at 0x80484cc
(gdb) r
...
/home/ale/rev1/example2/libreloc.so (6 segments) at address 0xb7fde000
header 0: start at address 0xb7fde000
header 1: start at address 0xb7fdf534
header 2: start at address 0xb7fdf548
header 3: start at address 0xb7fde0f4
header 4: start at address 0xb7fde4e4
header 5: start at address 0xb7fde000
...
Il programma precedente riporta tutte le librerie che ha caricato. Possiamo notare che i 6 segmenti visualizzati sono
gli stessi riportati da readelf ma rilocati agli indirizzi di memoria finali.
libreloc.so è stata posizionata all’indirizzo virtuale 0xb7fde000
con readelf il secondo segmento era posizionato all’offset 0x00001534 mentre in memoria è stato caricato
all’indirizzo virtuale 0xb7fdf534
la variable globale rel_global, prima del caricamento, risiedeva all’offset 0x163c (il linker assume che che
la shared library sia stata caricata all’indirizzo 0x0)
pertanto se la shared library è stata carita all’indirizzo 0xb7fde000 allora la variabile globale rel_global
risiede all’indirizzo 0xb7fde000 + 0x163c = 0xb7fdf63c
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
33 / 60
ELF: Executable and Linkable
Load-time relocation
ale@iron3:~/rev1/example2$ gdb -q driver
...
(gdb) p/x &rel_global
$1 = 0xb7fdf63c
(gdb) p/x rel_global
$2 = 0x1337c0d3
(gdb) disassemble rel_function
Dump of assembler code for function rel_function:
0xb7fde46c <+0>:
push
%ebp
0xb7fde46d <+1>:
mov
%esp,%ebp
=> 0xb7fde46f <+3>:
mov
0xb7fdf63c,%eax
0xb7fde474 <+8>:
add
0x8(%ebp),%eax
0xb7fde477 <+11>:
mov
%eax,0xb7fdf63c
0xb7fde47c <+16>:
mov
0xb7fdf63c,%eax
0xb7fde481 <+21>:
add
0xc(%ebp),%eax
0xb7fde484 <+24>:
pop
%ebp
0xb7fde485 <+25>:
ret
End of assembler dump.
L’indirizzo reale di rel_global in memoria virtuale è stato correttamente sostituito in
ogni punto specificato dalle relocation entry
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
34 / 60
ELF: Executable and Linkable
Load-time relocation
Relocation function call
int rel global = 0x1337C0D3;
int rel call function(void)
{
return 0xcd9a000d;
}
int rel function(int a, int b)
{
rel global ˆ= rel call function();
rel global += a;
return b + rel global;
}
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
35 / 60
ELF: Executable and Linkable
Load-time relocation
Relocation function call
000004b6 <rel_function>:
4b6:
55
4b7:
89 e5
4b9:
e8 fc ff ff ff
4be:
8b 15 00 00 00 00
4c4:
31 d0
4c6:
a3 00 00 00 00
4cb:
a1 00 00 00 00
4d0:
03 45 08
4d3:
a3 00 00 00 00
4d8:
a1 00 00 00 00
4dd:
03 45 0c
4e0:
5d
4e1:
c3
4e2:
90
...
Alessandro Reina
push
mov
call
mov
xor
mov
mov
add
mov
mov
add
pop
ret
nop
%ebp
%esp,%ebp
4ba <rel_function+0x4>
0x0,%edx
%edx,%eax
%eax,0x0
0x0,%eax
0x8(%ebp),%eax
%eax,0x0
0x0,%eax
0xc(%ebp),%eax
%ebp
Reverse engineering: executable file format
A.A. 2011–2012
36 / 60
ELF: Executable and Linkable
Load-time relocation
Relocation function call
ale@iron3:~/rev1/example3$ readelf -r libreloc.so
Relocation section
Offset
Info
000016c0 00000008
000004ba 00000502
000004c0 00000b01
000004c7 00000b01
’.rel.dyn’ at offset 0x330 contains 10 entries:
Type
Sym.Value Sym. Name
R_386_RELATIVE
R_386_PC32
000004ac
rel_call_function
R_386_32
000016c4
rel_global
R_386_32
000016c4
rel_global
L’entry 0x000004ba è l’argomento dell’istruzione call di tipo R_386_PC32
(S + A - P). Il tipo R_386_PC32 significa somma il valore del simbolo (S) con il valore
contenuto all’offset specificato nella relocation entry (A) meno l’indirizzo dove si deve
applicare la rilocazione (P) (indirizzi a load-time).
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
37 / 60
ELF: Executable and Linkable
Load-time relocation
Relocation function call
(gdb) disassemble /r rel_function
Dump of assembler code for function
0xb7fde4b6 <+0>:
55
0xb7fde4b7 <+1>:
89 e5
=> 0xb7fde4b9 <+3>:
e8 ee ff ff
0xb7fde4be <+8>:
8b 15 c4 f6
0xb7fde4c4 <+14>:
31 d0
0xb7fde4c6 <+16>:
a3 c4 f6 fd
0xb7fde4cb <+21>:
a1 c4 f6 fd
0xb7fde4d0 <+26>:
03 45 08
0xb7fde4d3 <+29>:
a3 c4 f6 fd
0xb7fde4d8 <+34>:
a1 c4 f6 fd
0xb7fde4dd <+39>:
03 45 0c
0xb7fde4e0 <+42>:
5d
0xb7fde4e1 <+43>:
c3
End of assembler dump.
rel_function:
push
%ebp
mov
%esp,%ebp
ff
call
0xb7fde4ac <rel_call_function>
fd b7 mov
0xb7fdf6c4,%edx
xor
%edx,%eax
b7
mov
%eax,0xb7fdf6c4
b7
mov
0xb7fdf6c4,%eax
add
0x8(%ebp),%eax
b7
mov
%eax,0xb7fdf6c4
b7
mov
0xb7fdf6c4,%eax
add
0xc(%ebp),%eax
pop
%ebp
ret
Quindi applicando il tipo di rilocazone R_386_PC32 si ottiene:
0xb7fde4ac + 0xfffffffc - 0xb7fde4ba = 0xffffffee.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
38 / 60
ELF: Executable and Linkable
Dynamic linking
Problema
Se la shared library è utilizzata da molti processi (code sharing)
quali problemi possono esserci?
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
39 / 60
ELF: Executable and Linkable
Dynamic linking
Problema
Se la shared library è utilizzata da molti processi (code sharing)
quali problemi possono esserci?
il code segment deve essere read/exec
il data segment non deve essere condiviso
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
39 / 60
ELF: Executable and Linkable
Dynamic linking
Problema
Se la shared library è utilizzata da molti processi (code sharing)
quali problemi possono esserci?
il code segment deve essere read/exec
il data segment non deve essere condiviso
allora è necessaria la rilocazione... come si può effettuare il
patching del codice se è read?
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
39 / 60
ELF: Executable and Linkable
Dynamic linking
Problema
Se la shared library è utilizzata da molti processi (code sharing)
quali problemi possono esserci?
il code segment deve essere read/exec
il data segment non deve essere condiviso
allora è necessaria la rilocazione... come si può effettuare il
patching del codice se è read?
data segment è ad un offset conosciuto rispetto al code
segment, quindi
need_address = current_eip + known_offset
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
39 / 60
ELF: Executable and Linkable
Dynamic linking
Shared object
Linux permette l’uso di PIC (Position Independent Code). Shared
object che sono stati compilati PIC non richiedono rilocazione a
load-time.
Purtroppo in x86 non esiste un modo immediato per accedere alla
memoria in modo relativo rispetto all’instruction pointer
(contrariamente a amd64).
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
40 / 60
ELF: supporto al dynamic linking
GOT e PLT: cosa sono?
Global Offset Table e Procedure Linkage Table
La GOT redirige indirizzi position-independent ad indirizzi assoluti. La PLT redirige
chiamate a funzioni position-independent ad indirizzi assoluti.
sezioni (.got e .plt) presenti in eseguibili che utilizzano dynamic linking
l’indirizzo della GOT è relativo al codice che lo referenzia
PLT aggiunge un livello di indirettezza alle chiamate a funzione, consentendo
anche il lazy binding dei relativi indirizzi
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
41 / 60
ELF: supporto al dynamic linking
Algoritmo
1
il sistema operativo mappa il loader in memoria e lo esegue
2
il linker riloca e risolve i riferimenti alle proprie funzioni
3
il linker esplora la .dynamic section per enumerare tutte le
librerie necessarie al caricamento dell’eseguibile
4
dopo aver verificato l’esistenza della libreria sul filesystem
procede al mapping della stessa in memoria e carica
ricorsivamente tutte le sue dipendenze
5
il linker effettua le rilocazioni necessarie e completa la GOT
6
se la variabile d’ambiente LD_BIND_NOW è configurata
opportunamente il linker completa sin dal caricamento anche
la PLT altrimenti farà lazy linking
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
42 / 60
ELF: supporto al dynamic linking
Esempio
ale@iron2:~$ objdump -h -j .plt -j .got ‘which ls‘
/bin/ls:
file format elf32-i386
Sections:
Idx Name
12 .plt
22 .got
Alessandro Reina
Size
00000600
CONTENTS,
00000008
CONTENTS,
VMA
LMA
File off
080495a8 080495a8 000015a8
ALLOC, LOAD, READONLY, CODE
08060084 08060084 00017084
ALLOC, LOAD, DATA
Algn
2**2
2**2
Reverse engineering: executable file format
A.A. 2011–2012
43 / 60
ELF: supporto al dynamic linking
GOT e PLT: come funzionano?
Chiamata ad una funzione shared
1
chiamata f() shared → chiamata ad una entry della PLT
2
PLT: jmp indiretto ad una entry della GOT che conterrà:
la prima volta, l’indirizzo di una entry della PLT che trasferisce il controllo al linker, per risoluzione
e aggiornamento della GOT
successivamente, l’indirizzo effettivo della shared function
Esempio
ale@iron3:~/rev1/example4$ objdump -d test
...
080482e8 <puts@plt-0x10>:
80482e8:
ff 35 04 96 04 08
pushl
80482ee:
ff 25 08 96 04 08
jmp
80482f4:
00 00
add
...
080482f8 <puts@plt>:
80482f8:
ff 25 0c 96 04 08
jmp
80482fe:
68 00 00 00 00
push
8048303:
e9 e0 ff ff ff
jmp
...
080483e4 <main>:
...
80483f4:
e8 ff fe ff ff
call
...
Alessandro Reina
0x8049604 # GOT + 4 (link_map)
*0x8049608 # GOT + 8 (runtime linker)
%al,(%eax)
*0x804960c
$0x0
80482e8 <_init+0x30>
80482f8 <puts@plt>
Reverse engineering: executable file format
A.A. 2011–2012
44 / 60
ELF: supporto al dynamic linking
jmp *<GOT+n>
<puts@plt>+6:
...linker ...
<GOT+n>:
Alessandro Reina
<puts@plt+6>
Reverse engineering: executable file format
.plt
<puts@plt>+0:
.got
call <puts@plt>
.text
Esempio .got e .plt
A.A. 2011–2012
45 / 60
ELF: supporto al dynamic linking
call <puts@plt>
.text
Esempio .got e .plt
jmp *<GOT+n>
<puts@plt>+6:
...linker ...
<GOT+n>:
Alessandro Reina
<puts@plt+6>
Reverse engineering: executable file format
.got
<puts@plt>+0:
.plt
1
A.A. 2011–2012
45 / 60
ELF: supporto al dynamic linking
call <puts@plt>
.text
Esempio .got e .plt
jmp *<GOT+n>
<puts@plt>+6:
...linker ...
<GOT+n>:
Alessandro Reina
<puts@plt+6>
Reverse engineering: executable file format
2
.got
<puts@plt>+0:
.plt
1
A.A. 2011–2012
45 / 60
ELF: supporto al dynamic linking
call <puts@plt>
.text
Esempio .got e .plt
jmp *<GOT+n>
<puts@plt>+6:
...linker ...
<GOT+n>:
Alessandro Reina
<puts>
Reverse engineering: executable file format
2
.got
<puts@plt>+0:
.plt
1
A.A. 2011–2012
45 / 60
ELF: supporto al dynamic linking
call <puts@plt>
.text
Esempio .got e .plt
jmp *<GOT+n>
<puts@plt>+6:
...linker ...
<GOT+n>:
Alessandro Reina
<puts>
Reverse engineering: executable file format
.got
<puts@plt>+0:
.plt
3
A.A. 2011–2012
45 / 60
ELF: supporto al dynamic linking
ale@iron3:~/rev1/example4$ readelf -r mix.o
Relocation section
Offset
Info
0000000b 00000f02
00000011 0000100a
00000025 00000e04
0000002f 00000409
00000035 00000c03
00000041 00000b04
...
Alessandro Reina
’.rel.text’ at offset 0x3ec contains 6 entries:
Type
Sym.Value Sym. Name
R_386_PC32
00000000
__i686.get_pc_thunk.bx
R_386_GOTPC
00000000
_GLOBAL_OFFSET_TABLE_
R_386_PLT32
00000000
rel_function
R_386_GOTOFF
00000000
.rodata
R_386_GOT32
00000000
rel_global
R_386_PLT32
00000000
printf
Reverse engineering: executable file format
A.A. 2011–2012
46 / 60
ELF: supporto al dynamic linking
00000000 <main>:
0:
55
1:
89 e5
3:
53
4:
83 e4 f0
7:
83 ec 20
a:
e8 fc ff
f:
81 c3 02
15:
c7 44 24
1c:
ba
1d:
c7 04 24
24:
e8 fc ff
29:
89 44 24
2d:
8d 83 00
33:
8b 93 00
39:
89 54 24
3d:
89 04 24
40:
e8 fc ff
45:
b8 00 00
4a:
8b 5d fc
4d:
c9
4e:
c3
Alessandro Reina
ff ff
00 00 00
04 fe af dc
be
ff
1c
00
00
04
ba fe ca
ff
00 00
00 00
ff ff
00 00
push
mov
push
and
sub
call
add
movl
%ebp
%esp,%ebp
%ebx
$0xfffffff0,%esp
$0x20,%esp
b <main+0xb>
$0x2,%ebx
$0xbadcaffe,0x4(%esp)
movl
call
mov
lea
mov
mov
mov
call
mov
mov
leave
ret
$0xcafebabe,(%esp)
25 <main+0x25>
%eax,0x1c(%esp)
0x0(%ebx),%eax
0x0(%ebx),%edx
%edx,0x4(%esp)
%eax,(%esp)
41 <main+0x41>
$0x0,%eax
-0x4(%ebp),%ebx
Reverse engineering: executable file format
A.A. 2011–2012
47 / 60
ELF: supporto al dynamic linking
00000000 <__i686.get_pc_thunk.bx>:
0:
8b 1c 24
mov
3:
c3
ret
(%esp),%ebx
__i686.get_pc_thunk.bx stub utilizzato per emulare indirizzamento pc-relative
salva nel registro ebx l’indirizzo di ritorno, cioè l’indirizzo dell’istruzione
successiva alla call (shellcode-like)
ebx contiene il l’indirizzo di memoria dell’istruzione add che deve essere rilocata
per mezzo della GOT
tipo di rilocazione applicato: R_386_GOTPC (GOT + A - P)
quando il linker costruisce la GOT (executable o shared library) conosce l’indirizzo
virtuale della GOT stessa
Se la GOT si trova all’indirizzo virtuale 0x080497c8 ed il base address è 0x08048034 si
ottiene che R_386_GOTPC = 0x080497c8 + 0x02 - (0x08048034 + 0x11) = 0x1285
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
48 / 60
ELF: supporto al dynamic linking
Dump of assembler code for function main:
0x08048534 <+0>:
push
%ebp
0x08048535 <+1>:
mov
%esp,%ebp
0x08048537 <+3>:
push
%ebx
0x08048538 <+4>:
and
$0xfffffff0,%esp
0x0804853b <+7>:
sub
$0x20,%esp
0x0804853e <+10>:
call
0x8048583 <__i686.get_pc_thunk.bx>
=> 0x08048543 <+15>:
add
$0x1285,%ebx
0x08048549 <+21>:
movl
$0xbadcaffe,0x4(%esp)
0x08048551 <+29>:
movl
$0xcafebabe,(%esp)
0x08048558 <+36>:
call
0x8048468 <rel_function@plt>
0x0804855d <+41>:
mov
%eax,0x1c(%esp)
0x08048561 <+45>:
lea
-0x1178(%ebx),%eax
0x08048567 <+51>:
mov
-0x4(%ebx),%edx
0x0804856d <+57>:
mov
%edx,0x4(%esp)
0x08048571 <+61>:
mov
%eax,(%esp)
0x08048574 <+64>:
call
0x8048438 <printf@plt>
0x08048579 <+69>:
mov
$0x0,%eax
0x0804857e <+74>:
mov
-0x4(%ebp),%ebx
0x08048581 <+77>:
leave
0x08048582 <+78>:
ret
End of assembler dump.
(gdb) p/x $ebx
$1 = 0x8048543
(gdb) si
0x08048549 in main ()
(gdb) p/x $ebx
$2 = 0x80497c8
(gdb) x/4x 0x80497c8
0x80497c8 <_GLOBAL_OFFSET_TABLE_>: 0x080496e8 0xb7fff918 0xb7ff60b0 0x0804843e
(gdb) x/s 0x80497c8-0x1178
0x8048650: &rel_global = %p\n
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
49 / 60
ELF: supporto al dynamic linking
Lazy binding: performance
$ time (mplayer >/dev/null)
real
0m0.039s
user
0m0.024s
sys
0m0.012s
$ time (LD_BIND_NOW=1 mplayer >/dev/null)
real
0m0.141s
user
0m0.100s
sys
0m0.016s
Esempio: dump librerie e dynamic loader
ale@iron3:~/rev1/example4$ ldd test
libc.so.6 => /lib32/libc.so.6 (0xb765c000)
/lib/ld-linux.so.2 (0xb77c1000)
ale@iron3:~/rev1/example4$ readelf ./test -x .interp
Hex dump of section ’.interp’:
0x08048134 2f6c6962 2f6c642d 6c696e75 782e736f /lib/ld-linux.so
0x08048144 2e3200
.2.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
50 / 60
PE: Portable Executable
Tipologie di file PE [2, 3]
1
executable
2
object
3
DLL
4
COM files, OCX controls, CLP applets, .NET executables
5
device driver
6
...
Esempio
roby@gandalf:/tmp$ file test.exe
test.exe: PE32 executable for MS Windows (console) Intel 80386 32-bit
roby@gandalf:/tmp$ file test.o
test.o: 80386 COFF executable not stripped - version 30821
roby@gandalf:/tmp$ file test.dll
test.dll: PE32 executable for MS Windows (DLL) (console) Intel ...
roby@gandalf:/tmp$ file test.sys
test.sys: PE32 executable for MS Windows (DLL) (native) Intel ...
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
51 / 60
PE: Portable Executable
Struttura file PE
DOS header DOS stub
PE header
Section table
.text section
.data section
Per retrocompatibilità
...
...
PE executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
52 / 60
PE: Portable Executable
Struttura file PE
DOS header DOS stub
PE header
Section table
.text section
.data section
...
Contiene informazioni
sull’organizzazione del file
...
PE executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
52 / 60
PE: Portable Executable
Struttura file PE
DOS header DOS stub
PE header
Section table
.text section
.data section
...
Contengono i dati “effettivi” (e.g., istruzioni,
dati, rilocazione)
...
PE executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
52 / 60
PE: Portable Executable
Struttura file PE
DOS header DOS stub
PE header
Section table
.text section
.data section
...
Informazioni relative alle sezioni
(e.g., nome, dimensione)
...
PE executable file
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
52 / 60
PE: Portable Executable
Introduzione
modulo: file PE caricato in memoria (e “riorganizzato” dal
loader)
RVA: Relative Virtual Address
indirizzo relativo al base address dell’immagine in memoria
RVA 6= file offset
strutture definite in winnt.h
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
53 / 60
PE: Portable Executable
DOS header & stub
DOS header
typedef struct IMAGE DOS HEADER {
WORD e magic;
...
LONG e lfanew;
} IMAGE DOS HEADER,∗PIMAGE DOS HEADER;
64 byte, magic number \x4d\x5a (“MZ”)
e lfanew: offset PE header
segue DOS stub
DOS stub
“This program cannot be run in DOS mode”
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
54 / 60
PE: Portable Executable
PE header
typedef struct IMAGE NT HEADERS {
DWORD Signature; // ”\x50\x45\x00\x00” (”PE\x00\x00”)
IMAGE FILE HEADER FileHeader;
IMAGE OPTIONAL HEADER OptionalHeader;
} IMAGE NT HEADERS32,∗PIMAGE NT HEADERS32;
typedef struct IMAGE FILE HEADER {
WORD Machine;
WORD NumberOfSections;
...
} IMAGE FILE HEADER,∗PIMAGE FILE HEADER;
typedef struct IMAGE OPTIONAL HEADER { // non e’ opzionale!
...
DWORD AddressOfEntryPoint;
...
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
...
WORD Subsystem;
...
IMAGE DATA DIRECTORY DataDirectory[IMAGE NUMBEROF DIRECTORY ENTRIES];
} IMAGE OPTIONAL HEADER32,∗PIMAGE OPTIONAL HEADER32;
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
55 / 60
PE: Portable Executable
Section table
typedef struct IMAGE SECTION HEADER {
BYTE Name[IMAGE SIZEOF SHORT NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
...
DWORD Characteristics;
} IMAGE SECTION HEADER,∗PIMAGE SECTION HEADER;
Alcune sezioni
1
executable code section (.text) (di solito,
AddressOfEntryPoint ∈ .text)
2
data sections (.data, .rdata, .bss, . . . )
3
.rsrc, .edata, .reloc, .debug, . . .
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
56 / 60
PE: Portable Executable
Import section (.idata)
OriginalFirstThunk
TimeDateStamp
thunk1
thunk2
h1
name1
h2
name2
...
...
...
...
thunk2
...
thunkn
thunkn
hn
Name
thunk1
namen
FirstThunk
= IMAGE IMPORT DESCRIPTOR
= import name table
Alessandro Reina
= IMAGE IMPORT BY NAME
= import address table
Reverse engineering: executable file format
A.A. 2011–2012
57 / 60
PE: Portable Executable
Import section (.idata)
OriginalFirstThunk
TimeDateStamp
thunk1
thunk2
h1
name1
h2
name2
...
...
...
...
&name2
...
thunkn
&namen
hn
Name
&name1
namen
FirstThunk
= IMAGE IMPORT DESCRIPTOR
= import name table
Alessandro Reina
= IMAGE IMPORT BY NAME
= import address table
Reverse engineering: executable file format
A.A. 2011–2012
57 / 60
PE: Portable Executable
Import section (.idata) – invocazione di funzioni importate
0040142d: call 004015c0 < LoadLibraryA@4>
...
004015c0 < LoadLibraryA@4>:
004015c0: jmp ∗0x00405098
Alessandro Reina
richiede 1 call + 1 jmp
jump stubs ∼ .got
differenze?
Reverse engineering: executable file format
A.A. 2011–2012
58 / 60
PE: Portable Executable
Import section (.idata) – invocazione di funzioni importate
0040142d: call 004015c0 < LoadLibraryA@4>
...
004015c0 < LoadLibraryA@4>:
004015c0: jmp ∗0x00405098
01007105: call ∗0x0100108c
richiede 1 call + 1 jmp
jump stubs ∼ .got
differenze?
solo 1 call
declspec(ddlimport)
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
58 / 60
Prossima lezione
tecniche di disassembly
installare IDA Pro!
versione freeware:
http://www.hex-rays.com/idapro/idadownfreeware.htm
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
59 / 60
Bibliografia I
E. Eilam.
Reversing: Secrets of Reverse Engineering.
Wiley Publishing, Inc., 2005.
M. Pietrek.
An In-Depth Look into the Win32 Portable Executable File Format – Part 1.
MSDN Magazine, 2002.
M. Pietrek.
An In-Depth Look into the Win32 Portable Executable File Format – Part 2.
MSDN Magazine, 2002.
TIS Committee.
Tool Interface Standard (TIS) Executable and Linking Format (ELF)
Specification Version 1.2.
May 1995.
Alessandro Reina
Reverse engineering: executable file format
A.A. 2011–2012
60 / 60

Documenti analoghi

Reverse engineering: executable file format

Reverse engineering: executable file format [15:35:02] roby@gandalf:/tmp$ readelf ./test -x .interp Hex dump of section ’.interp’: 0x08048114 2f6c6962 2f6c642d 6c696e75 782e736f /lib/ld-linux.so 0x08048124 2e3200

Dettagli

Reverse engineering: executable file format

Reverse engineering: executable file format [15:35:02] roby@gandalf:/tmp$ readelf ./test -x .interp Hex dump of section ’.interp’: 0x08048114 2f6c6962 2f6c642d 6c696e75 782e736f /lib/ld-linux.so 0x08048124 2e3200

Dettagli