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

Reverse engineering: disassembly disassembly difficoltoso il processo di disassembly può “desincronizzarsi”

Dettagli

L`assembler INTEL IA32

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

Dettagli

Reverse engineering: debugging

Reverse engineering: debugging (%edx),%eax %eax,0xc(%ebp) (%ecx),%eax %eax,0x8(%ebp) (%esp),%ebx 0x4(%esp),%esi 0x8(%esp),%edi

Dettagli