Zoom Icon

Impariamo ad Usare Softice

From UIC

Impariamo ad Usare SoftIce

Contents


Impariamo ad Usare Softice
Author: Quequero
Email: Que addr.gif
Website: http://quequero.org
Date: 16/02/1999 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Flag Italian.gif
Comments:



Introduzione

In questo tutorial impareremo ad usare SoftICE, conosceremo l'uso delle varie funzioni ed impareremo anche a modificare il codice di un programma.


SoftIce

Come abbiamo già detto SoftICE ci mostra il codice assembler di un programma, noi poi per scraccherellare il tutto abbiamo bisogno sia di conoscere l'Assembly, sia di saper usare il debugger, infatti come potremmo guidare una macchina senza conoscere il codice stradale, e senza avere la patente? Uno dei comandi che useremo più spesso sarà sicuramente bpx cioè breakpoint on execution che in pratica fa poppare Sice quando, per esempio, viene richiamata la funzione su cui abbiamo messo il breakpoint (GetWindowTextA, GetDlgItemTextA, MessageboxA ecc...) ma ovviamente ne esistono altri come per esempio:

bpm
breakpoint su un accesso alla memoria (possiamo utilizzarlo per vedere se una funzione legge o scrive su un determinato indirizzo)
bpr
bp (breakpoint) su un rango di memoria
bpio
bp su un accesso I/O
bpint
bp su un interrupt
bmsg
bp su un messaggio (lo useremo per brekkare su funzioni come WM_GETTEXT).
task
Questo comando visualizza tutti i processi attivi, viene in genere utilizzato in combinazione con Hwnd.
hwnd
mostra l'handle delle finestre di un determinato programma.

Ora vi spiegherò meglio come utilizzare questo comando insieme a bmsg. Per prima cosa scegliete un programma vittima (io userò Hex-Workshop), avviatelo ed aprite la finestra di registrazione, avviate Sice (^D) e scrivete task per vedere con quale nome gira sotto Windows l'Hex-Workshop. Il nome che appare per primo, e che sembra essere l'unico possibile, è: Hworks32. Bene bene, scriviamo: hwnd Hworks32 e premiamo invio. Vedrete adesso molte scritte, noi vogliamo cercare l'handle della casella di testo nella quale dobbiamo scrivere il numero seriale, ma come si fà? Bhè l'unico modo che io conosca è scriversi tutti gli handle (prima colonna a sinistra) che presentano l'attributo edit nella colonna class-name (la 4° da sinistra) e poi provarli uno ad uno scrivendo: bmsg xxxx (qui va inserito un handle) wm_gettext, ecco un esempio:

task
hwnd hworks32
bmsg 01A5C wm_gettext.

Una volta trovato quello giusto Sice popperà dopo aver premuto il pulsante di registrazione.

bd*
Disabilita tutti i bp, può essere sostituito p.e. con bd00 (disabilita il 1° bp)
be*
Abilita tutti i bp il resto è uguale a bd
bl
Lista tutti i bp che stiamo utilizzando se appare un "*" il bp è disabilitato
bc*
Cancella tutti i bp, la sintassi è come bp e be
bh
Ci dice tutti i bp che abbiamo usato dall'accensione del pc (molto utile)
?
p.e. ? eax ci dice quale valore esadecimale, decimale ed ASCII contiene eax
d
d eax dump eax, ci fa vedere a cosa punta il registro eax
code on-off
fa apparire il codice esadecimale di fianco alle istruzioni, ecco un esempio:
015F:00425867 JNZ 00425921 <-------code off
015F:00425867 751E JNZ 00425921 <-------code on
|----| <-------codice esadecimale

cercate di tenere questa istruzione sempre abilitata perché è molto importante, ora mi spiegherò meglio: se vogliamo cambiare un JNZ 00425921 in JMP 00425921 dovremo aprire l'eseguibile con l'editor esadecimale, cercare 751E e cambiarlo in EB1E, infatti EB significa JMP e 1E significa vai avanti fino a 00425921, nelle prossime pagine vi mostrerò una tabella con i valori esadecimali di alcune istruzioni, dovrete ricordare sempre che l'ultimo byte dell'opcode (funziona solo per le istruzioni semplici a 2 byte, le altre cambiano) indica l'indirizzo, o il registro, a cui si riferiscono, quindi dovrete cambiare solo il primo byte e non l'ultimo, a meno che non vogliate cambiare la direzione del salto oppure, il nome del registro a cui si riferisce l'istruzione. P.E: il valore 85D2 significa: TEST EDX, EDX (ricordate questa istruzione? se no rileggete il primo tutorial) però se lo cambiamo in 85F6 diventerà: TEST ESI, ESI, avete capito?

