Magaz, The Greek Linux Magazine
Magaz Logo

Επόμενο  Προηγούμενο  Περιεχόμενα

5. Χρήσιμες έως πολύ χρήσιμες πληροφορίες ΙΙ

5.1 Dead Listing και Εργαλεία

Τι είναι το dead listing

Dead listing είναι η παρουσίαση του κώδικα ενός εκτελέσιμου σε στατική μορφή. Κύριο πλεονέκτημα αυτού του τρόπου μελέτης του κώδικα είναι πως δίνει μια πιο ολοκληρωμένη άποψη για τη λειτουργία του, και, ανάλογα με την ποιότητα του disassembler, ένα πλήθος πληροφοριών (function calls, strings κτλ). Το βασικό μειονέκτημα είναι ότι δε μπορεί να μας δώσει χρήσιμα αποτελέσματα αν ο κώδικας αλλάζει κατά τη διάρκεια της εκτέλεσης (πχ self-modifying code, συμπιεσμένα/κρυπτογραφημένα εκτελέσιμα) ή αν υπάρχουν πολλά έμμεσα jmp και calls (πχ jmp [eax]), διότι δεν μπορούμε να ακολουθήσουμε (έστω και νοητικά) την πορεία της εκτέλεσης. Το καλύτερο που έχουμε να κάνουμε σε τέτοιες περιπτώσεις, είναι να φέρουμε το εκτελέσιμο σε μια μορφή που να μπορεί να διαβάσει ο disassembler, ώστε να εκμεταλλευτούμε τις ευκολίες που μας προσφέρει.

Δυστυχώς, οι disassembly δυνατότητες του objdump δεν είναι αρκετά ικανοποιητικές (μη ξεχνάμε βέβαια πως το objdump δε σχεδιάστηκε για αυτό). Εκτός από ο γεγονός ότι δε φροντίζει να παρουσιάζει τα cross-references (πχ αν μια διεύθυνση μνήμης είναι στόχος μιας jump ή call εντολής), το disassembly του είναι γραμμικό και δε γίνεται καμία προσπάθεια να ακολουθηθεί η ροή του προγράμματος. Για παράδειγμα το παρακάτω κομμάτι κώδικα ο ΗΤEditor το κάνει disassemble σωστά...

8048080 !                                                                                                                
....... ! entrypoint:
....... !   jmp     loc_8048083                                                                                          
8048082     db      86h                                                                                                  
8048083 !                                                                                                                
....... ! loc_8048083:                    ;xref j8048080                                                                 
....... !   cmp     eax, ebx                                                                                             
8048085 !   ret

...ενώ το objdump δεν καταλαβαίνει ότι ο έλεγχος θα πάει στη διεύθυνση 0x8048083 και συνεχίζει το disassembly με το επόμενο byte (dummy byte), με αποτέλεσμα να αποσυγχρονιστεί το listing από εκεί και κάτω.
08048080 <_start>:
 8048080:       eb 01                   jmp    8048083 <_start+0x3>
 8048082:       86 39                   xchg   BYTE PTR [ecx],bh
 8048084:       d8 c3                   fadd   %st,st(3)

Μπορεί τα "κανονικά" προγράμματα να μην έχουν κώδικα αυτής της μορφής αλλά πρόκειται για μια πολύ κοινή τεχνική για προστασία έναντι των "χαζών" disassemblers.

Εργαλεία

Παρακάτω παρουσιάζονται συνοπτικά μερικοί disassemblers και το disassembly που παράγουν για το γνωστό :) πρόγραμμα.


#include <stdio.h>

int main(int argc, char **argv)
{
    int num;

    if (argc<2) {
        printf("Usage: %s <number>\n",argv[0]);
        exit(1);
    }

    num=alf(argv[1]);

    if (num>10)
        printf("Ok!\n");
    else
        printf("Failed!\n");

    return 1;
}

int alf(char *s)
{
    return atoi(s);
}


IDA

Ένα από τα καλύτερα εργαλεία για disassemby είναι ο IDA (Interactive DisAssembler). Υπάρχει μια freeware έκδοση που δουλεύει σε DOS, ενώ η εμπορική υπάρχει και για περιβάλλον Windows. Υποστηρίζει πλήθος αρχιτεκτονικών, εκτελέσιμων και compilers, ενώ περιέχει μια script γλώσσα για διάφορες αυτοματοποιήσεις. Στο linux μπορεί να εκτελεστεί μέσω wine. Το επίσημο site είναι http://www.datarescue.com, ενώ τη freeware εκδοση μπορείτε να τη βρείτε με μια αναζήτηση στο google.

