Reverse engineering: disassembly
Transcript
Reverse engineering: disassembly
Università degli Studi di Milano Facoltà di Scienze Matematiche, Fisiche e Naturali Reverse engineering: disassembly Roberto Paleari <[email protected]> Emanuele Passerini <[email protected]> A.A. 2009–2010 Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 1 / 21 Tecniche statiche Disassembly Cos’è? stream of bytes disassembly sequence of assembly instructions Esempio $ echo -ne "\x89\x04\x24\xc3" | ndisasm -u 00000000 890424 mov [esp],eax 00000003 C3 ret Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 2 / 21 Tecniche statiche Disassembly Cos’è? stream of bytes disassembly sequence of assembly instructions Esempio $ echo -ne "\x89\x04\x24\xc3" | ndisasm -u 00000000 890424 mov [esp],eax 00000003 C3 ret Instruction set istruzioni a lunghezza fissa (RISC, e.g., SPARC) decodifica più efficiente per il processore istruzioni a lunghezza variabile (CISC, e.g., Intel x86) codice più compatto Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 2 / 21 Tecniche statiche Disassembly Indecidibilità della separazione tra codice e dati Intel x86: 248/256 byte rappresentano l’inizio di un’istruzione valida Esempio ...0x0f 0x85 0xc0 0x0f 0x85 . . . se consideriamo il byte 0x0f come codice: jne offset se consideriamo il byte 0x0f come data e il byte 0x85 come codice: 0x0f // data test eax, eax jne offset Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 3 / 21 Disassembly Problema: esplosione di complessità 1 2 3 4 5 6 7 8 9 10 11 12 13 Roberto Paleari, Emanuele Passerini int main(int argc, char ∗∗argv) { int num; scanf(”%d”, &num); if(num == 1234) printf(”ok\n”); else printf(”no\n”); return 0; } Reverse engineering: disassembly A.A. 2009–2010 4 / 21 Disassembly Problema: esplosione di complessità push mov sub call call call leave ret pushl jmp add jmp push jmp jmp push jmp jmp push jmp jmp push jmp xor pop mov and push push push push push push push push call hlt nop nop push mov %ebp %esp,%ebp $0x8,%esp 8048304 8048360 8048490 0x80495dc *0x80495e0 %al,(%eax) *0x80495e4 $0x0 8048290 *0x80495e8 $0x8 8048290 *0x80495ec $0x10 8048290 *0x80495f0 $0x18 8048290 %ebp,%ebp %esi %esp,%ecx $-16,%esp %eax %esp %edx $0x80483e0 $0x8048430 %ecx %esi $0x8048384 80482c0 %ebp %esp,%ebp push sub call pop add mov test je call pop pop leave ret nop ... push mov sub cmpb je jmp add mov call mov mov test jne movb leave ret nop push mov sub mov test je mov test je movl call Roberto Paleari, Emanuele Passerini %ebx $0x4,%esp 8048310 %ebx $0x12c8,%ebx -4(%ebx),%edx %edx,%edx 8048326 80482d0 %eax %ebx leave ret nop push mov sub and mov add add shr shl sub lea %ebp mov %esp,%ebp movl $0x8,%esp call mov $0x0,0x8049600 804834b cmp 804835d jne $0x4,%eax movl %eax,0x80495fc call jmp *%edx movl 0x80495fc,%eax call (%eax),%edx mov %edx,%edx leave 8048341 ret $0x1,0x8049600 nop ... push mov %ebp push %esp,%ebp push $0x8,%esp push 0x8049508,%eax call %eax,%eax add 8048381 sub $0x0,%eax lea %eax,%eax lea 8048381 sub $0x8049508,(%esp)sar *%eax lea cmp je %ebp lea %esp,%ebp call $0x18,%esp dec $-16,%esp cmp $0x0,%eax jne $0xf,%eax lea $0xf,%eax call $0x4,%eax add $0x4,%eax pop %eax,%esp pop -4(%ebp),%eax pop %eax,0x4(%esp) pop $0x80484e8,(%esp)ret 80482b0 lea -4(%ebp),%eax push $0x4d2,%eax mov 80483cb push $0x80484eb,(%esp)push 80482a0 push 80483d7 call $0x80484ee,(%esp)add 80482a0 sub $0x0,%eax call lea lea sub %ebp sar %esp,%ebp mov %edi je %esi xor %ebx mov 8048483 lea $0x11ed,%ebx lea $0xc,%esp inc -224(%ebx),%eax call -224(%ebx),%edi add %edi,%eax cmp $0x2,%eax jne Reverse engineering: disassembly -1(%eax),%esi $-1,%esi 8048419 0x0(%esi),%esi *(%edi,%esi,4) %esi $-1,%esi 8048410 0x0(%esi),%esi 80484c4 $0xc,%esp %ebx %esi %edi %ebp 0x0(%esi),%esi %ebp %esp,%ebp %edi %esi %ebx 8048483 $0x119d,%ebx $0xc,%esp 8048278 -224(%ebx),%eax -224(%ebx),%edx %edx,%eax $0x2,%eax %eax,-16(%ebp) 804847b %edi,%edi %edx,%esi 0x0(%esi),%esi 0x0(%edi),%edi %edi *(%esi) $0x4,%esi %edi,-16(%ebp) 8048470 add pop pop pop pop ret mov ret nop ... push mov push sub mov cmp je mov lea lea call mov sub cmp jne pop pop pop ret nop ... push mov push sub call pop add call pop pop leave ret $0xc,%esp %ebx %esi %edi %ebp (%esp),%ebx %ebp %esp,%ebp %ebx $0x4,%esp 0x80494f8,%eax $-1,%eax 80484bd $0x80494f8,%ebx 0x0(%esi),%esi 0x0(%edi),%edi *%eax -4(%ebx),%eax $0x4,%ebx $-1,%eax 80484b0 %eax %ebx %ebp %ebp %esp,%ebp %ebx $0x4,%esp 80484d0 %ebx $0x1108,%ebx 8048330 %ecx %ebx A.A. 2009–2010 4 / 21 Disassembly Instruction set istruzioni a lunghezza fissa ogni istruzione inizia ad un indirizzo multiplo della sua lunghezza istruzioni a lunghezza variabile disassembly difficoltoso il processo di disassembly può “desincronizzarsi” Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 5 / 21 Disassembly Instruction set istruzioni a lunghezza fissa ogni istruzione inizia ad un indirizzo multiplo della sua lunghezza istruzioni a lunghezza variabile disassembly difficoltoso il processo di disassembly può “desincronizzarsi” Problemi interposizione di dati e istruzioni nello stesso address space (come distinguerli?) istruzioni di lunghezza variabile trasferimenti di controllo indiretti (function pointer, dynamic linking, jump table, . . . ) Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 5 / 21 Disassembly Complicazioni Nella fase di compilazione si perdono: nomi delle variabili informazioni sui tipi concetto di “blocco” macro commenti . . . altri problemi riconoscere i limiti delle funzioni distinguere i parametri delle funzioni Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 6 / 21 Disassembly Sintassi AT&T vs Intel $ objdump -M att -d /bin/ls ... push %ebp xor %ecx,%ecx mov %esp,%ebp sub $0x8,%esp mov %ebx,(%esp) mov 0x8(%ebp),%ebx mov %esi,0x4(%esp) mov 0xc(%ebp),%esi mov (%ebx),%edx mov 0x4(%ebx),%eax xor 0x4(%esi),%eax xor (%esi),%edx or %edx,%eax je 8049c60 <exit@plt+0x13c> mov %ecx,%eax mov (%esp),%ebx mov 0x4(%esp),%esi mov %ebp,%esp pop %ebp ret Roberto Paleari, Emanuele Passerini $ objdump -M intel -d /bin/ls ... push ebp xor ecx,ecx mov ebp,esp sub esp,0x8 mov DWORD PTR [esp],ebx mov ebx,DWORD PTR [ebp+0x8] mov DWORD PTR [esp+0x4],esi mov esi,DWORD PTR [ebp+0xc] mov edx,DWORD PTR [ebx] mov eax,DWORD PTR [ebx+0x4] xor eax,DWORD PTR [esi+0x4] xor edx,DWORD PTR [esi] or eax,edx je 8049c60 <exit@plt+0x13c> mov eax,ecx mov ebx,DWORD PTR [esp] mov esi,DWORD PTR [esp+0x4] mov esp,ebp pop ebp ret Reverse engineering: disassembly A.A. 2009–2010 7 / 21 Disassembly Esempio 08048350 08048355 08048357 08048358 0804835F 08048366 0804836B 08048370 08048375 0804837A 0804837C 08048381 Roberto Paleari, Emanuele Passerini B8 FF C3 48 6F BA B9 BB B8 CD B8 C3 66 83 04 08 D0 65 72 0E 58 00 04 80 00 6C 6C 00 83 00 00 6C 64 00 04 00 00 6F 20 57 21 0A 0D 00 08 00 00 00 00 00 mov $0x8048366,%eax call *%eax ret (data) (data) mov $0xe,%edx mov $0x8048358,%ecx mov $0x0,%ebx mov $0x4,%eax int $0x80 mov $0x0,%eax ret Reverse engineering: disassembly A.A. 2009–2010 8 / 21 Disassembly Esempio 08048350 08048355 08048357 08048358 0804835F 08048366 0804836B 08048370 08048375 0804837A 0804837C 08048381 B8 FF C3 48 6F BA B9 BB B8 CD B8 C3 66 83 04 08 D0 65 72 0E 58 00 04 80 00 6C 6C 00 83 00 00 6C 64 00 04 00 00 6F 20 57 21 0A 0D 00 08 00 00 00 00 00 mov $0x8048366,%eax call *%eax ret (data) (data) mov $0xe,%edx mov $0x8048358,%ecx mov $0x0,%ebx mov $0x4,%eax int $0x80 mov $0x0,%eax ret Tecniche utilizzate linear sweep disassembly recursive traversal disassembly Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 8 / 21 Linear sweep disassembly (e.g., objdump) inizia al primo byte del segmento testo procedi decodificando un’istruzione dopo l’altra assunzione: istruzioni memorizzate in locazioni adiacenti 08048350 08048355 08048357 08048358 08048359 0804835A 0804835B 0804835C 0804835D 08048360 08048362 08048365 0804836A 08048370 08048375 0804837A 0804837C 08048381 Roberto Paleari, Emanuele Passerini B8 FF C3 48 65 6C 6C 6F 20 72 64 0D 00 BB B8 CD B8 C3 66 83 04 08 D0 57 6C 21 BA B9 00 04 80 00 6F 0A 0E 58 00 00 00 83 00 00 00 04 08 00 00 00 00 00 mov $0x8048366,%eax call *%eax ret dec %eax gs insb (%dx),%es:(%edi) insb (%dx),%es:(%edi) outsl %ds:(%esi),(%dx) and %dl,0x6f(%edi) jb 0x80483ce and %ecx,%fs:(%edx) or $0xeba,%eax add %bh,0x8(%ecx) mov $0x0,%ebx mov $0x4,%eax int $0x80 mov $0x0,%eax ret Reverse engineering: disassembly A.A. 2009–2010 9 / 21 Linear sweep disassembly (e.g., objdump) inizia al primo byte del segmento testo procedi decodificando un’istruzione dopo l’altra assunzione: istruzioni memorizzate in locazioni adiacenti 08048350 08048355 08048357 08048358 08048359 0804835A 0804835B 0804835C 0804835D 08048360 08048362 08048365 0804836A 08048370 08048375 0804837A 0804837C 08048381 Roberto Paleari, Emanuele Passerini B8 FF C3 48 65 6C 6C 6F 20 72 64 0D 00 BB B8 CD B8 C3 66 83 04 08 D0 57 6C 21 BA B9 00 04 80 00 6F 0A 0E 58 00 00 00 83 00 00 00 04 08 00 00 00 00 00 mov $0x8048366,%eax call *%eax ret dec %eax IA-32 disassembly gs insb (%dx),%es:(%edi)è self-repairing insb (%dx),%es:(%edi) outsl %ds:(%esi),(%dx) and %dl,0x6f(%edi) jb 0x80483ce and %ecx,%fs:(%edx) or $0xeba,%eax add %bh,0x8(%ecx) mov $0x0,%ebx mov $0x4,%eax int $0x80 mov $0x0,%eax ret Reverse engineering: disassembly A.A. 2009–2010 9 / 21 Linear sweep disassembly IA-32: self-repairing disassembly Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 10 / 21 Recursive traversal disassembly (e.g., IDA Pro) 1 2 inizia dall’entry point quando incontri un’istruzione di branch: determina possibili successori riprendi il disassemby a questi indirizzi 08048350 08048355 08048357 Roberto Paleari, Emanuele Passerini B8 66 83 04 08 FF D0 C3 mov $0x8048366,%eax call *%eax ret Reverse engineering: disassembly A.A. 2009–2010 11 / 21 Offuscamento di codice binario Obiettivo preservare la semantica di un programma e, allo stesso tempo, rendere più difficile la comprensione del suo funzionamento interno [1] Come fare? junk byte in posizioni non raggiungibili a run-time branch function per modificare il normale comporamento delle chiamate a funzione overlapping instruction (difficile da realizzare nella pratica) ... Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 12 / 21 Offuscamento di codice binario Junk byte Caratteristiche 1 i junk byte devono essere istruzioni parziali 2 non devono essere raggiungibili a run-time Basic block candidati non possono essere “attraversati” dal flusso di esecuzione (i.e., i loro predecessori devono terminare con una CTI incondizionata) quali junk byte inserire prima di questi blocchi? Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 13 / 21 Thwarting linear sweep Come? junk byte prima dei candidate block branch flipping può aumentare il numero di candidati: bcc addr becomes L0 : Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly bcc L0 jmp addr ... A.A. 2009–2010 14 / 21 Thwarting recursive traversal Idea 1 i disassembler assumono che le CTIs si comportano in modo “ragionevole” 2 difficile identificare i target di una CTI indiretta Tecniche branch function predicati opachi jump table spoofing ... Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 15 / 21 Thwarting recursive traversal: branch function data una mappa finita ϕ = {a1 → b1 , . . . , an → bn }, una branch function fϕ è una funzione tale che: a1 : a2 : an : jmp b1 ... jmp b2 ... jmp bn a1 : is replaced with a2 : an : call ϕ ... call ϕ ... call ϕ offuscamento del control flow può ingannare disassembler ricorsivi (i path di fall-back delle istruzioni di call non sono più validi) Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 16 / 21 Control flow graph Cos’è? struttura fondamentale in program analysis grafo orientato in cui: nodi: computazioni (basic block) archi: possibili flussi di esecuzione Basic block sequenza non interrompibile di istruzioni singolo entry point singolo exit point Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 17 / 21 Control flow graph Esempio 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int find max(int ∗v, int n) { unsigned int max, i; int ris; if(n <= 0) ris = −1; else { max = v[0]; i = 1; while(i < n) { if(v[i] > max) max = v[i]; i = i + 1; } ris = max; } return ris; B1: if(n <= 0) goto B2 true false B3: max = v[0] i = 1 B2: ris = -1 B4: if(i < n) goto B5 false true B6: ris = max true B9: return ris } Roberto Paleari, Emanuele Passerini B5: if(v[i] > max) goto B7 false B7: max = v[i] B8: i = i + 1 Reverse engineering: disassembly A.A. 2009–2010 18 / 21 Call graph Cos’è? grafo orientato C = (R, F ) i nodi rappresentano procedure gli archi sono relazioni chiamante-chiamato se (ri , rj ) ∈ R, nel corso di ri si ha almeno una chiamata a rj Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 19 / 21 Call graph Cos’è? grafo orientato C = (R, F ) i nodi rappresentano procedure gli archi sono relazioni chiamante-chiamato se (ri , rj ) ∈ R, nel corso di ri si ha almeno una chiamata a rj Esempio Roberto Paleari, Emanuele Passerini P1 P3 P2 P4 Reverse engineering: disassembly A.A. 2009–2010 19 / 21 Identificazione funzioni Prologo push %ebp mov %esp, %ebp sub X, %esp Epilogo mov %ebp, %esp pop %ebp ret oppure leave ret IDA Pro → FLIRT Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 20 / 21 Bibliografia I G. Vigna. Malware Detection, chapter Static Disassembly and Code Analysis. Advances in Information Security. Springer, 2007. Roberto Paleari, Emanuele Passerini Reverse engineering: disassembly A.A. 2009–2010 21 / 21
Documenti analoghi
Reverse engineering: disassembly
disassembly difficoltoso
il processo di disassembly può “desincronizzarsi”
L`assembler INTEL IA32
• Nell'assembler
Intel
(sintassi
AT&T)
si
usa
dis>nguere
anche
se
l'istruzione
opera
su
byte
(b),
su
word
a
16bit
(w)
o
su
...
Reverse engineering: debugging
(%edx),%eax
%eax,0xc(%ebp)
(%ecx),%eax
%eax,0x8(%ebp)
(%esp),%ebx
0x4(%esp),%esi
0x8(%esp),%edi