a (address)
a 015F:00425867 ci permette di cambiare ciò che si trova all'indirizzo 015F:00425867, una volta premuto invio potremo scrivere per esempio: TEST EAX, EAX così il jnz verrà cambiato in test...
e (address)
edit address, con questa funzione non possiamo cambiare le istruzioni come con a 015F:00425867 ma dovremo agire direttamente sugli opcode. Una volta premuto invio apprirà una finestra con i valori, noi andremo a prendere i primi 2 byte 751E ed andremo a scrivere EB1E, vorrei ricordare che tutti i cambiamenti fatti dal debugger funzionano solo fino a che si riavvia il prog, dopodichè va tutto a farsi benedire.

Funzioni

Ecco l'elenco di alcune funzioni utili per il reverser, suddivise per linguaggi.

Visual Basic

__vbastrcmp, __vbastrcomp
Queste chiamate vengono usate in VB per far confrontare due stringhe. Per usarle si deve mettere un bp su una delle due, inserire un numero nel box di registrazione, premere ok, aspettare Sice e prima di premere F11vedrete cos'è stato messo nello stack.
__vbaR8Str
non ne sono sicuro ma dovrebbe essere l'equivalente di GetWindowTextA.
rtcmsgbox
Questo è MessageboxA in VB

C/C++

GetPrivateProfileStringA
Legge il file .INI dove spesso viene registrato il seriale, questa funzione si usa per disabilitare il number check all'avvio del programma.
GetWindowTextA
L'abbiamo già usata, comunque serve a copiare ciò che si trva nelle caselle di testo.
GetDlgItemTextA
Praticamente uguale alla precedente.
hmemcpy
Questa funzione grabba i tasti premuti sulla tastiera e può essere sfruttata a nostro vantaggio nei sistemi di protezione che non utilizzano funzioni standard (GetWindowTextA, GetDlgItemInt, MessageBoxA ecc...) oppure in quei sistemi che abilitano il pulsante di registrazione solo se il codice è esatto, questo breakpoint funziona infatti ogni volta che noi premiamo un tasto... bello vero?
MessageBoxA
Fà apparire un box di messaggio, la possiamo usare per entrare nel codice del programma dopo la Beggar off cioè il messaggio che ci dice che abbiamo sbagliato il seriale ecc....
GetSystemTime
Vede l'ora del sistema e si usa nei programmi che scadono dopo un'ora, due ore ecc... Per utilizzarla basta mettere un bp su di essa ed avviare il programma.
GetLocalTime
Controlla l'ora, il giorno ed il mese. Si usa nei programmi a scadenza di 30, 60, 90 gg ecc... Funziona come la precedente.
GetTickCount
Restituisce il numero di millisecondi da quando il sistema è stato avviato, anche in questo caso viene utilizzato spesso da quei programmi con termini di scadenza nell'ordine dei minuti/ore.

Patchare un programma

Il nostro crack consiste nel cambiare un JE 004010DD in JMP 004010DD, per farlo avremo bisogno di cercare quel pezzo di codice esadecimale all'interno di Hex-Workshop. Prendiamo nota di qualche opcode prima e dopo del salto, come ad esempio 85c0740940E8E6, clicchiamo sul pulsante "find" ed inseriamo quei numeri, il nostro bersaglio è il num. 7409 e per cambiarlo in jmp basterà prendere dalla tabella qui sotto il primo byte dell'istruzione JMP e mantenere integri i secondi due. Così facendo sostituiremo l'istruzione 7409 in EB09 (se nel codice del debugger doveste trovare un jump che abbia più di 2 byte come opcode, allora dovrete usare il comando a jmp xxxxxxxx, fare i cambiamenti a mano, e vedere cosa appare in Sice, segnarle i nuovi byte e cambiarli nell'editor). E se il nostro crack avesse richiesto l'eliminazione dell'istruzione inc eax? In questo caso bastava cercare la solita stringa, e cambiare il 40 con 90, questo numero equivale all'istruzione NOP, cioè No Operation, indica al processore di non fare nulla e passare oltre. Se vi capitasse di dover cancellare un'istruzione, o di dover lasciare spazi vuoti, (p.e. se 68c88c deve diventare un jmp non potrete mai scrivere ebc88c) ricordate di sostituire i byte che avanzano SEMPRE con un NOP. Se per caso non siete sicuri di qualche cambiamento, vi ripeto di provare prima con a xxxxxxxx.

Opcode Utili

Opcode Istruzione Significato
EB XX JMP jump
75 XX JNZ jump if not zero
7C XX JL jump if less
7E XX JLE jump if less or equal
74 XX JE/JZ jump if equal/jump if zero
7D XX JGE jump if greater or equal
7F XX JG jump if greater
77XX JA jump if above
73 XX JAE jump if above or equal
76 XX JBE jump if below or equal
33 XX XOR xxx, yyy xor xxx with yyy
85 XX TEST xxx, yyy test xxx against yyy
0B XX OR xxx, yyy or xxx with yyy
90 NOP do nothing
C3 RET return
Quequero


Conclusioni

Nel prossimo tutorial attaccheremo un target più semplice e mostreremo nuovamente come si fa a patchare un programma.


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.