- IDA Pro 3.8
(Tutorial version 1.1)
- =====================================================================================
- What's new:
- Corretti alcuni errori di ortografia ;))
- Chiarita la funzione del comando "Code" anche con
un esempio
- Spiegata pi∙ approfonditamente la funzione del comando
"Undefine" anche con un esempio
- Analizzata la funzione "Struct" con esempi
vari e spiegazioni pi∙ accurate
- Spiegata MOLTO meglio ;) la funzione "Enum" anche
con degli esempi
- Chiarito l'uso della tecnologia FLIRT
- Spiegato MOLTO chiaramente l'uso ed il significato
dell'istruzione PTR
- Illustrato chiaramente il funzionamento dei puntatori
- Spiegato l'utilizzo delle funzioni "mov" e
"lea"
- Spiegato qualcosa riguardo l'indirizzamento indiretto e
l'offset
- =====================================================================================
-
- Salve a tutti, in questo tutorial cercher≥ di spiegarvi nel modo
pi∙ chiaro possibile l'utilizzo del miglior dissassembler che esiste, cioΦ: IDA Pro
3.8x, il tutorial non Φ orientato ai NewBies NewBies per≥ possono provarci anche loro,
il documento non Φ da considerarsi definitivo infatti cercher≥ di ampliarlo sempre pi∙
nel corso del tempo.
-
- IDA Pro sta a significare: Intercative Disassembler Pro, infatti
Φ verissimo che ida Φ interattivo, ma andiamo per gradini ed iniziamo. Scegliamo un file
da disassemblare, possibilmente uno molto piccolo e magari per windows, clicchiamo su
Idaw.exe, vediamo apparire la finestra del nostro amato programma, premiamo ok e scegliamo
il file, a questo punto Ida aprirα una finestra con scritto in alto "Load File of
New Format", nelle prime tre righe ci viene chiesto di scegliere il tipo di file che
si vuole disassemblare, cioΦ se un eseguibile Windows (o che comunque usi il formato PE),
un eseguibile DOS oppure un file binario, checkiamo la prima casella: Portable Esecutable,
pi∙ in basso vediamo la scritta "Loading Segment", qui dovrete inserire l'entry
point del programma, in genere Φ 0x1000, come di default, ma se siete incerti aprite il
file col ProcDump e vedetelo, lasciamo quindi 0x1000, pi∙ in basso appare un altro campo
"Loading offset", nel quale dovremmo inserire l'offset del primo byte
dell'inizio del primo segmento, ma a noi non interessa infatti questa opzione va
utilizzata solo se si vuole disassemblare un file binario, pi∙ in basso dobbiamo checkare
altre caselle, per ora ve le enumero e poi ve le spiego:
-
- Create segments
Load resources
Rename DLL entries
Manual load
Fill segment gaps
Make imports section
Don't align segments
-
- Allora, Create segments Φ un'opzione utile per i file binari,
infatti ci crea i vari segmenti, ma ci≥ non Φ necessario se si vuole disassemblare un
eseguibile, Load resources invece carica le risorse dai file NE, neanche questa Φ
necessaria se si disassembla un eseguibile con formato PE, Rename DLL entries Φ
un'opzione che se non attivata permette a IDA di piazzare tra il disassemblato dei
commenti ripetibili ad ogni funzione importata, Manual load non ci interessa nel caso dei
file con formato PE, se per≥ il formato Φ diverso allora l'opzione pu≥ essere attivata
e IDA ci chiederα l'indirizzo per il caricamento di ogni oggetto del file, Fill segment
gaps Φ lo stesso utile solo per formati diversi dal PE, se checkata IDA non fa altro che
riempire tutti i "buchi" tra i vari segmenti, Make imports section Φ invece
utile per i file in formato PE, se attivata dice a IDA di eliminare la sezione .idata dal
file e di convertire tutte quante le definizioni in essa presenti come direttive esterne,
la guida ci dice che qualche volta nella sezione .idata possiamo trovare delle
informazioni aggiuntive e dobbiamo quindi disabilitare questa opzione, Don't align
segments, come dice la parola stessa, se checkiamo questa opzione non permettiamo il
riallineamento dei segmenti, ma non serve per i file con formato PE. A questo punto ci
troviamo davanti anche due pulsanti uno con scritto "Processor Type", a
differenza di ci≥ che potreste credere qui non dovrete specificare il tipo di processore
che avete ma il tipo di processore per il quale Φ stato scritto il programma, di default
Φ 80386 ed Φ giusto che sia cos∞, quindi potete lasciare inalterata questa opzione,
l'altro pulsante reca il testo "Analisys options", cliccate anche qui sopra e
vedrete altri due pulsanti e due opzioni, esaminiamo prima queste due:
- Analysis enabled: se la casella Φ checkata allora IDA analizzerα
il programma mentre noi non stiamo agendo sul disassemblato, lasciando comunque la
prioritα alle nostre richieste, questa opzione deve essere abilitata, se non lo fosse
potremmo incorrere in problemi di varia natura.
Indicator enabled: Φ quel contatore che si trova in alto a destra e che reca le scritte:
-
- AU:__idle__ AutoAnalysis is finished.
AU:disable AutoAnalysis is disabled.
FL:<address> execution flow is being traced
PR:<address> function is being created
AC:<address> the code analysis goes through the noted address
LL:<number> a signature file is being loaded
L1:<address> the first pass of FLIRT
L2:<address> the second pass of FLIRT
L3:<address> the third pass of FLIRT
FI:<address> the final pass of autoanalysis
??:<address> the noted address becomes unexplored
@:<number> indication of various activity
- a seconda di cosasta facendo IDA...╚ meglio lasciarlo abilitato.
Poi abbiamo i due pulsanti, clickiamo sul primo "Kernel analyser options" e
vediamo apparirci davanti una morra di opzioncine eccole:
-
- Create offsets and segments using fixup info
Mark typical code sequences as code
Delete instructions with no xrefs
Trace execution flow
Create functions if call is present
Analyse and create all xrefs
Use flirt signatures
Create function if data xref data->code32 exists
Rename jump functions as j_...
Rename empty functions as nullsub_...
Create stack variables
Trace stack pointer
Create ascii string if data xref exists
Convert 32bit instruction operand to offset
Create offset if data xref to seg32 exists
Make final analysis pass
Locate and create jump tables
Coagulate data segments in the final pass
-
- Dhe hi hi, ora ci divertiamo, tralascerei volentieri la
spiegazione di tutte queste funzioni ma, come ogni guida che si rispetti devo analizzare
il programma da cima a fondo....Chissα forse un giorno qualcuno domanderα a qualcun
altro "Hei dove imparo ad usare IDA?" e quel qualcun altro dirα "Prova sul
sito di Quequero, ha scritto un'ottima guida"....Dhe hi hi lascietemi sognare
;))))))))
- Riprendendo il filo del discorso ecco la spiegazione:
- Create offsets and segments using fixup info: IDA per rendere pi∙
piacevole il disassemblato fa uso delle informazioni di rilocazione e converte tutti gli
oggetti con le info di rilocazione in word o doubleword e se un'istruzione ha assegnate
delle informazioni di rilocazione IDA converte i dati ad un offset oppure ad un segmento,
per esempio poniamo di avere nel nostro codice sorgente qualcosa di questo genere:
-
- .386
- -----snip snip-----
- .data
qualcosa dd 000F3785h
.code
- start:
- mov eax, offset qualcosa
- end start
-
- Se disassembliamo il file con W32Dasm otteniamo qualcosa come:
- mov eax, 0040200
- Se invece lo disassemblassimo con IDA e con l'opzione di cui sopra
attivata allora otterremo qualcosa come questa:
- mov eax, offset qualcosa
- Capitoooooo!!!! ;)
- Mark typical code sequences as code: a detta dell'autore IDA
riconosce alcune sequenze tipiche di codice (esempio: push bp e mov bp, sp) e durante il
caricamento se ne trova qualcuna la converte in istruzione
-
- Delete instructions with no xrefs: permette a IDA di non definire
le istruzioni non referenziate, in pratica se noi eseguiamo il comando
"undefine" (che vi spiegher≥ in seguito) all'inizio di una funzione il
programma cancellerα tutte le istruzioni che hanno perso contatto con l'istruzione appena
"undefinita"...vi si chiarirα tutto pi∙ tardi non preoccupatevi ;)
-
- Trace execution flow: permette a IDA di convertire tutte le
referenze a dei byte in istruzioni
-
- Create functions if call is present: fa si che IDA crei una
funzione se nel codice Φ presente una chiamata, in pratica se nel codice troviamo una
chiamata di questo genere:
- call routine
- allora IDA creerα una funzione all'etichetta "routine",
questa opzione cerca di "staccare" le chiamate dal resto del codice per
permetterci un approccio visuale, ma anche tecnico, pi∙ semplice
-
- Analyse and create all xrefs: questa Φ l'opzione che fa la
differenza tra IDA ed il W32dasm, senza di essa il nostro programma non analizzerebbe il
file e non creerebbe tutte le xreferences e le altre chicche caratteristiche di IDA.
-
- Use flirt signatures: permette l'uso della tecnologia FLIRT, non
preoccupatevi non vedrete IDA e IDO fare gli sporcaccioni sul monitor ;)))))), questa
tecnologia consente di riconoscere il tipo di compilatore usato e di identificare le
chiamate standard, in questo modo invece di vedere questo: call 00469187, vedremo: call
MessageboxA, nel caso che questa tecnologia fallisca nel riconoscere i compilatori (leggi:
Delphi) la si pu≥ sempre forzare ad usare le istruzioni del compilatore che reteniamo sia
stato usato per fare quel determinato programma semplicemente aprendo il menu "View |
Signatures" e premendo "ins" per far apparire la lista dei
compilatori disponibili.
-
- Create function if data xref data->code32 exists: se IDA
incontra un riferimento ad un dato da un SEGMENTO DATI ad un SEGMENTO CODICE a 32bit
controlla la presenza di istruzioni disassemblabili utili, se trova un'istruzione la marca
(manco a dirlo ;) come un'istruzione e crea l∞ una funzione
-
- Rename jump functions as j_...: funzione di utilitα elevatissima,
questa opzione permette ADDIRITTURA di cambiare una istruzione come:
- jmp dovevuoi
- in:
- j_dovevuoi
- vi rendete conto...Ma dico ve ne rendete conto di quanto la
presenza di questa opzione possa permettere anche a mio cugino di 10 anni di diventare
cracker...Mio dio che genio l'autore del programma ;))))))))))))))))) scherzi a parte lui
Φ stato davvero un genio
-
- Rename empty functions as nullsub_...: permette a IDA di
rinominare le funzioni vuote, cioΦ quelle contenenti solo l'istruzione "ret"
come nullsub_1...nullsub_2 ecc...Anche questa funzione deve essere stata pensata per
decenni ;))))
-
- Create stack variables: fa si che IDA crei automaticamente le
variabili dello stack ed i parametri delle funzioni
-
- Trace stack pointer: con questa opzione attivata IDA traccerα il
valore dello Stack Pointer (SP)
-
- Create ascii string if data xref exists: se IDA incontra una
referenza ad un oggetto non definito allora cerca per la presenza di una stringa
ASCII, se la lunghezza della stringa Φ abbastanza allora IDA crea guarda caso una stringa
ASCII ;)
-
- Convert 32bit instruction operand to offset: funzia solo su
segmenti a 32bit, se un'istruzione ha un operando che pu≥ essere convertito ad un'utile
esepressione allora la converte in offset, il valore dell'operando deve per≥ essere pi∙
grande di 0x10000
-
- Create offset if data xref to seg32 exists: se nel programma IDA
incontra un riferimento ad un segmento a 32bit ed il file contiene un valore che pu≥
essere rappresentato come un offset allora IDA lo converte.....ad un offset
-
- Make final analysis pass: questa opzione permette a IDA di
coagulare tutti i byte non esplorati convertendoli da dati ad istruzioni
-
- Locate and create jump tables: questa opzione permette a IDA di
ipotizzare la dimensione e l'indirizzo di una "jump table"
-
- Coagulate data segments in the final pass: questa opzione torna
utile solo se Φ attivata anche l'opzione "Make final analysis pass" e permette
a IDA di convertire i byte insplorati ad array di dati nel segmento dati. Se disabilitiamo
questa opzione IDA coagulerα solo il segmento codice.
- Ottimo, abbiamo finito questo pulsante, lasciamo le impostazioni
di default, o se volete disabilitate quella che converte i jump xxxx in j_xxxx che spesso
Φ pi∙ scomoda che utile e premiamo esc per entrare nei meandri del pulsante
"Processor specific analysis options", dopo il click ci si presentano solo 4
opzioni e spieghiamole come solito una ad una:
-
- Convert immediate operand of "push" to offset
Convert db 90h after "jmp" to "nop"
Convert immediate operand of "mov reg,..." to offset
Convert immediate operand of "mov memory,..." to offset
- Convert immediate operand of "push" to offset: se ida
vede una sequenza tipo questa: push seg, push gino, proverα a convertire gino in un
offset
-
- Convert db 90h after "jmp" to "nop": se dopo
un jump troviamo "db 90h" invece di lasciarlo com'Φ lo trasforma in nop (No
operation)
-
- Convert immediate operand of "mov reg,..." to offset:
anche qui se ida trova qualcosa come: mov ax, 258h, mov sp, es allora convertirα
258h in un offset
-
- Convert immediate operand of "mov memory,..." to offset:
ancora se IDA trova istruzioni come: mov ax, 895h mov X, seg (X Φ un riferimento ad
una memoria) allora converte 895h in offset
-
- Ottimo premiamo esc due volte e diamo un'occhiata al pannello,
l'unica cosa che c'Φ rimasta Φ quel campo indicato da dll directory, l∞ dobbiamo
inserire la directory nella IDA andrα a guardare per trovare i riferimenti alle varie
DLL, il problema Φ che ida non cerca le DLL bens∞ i file .ids, la directory nel mio caso
Φ: c:\ida\ids\Win se usate windows altrimenti cambierα solo l'ultima cartella.
-
- Siamo pronti a questo punto per iniziare il disassembling del
file, sceglietene uno piccolo....molto piccolo consiglio 8-15 kb che ci vogliono pochi
secondi, lo dico per coloro che IDA la stanno conoscendo solo ora, questo programma Φ
molto ma molto pi∙ lento del W32dasm vi garantisco per≥ che tutto il tempo in pi∙ che
perdete nel disassembling lo riguadagnate dopo, quindi premete "OK" ed
aspettate....Allora, appena il segnalatore in alto a destra recherα la scritta
"ready" vorrα dire che IDA avrα finito, a quel punto avrete davanti come prima
cosa una pagina come questa:
-
- CODE:00401000
; File Name : C:\esempio.exe
CODE:00401000
; Format : Portable executable (PE)
CODE:00401000
; Section 1. (virtual address 00001000)
CODE:00401000
; Virtual size : 00001000 ( 4096.)
CODE:00401000
; Section size in file : 00000400 ( 1024.)
CODE:00401000
; Offset to raw data for section: 00000600
CODE:00401000
; Flags 60000020: Text Executable Readable
CODE:00401000
; Alignment : 16 bytes ?
CODE:00401000
p386n
CODE:00401000
model flat
CODE:00401000
;
----------------------------------------------------------------
CODE:00401000
; Segment type: Pure code
CODE:00401000
CODE segment para public 'CODE' use32
CODE:00401000
assume cs:CODE
CODE:00401000
assume es:nothing, ss:nothing, ds:nothing, fs:nothing,
gs:nothing
CODE:00401000
;____________________________________________
CODE:00401000
; S u b r o u t i n e
CODE:00401000
public start
CODE:00401000
start proc near
- In questa prima parte abbiamo tutte le intestazioni iniziali del
file, quelle in pratica che vedremmo se avessimo il sorgente e soprattutto IDA ci informa
del tipo di file appena disassemblato nel caso non lo avessimo saputo prima. Vorrei
passare per≥ ad un esempio pratico, l'autore ci dice che possiamo utilizzare IDA per tre
scopi:
- 1) Imparare un trucco di programmazione in un programma
interessante
- 2) Patchare il file se non si ha il sorgente
- 3) Ottenere un codice compilabile dal disassemblato
-
- Noi faremo tutte e tre le cose, iniziamo.
- Quello che vi propongo ora Φ il codice assembly di un
programmillo che genera una messagebox a seconda del valore che assume eax, ecco il
codice, capirete con il commento:
- ---------------------------------------------------8<-------------------------------------------------------
- ; Per compilare il sorgente Φ necessario possedere TASM
5.0 reperibile sul
; mio sito: http://quequero.cjb.net nella sezione tools
;
; Ecco le istruzioni di compilazione, basta scriverle in un prompt di DOS
; tasm32 /t -ml -m5 -q esempio
; tlink32 -Tpe -aa -x -c esempio ,,, import32
.386p
.model flat, stdCALL
extrn MessageBoxA:Proc ; definiamo le API necessarie
extrn ExitProcess:Proc
include windows.inc
.data
Caption db 'Esempio - -
Coded by Quequero',0
Messaggio db 'Il registro EAX ha assunto un
valore inferiore di 1.771.590.911',0
Random1 dd 12553
; valori casuali utilizzati nell'algoritmo
Random2 dd 2212
; di Lehmer
null equ 0
- .code
start:
xor eax, eax
; Azzeriamo EAX
mov ecx, 01ffffffh
; Queste due righe servono
a creare un timer, l'istruzione
wait: loop wait
; "loop" decrisa ogni volta ECX fino a che contiene
zero, il
-
; loop in questione fa comparire il messagebox dopo circa
-
; un secondo dall'avvio del programma
casuale: mov
eax, Random1
;
Algoritmo di Lehmer per la generazione di numeri
mul Random2
; casuali (anche se dovremmo parlare di pseudo-casualitα)
inc eax
mov Random1, eax
; Fine algoritmo
cmp Random1, 699854ffh ; Confronta Random1
con 1.771.590.911 (699854ffh)
jae casuale
; Se Random1 contiene un valore maggiore o uguale a quello
; stabilito prima ripeti l'algoritmo altrimenti continua sotto
push MB_OK OR MB_ICONQUESTION ; Genera una messagebox
con un pulsante di ok,
push offset Caption
; l'icona della "i" di informazione ed il
testo
push offset Messaggio
; contenuto nelle stringhe "Caption" e
"Messaggio"
push null
call MessageBoxA
call ExitProcess
; Esci dal programma
end start
---------------------------------------------------8<-------------------------------------------------------
come potete vedere il programma setta un timer ad un secondo e poi da il via alla
generazione di un numero pseudo-casuale tramite l'algoritmo di Lehmer, il timer all'inizio
Φ dovuto al fatto che la CPU impiega un tempo infinitesimale a generare tanti numeri
affinchΦ uno sia minore del valore da noi proposto, in questo modo ritardiamo il sorgere
della messagebox.
- Supponiamo di essere a conoscenza della presenza dell'algoritmo di
Lehmer in questo programma, questo algoritmo ci serve assolutamente ma non sappiamo dove
reperirlo, cosa facciamo allora? Ovvio! Disassembliamo il programma e cerchiamo di
ritrovarcelo lα in mezzo, apriamo IDA e vediamo cosa ci racconta:
-
- CODE:00401000 ; File Name : C:\tasm\prog\wind.EXE
CODE:00401000 ; Format : Portable executable (PE)
CODE:00401000 ; Section 1. (virtual address 00001000)
CODE:00401000 ; Virtual size : 00001000 ( 4096.)
CODE:00401000 ; Section size in file : 00000200 ( 512.)
CODE:00401000 ; Offset to raw data for section: 00000600
CODE:00401000 ; Flags 60000020: Text Executable Readable
CODE:00401000 ; Alignment : 16 bytes ?
CODE:00401000 p386n
CODE:00401000 model flat
CODE:00401000 ;
----------------------------------------------------------------
CODE:00401000 ; Segment type: Pure code
CODE:00401000 CODE segment para public 'CODE' use32
CODE:00401000 assume cs:CODE
CODE:00401000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
CODE:00401000 ; ________________________________________________________________
CODE:00401000 ; S u b r o u t i n e
CODE:00401000 33 C0 public start
CODE:00401000 start proc near
CODE:00401000 xor eax, eax
CODE:00401002 B9 FF FF FF 01 mov ecx, 1FFFFFFh
CODE:00401007 CODE_401007: ; CODE XREF: start+7j
CODE:00401007 E2 FE loop CODE_401007
CODE:00401009 CODE_401009: ; CODE XREF: start+24j
CODE:00401009 A1 5E 20 40 00 mov eax, ds:DATA_40205E
CODE:0040100E F7 25 62 20 40 00 mul ds:DATA_402062
CODE:00401014 40 inc eax
CODE:00401015 A3 5E 20 40 00 mov ds:DATA_40205E, eax
CODE:0040101A 81 3D 5E 20 40 00+cmp ds:DATA_40205E, 699854FFh
CODE:00401024 73 E3 jnb short CODE_401009
CODE:00401026 6A 20 push 20h
CODE:00401028 68 00 20 40 00 push offset str->Esempio--CodedB
CODE:0040102D 68 1E 20 40 00 push offset str->IlRegistroEaxHa
CODE:00401032 6A 00 push 0
CODE:00401034 E8 05 00 00 00 call j_MessageBoxA
CODE:00401039 E8 06 00 00 00 call j_ExitProcess
CODE:00401039 start endp
CODE:0040103E ;
________________________________________________________________
CODE:0040103E ; S u b r o u t i n e
CODE:0040103E j_MessageBoxA proc near ; CODE XREF:
start+34p
CODE:0040103E FF 25 4C 30 40 00 jmp ds:MessageBoxA
CODE:0040103E j_MessageBoxA endp
CODE:00401044 ;
________________________________________________________________
CODE:00401044 ; S u b r o u t i n e
CODE:00401044 j_ExitProcess proc near ; CODE XREF:
start+39p
CODE:00401044 FF 25 54 30 40 00 jmp ds:ExitProcess
CODE:00401044 j_ExitProcess endp
CODE:0040104A 00 00 00 00 00 00+align 200h
CODE:00401200 ?? ?? ?? ?? ?? ??+db 0E00h dup(?)
CODE:00401200 ?? ?? ?? ?? ?? ??+CODE ends
DATA:00402000 ; Section 2. (virtual address 00002000)
DATA:00402000 ; Virtual size : 00001000 ( 4096.)
DATA:00402000 ; Section size in file : 00000200 ( 512.)
DATA:00402000 ; Offset to raw data for section: 00000800
DATA:00402000 ; Flags C0000040: Data Readable Writable
DATA:00402000 ; Alignment : 16 bytes ?
DATA:00402000 ;
----------------------------------------------------------------
DATA:00402000 ; Segment type: Pure data
ªDATA:00402000 DATA segment para public 'DATA' use32
ªDATA:00402000 assume cs:DATA
ªDATA:00402000 45 73 65 6D 70 69+str->Esempio--CodedB db
'Esempio - - Coded by Quequero',0
ªDATA:00402000 6F 20 2D 20 2D 20+ ; DATA XREF: start+28o
ªDATA:0040201E 49 6C 20 72 65 67+str->IlRegistroEaxHa db 'Il registro EAX ha assunto
un valore infe
ªDATA:0040201E 69 73 74 72 6F 20+ ; DATA XREF: start+2Do
ªDATA:0040205E*09 31 00 00 DATA_40205E dd 3109h ; DATA XREF: start+9r
ªDATA:0040205E* ; start+15w
ªDATA:0040205E* ; start+1Ar
ªDATA:00402062 A4 08 00 00 DATA_402062 dd 8A4h ; DATA XREF: start+Er
ªDATA:00402066 00 00 00 00 00 00+align 1000h
ªDATA:00402066 00 00 00 00 00 00+DATA ends
ª.idata:0040304C ;
ª.idata:0040304C ; Imports from USER32.dll
ª.idata:0040304C ;
ª.idata:0040304C ; Section 3. (virtual address 00003000)
ª.idata:0040304C ; Virtual size : 00001000 ( 4096.)
ª.idata:0040304C ; Section size in file : 00000200 ( 512.)
ª.idata:0040304C ; Offset to raw data for section: 00000A00
ª.idata:0040304C ; Flags C0000040: Data Readable Writable
ª.idata:0040304C ; Alignment : 16 bytes ?
ª.idata:0040304C ;
--------------------------------------------------------------
ª.idata:0040304C ; Segment type: Externs
ª.idata:0040304C ; _idata
ª.idata:0040304C ?? ?? ?? ?? extrn MessageBoxA:dword ; DATA
XREF: j_MessageBoxAr
ª.idata:00403050
ª.idata:00403054 ;
ª.idata:00403054 ; Imports from KERNEL32.dll
ª.idata:00403054 ;
.idata:00403054 ?? ?? ?? ?? extrn ExitProcess:dword ; DATA XREF: j_ExitProcessr
.idata:00403058 00 00 00 00 end start
-
- Come potete notare il codice Φ di difficile interpretazione, non
per la difficoltα ma per il casino di numeri, per diminuire il bordello possiamo fare una
cosa cioΦ: sappiamo che in un programma salvo eccezione il codice che ci interessa si
trova nelle sezioni CODE (nel caso sia stato compilato con un compilatore Borland) e .text
(se Φ stato compilato con qualcos'altro), come potete ben vedere, di lato al virtual address c'Φ il nome della sezione ".idata.00403054" cos∞ facendo potremmo tagliar via una buona parte di codice
"futile", ma perchΦ farlo a mano quando IDA ci mette a disposizione un'opzione
molto utile? Bene usiamola, andate nel menu "View2 e cliccate su "Segments"
e scegliete "CODE", doppioclickateci sopra e guradate un po' cosa abbiamo
davanti?....
-
- CODE:00401000
start
proc near
CODE:00401000
xor
eax, eax
CODE:00401002
mov
ecx, 1FFFFFFh
CODE:00401007 CODE_401007: ; CODE XREF: start+7j
CODE:00401007
loop
CODE_401007
CODE:00401009 CODE_401009: ; CODE XREF: start+24j
CODE:00401009
mov
eax, ds:DATA_40205E
CODE:0040100E
mul
ds:DATA_402062
CODE:00401014
inc
eax
CODE:00401015
mov
ds:DATA_40205E, eax
CODE:0040101A
cmp
ds:DATA_40205E, 699854FFh
CODE:00401024
jnb
short CODE_401009
CODE:00401026
push
20h
CODE:00401028
push
offset str->Esempio--CodedB
CODE:0040102D
push
offset str->IlRegistroEaxHa
CODE:00401032
push
0
CODE:00401034
call j_MessageBoxA
CODE:00401039
call j_ExitProcess
CODE:00401039 start endp
Tadαααααα i sofficiniiiii.....Ehm scusate
volevo dire....Tadααααααααα il codiceeee!!!! Un po' cambiato ma in fondo Φ
quello, allora cerchiamo di capire come funzia sto algoritmo, possiamo identificarlo
subito, parte all'indirizzo 00401009 e termina tre righe sotto, comunque eccolo:
-
- CODE:00401009
mov
eax, ds:DATA_40205E
CODE:0040100E
mul
ds:DATA_402062
CODE:00401014
inc
eax
CODE:00401015
mov
ds:DATA_40205E, eax
- allora, facciamo finta di non aver creato noi il programma e di
aver identificato l'algoritmo andando per esclusione, ci troviamo davanti due valori che
non sappiamo di che genere siano e questi sono: DATA_40205E e DATA_402062, come
facciamo a sapere che valori contengono? Semplice premete in IDA "G" che
significa "Go to address" e scriviamo nel box che i Φ appena apparso
"DATA:40205E" e poi invio, potevamo anche cliccare su "View |
Segments", andare su "DATA" e cercare l'indirizzo manualmente, ma cos∞ si
fa prima, molto pi∙ seplice era doppioclickare su quel nome ;), ecco comunque ci≥ che ci
appare davanti:
-
- DATA:0040205E
DATA_40205E dd 3109h
; DATA XREF: start+9r
DATA:0040205E*
; start+15w
DATA:0040205E*
; start+1Ar
DATA:00402062
DATA_402062 dd 8A4h
; DATA XREF: start+Er
- Dhe hi hi, guardate un po', abbiamo due valori esadecimali che se
convertiti in decimali sono gli stessi di quelli che avevamo usato noi per Random1 e
Random2, se siamo proprio dei beoti e non capiamo ancora l'algoritmo usiamo una delle
funzione che amo di pi∙ cioΦ quella che ci permette di rinominare le istruzioni,
clickiamo una volta su DATA_40205E e premiamo "N",
scriviamo nel box "Random1", clickiamo poi su DATA_402062 e
facciamo la stessa cosa solo inserendo "Random2", torniamo al pezzo di codice
precedente premendo esc e guardate un po' la sorpresa:
-
- CODE:00401009
mov eax,
ds:Random1
CODE:0040100E
mul ds:RANDOM2
CODE:00401014
inc eax
CODE:00401015
mov ds:Random1, eax
- proviamo ora a fare una bella cosa, selezionate queste quattro
righe in IDA col mouse (cliccate sulla prima riga e scendete fino alla quarta), cliccate
poi sul menu "File" poi "Produce output file" e poi ancora
"Produce asm file..." salvate il file con un nome qualunque ed andate ad aprirlo
con il notepad, togliete tutti i "ds", ricordate anche che IDA ci ha fatto
vedere che Random1 e Random2 erano delle doubleword contenenti i valori 3109h e 8a4h....ed
ecco il risultato:
-
- Random1 dd 12553
; questo ce lo aggiungete voi, 12553 e
2212 sono i valori esadecimali
- Random2
dd 2212 ; covertiti in decimali
-
- mov eax, Random1
mul RANDOM2
- inc eax
mov Random1, eax
- ragazzi ecco per voi l'algoritmo che cercavamo uguale identico a
quello del nostro sorgente. Abbiamo scoperto come si fa a "leggere" un
disasemblato, impariamo ora come si patcha. IDA ci da la possibilitα di cambiare i byte
di un programma e di produrre un eseguibile "patchato" ma come potete vedere
essa gira in una shell DOS ed anche per questo motivo non pu≥ creare eseguibili in
formato non DOS, di conseguenza non possiamo patchare il programma appena visto ma
dobbiamo crearne uno appositamente fatto per girare sotto DOS, ecco il codice assembly:
- ---------------------------------------------------8<-------------------------------------------------------
; Per compilare il sorgente Φ necessario possedere TASM 5.0 reperibile sul
; mio sito: http://quequero.cjb.net nella sezione tools
;
; Ecco le istruzioni di compilazione, basta scriverle in un prompt di DOS
; tasm esempio
; tlink esempio
.286
.model small
.stack 100h
.DATA
Stringa db 'Bravo mi hai patchato correttamente!!!',0Dh,0Ah,'$'
.CODE
start:
mov ax,@data
; Setta il segment register
mov ds, ax
mov es, ax
xor ax, ax
; Azzera AX
cmp ax, 1
; Vedi se Φ uguale ad 1 ?!
je esatto
; ╚ uguale? Mostra la stringa altrimenti chiudi il programma
mov ah,4ch
; Funzione 'Chiudi'
int 21h
esatto:
mov dx, offset Stringa
mov ah, 09h
; Visualizziamo la stringa
int 21h
end start
- ---------------------------------------------------8<-------------------------------------------------------
Questo programmillo non fa altro che azzerare Ax, controllarlo per vedere se Φ uguale a 1
e mostrare una stringa se ci Φ, il problema Φ che se azzeriamo Ax, non potrα mai essere
uguale a 1 e quindi il programma si chiuderα sempre, ecco perchΦ abbiamo bisono di
patcharlo. Apriamo IDA, selezioniamo questo file e disassembliamolo, le vie che ci si
pongono sono essenzialmente due cioΦ: cambiare l'istruzione "cmp ax, 1" in modo
da farla diventare "cmp ax, 0" oppure forzare il "he esatto" facendolo
diventare "jmp esatto", noi comunque le esamineremo tutte e due. Facciamo un
click sull'istruzione "cmp ax, 1", clicchiamo in alto nel menu "edit"
e successivamente su "patch program" poi dobbiamo scegliere se cambiare un byte,
una word oppure assemblare l'istruzione, in questo caso scegliamo "Assemble..."
e scriviamo nel box "cmp ax, 0", il programma ora Φ patchato, ma vediamo anche
l'altro metodo, clickiamo su "je esatto" andiamo nel menu di cui sopra,
clichiamo su change byte e scriviamo......cosa scriviamo? BhΦ Φ semplice, dobbiamo
cambiare un salto condizionato in uno incondizionato, sappiamo che tutti i jump short non
condizionati hanno la forma "EB XX" quindi non dobbiamo fare altro che
sostituire i byte "74 04" con "EB 04" ed il gioco Φ fatto, a questo
punto andate nel menu "File" poi "Produce output file" ed infine
"Produce exe file", salvatelo con un nome qualunque e cliccateci sopra, vedete
la stringa? Bene allora l'avete patchato come Iddio comanda.
- Non mi soffermo ulteriormente su questo punto dato che Φ molto
facile patchare un programma, ma non lo farete comunque mai con IDA dal momento che di
programmi per dos ce ne sono rimasti davvero pochi. Passiamo ora ad analizzare l'aspetto
pi∙ importante di IDA cioΦ: come ricavare un sorgente compilabile dal disassemblato. Per
prima cosa stavolta non vi do il codice ma il disassemblato di modo che possiate imparare
a ricostruire un sorgente, il codice che ho scritto ve lo dar≥ alla fine, volevo
reversare un programmino di winzoz ma non ne ho trovato nessuno abbastanza piccolo per
iniziare, gli unici piccoli erano poi in formato NE, comunque ecco il file smembrato ;) :
- ---------------------------------------------------8<-------------------------------------------------------
- ; File Name : C:\tasm\prog\wind.EXE
; Format : Portable executable (PE)
; Section 1. (virtual address 00001000)
; Virtual size :
00001000 ( 4096.)
; Section size in file : 00000200 (
512.)
; Offset to raw data for section: 00000600
; Flags 60000020: Text Executable Readable
; Alignment : 16 bytes ?
p386n
model flat
;
═══════════════════════════════════════════════════════════════════════════
; Segment type: Pure code
CODE segment para public 'CODE' use32
assume cs:CODE
assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
;
███████████████████████████████████████████████████████████████████████████
; S u b r o u t i n e
public start
start proc near ; CODE XREF:
start+30j start+45j
push 23h
push offset str->Esempio2--Coded
push offset str->CiauzCliccaSuUn
push 0
call j_MessageBoxA
cmp eax, 6
jz short CODE_401032
cmp eax, 2
jz short CODE_401047
push 20h
push offset str->Esempio2--Coded
push offset str->HaiSceltoNo
push 0
call j_MessageBoxA
jmp short start
CODE_401032: ;
CODE XREF: start+16j
push 20h
push offset str->Esempio2--Coded
push offset str->BravoHaiSceltoO
push 0
call j_MessageBoxA
jmp short start
CODE_401047: ;
CODE XREF: start+1Bj
call $+5
jmp ds:ExitProcess
start endp
;
███████████████████████████████████████████████████████████████████████████
; S u b r o u t i n e
j_MessageBoxA proc near ;
CODE XREF: start+Ep start+2Bp
start+40p
jmp ds:MessageBoxA
j_MessageBoxA endp
align 200h
db 0E00h dup(?)
CODE ends
; Section 2. (virtual address 00002000)
; Virtual size :
00001000 ( 4096.)
; Section size in file : 00000200 (
512.)
; Offset to raw data for section: 00000800
; Flags C0000040: Data Readable Writable
; Alignment : 16 bytes ?
;
═══════════════════════════════════════════════════════════════════════════
; Segment type: Pure data
DATA segment para public 'DATA' use32
assume cs:DATA
str->Esempio2--Coded db 'Esempio 2 - -
Coded by Quequero',0 ; DATA XREF: start+2o
; start+1Fo start+34o
str->CiauzCliccaSuUn db 'Ciauz!!! Clicca su un tasto',0 ; DATA XREF:
start+7o
str->BravoHaiSceltoO db 'Bravo hai scelto SI!!!',0 ; DATA XREF:
start+39o
str->HaiSceltoAnnull db 'Hai scelto annulla!!!',0
str->HaiSceltoTermin db 'Hai scelto termina',0
str->HaiSceltoNo db 'Hai scelto NO!!!',0 ; DATA XREF: start+24o
align 1000h
DATA ends
;
; Imports from KERNEL32.dll
;
; Section 3. (virtual address 00003000)
; Virtual size :
00001000 ( 4096.)
; Section size in file : 00000200 (
512.)
; Offset to raw data for section: 00000A00
; Flags C0000040: Data Readable Writable
; Alignment : 16 bytes ?
;
═══════════════════════════════════════════════════════════════════════════
; Segment type: Externs
; _idata
extrn ExitProcess:dword ; DATA XREF: start+4Cr
;
; Imports from USER32.dll
;
extrn MessageBoxA:dword ; DATA XREF:
j_MessageBoxAr
end start
- ---------------------------------------------------8<-------------------------------------------------------
- Bene bene, il codice l'ho scritto io e non Φ difficile anzi
direi che la conversione Φ piuttosto immediata vi consiglio comunque di studiarvi un
attimo il disassemblato qua sopra prima di procedere.....fatto? Ok vediamo un po' di
rinominare qualche funzione, guardate il codice e ve lo spiego:
-
- push 23h
push offset str->Esempio2--Coded
push offset str->CiauzCliccaSuUn
push 0
call j_MessageBoxA
- Come potete ben vedere queste 5 righe non sono altro che la
routine di generazione di una messagebox, la struttura Φ questa:
-
- MessageBox(
-
UINT uType
// stile del messagebox (bottoni e icone)
- LPCTSTR lpCaption,
// offset del titolo del message
box
- LPCTSTR lpText,
//
offset del testo del messagebox
- HWND hWnd,
// handle della finestra (NULL se Φ assente)
- );
-
- in assembly tale funzione avrebbe pi∙ o meno queste fattezze:
-
- push MB_OK OR
MB_ICONQUESTION
- push offset TITOLO
- push offset TESTO
- push NULL
; NULL se non abbiamo una finestra genitrice
- call MessageBoxA
-
- bene bene, ma 23h cos'Φ? Allora il file windows.inc ci suggerisce
tali cose:
-
- MB_OK =
0000H
- MB_OKCANCEL =
0001H
- MB_ABORTRETRYIGNORE = 0002H
- MB_YESNOCANCEL =
0003H
- MB_YESNO =
0004H
- MB_RETRYCANCEL =
0005H
- MB_ICONHAND =
0010H
- MB_ICONQUESTION =
0020H
- MB_ICONEXCLAMATION = 0030H
- MB_ICONASTERISK =
0040H
-
- una semplice addizione ci rivela che 23h Φ
uguale a 0020h+0003h cioΦ MB_ICONQUESTION+MB_YESNOCANCEL, ci≥ vuol dire che il
programmatore (io) nella prima riga ha usato questi parametri:
-
- push MB_YESNOCANCEL OR MB_ICONQUESTION.
-
- adesso rinominiamo in IDA le stringhe in modo da avere qualcosa
come:
-
- push offset caption
-
- invece di: push offset str->Esempio2...
-
- Senza che vi dico come si fa che l'avete imparato prima, a questo
punto possiamo giα ricostruire tutte le routine di messagebox presenti nel codice,
rinominate tutte le stringhe come "Caption", "Testo",
"Testo2" ecc....Avremo in questo modo la struttura originale, ma manca una cosa,
se guardate bene dopo ogni chiamata ad un messagebox c'Φ un "cmp eax, ?", cosa
sarα mai? BhΦ, prendiamo la nostra API reference preferita ed andiamo a vedere.....Ci
dice che l'ID del tasto premuto viene mosso in eax, ma come facciamo a sapere a cosa
corrisponde il numero che sta l∞? Semplice, sempre con la nostra API reference! Ecco la
tabella:
-
- IDOK = 1
- IDCANCEL = 2
- IDABORT = 3
- IDRETRY = 4
- IDIGNORE = 5
- IDYES = 6
- IDNO = 7
-
- e cos∞ notiamo con piacere che dopo ogni chiamata
il programma checka EAX per vedere quale pulsante Φ stato premuto ed aprire un altro
messagebox, quindi finiamo di rinominare tutti quanti i vari jump e vediamo come Φ
diventato il nostro codice...:
- public start
start proc near ; CODE XREF:
start+30j start+45j
push MB_ICONQUESTION or MB_YESNOCANCEL
push offset Caption
push offset Messaggio
push NULL
call MessageBoxA
cmp eax, 6
jz short SI_PREMUTO
cmp eax, 2
jz short ESCI
push MB_ICONQUESTION or MB_OK
push offset Caption
push offset No_Premuto
push NULL
call MessageBoxA
jmp short start
SI_PREMUTO ;
CODE XREF: start+16j
push MB_ICONQUESTION or MB_OK
push offset Caption
push offset Messaggio
push NULL
call MessageBoxA
jmp short start
ESCI: ;
CODE XREF: start+1Bj
call ExitProcess
start endp
-
- Ottimo!!! Vorrei darvi per≥ ancora dei consigli,
a dire il vero non Φ facile ricordare tutti gli ID a memoria e per facilitarci il lavoro
IDA ci mette a disposizione i "commenti", i commenti non sono altro che degli
appunti a bordo riga che mette IDA o che mettiamo noi, ne esistono due tipi: ripetibili e
non, la differenza sta nel fatto che se mettiamo su un jump un commenti ripetibile del
tipo "questo fa uscire dal programma" IDA posizionerα la stessa frase
all'arrivo di quel jump, mentre nel caso di un commento non ripetibile questo non succede,
per inserire un commento ripetibile basta cliccare sulla riga che ci interessa e premere ;
(si un punto e virgola) se invece ne vogliamo inserire uno non ripetibile allora dobbiano
premere : (due punti) e poi scriverlo nel box, sappiamo tutto ora del programma, ci resta
solo di andarci a leggere tutte le varie stringhe che si trovano nella sezione data ed
unirle....fatto ecco il codice:
-
- .386p
.model flat, stdCALL
EXTRN ExitProcess:PROC
EXTRN MessageBoxA:PROC
INCLUDE WINDOWS.INC
.DATA
null equ 0
Caption db
'Esempio 2 - - Coded by Quequero',0
Messaggio db 'Ciauz!!! Clicca su un
tasto',0
Messaggio1 db 'Bravo hai scelto occhei!!!',0
Messaggio2 db 'Hai scelto annulla!!!',0
Messaggio3 db 'Hai scelto termina',0
Messaggio4 db 'Hai scelto NO!!!',0
- .code
start:
push MB_YESNOCANCEL or MB_ICONQUESTION
push offset Caption
push offset Messaggio
push NULL
call MessageBoxA
cmp eax, 6
; YES premuto?
je occhei
cmp eax, 2
; CANCEL premuto?
je exit
push MB_OK or MB_ICONQUESTION
push offset Caption
push offset Messaggio4
push NULL
call MessageBoxA
jmp start
occhei:
push MB_OK OR MB_ICONQUESTION
push offset Caption
push offset Messaggio1
push NULL
call MessageBoxA
jmp start
exit:
call ExitProcess
end start
-
- Lo so che la stringa "Hai premuto termina..." non
viene mai usata, lei sta li solo per confondere le idee ;))))
- La nostra cara IDA ha altre doti "nascoste" che
vengono usate di meno e che mi accinger≥ a spiegarvi. Se andate nel menu
"file"|"Load file" vedrete varie opzioni e pi∙ precisamente:
-
- IDC file...
Additional binary file...
IDS file...
Debug information file...
FLIRT signature file...
- IDC file: i file IDC sono dei file script che possono
tranquillamente essere scritti a mano per creare delle proprie macro
-
- Additional binary file: da qui carichiamo un file binario
addizionale e aggiungiamo le nuove informazioni in coda alle vecchie
-
- IDS file: questa non serve potenzialmente mai, i file .IDS
sonon quelli contenenti tutte le informazioni sulle varie funzioni di winzoz ma IDA le
carica da sola durante il disassembling
-
- Debug information file: bhΦ se IDA trova un file DBG
inerente al file che stiamo disassemblando allora si preoccupa di caricarlo, se invece non
lo trova allora glielo possiamo fare caricare noi
-
- FLIRT signature file: avete presente i file .SIG del PGP?
BhΦ non c'entrano 'na mazza ;) da questi file IDA carica delle funzioni modello standard
che l' aiuteranno a riconoscere delle funzioni standard, IDA cerca il file adatto da sola
ma non sempre ci riesce, nel caso lo volessimo fare a mano troveremmo tali file nella
directory SIG, per caricarne o scaricarne uno basta aprire la finestra
"signature" e premere ins per inserirne uno e del per scaricarne uno.
- Esploriamo adesso il menu "Produce output file...",
ecco le varie opzioni:
-
- Produce MAP file... Shift-F10
Produce ASM file... Alt-F10
Produce LST file...
Produce EXE file... Ctrl-F10
Produce DIF file...
Dump database to IDC file...
- ╚ giunto il momento di conoscere anche loro, hehehehe
iniziamo.
-
- Produce MAP file: IDA scriverα un file con tutte le
informazioni riguardo ai segmenti ed i nomi ordinati a seconda dei loro valori
-
- Produce ASM file: giα incontrata, produce comunque un file
.asm contenente il testo asm da noi selezionato, Φ molto utile quando si creano i
keygenerator
-
- Produce LST file: IDA scrive un file con il disassemblato
attuale oppure con una porzione di codice da noi selezionata
-
- Produce EXE file: come giα detto ricrea l'eseguibile nel
caso lo avessimo modificato (funziona solo con i file DOS)
-
- Produce DIF file: questa funzione crea se non erro un file in
pieno testo nel quale sono annotati i valori originali e quelli che sono stati cambiati,
la guida dice che il file assumerebbe queste sembianze:
-
- commento
nome_del_file
offset: vecchio_valore nuovo_valore
-
- Dump database to IDC file: con questa opzione IDA salva il
database in un file di testo.
- Il menu "IDC command..." ci consente di
caricare un piccolo script scritto specificatamente per IDA, la lista Φ talmente lunga
che se ne avete bisogno aprite il menu e premete F1 per vedervela ;))))
- Scusate ma sto iniziando a sentire i primi sintomi
della fatica, sono infatti 4 ore che sto scrivendo......Senza contare quelle dei giorni
precedenti ovviamente ;))
- I restanti mi sebrano superflui, passiamo al
successivo menu cioΦ "Edit", un menu maledettamente ricco di opzioni, ecco cosa
si presenta davanti ai nostri occhi una volta aperto:
-
- Code
Data
ASCII
Array...
Undefine
Rename...
Operand type
Comments
Segments
Structs
Enums
Functions
Patch program
Other
C'mon babe let's go explain.......Code: opzione alquanto
carina che serve a convertire in istruzioni i byte segnati da IDA cone inesplorati,
allora, questa istruzione spesso e volentieri sarα pi∙ che indispensabile per giungere
ai vostri pi∙ oscuri scopi, ecco che vi presento un esempio pratico dell'uso di questo
comando che sarebbe altrimenti un po' oscuro.
- Pu≥ capitare (anzi, con eseguibili dos capita sempre :) che
IDA non riconosca al primo colpo dei byte
utili di codice con istruzioni importanti, questo potrebbe succedere con programmi senza
uno specificato entry point oppure se IDA non ha trovato un determinato path di
esecuzione, in tal caso il codice che avremmo sarebbe di questo tipo (esempio preso dal
disasm di un crackme ;):
-
- seg000:0100
start:
seg000:0100 jmp short seg000_15B
seg000:0102 nop
seg000:0103 or ax, 610Ah
seg000:0106 db 6Ah ; j
seg000:0107 db 61h ; a
seg000:0108 db 78h ; x
seg000:0109 db 20h ;
seg000:010A db 66h ; f
seg000:010B db 88h ; Ω
seg000:010C db 74h ; t
seg000:010D db 65h ; e
seg000:010E db 20h ;
seg000:010F db 64h ; d
seg000:0110 db 75h ; u
seg000:0111 db 20h ;
seg000:0112 db 66h ; f
seg000:0113 db 6Ch ; l
seg000:0114 db 65h ; e
seg000:0115 db 75h ; u
seg000:0116 db 72h ; r
seg000:0117 db 20h ;
seg000:0118 db 63h ; c
seg000:0119 db 72h ; r
seg000:011A db 61h ; a
seg000:011B db 63h ; c
seg000:011C db 6Bh ; k
seg000:011D db 6Dh ; m
seg000:011E db 65h ; e
seg000:011F
db 2Ch ; ,
seg000:0120 db 20h ;
seg000:0121 db 31h ; 1
seg000:0122 db 30h ; 0
seg000:0123 db 20h ;
seg000:0124 db 63h ; c
seg000:0125 db 68h ; h
seg000:0126 db 61h ; a
seg000:0127 db 72h ; r
seg000:0128 db 73h ; s
seg000:0129 db 2Ch ; ,
seg000:012A db 20h ;
seg000:012B db 6Eh ; n
seg000:012C db 6Fh ; o
seg000:012D db 20h ;
seg000:012E db 68h ; h
seg000:012F db 65h ; e
seg000:0130 db 78h ; x
seg000:0131 db 65h ; e
seg000:0132 db 64h ; d
seg000:0133 db 69h ; i
seg000:0134 db 74h ; t
seg000:0135 db 6Fh ; o
seg000:0136 db 72h ; r
seg000:0137 db 20h ;
seg000:0138 db 61h ; a
seg000:0139 db 6Ch ; l
seg000:013A db 6Ch ; l
seg000:013B db 6Fh ; o
seg000:013C db 77h ; w
seg000:013D db 65h ; e
seg000:013E db 64h ; d
seg000:013F db 3Ah ; :
seg000:0140 db 20h ;
seg000:0141 db 24h ; $
seg000:0142 db 0Dh ;
seg000:0143 db 0Ah ;
seg000:0144 db 77h ; w
seg000:0145 db 72h ; r
seg000:0146 db 6Fh ; o
seg000:0147 db 6Eh ; n
seg000:0148 db 67h ; g
seg000:0149 db 24h ; $
seg000:014A db 0Dh ;
seg000:014B db 0Ah ;
seg000:014C db 0Dh ;
seg000:014D db 0Ah ;
seg000:014E db 72h ; r
seg000:014F db 69h ; i
seg000:0150 db 67h ; g
seg000:0151 db 68h ; h
seg000:0152 db 74h ; t
seg000:0153 db 24h ; $
seg000:0154 db 0Dh ;
seg000:0155 db 0Ah ;
seg000:0156 db 0Ah ;
seg000:0157 db 0 ;
seg000:0158 db 0 ;
seg000:0159 db 0 ;
seg000:015A db 0 ;
seg000:015B seg000_15B:
seg000:015B mov ah, 9
- a questo punto vi starete chidendo: "Miiiii
ma sta roba che ΦΦΦΦΦΦΦΦΦ!!!", giα infatti me lo sono chiesto anche io, se
guardiamo meglio vediamo che non Φ altro che una stringa ASCII, ma perchΦ allora IDA non
me la messa nella sua forma caratteristica? PerchΦ non lei c'ha capito meno di noi ;))))
per aiutarla a comprendere meglio possiamo fare una cosa, selezionate col mouse tutto il
tratto da seg000:0106 a seg000:015A, a questo punto premete "C"...et voilα ecco la nostra
stringa ASCII in una forma pi∙ "umana" ;):
-
- seg000:0106 str->JaxFiteDuFleurC db 'jax fΩte du fleur crackme, 10 chars, no hexeditor allowed: $'
seg000:0106 db 'wrong$',0Dh,0Ah
seg000:0106 db 0Dh,0Ah
seg000:0106 db 'right$',0Dh,0Ah
seg000:0106 db 0Ah,0
seg000:0158 db 3 dup(0)
- e questo ci aiuta non poco a capire il codice, bhΦ se ci da una
mano nel caso di una stringa ASCII figuratevi quanto ci pu≥ aiutare nel caso di un po'
codice, se non l'avevate capito questa opzione serve principalmente a convertire il codice
mal interpretato. Per riconoscere questi pezzetti un po' "pazzi" possiamo
avvalerci dell'aiuto che ci da IDA con i colori, infatti lei marca di bianco su sfondo
nero l'indirizzo di questi pezzi cioΦ:
-
- seg000:014F
db 69h ; i
seg000:0150
db 67h ; g
seg000:0151
db 68h ; h
seg000:0152
db 74h ; t
seg000:0153
db 24h ; $
- a parte le battutacce di prima, Φ assolutamente normale che IDA
confonda il codice che riceve, per aiutarla nella sua missione possiamo disattivare
l'opzione "Make final analysis pass" che si trova nel menu "Kernel analysis
options", pu≥ comunque essere utile disattivare nello stesso pannello anche
l'opzione "Coagulate Data Segments", se vi dovesse capitare un programma
completamente marcato di bianco non vuol dire che IDA non c'ha capito 'na mazza ma
significa che Φ statto crittato/packato, in tal caso dovete decomprimere il programma
oppure, da bravi reverser quali siete, reversare l'algoritmo di crittazione e creare un
piccolo decrittatore in IDA C.
-
- Data: bell'opzione anche questa, serve a convertire i byte
inesplorati in dati, ecco le conversioni che applica:
-
- db -> dw -> dd -> float -> dq -> double -> dt
-> packreal -\
^
|
\----------------<----------------<----------------<----------------/
- In pratica converte un byte in una word, se lo riapplichiamo
lo coneverte in una doublword e cos∞ di seguito, se un file non supporta quel determinato
tipo di dato allora si salta al passo successivo
-
- ASCII: questa serve a convertire i byte inesplorati in stringhe
-
- Array: ci permette di dichiarare la grandezza di
un array
-
- Undefine: selezionate del testo, cliccate su
Undefine e come per magia tutti byte selezionati verranno convertiti ad inesplorati, vi
starete chiedendo: "Ma a che mi serve convetire ad inesplorato un determinato numero
di byte?". Posso assicurarvi che vi pu≥ servire e come, per esempio IDA a volte
scambia dei byte con altri tipi di istruzioni e poi ce li presenta in modo errato, vedere
per credere:
-
- seg000:0157
db 20202020h;
seg000:0158 db 20202020h;
seg000:0159 db 20202020h;
- sapete cosa Φ successo? Dovete sapere che 20h
equivale in ASCII ad un carattere di spaziatura, IDA quindi ha commesso l'errore di
definire una probabile stringa ASCII come 3 doubleword, come fare a rimediare? Semplice,
non dobbiamo far altro che convertire quei dati in caratteri ASCII, per farlo sarebbe
necessario selezionare le tre db e premere "A" ma non possiamo farlo in quanto
IDA non considera quei byte con solitari o inesplorati ma li ha giα segnati come db,
possiamo rimediare al problema selezionando col mouse le tre doubleword, premendo
"U" per Undefinirle e poi "A" per dire ad IDA che li deve considerare
come caratteri ASCII, l'errore che vi ho mostrato non accade pi∙ dalla versione 3.82
per≥ questo era un esempio per farvi capire la funzione di questo comando, vi capitera
spesso infatti di doverlo usare.
-
- Rename: abbiamo giα usato questa funzione ma
abbiamo delle sotto-opzioni disponibili e precisamente sono:
- Include in names list:
IDA ha una gamma di nomi predefiniti e questi sono:
-
- sub_ instruction,
subroutine start
locret_ 'return' instruction
loc_ instruction
off_ data, contains offset value
seg_ data, contains segment address value
asc_ data, ascii string
byte_ data, byte (or array of bytes)
word_ data, 16-bit (or array of words)
dword_ data, 32-bit (or array of dwords)
qword_ data, 64-bit (or array of qwords)
flt_ floating point data, 32-bit (or
array of floats)
dbl_ floating point data, 64-bit (or array
of doubles)
tbyte_ floating point data, 80-bit (or array of tbytes)
stru_ structure (or array of structures)
algn_ alignment directive
unk_ unexplored byte
Attivando questa opzione IDA inserisce in
nome nella lista che sta qua sopra.
Public name: possiamo
dichiarare un nome pubblico, se il file supporta la direttiva "public" allora il
nome sarα utilizzato da IDA altrimenti sarα mostrato solo come commento.
- Autogenerated name: nome
autogenerato dal programma, appari di un colore marroncino e scompare da solo se
"undefiniamo" i byte di quel nome
- Weak name: stessa cosa di public
name, se il programma supporta la direttiva "weak" allora IDA lo userα
altrimenti il nome sarα mostrato come commento
- Create name anyway: se per
qualche masochistico motivo volessimo creare un nome nonostante ne esista uno identico
allora dovremmo checkare questa opzione per permettere alla povera IDA di aggiungere un
suffisso al nome pre-esistente
-
- Operand types: altro menu
stramaledettamente carico di opzioncine, ne elencher≥ solo le pi∙ incomprensibili:
-
- Convert to number
Convert to hex number
Convert to decimal number
Convert to binary number
Convert to octal number
Convert to character
Mark as variable
Convert to segment
Convert to offset (DS)
Convert to offset (CS)
Convert offset by any segment
Convert offset by any user-specified base
Convert to struct offset
Convert to enum
Convert to stack variable
Change sign of operand
User-defined operand
-
Mark as variable <"#Mark as variable">: questa opzione marka e unmarka i byte
selezionati come variabili, le variabili si riconoscono perchΦ iniziano con un asterisco
"*"
-
Convert to offset (DS): questo comando converte un
operando di un'istruzione corrente in un offset dal segmento dati (DS) corrente
- Convert offset by any segment: stessa
cosa di sopra solo che converte un operando in un offset di qualunque segmento
- Convert to struct offset: uesto
comando converte un operando di un'istruzione corrente in un offset all'interno di una
specificata struttura
-
- Poi abbiamo la sezione "Structs" che serve a creare e modificare delle strutture, se non sapete cosa
sia una struttura vi faccio il solito esempio, ecco allora una struttura in C (Φ un
esempio e non funziona serve solo a farvi capire :):
-
- ---------------------------------------------------8<-------------------------------------------------------
- #include <stdio.h>
struct client{
char code;
long id;
char name[32];
client *next;
};
void main(client *ptr) {
while (ptr != NULL) {
printf("ID: %4ld Name:
%-32s\n",ptr->id,ptr->name);
ptr=ptr->next;
}
}
- ---------------------------------------------------8<-------------------------------------------------------
- una struttura non Φ altro che una variabile in grado di
contenere pi∙ tipi di dati, se per esempio state realizzando uno sparatutto e dovete dare
delle caratteristiche ad un mostro di un qualche quadro allora potreste creare una
stuttura simile a questa:
-
- struct Mostro{
- char nome[20];
- int forza;
- long proiettili;
- };
-
- nella quale definite con comoditα il nome del
mostro, la forza ed il numero di proiettili che si porta dietro, come potete vedere
abbiamo inserito tre tipi di dati (char, int e long) in una sola variabile, potemmo poi
modificare a piacere simili dati durante il gioco semplicemente richiamando tale struttura
(vedi esempio in alto. Adesso che sapete cos'Φ una struttura potete facilmente intuirne
la comoditα, per≥ potreste avere un dubbio del tipo: "Ma cosa mi interessa sapere a
che servono e cosa sono le strutture?". Conoscere le strutture vi serve perchΦ i
programmatori ne fanno un uso smodato nei loro programmilli maledetti e ce le ritroviamo
nel disasm ogni volta, il problema non si sarebbe posto se IDA le avesse ricreate
autonomamente ma, dal momento che non lo fa, la dobbiamo come al solito aiutare noi (anche
se non serve a nulla ricreare una struttura tranne che alla nostra comoditα). Supponiamo
di aver disassemblato un programma che usi delle strutture e del quale possediamo i
sorgenti, lo guardiamo a fondo e notiamo che nel frammento di codice dove ci dovrebbe
essere la struttura "Mostro" c'Φ solo una serie di confusi numeri.....Niente
paura, clicchiamo sul menu "View | Structures" ed iniziamo a ricreare
manualmente la struttura presente nel nostro sorgente, nella finestra dove ci troviamo
premiamo "Ins" e scriviamo il nome della nostra struttura cioΦ: Mostro,
premiamo poi "D" per creare un membro della struttura e chiamiamolo come il
primo membro della stessa del nostro sorgente cioΦ: Nome, clicchiamo con il mouse una
riga sotto al nuovo membro e inseriamo gli altri due membri, una volta finito avrete
qualcosa del genere:
-
- 0000 Mostro struc
0000 Nome db ?
0001 Forza db ?
0002 Proiettili db ?
0003 Mostro ends
- notate qualcosa? Credo di si, abbiamo commesso due
errori, il primo Φ che il membro "Nome" non possiamo definirlo come byte dal
momento che nel sorgente era definito come array (char nome[20]; ) dobbiamo quindi
tramutare "db ?" in un array, per farlo Φ sufficiente cliccare una volta sulla
riga del membro che ci interessa e poi premere "A", ci apparirα un men∙ nel
quale ci verrα chiesto di inserire la grandezza di questo array, inserite 20 e cos∞
abbiamo risolto il primo errore, vedete anch il secondo? Credo di si, se date uno sguardo
al sorgente vedrete che il membro proiettili era definito come long (long proiettili;
), quindi
in questo caso dovremo va cambiare "db ?" in "dd ?" per farlo cliccate
come al solito sulla riga che vi interessa e premete "D", in questo modo
"db ?" diventerα prima "dw ?" e poi "dd ?". Abbiamo ora
creato la struttura, ma come la inseriamo nel disasm? Semplice, chiudiamo la finestra che
stavamo usando, clicchiamo nel punto di codice che ci interessa ed andiamo nel menu
"Edit | Operand types | Struct offset...", o pi∙ semplicemente premiamo
"T" ;)))) e tadαααα come per magia se l'avete messa al punto giusto il
disasm muterα leggermente divenendo un po' pi∙ leggibile, avrete in sostanza dei
cambiamenti tipo questi:
-
- prima: push
dword ptr [esi+1]
- dopo: push
dword ptr [esi+Mostro.Name+1]
-
- Prima di concludere la spiegazione vorrei aprire una parentesi sul
significato dell'istruzione PTR, se avete mai programmato in assembly, disassemblato o
debbuggato qualcosa allora avrete sicuramente visto delle istruzioni come queste:
-
- mov eax, dword PTR [00454898]
- mov byte PTR [esi], 0
- mov word PTR [qualcosa], ebx
- mov word PTR qualcosa, ebx
- mov ecx, word PTR [esi+71]
- mov [ebp+00402588], byte PTR 95h
- mov cl, byte PTR [eax]
-
- tutte queste instruzioni hanno in comune una cosa cioΦ
l'istruzione PTR, ma vi siete mai chiesti cosa significa? BhΦ se l'avete fatto e non
avete trovato risposta ecco che vi do la soluzione, la Intel ci mette a disposizione tre
parole riservate cioΦ: Byte PTR, Word PTR, Dword PTR, bene, queste significano
rispettivamente: PoinTeR to a byte,PoinTeR to a word, PoinTeR to a doubleword, cioΦ puntatore ad un byte, ad una word, ad una
doubleword e DEVONO essere usati quando facciamo uso di un puntatore ad una costante,
spieghiamo per≥ il concetto di puntatore: allora facciamo un esempio:
-
- stringa db
"+Malattia Φ un grande",0
- mov eax, 12345678h
- mov eax, offset stringa
-
- cosa c'Φ di differente tra queste due istruzioni? Molto
vi dir≥ io, la prima istruzione muove in EAX il valore 12345678h, quindi se nella
finestra di un debugger a caso ;) guardiamo il registro EAX, oppure scriviamo "?
eax" ci verrα stampato qualcosa come: 12345678
0305419896 "⌠4Vx", ci≥ significa che eax CONTIENE il valore 12345678h, nella seconda
istruzione invece, eax PUNTA ad una stringa, cosa significa punta? Significa che se
andiamo a scrivere "? eax" non vedremo il testo della stringa bens∞ un numero
tipo questo: 00404F95.....Mmmmm ma allora la stringa dove sta?????? BhΦ la stringa che
come dicevamo non Φ CONTENUTA in eax ma PUNTATA da eax si trova all'offset 00404F95,
quindi se la vogliamo vedere non dobbiamo far altro che scrivere nel debugger "d
eax" oppure andare a spulciare con lo stesso comando a quell'offset. Ma se invece di
far puntare la stringa da eax la volessi spostare in eax come dovrei fare? Semplice, ora
dobbiamo far uso dell'istruzione PTR, infatti non potremmo scrivere "mov eax,
stringa" perchΦ riceveremmo errore, possiamo per≥ scrivere: "mov eax, Dword PTR stringa", in
questo modo spostiamo in eax una doubleword (4 byte) ed andando a verificare il contenuto
di eax con "? eax" vedremmo le lettere: "+mal"....No non Φ esatto,
per il modo in cui funzionano i nostri processori vedremmo scritto "lam+"....al
contrario in pratica........Hahahahahahahahahahahaha hahahahahahahaha Lama+, +lama
hahahahahahahahahaha....Questa +Malattia non me la perdonerα mai (hei +Ma giuro di non
averlo fatto di proposito) per≥ mi fa ridere hahahahahahahahaha (hei +Ma pensa quanto si
divertirα xOANON ora che glielo dir≥ hahahahah :), vabbΦ torniamo a noi, come dicevamo
eax conterrα solo 4 lettere questo perchΦ eax Φ grande 4 byte, quando i processori
saranno a 64 bit avremmo i registri di 8 byte :), se invece avessimo voluto spostare in
eax solo un byte della stringa avremmo dovuto scrivere "mov eax, byte ptr
stringa". Il motivo per il quale si usano i puntatori Φ proprio perchΦ anche
volendo non potremmo spostare in un registro 200 parole......Se siete bravi ragazzi ora vi
dovreste chiedere: "E se io volessi spostare il valore che punta eax in un altro
registro come potrei fare?"...BhΦ se dite che si possa fare cos∞: "mov ebx,
eax" allora avete sbagliato, per≥ potete scrivere questo: "mov ebx, [eax]"
oppure "mov ebx, dword ptr [eax]", rispettivamente significano: muovi in ebx il
valore puntato da eax, qualunque esso sia e di qualunque dimensione finchΦ non riempi
ebx, e l'altra: muovi in ebx la prima dword (quindi i primi 4 byte) puntata da eax, ci≥
significa che in tutti e due i casi avremmo lo stesso risultato, cioΦ ebx contenente
"lam+" per≥ la prima istruzione Φ pi∙ veloce. Vi faccio un altro esempio di
utilizzo dell'istruzione PTR e poi vi spiego l'uso dell'istruzione "lea".
-
- .386p
- .model flat, STDcall
- extrn ExitProcess:Proc
-
- .data
- stringa
db 2Bh, 6Dh, 61h, 6Ch, 61h, 74h,
74h, 69h, 61h ; questi numeri in ASCII significano
-
;
+malattia
- .code
- start:
-
xor
ecx, ecx
- continua: mov al, byte ptr stringa+ecx
-
inc
ecx
-
cmp
ecx, 9
-
jne
continua
-
call
ExitProcess
- end start
-
- Sapete cosa fa il programmillo qui sopra? Azzera ecx, inizia
un conto da zero ed ogni volta carica in al un byte della nostra stringa, come potete
vedere copia esattamente un byte (byte ptr) della stringa + ecx, cos'Φ quel +ecx? Se
guardate la stringa in alto notate che ho suddiviso ogni lettera, se poi guardate anche il
programma notate che ad ogni loop incrisa ecx, quindi al terzo loop al conterrα la
stringa+3, cioΦ 61h, capitooooooo...Se no rileggete questo pezzo...;) Se avessi voluto
spostare due lettere in ax ad ogni loop avrei dovuto cambiare l'istruzione in questo modo:
mov ax, byte ptr stringa+ecx, se invece ci avessi voluto spostare una intera doubleword
allora avrei dovuto scrivere: mov eax, dword ptr stringa+ecx....bhΦ basta parlare di PTR,
l'ha capito mio fratello, non lo capite voi!!!!!! ;))))))
- Per caricare un puntatore in un registro possiamo usare
anche l'istruzione LEA (Load Effective Address) che funziona in questo modo:
- "lea eax, stringa", se al posto di lea avessimo
utilizzato mov il compilatore ci avrebbe dato errore ma cos∞ non lo fa perchΦ "lea
eax, stringa" significa: carica in eax l'offset di stringa, il risultato ottenuto
usando lea e mov Φ uguale ma Φ ottenuto a due velocitα di esecuzione estremamente
differenti, la prima infatti Φ molto pi∙ veloce essendo l'offset una costante giα nota
all'assembler, mentre la seconda va pi∙ pianino ;)) per chi non lo sapesse la maggioranza
dei compilatori di alto livello (leggi: microsoft visual c++) sostituiscono tutte le
istruzioni come "mov reg, offset xxx" con "lea reg,
xxx" rallentando di molto l'esecuzione. Credo di aver chiarito l'uso e la
funzione
-
- "Enums" da qui possiamo definire un tipo di Enum, in tutti i linguaggi
spesso si usa fare delle enumerazioni di qualche genere, ecco un esempio di enumerazione
in C:
-
- enum Calore_t{
- LAMPADA,
/* Cose calde */
-
SOLE,
-
GHIACCIO, /* Cose fredde */
-
GRANDINE
- };
- enum stagione_t {Primavera, Estate, Autunno, Inverno};
- enum bool_t {FALSE, TRUE};
-
- int ╚_una_bella_giornata(Calore_t caldo, stagione_t
stagione) {
- if ( (stagione==Primavera||stagione==Estate)
&& caldo==LAMPADA||caldo==SOLE) return TRUE;
-
- if ( (stagione==Inverno||stagione==Autunno)
&& caldo==GHIACCIO||caldo==GRANDINE) return
TRUE;
- return FALSE;
- }
-
- Durante il disasm verrebbero mostrati a schermo dei
numeri e non dei nomi come "Sole, Estate, Ghiaccio" quindi per nostra chiarezza
sarebbe meglio poter vedere scritto "Sole, Estate, Ghiaccio" invece di 1,2,3
ecc....Andate quindi nel menu "Options | Enumarations", apparirα una finestra
molto simile a quella di prima nella quale dovrete ricreare l'enumerazione, in quale modo?
Premete "ins" e create come prima cosa i valori booleani
"False/True", scrivete quindi "Boolean Value" e premete invio, per
inserire un membro in questa enumerazione andate con il mouse sull'ultima riga e premete
ctrl+N, scrivete "False" e come valore lasciate 0, spostatevi di nuovo
sull'ultima riga e scrivete "True" dando 1 come valore, create poi un'altra
enumerazione e chimatela Calore, e cos∞ via fino ad avere qualcosa di simile:
-
- ª00000000
; enum Boolean_Value
ª00000000
False = 0
; Valore Vero/Falso
ª00000001
True = 1
- ª00000000
; enum Stagione
ª00000000
Estate = 0
; Stagioni
ª00000001
Autunno = 1
ª00000002
Primavera = 2
ª00000003
Inverno = 3
- ª00000000
; enum Calore
ª00000000
Lampada = 0
; Cose calde e cose fredde
ª00000001
Sole = 1
ª00000002
Ghiaccio = 2
ª00000003
Grandine = 3
- da adesso in poi la pappa Φ sempre la stessa, cercate il
punto dove volete applicare l'enumerazione, ci clickate col mouse, aprite il menu
"Edit | Operand types | Enum member...", oppure premete "M", e la
inserite dove vi serve ;)))
-
- "Functions" da qui possiamo aggiungere ed editare
le varie funzioni, non vi illustro il funzionamento in quanto Φ qualcosa di troppo
intuitivo
-
- "Patch program" giα spiegato in precedenza
-
- "Other" e
sottomenu:
- (Re)name any address...: indovinate un po'?
DA qui potete nominare/rinominare/cancellare un indirizzo
Variable: uguale a "Mark as Variable"
Jump table...: se troviamo un jump indiretto da una tavola possiamo informare IDA della
grandezza e dell'indirizzo di questa tavola di modo che possa continuare la sua analisi
convertendo per esempio in codice tutti quegli indirizzi riferiti a quella tavola
Alignment...: questo comando consente di creare una direttiva di allineamento, questa
direttiva rimpiazzerα il numero di byte inutili inseriti dal linker del programma per
allineare il codice ed i dati in un paragrafo, possiamo provare a selezionare un'area che
desideriamo convertire ed IDA proverα ad individuare un allineamento corretto
Manual instruction...: Questo comando ci permette di specificare la rappresentazione di
un'istruzione o di un dato in un programma
Hide/show item: Questo comando ti permette di nascondere e mostrare un'istruzione o un
dato
Hide/show border: Se attivata nasconde il sottile bordo creato da IDA per dividere le
istruzioni dai dati
-
- Menu "Navigate" di questo spiegher≥ solo pochissime funzioni le pi∙ utili e meno
comprensibili come solito.
- Empty navigation stack:
vuota lo stack di navigazione che usa IDA
- Jump to... | Problem...: salta alla prima
funzione che IDA dichiara affetta da problemi i quali sono:
- Can't
find offset base
Can't find name
Can't find alternative
string for an operand
Can't find comment
Can't find references
Indirect execution flow
Can't disassemble
Already data or code
Execution flows beyond
limits
Too many lines
Attention! Probably
erroneous situation
Decision to convert to
instruction/data is made by IDA
- Search for | next void: i void sono delle istruzioni alle quali
dobbiamo stare attenti dal momento che IDA non Φ in grado di riconoscere se si tratta di
Offser oppure di Numeri, con questo comando li andiamo ad esaminare per vedere se possiamo
risolvere noi il problema
- Search for | text....: cerchiamo del testo come ad esempio una
stringa del tipo "sei un coglione hai sbagliato la password"
Search for | text in core....: la stessa cosa di sopra solo molto pi∙ veloce
- Search for | not
function: cerca i primi byte che non sembrano una funzione
-
- Menu "View" anche di questo spiegher≥ le funzioni pi∙ importanti:
- View | Functions: ci
mostra tutte le funzioni chiamate dal programma
- View | Enumeratios: questo comando apre la
finestra "enum" dalla quale possiamo cambiare, aggiungere e modificare le
enumerazioni.
- Oki e questi s≥ finiti adesso manca il menu pi∙ lungo
quindi se siete stanchi di leggere andate a riposarvi e continuate domani mattina.
-
- Options:
- Text
representation...
Cross references...
Assembler directives...
Name representation...
Demangled names...
ASCII strings style...
ASCII strings options...
Colors...
Dump/normal view
Setup data types
Processor type...
Target assembler...
Analysis options...
Search direction
Allora allorino continuaiamo questa tediosa seduta
parlando delle "opzioni" vere e proprie riguardo la configurazione del
programma, salterei volentieri questo passaggio per volare felice alla conclusione ma
"una forza dentro dentro che neanch'io so spiegare come" (by Yale«) mi
trattiene su questa sedia a scrivere un inutile tutorial che molto probabilmente sarα
letto da poche decine di persone..;(((
- Bando alle ciance: Text
representation...: menu a dir poco arzigogolato che
ci presenta una miriade di piccole opzioncine che andremo ora ad esaminare.
- Line prefixes: se la
disattiviamo vedremo scomparire gli indirizzi davanti ai byte
Number of opcode bytes: gli opcode sono i codice
esadecimali di ogni istruzioni, IDA di default ne rappresenta 6 e se l'istruzione ne
richiede di pi∙ allora aggiunge un "+" alla fine (c'Φ caduta pure la rima ;)
- Use segment names: abilita o
disabilita la nomenclatura dei segmenti cos∞ se abilitato vedremo
"segment:3200" invece di "3000:3200"
- Segment addresses: se Φ
abilitata vedremo il segmento davanti ad un indirizzo: "segment:3000" invece di
un semplice "3000", questa la tengo disabilitata che fa meno bordello
- Display 'void' marks: fa
comparire dei segni di riconoscimento davanti ai "void"
- Display empty lines: se
abilitata fa comparire delle linee vuote diminuendo lo spazio utile sul monitor
Display borders between data/code: se disabilitato
fa scomparire la linea separatrice tra i dati ed i segmenti
- Display bad instructions <BAD> marks: tutti i processori hanno le loro belle funzioni non documentate e
quando una di queste passa sotto il disasm il programma dice "e tu ki kazzo
sei?", IDA Φ molto sensibile da questo punto di vista e se trova una funzione che
non conosce prova ad identificarla ma se proprio non ci riesce la marchia con tanta
ferocia quanto un tedesco ad un povero ebreo e con un bel tatuaggio rosso le scrive sopa <BAD>
- Use tabulations in output: con
questa opzione abilitata IDA disabilita il conosciutissimo tab-stop (0x09) nel suo file di
output
-
- Questi mi sembrano intuitivi:
- Display comments
Display repeatable comments
Display auto comments
Instructions indention: letteralmente: spaziatura delle istruzioni, settate questo
valore a 2-3
- Comments indention: che
sarα mai????? ;)))
- void's low limit: vedi
sotto
void's high limit: questi due valori sono molto
importanti in quanto dichiarano se una istruzione Φ oppure no un "void", un
oggetto Φ detto "void" se ha un valore immediato come operando o parte di un
operando e questo valore immediato Φ tra quelli che definiamo noi nei box "low
limit" e "high limit", Φ questa l'importanza dei due box
-
"Cross
references" ecco le opzioni che ci mette a disposizione questo menu:
-
- Display segments in xrefs: ecco
la differenza tra abilitato e disabilitato:
- ; CODE REF: 3000:1025 - enabled
; CODE REF: 1025 - disabled
Display xref type mark: chissα forse marka le xref
Display function offsets: bho! Ci mostrerα gli
offset delle funzioni? ;)))
Display xref values: su questa poi non so che dirvi,
forse mostra i valori dell xref ;)))
Right margin: opzione di difficilissima
interpretazione pu≥ darsi che si la misura del margine destro, ma chissα le vie del
signore sono infinite ;))))
Cross reference depth: questa invece Φ un po' pi∙
seria e per non confondervi vi riporto l'esempio dell guida, l'autore suppone di avere un
array
- A db
100 dup(0)
- se alcune istruzioni si riferiscono all'elemento 5-th
dell'array:
- mov al, A+5
- con TD=3 non ci
verranno mostrate xrefs
- con TD=10 ci verranno invece
mostrate
Number of xrefs to display: la funzione Φ ovvia,
alzatela per≥ di un po'
"Assembler
directives...": altro piccolo menu
ASSUME directives: questa opzione attiva o disattiva
la generazione di alcune direttve quali "assume" e "origin",
lasciatela abilitata pu≥ essere utile nel ricostruire il sorgente
.ORG directives: la stessa cosa di prima solo che Φ
valida per i file .com
-
- "Name
representation...": poco da dire, qui ci
viene chiesto in che modo chiamare i vari segmenti e credo che l'opzione di default sia la
migliore, le altre 4 opzioni riguardanti i tipi di nomi non saranno analizzate in quanto
le ho giα spiegate prima
-
- "Demangled
names...":
IDA pu≥ rimettere a posto i nomi maciullati (hei la
guida dice proprio maciullati=mangled) dai compilatori C++ ed in questo menu ci
chiede come farlo, se sotto forma di commento, di nome o di macellato ;)), il setup dei
nomi lunghi e corti lo lascio a voi in quanto Φ facilissimo
-
- "ASCII strings
style...":
in questo menu possiamo definire lo stile delle
stringhe e possiamo anche definirne una al momento che ci serve, qui non c'Φ altro da
spiegare
-
- "ASCII strings
options...": ahhhhhh!!! Uno dei menu che mi
fanno godere di pi∙ aahhhhhhhh, sembro Homer ;) ecco cosa possiamo fare:
-
- Generate names: le vogliamo
le stringhe ASCII? Allora abilitiamola ;)
Names prefix: cambiate questa maledetta stringa e
metteteci qualco's altro
Mark as autogenerated: segna la stringa come
autogenerata
Serial number: vi genera il seriale esatto per
QUALUNQUE programma protetto da password, trova anche le pass per i file .zip e . rar
protetti ;)))) hahahahaha
- Serial width: vi chiede
quanto lungo volete il seriale per il programma ;))))))))))
ASCII next line char: questa Φ grande infatti vi fa
scegliere la parola che volete codificare nel serial ;)))))) porka vakka quanto sto
rincoglionito ;))))
-
- "Colors...": scegliete la palette che volete usare ma vaaaaaaaaaaaa ;)))))))
- "Dump/normal
view": vi fa scegliere tra la visuale come editor esadecimale e quella
come disassembler
- "Setup data types": vi chiede che tipo
di dati volete usare nel comando MakeData
- Oki i menu sono finiti, ed io spero di avervi fatto
capire il funzionamento di IDA, a presto
-
Quequero
Home Page: http://quequero.cjb.net
-
E-mail. UIC@mail.usa.com
- P.S.
- Ahhhhhhhhhh, in quest'ultima release il documento Φ diventato 43
kbyte pi∙ pesante ed anche oggi ci ho perso le mie buone 4 ore per finirlo, continuer≥
ad aggiornare questo tutorial che tra poco diventerα un libro e lo far≥ pubblicare
;))))))))))) scherzi a parte devo dirvi che per scriverlo tuttto mi ci sono proprio fatto
il culo ;)))))))))) ciauuuuuuzzzzzzzz alla prossima release che, viste le previsioni non
sarα poi tropo lontana ;))) ciauz Quequero