.text:0804838C ; ??????????????? S U B R O U T I N E ???????????????????????????????????????
.text:0804838C 
.text:0804838C ; Attributes: bp-based frame
.text:0804838C 
.text:0804838C                 public main
.text:0804838C main            proc near               ; DATA XREF: _start+17 o
.text:0804838C 
.text:0804838C var_4           = dword ptr -4
.text:0804838C arg_0           = dword ptr  8
.text:0804838C arg_4           = dword ptr  0Ch
.text:0804838C 
.text:0804838C                 push    ebp
.text:0804838D                 mov     ebp, esp
.text:0804838F                 sub     esp, 8
.text:08048392                 and     esp, 0FFFFFFF0h
.text:08048395                 mov     eax, 0
.text:0804839A                 sub     esp, eax
.text:0804839C                 cmp     [ebp+arg_0], 1
.text:080483A0                 jg      short loc_80483C1
.text:080483A2                 sub     esp, 8
.text:080483A5                 mov     eax, [ebp+arg_4]
.text:080483A8                 push    dword ptr [eax]
.text:080483AA                 push    offset aUsageSNumber ; "Usage: %s <number>\n"
.text:080483AF                 call    _printf
.text:080483B4                 add     esp, 10h
.text:080483B7                 sub     esp, 0Ch
.text:080483BA                 push    1
.text:080483BC                 call    _exit
.text:080483C1 
.text:080483C1 loc_80483C1:                            ; CODE XREF: main+14 j
.text:080483C1                 sub     esp, 0Ch
.text:080483C4                 mov     eax, [ebp+arg_4]
.text:080483C7                 add     eax, 4
.text:080483CA                 push    dword ptr [eax]
.text:080483CC                 call    alf
.text:080483D1                 add     esp, 10h
.text:080483D4                 mov     [ebp+var_4], eax
.text:080483D7                 cmp     [ebp+var_4], 0Ah
.text:080483DB                 jle     short loc_80483EF
.text:080483DD                 sub     esp, 0Ch
.text:080483E0                 push    offset aOk      ; "Ok!\n"
.text:080483E5                 call    _printf
.text:080483EA                 add     esp, 10h
.text:080483ED                 jmp     short loc_80483FF
.text:080483EF ; ---------------------------------------------------------------------------
.text:080483EF 
.text:080483EF loc_80483EF:                            ; CODE XREF: main+4F j
.text:080483EF                 sub     esp, 0Ch
.text:080483F2                 push    offset aFailed  ; "Failed!\n"
.text:080483F7                 call    _printf
.text:080483FC                 add     esp, 10h
.text:080483FF 
.text:080483FF loc_80483FF:                            ; CODE XREF: main+61 j
.text:080483FF                 mov     eax, 1
.text:08048404                 leave
.text:08048405                 retn
.text:08048405 main            endp
.text:08048405 
.text:08048406 
.text:08048406 ; ??????????????? S U B R O U T I N E ???????????????????????????????????????
.text:08048406 
.text:08048406 ; Attributes: bp-based frame
.text:08048406 
.text:08048406                 public alf
.text:08048406 alf             proc near               ; CODE XREF: main+40 p
.text:08048406  
.text:08048406 arg_0           = dword ptr  8
.text:08048406 
.text:08048406                 push    ebp
.text:08048407                 mov     ebp, esp
.text:08048409                 sub     esp, 8
.text:0804840C                 sub     esp, 0Ch
.text:0804840F                 push    [ebp+arg_0]
.text:08048412                 call    _atoi
.text:08048417                 add     esp, 10h
.text:0804841A                 leave
.text:0804841B                 retn
.text:0804841B alf             endp
.text:0804841B 
.text:0804841C 

Bastard Disassembly Enviroment

Στον κόσμο του open source τώρα, στο sourceforge θα βρείτε projects που υπόσχονται πολλά αλλά δυστυχώς είναι σε πρώιμο στάδιο. Ένα από αυτά είναι το Bastard Disassembly Enviroment. Πρακτικά πρόκειται για μια scripting γλώσσα και το αντίστοιχο interpreter shell. Site: http://bastard.sourceforge.net.

