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
[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
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