main:
0804838C 55                             push    ebp
0804838D 89 E5                          mov     ebp , esp
0804838F 83 EC 08                       sub     esp , 0x8
08048392 83 E4 F0                       and     esp , 0xF0
08048395 B8 00 00 00 00                 mov     eax , 0x0
0804839A 29 C4                          sub     esp , eax
0804839C 83 7D 08 01                    cmp     [ebp+0x08] , 0x1
080483A0 7F 1F                          jg      loc_080483C1  ;(0x80483C1 was +31) ;  xrefs: >080483C1[x]
080483A2 83 EC 08                       sub     esp , 0x8
080483A5 8B 45 0C                       mov     eax , [ebp+0x0C]
080483A8 FF 30                          push    [eax]
080483AA 68 64 84 04 08                 push    0x8048464
080483AF E8 F8 FE FF FF                 call    printf  ;(0x80482AC was -264) ;  xrefs: >080482AC[x]
080483B4 83 C4 10                       add     esp , 0x10
080483B7 83 EC 0C                       sub     esp , 0xC
080483BA 6A 01                          push    0x1
080483BC E8 FB FE FF FF                 call    exit  ;(0x80482BC was -261) ;  xrefs: >080482BC[x]
loc_080483C1:
080483C1 83 EC 0C                       sub     esp , 0xC  ;  xrefs: <080483A0[x]
080483C4 8B 45 0C                       mov     eax , [ebp+0x0C]
080483C7 83 C0 04                       add     eax , 0x4
080483CA FF 30                          push    [eax]
080483CC E8 35 00 00 00                 call    alf  ;(0x8048406 was +53) ;  xrefs: >08048406[x]
080483D1 83 C4 10                       add     esp , 0x10
080483D4 89 45 FC                       mov     [ebp-0x04] , eax
080483D7 83 7D FC 0A                    cmp     [ebp-0x04] , 0xA
080483DB 7E 12                          jle     loc_080483EF  ;(0x80483EF was +18) ;  xrefs: >080483EF[x]
080483DD 83 EC 0C                       sub     esp , 0xC
080483E0 68 78 84 04 08                 push    0x8048478
080483E5 E8 C2 FE FF FF                 call    printf  ;(0x80482AC was -318) ;  xrefs: >080482AC[x]
080483EA 83 C4 10                       add     esp , 0x10
080483ED EB 10                          jmp     loc_080483FF  ;(0x80483FF was +16) ;  xrefs: >080483FF[x]
loc_080483EF:
080483EF 83 EC 0C                       sub     esp , 0xC  ;  xrefs: <080483DB[x]
080483F2 68 7D 84 04 08                 push    0x804847D
080483F7 E8 B0 FE FF FF                 call    printf  ;(0x80482AC was -336) ;  xrefs: >080482AC[x]
080483FC 83 C4 10                       add     esp , 0x10
loc_080483FF:
080483FF B8 01 00 00 00                 mov     eax , 0x1  ;  xrefs: <080483ED[x]
08048404 C9                             leave
08048405 C3                             ret
alf:
08048406 55                             push    ebp   ;  xrefs: <080483CC[x]
08048407 89 E5                          mov     ebp , esp
08048409 83 EC 08                       sub     esp , 0x8
0804840C 83 EC 0C                       sub     esp , 0xC
0804840F FF 75 08                       push    [ebp+0x08]
08048412 E8 B5 FE FF FF                 call    atoi  ;(0x80482CC was -331) ;  xrefs: >080482CC[x]
08048417 83 C4 10                       add     esp , 0x10
0804841A C9                             leave
0804841B C3                             ret

HT Editor

Πρόκειται για ένα ιδιαίτερα χρήσιμο και καλοφτιαγμένο εργαλείο. Ο HT Editor είναι ένας editor με έμφαση στα εκτελέσιμα αρχεία. Τα file formats που υποστηρίζει είναι τα COFF, ELF, LE, NE, PE, MZ, και Java Class. Εκτός από τη δυνατότητα για εύκολη επεξεργασία των headers, sections, symbols κτλ των αρχείων, προσφέρει έναν αρκετά καλό disassembler. Το μόνο πρόβλημα που υπάρχει (στην έκδοση 0.7.3 τουλάχιστον), είναι ότι ο C++ demangler δεν υποστηρίζει ακόμα το gnu-V3 mangling, οπότε αν κάποιο πρόγραμμα έχει γίνει compile με g++ 3 τα σύμβολα θα είναι ακαταλαβίστικα. Site: http://hte.sourceforge.net.

....... ! ;********************************************************                                                      
....... ! ; function main (global)                                                                                       
....... ! ;********************************************************                                                      
....... ! main:                           ;xref o80482f3                                                                 
....... !   push    ebp                                                                                                  
804838d !   mov     ebp, esp                                                                                             
804838f !   sub     esp, 8                                                                                               
8048392 !   and     esp, 0fffffff0h                                                                                      
8048395 !   mov     eax, 0                                                                                               
804839a !   sub     esp, eax                                                                                             
804839c !   cmp     dword ptr [ebp+8], 1                                                                                 
80483a0 !   jg      loc_80483c1                                                                                          
80483a2 !   sub     esp, 8                                                                                               
80483a5 !   mov     eax, [ebp+0ch]                                                                                       
80483a8 !   push    dword ptr [eax]                                                                                      
80483aa !   push    strz_Usage:__s__number___8048464                                                                     
80483af !   call    printf@@GLIBC_2.0                                                                                    
80483b4 !   add     esp, 10h                                                                                             
80483b7 !   sub     esp, 0ch                                                                                             
80483ba !   push    1                                                                                                    
80483bc !   call    exit@@GLIBC_2.0                                                                                      
80483c1 !                                                                                                                
....... ! loc_80483c1:                    ;xref j80483a0                                                                 
....... !   sub     esp, 0ch                                                                                             
80483c4 !   mov     eax, [ebp+0ch]                                                                                       
80483c7 !   add     eax, 4                                                                                               
80483ca !   push    dword ptr [eax]                                                                                      
80483cc !   call    alf                                                                                                  
80483d1 !   add     esp, 10h                                                                                             
80483d4 !   mov     [ebp-4], eax
80483d4 !   mov     [ebp-4], eax                                                                                         
80483d7 !   cmp     dword ptr [ebp-4], 0ah                                                                               
80483db !   jng     loc_80483ef                                                                                          
80483dd !   sub     esp, 0ch                                                                                             
80483e0 !   push    data_8048478                                                                                         
80483e5 !   call    printf@@GLIBC_2.0                                                                                    
80483ea !   add     esp, 10h                                                                                             
80483ed !   jmp     loc_80483ff                                                                                          
80483ef !                                                                                                                
....... ! loc_80483ef:                    ;xref j80483db                                                                 
....... !   sub     esp, 0ch                                                                                             
80483f2 !   push    strz_Failed___804847d                                                                                
80483f7 !   call    printf@@GLIBC_2.0                                                                                    
80483fc !   add     esp, 10h                                                                                             
80483ff !                                                                                                                
....... ! loc_80483ff:                    ;xref j80483ed                                                                 
....... !   mov     eax, 1                                                                                               
8048404 !   leave                                                                                                        
8048405 !   ret                                                                                                          
8048406 !                                                                                                                
....... ! ;********************************************************                                                      
....... ! ; function alf (global)                                                                                        
....... ! ;********************************************************                                                      
....... ! alf:                            ;xref c80483cc                                                                 
....... !   push    ebp                                                                                                  
8048407 !   mov     ebp, esp                                                                                             
8048409 !   sub     esp, 8                                                                                               
804840c !   sub     esp, 0ch                                                                                             
804840f !   push    dword ptr [ebp+8]                                                                                    
8048412 !   call    atoi@@GLIBC_2.0                                                                                      
8048417 !   add     esp, 10h                                                                                             
804841a !   leave                                                                                                        
804841b !   ret

LDasm

Το ldasm είναι ένα πρόγραμμα που χρησιμοποιεί και επεκτείνει την έξοδο του objdump. Χρησιμοποιεί perl/Tk για να δώσει ένα οπτικό αποτέλεσμα παρόμοιο με το W32Dasm που υπάρχει για Windows. Δυστυχώς, ο δημιουργός του το έχει παρατήσει και έτσι έχει ξεμείνει στην έκδοση 0.04.53 (!). Πάντως, έχει τις στοιχειώδεις δυνατότητες που χρειαζόμαστε, αν και αφού χρησιμοποιεί το objdump, έχει και τα ίδια αδύνατα σημεία. Site: http://Feedface.com/projects/ldasm.

Exported fn(): main
:0804838c 55                     push ebp
:0804838d 89e5                   mov  ebp, esp
:0804838f 83ec08                 sub  esp, 8
:08048392 83e4f0                 and  esp, -16
:08048395 b800000000             mov  eax, 0
:0804839a 29c4                   sub  esp, eax
:0804839c 837d0801               cmpl ptr [ebp+8], 1
:080483a0 7f1f                   jg   080483c1
:080483a2 83ec08                 sub  esp, 8
:080483a5 8b450c                 mov  eax, ptr [ebp]
:080483a8 ff30                   pushl (eax)

* Possible StringData Ref from Code Obj ->"Usage: %s <number>"
                                 |
:080483aa 6864840408             push 8048464

* Reference To: GLIBC_2.0::printf 
                                 |
:080483af e8f8feffff             call 080482ac
:080483b4 83c410                 add  esp, 10
:080483b7 83ec0c                 sub  esp, c
:080483ba 6a01                   push 1

* Reference To: GLIBC_2.0::exit -.
                                 |
:080483bc e8fbfeffff             call 080482bc

Referenced by a (U)nconditional or (C)onditional Jump at Address:
| :080483a0
|
:080483c1 83ec0c                 sub  esp, c
:080483c4 8b450c                 mov  eax, ptr [ebp]
:080483c7 83c004                 add  eax, 4
:080483ca ff30                   pushl (eax)

* Reference To: alf -------------.
                                 |
:080483cc e835000000             call 08048406
:080483d1 83c410                 add  esp, 10
:080483d4 8945fc                 mov  ptr [ebp-4], eax
:080483d7 837dfc0a               cmpl ptr [ebp-4], a
:080483db 7e12                   jle  080483ef
:080483dd 83ec0c                 sub  esp, c

* Possible StringData Ref from Code Obj ->"Ok!"
                                 |
:080483e0 6878840408             push 8048478

* Reference To: GLIBC_2.0::printf 
                                 |
:080483e5 e8c2feffff             call 080482ac
:080483ea 83c410                 add  esp, 10
:080483ed eb10                   jmp  080483ff

Referenced by a (U)nconditional or (C)onditional Jump at Address:
| :080483db
|
:080483ef 83ec0c                 sub  esp, c

* Possible StringData Ref from Code Obj ->"Failed!"
                                 |
:080483f2 687d840408             push 804847d

* Reference To: GLIBC_2.0::printf 
                                 |
:080483f7 e8b0feffff             call 080482ac
:080483fc 83c410                 add  esp, 10

Referenced by a (U)nconditional or (C)onditional Jump at Address:
| :080483ed
|
:080483ff b801000000             mov  eax, 1
:08048404 c9                     leave
:08048405 c3                     ret

Referenced by a Call at Address:
| :080483cc
|
Exported fn(): alf
:08048406 55                     push ebp
:08048407 89e5                   mov  ebp, esp
:08048409 83ec08                 sub  esp, 8
:0804840c 83ec0c                 sub  esp, c
:0804840f ff7508                 pushl ptr [ebp+8]

* Reference To: GLIBC_2.0::atoi -.
                                 |
:08048412 e8b5feffff             call 080482cc
:08048417 83c410                 add  esp, 10
:0804841a c9                     leave
:0804841b c3                     ret

5.2 Packed Executables - Συμπιεσμένα Εκτελέσιμα

Τι είναι;

Τα εκτελέσιμα αρχεία, όπως και όλα τα αρχεία, περιέχουν μέσα τους επαναλήψεις που καθιστούν δυνατή τη συμπίεση τους. Η συμπίεση στα εκτελέσιμα, εφόσον η αποσυμπίεση μπορεί να εκτελεστεί αρκετά γρήγορα ώστε να μη γίνεται αισθητή, είναι σίγουρα επιθυμητή. Τα αρχεία καταλαμβάνουν λιγότερο χώρο και επίσης είναι πιο δύσκολο να ερευνηθούν και να αλλαχτούν (βέβαια, για όσους κάνουμε RCE αυτό είναι μεγάλο πρόβλημα). Μάλιστα, πολλά προγράμματα συμπίεσης εκτελέσιμων εφαρμόζουν και άλλες τεχνικές, όπως κρυπτογράφηση και CRC ελέγχους. Είναι σαφές πως δε βολεύει απλώς να συμπιεστεί το αρχείο με κάποια παραδοσιακή μέθοδο (πχ με το gzip). Αυτό συμβαίνει, διότι εκτός από το ότι το εκτελέσιμο δεν είναι πια εκτελέσιμο (η κατάσταση διορθώνεται με χρήση scripts για αυτόματη αποσυμπίεση, το utility gzexe λειτουργεί έτσι), χάνεται η προστασία από το RCE, αφού τελικά το εκτελέσιμο θα βρεθεί στην αρχική του μορφή πριν εκτελεστεί. Για αυτό, έχουν αναπτυχθεί διάφορες άλλες τεχνικές για συμπίεση προγραμμάτων.

Βασικές Τεχνικές packing

Καταρχάς θα δούμε την απλή packing τεχνική που αναφέραμε στην εισαγωγή . Η βασική της λειτουργία φαίνεται στο παρακάτω σχήμα:

Ο packer συμπιέζει όλο το εκτελέσιμο και δημιουργεί ένα καινούργιο που περιλαμβάνει τα συμπιεσμένα δεδομένα και τον κώδικα αποσυμπίεσης. Ο κώδικα αποσυμπιέζει τα συμπιεσμένα δεδομένα (αρχικό εκτελέσιμο), τα σώζει σε ένα προσωρινό αρχείο, και μετά το εκτελεί συνήθως με exec(). Η αδυναμία του βρίσκεται στο γεγονός πως εμφανίζεται το αυθεντικό εκτελέσιμο στο δίσκο, και επομένως δεν παρέχει ιδιαίτερη προστασία. Το θετικό στοιχείο του είναι η απλότητα.

Μια πιo εξελιγμένη τεχνική :

Εδώ τα πράγματα είναι πιο ενδιαφέροντα. Δε συμπιέζεται όλο το εκτελέσιμο αλλά μόνο τα segments του. Το καινούργιο εκτελέσιμο περιέχει τα συμπιεσμένα δεδομένα και τον κώδικα για το unpacking (κατά προτίμηση μετά τα δεδομένα).

Κατά την εκτέλεση φορτώνονται τα συμπιεσμένα segments στη μνήμη, με τέτοιο τρόπο, ώστε όταν αποσυμπιεστούν να έχουν τις αρχικές διευθύνσεις τους. Επίσης, ο unpacker πρέπει να κάνει και κάτι άλλο που δεν είναι φανερό με την πρώτη ματιά. Αν το αυθεντικό εκτελέσιμο χρησιμοποιούσε shared objects (βιβλιοθήκες), τότε μέσα στο αρχείο υπήρχαν οι πληροφορίες, ώστε ο dynamic linker να τα φορτώσει. Όμως το συμπιεσμένο εκτελέσιμο έχει διαφορετικές πληροφορίες και έτσι τα shared objects δε φορτώνονται. Θα πρέπει ο unpacker να επωμιστεί αυτό το βάρος και επιπλέον να διορθώσει τις αναφορές στα εξωτερικά σύμβολα. Αυτό γίνεται με χρήση των συναρτήσεων dlopen() και dlsym() που χρησιμοποιούνται για να φορτώνουν shared objects στο run-time (δείτε manpages). Ο unpacker, αφού ολοκληρώσει όλες τις εργασίες του, θα μεταφέρει τον έλεγχο στο OEP (original entry point) και έτσι θα αρχίσει το κυρίως πρόγραμμα.

Βασικές Τεχνικές Unpacking

Στην πιο απλή περίπτωση, όπου ο unpacker αποσυμπιέζει το αρχικό αρχείο στο δίσκο και το εκτελεί από εκεί, τα πράγματα είναι εύκολα. Αρκεί να βρούμε ποιο προσωρινό αρχείο χρησιμοποιείται και τελειώσαμε. Το /proc filesystem είναι ιδιαίτερα χρήσιμο, όπως θα φανεί και στο hands-on παράδειγμα που ακολουθεί.

Αν ο packer είναι εξελιγμένος, τότε θα πρέπει να φερθούμε και εμείς πιο έξυπνα. Η μέθοδος αυτή είναι σχετικά επίπονη αλλά μπορεί να εφαρμοστεί ακόμα και στις πιο δύσκολες περιπτώσεις. Σκοπός είναι να κάνουμε dump από τη μνήμη την εικόνα του εκτελέσιμου σε ένα αρχείο. Αυτό, βέβαια, δε θα είναι το πλήρες, αυθεντικό αρχείο αλλά συχνά είναι ότι καλύτερο μπορούμε να κάνουμε. Εξάλλου, μετά μπορούμε να κάνουμε διάφορες επεμβάσεις για να το "βελτιώσουμε".

Η διαδικασία αποτελείται από τα παρακάτω βήματα:

  1. Ανάκτηση του OEP (original entry point) : Εδώ προσπαθούμε να εντοπίσουμε τη διεύθυνση της πρώτης εντολής του αυθεντικού προγράμματος στην εικόνα του εκτελέσιμου μετά την αποσυμπίεση. Αυτό το βήμα είναι που απαιτεί την περισσότερη εμπειρία. Σημάδια πως τελειώνει ο κώδικας του unpacker και περνάμε στο αρχικό εκτελέσιμο είναι:
    • Unconditional jump ( άμεσο πχ jmp 0x8048954 ή έμμεσο πχ jmp eax ) σε κάποια "μακρινή" διεύθυνση.
    • Αλλαγή του ύφους του προγράμματος. Οι unpackers είναι συνήθως γραμμένοι σε assembly με το χέρι και το στυλ τους διαφέρει από τον κώδικα που έχει παραχθεί από compilers.
    • Χρήση των popa/popad (pop all registers). Επειδή η unpackers αλλοιώνουν το context της διεργασίας (πχ τιμές των registers) τους σώζουν όλους πριν αρχίσουν (με pusha/pushad) και τους επαναφέρουν πριν περάσουν τον έλεγχο στο αρχικό πρόγραμμα.
  2. Dump της εικόνας (image) του εκτελέσιμου σε ένα αρχείο : Κάνουμε dump την εικόνα του εκτελέσιμου, όπως είναι αυτή, ακριβώς πριν περάσει ο έλεγχος στο αυθεντικό εκτελέσιμο. Για αυτό χρειαζόμαστε το OEP που μας δινει το προηγούμενο βήμα. Αφου, λοιπόν, το έχουμε, αναγκάζουμε τη διεργασία να εκτελεστεί μέχρι το OEP (έτσι είμαστε σίγουροι πως όλα είναι unpacked όπως πρέπει) και τότε κάνουμε dump την εικόνα του εκτελέσιμου. Μπορούμε να χρησιμοποιήσουμε την εντολή dump του gdb. Η σύνταξη της είναι dump memory <file> <start> <stop>. Για να αποφασίσουμε ποιες διευθύνσεις θα κάνουμε dump μπορούμε να συμβουλευτούμε το map από το /proc/<pid>/. Για τα εκτελέσιμα στο linux, αρκούν συνήθως τα δύο πρώτα segments που είναι το code και data segment αντίστοιχα .
  3. Διόρθωση του ELF Header : Διορθώνουμε τον ELF Header του dumped αρχείου, ώστε να μπορεί να εξεταστεί και να εκτελεστεί. Συγκεκριμένα θέτουμε το entry point του εκτελέσιμου στο OEP, διορθώνουμε τα στοιχεία των segments και αναδημιουργούμε το DYNAMIC segment. Το τελευταίο είναι αρκετά επίπονο και όχι απαραίτητο αν απλώς θέλουμε να εξετάσουμε τον κώδικα (dissasembly). Αν δε γίνει αυτή η διόρθωση, τότε οι διευθύνσεις των συναρτήσεων των shared objects θα έχουν παντα τις τιμές που είχαν την στιγμή που κάναμε dump, διότι ο dynamic linker δε θα ενεργοποιηθεί. Αν χρησιμοποιούμε το dumped εκτελέσιμο μόνο στο δικό μας σύστημα και με τι ίδιες ακριβώς βιβλιοθήκες, ίσως να τη γλιτώσουμε.

Επόμενο  Προηγούμενο  Περιεχόμενα


Valid HTML 4.01!   Valid CSS!