Copy Link
Add to Bookmark
Report
Guida all uso del softice 3.2
Gli ____ _ ___ ___ __ ______ ____31-10-98
/ __/__ (_) _ \/ _ \___ / / ___ /_ __/__ ____/ _/ ASCII
_\ \/ _ \/ / ___/ ___/ _ \/ /_/ _ `// / / _ \/ __// / by
/___/ .__/_/_/ /_/ \___/____|_,_//_/ \___/_/ /___/RigoR MorteM
/_/
Presentano: Guida all'uso del softice 3.2
Creato da : B[a]T^MaN e Flamer
INTRODUZIONE ALL'USO DEL SOFTICE
Il softice 3.2 e' uno dei migliori debugger per windows. Imparare ad usarlo al
meglio permette di modificare efficacemente qualunque programma... anche per
scoprire e correggere errori (debugging) oppure per rimuovere protezioni software
(cracking).
In questa guida verranno introdotte le basi per comprendere il linguaggio
assembler, i comandi basilari del softice, e l'utilizzo dei breakpoint.
INSTALLAZIONE
Appena completata l'installazione il softice aggiungera' la seguente riga al
file autoexec.bat:
C:\...(directory del softice)...\WINICE.EXE
Questa riga deve necessariamente trovarsi alla fine del file, ed e' necessaria
perche' il softice deve avere il controllo sul windows per poter interrompere
ogni processo in qualsiasi momento, quindi deve essere caricato PRIMA del windows.
Tuttavia, se non si vuole che il softice venga caricato ad ogni avvio di
windows, e' possibile sostituire alla riga precedente il seguente listato:
CHOICE /C:SN /T:N,4 Devo caricare il softice
IF ERRORLEVEL 2 GOTO END
C:\...(directory del softice)...\WINICE.EXE
:END
In questo modo ad ogni avvio verra' richiesto se caricare il softice. Se
non si risponde entro 4 secondi, il sistema partira' senza caricare il softice.
Diamo ora uno sguardo all'assembler, poiche' e' fondamentale comprendere
questo linguaggio per utilizzare il softice.
Il linguaggio assembler Ë un linguaggio di programmazione di basso livello
che rispecchia le operazioni di base del computer.
Nel cracking Ë FONDAMENTALE perchË TUTTI i debugger presentano listati in
assembler, per cui la conoscenza (almeno parziale) di questo linguaggio Ë
indispensabile per poter manomettere le routine di protezione dei programmi
che ci interessano.
La prima cosa che serve Ë avere un'idea di che cosa siano i registri
della CPU.
Un registro Ë una specifica locazione di memoria usata per immagazzinare
informazioni per i processi della CPU.
I registri che pi˘ ci serviranno per i nostri 'loschi' scopi sono quelli
per la manipolazione dei dati e per operazioni matematiche.
Le dimensioni di quest' ultimi variano da 8 a 32 bit.
-I registri a 32 bit sono EAX, EBX, ECX, ed EDX, tutti composti da 4 byte.
-I registri a 16 bit (2 byte) sono AX, BX, CX, e DX.
Da notare che ognuno di questi registri puÚ essere suddiviso ulteriormente in
2 parti, ossia parte alta (high) (es. AH,BH,ecc.) e parte bassa (low) (AL,
BL,ecc.). Quindi in questa maniera ogni "parte" del registro puÚ contenere un
valore da 00 a FF (mentre il registro "intero" contiene valori da 0000 a FFFF).
Facciamo un esempio: se muoviamo un valore in AX (MOV AX, 01AFh), il registro AL
conterr‡ il valore AFh ed il registro AH conterr‡ invece 01h. Tutto qua!
Questi registri come ho gi‡ detto sono usati per la manipolazione di dati,
come ad esempio un confronto tra due valori:
-MOV EAX, 003F; MOV EBX [EBP-04); CMP EAX, EBX
o per operazioni matematiche:
-MOV AX,2; MOV BX,4; ADD AX,BX.
Nota: il registro CX Ë spesso usato come contatore, infatti l'istruzione
LOOP decrementa CX ad ogni 'passaggio' e termina quando CX=0.
Altri registri importanti sono i registri di segmento CS, DS, ES,
FS, GS, ed SS. Questi registri sono tutti a 16 bit e contengono
la prima parte di un indirizzo di memoria del tipo SSSS:OOOO (segmento:offset)
La memoria di un computer Ë divisa in segmenti (o partizioni), dentro i quali
trovano posto numerosi bytes. Per poter eseguire un programma la CPU deve
conoscere il segmento dentro il quale si trova il codice del programma e
la posizione nel file (offset) dell'istruzione da eseguire.
Nota: un indirizzo SSSS:OOOO viene convertito dal kernel del sistema operativo
in un indirizzo di memoria fisico.
I registri dell'offset sono EIP, ESP, EBP, ESI, ed EDI (registri a 32 bit),
e IP, SP, BP, SI, e DI (registri a 16 bit).
Un indirizzo completo di memoria sar‡, per quanto riguarda il codice eseguibile
CS:IP, per i dati DS:SI, per lo stack SS:SP etc....
Gli altri registri (registri di controllo [CR0, CR1, CR2, e CR3],
registri di debug [DR0, DR1, DR2, DR3, DR4, DR5, DR6, e DR7].....)
nel cracking sono poco importanti e quindi eviterÚ di parlarne per approfondire
quelli che maggiormente ci saranno utili.
[AX].... registro accumulatore, utilizzato per le operazioni matematiche e di
I/O. Tutto passa da questo registro, le funzioni di COMPARE (CMP) di solito
avvengono confrontando un valore inserito da voi (es. un numero del serial
number, una lettera della password, il numero riferito ad una icona da
scegliere) con quello contenuto in AH, AL o in tutto il registro
(non per una regola generale; Questi valori possono
essere anche contenuti in un'altro registro, es.BX, ma nel nel 99% dei casi Ë
cosÏ).
[BX].... Viene utilizzato di solito come base o puntatore ad una locazione.
[CX].... Il contatore. Viene usato per i loops (cicli) e viene decrementato
o incrementato secondo le esigenze. Di solito contiene un numero (ad es. il
numero delle volte che potete provare ad inserire la password prima che il
tutto si blocchi) che viene poi decrementato (con l'istruzione DEC CX oppure
SUB CX,AX) ogni volta che sbagliate. Utile in questo caso eliminare queste
istruzioni per poter lavorare con pi˘ tranquillit‡.
[DX].... Funzioni simili a BX.
Ora, i segment-registers:
[CS].... Il code-segment, cioË l'area di memoria nella quale si trova il
codice del programma che state analizzando. L'indirizzo CS:IP serve ad
identificare proprio l'istruzione che state per eseguire.
[DS].... Data-segment, l'area di memoria alla quale la CPU accede in lettura.
i dati.
[ES].... Extra-segment, altra area di memoria alla quale la CPU accede, ma
questa volta in scrittura. In pratica, la CPU legge da DS:SI e va a scrivere
il byte (o la word) letta in ES:SI.
[IP]..... Istruction Pointer. Cos'Ë? Semplice, l'indirizzo dell'istruzione
che state per eseguire nel code segment attuale. Volendo, durante il
crakkaggio nel debugger, si puÚ modificare questo registro invece del jump, in
maniera da non danneggiare per il momento il programma.
[SS].... Stack-segment, area di memoria di "parcheggio" nella quale la CPU
tiene nota di tutti i return-address dalle subroutines. Usando l'istruzione
PUSH o POP, lo stack viene riempito o svuotato.
Altri registri, ma questi li potete anche tralasciare, sono:
[SI]..... Source-index, usato insieme all'istruzione MOV. E' un puntatore
all'interno di un segment (di solito DS) che viene letto dalla CPU.
[DI]..... Destination-index, anche questo usato insieme a MOV. E' un puntatore
all'interno di un segment (di solito ES) dove la CPU va a scrivere. Andando
a vedere all'indirizzo ES:DI, se vedete che ci viene mosso qualcosa, potreste
anche capitare in locazioni interessanti... (potreste trovarci addirittura la
password che cercate!)
[BP]..... Base-pointer, usato insieme allo Stack-segment.
[SP]..... Stack-pointer, altro pointer usato insieme allo Stack-segment.
Una particolare nota merita il seguente registro:
[FLAG].. Nel vostro debugger, vedrete (di solito in cima) un'insieme di
lettere maiuscole e minuscole (oppure illuminate o no, oppure con sotto dei
numeri 0 e 1). Questi sono i flag, che servono ad indicare se un particolare
jump deve avvenire o no. Logicamente, flag=0=spento flag=1=acceso.
Facciamo un esempio:
CMP AL,2A......... confronta il valore di AL con 2A.
Il risultato Ë un cambiamento dello stato del flag
Z. CioË, se Ë vero il flag viene attivato (1),
altrimenti viene disattivato (0).
JZ 8EDF........... salta -SE- il flag Z=1 (quindi se AL=2A)
Bene, che ne dite dei registri?? Simpatici no??
Adesso Ë la volta delle istruzioni pi˘ importanti:
[MOV]..... E' un'istruzione le cui funzioni sono fondamentali nel cracking.
Difatti, molte volte vi ritroverete a dover magari muovere un valore giusto
in una locazione semplicemente cambiando un CMP in un MOV (poi vi spiego....
non temete). La sua sintassi Ë: MOV [destination],[source]
es 1. MOV AX,BX ----------> muove il valore di BX in AX
es 2. MOV CX,[0400] ----------> muove i due bytes contenuti all'indirizzo
specificato (DS:0400) in CX. In questo caso
se dumpate a DS:0400 trovate lo stesso
valore di CX, solo rovesciato (es. se in CX
c'Ë 002Ah, troverete 2A00h);
es 3. MOV AL,DL ----------> muove la parte bassa di DX nella parte bassa
di AX
es 4. MOV [ES:300],AX ---------> muove il valore di AX nella locazione
specificata. Notare che se ES non Ë
menzionato, si usa DS per default. Se prima
di una istruzione del genere si muove un valore
in BX (es. 03) questo viene usato come base
da aggiungere all'indirizzo specificato.
Quindi, in questo caso, il valore di AX
verrebbe mosso in ES:300+BX = ES:303.
[CMP]..... Semplicemente, confronta due valori in memoria, siano essi registri
oppure bytes, cambiando di conseguenza il flag relativo. La sintassi, secondo
i casi, puÚ essere:
es 1. CMP AX,01 -----> confronta AX con 01
es 2. CMP AX,BX -----> confronta AX con BX
es 3. CMP AX,[0550] -----> confronta AX con i 2 bytes a DS:0550
(eccetera eccetera...)
Questa istruzione funziona come una sottrazione source-destination,
cioË:
ponendo AX=20 e BX=21, il risultato del CMP AX,BX sar‡ 20-21=-1. Il risultato
di questa sottrazione attiver‡ il flag CARRY (C), attivato quando si sottrae
un valore pi˘ grande da uno pi˘ piccolo; se invece la sottrazione non d‡
risultato negativo, il flag rimane 0 (disattivato).
Dal punto di vista crakkistico, le istruzioni CMP sono usate *SEMPRE* per
verificare il vostro input, oppure per far sapere al programma se Ë registrato
o meno. Quindi, truffando il CMP si puÚ benissimo far credere al programma una
cosa per un'altra!
[JMP].... Lo troverete *SEMPRE* dopo il CMP, nelle varie forme.
La pi˘ semplice, e ovvia, Ë la forma JMP <indirizzo>, che naturalmente provoca
un salto all'indirizzo desiderato, quali che siano i valori dei flags dati
dal CMP. Per quanto riguarda l'indirizzo, questo puÚ essere nello stesso
CS (JMP 0AF4) oppure in un'altro (JMP 2000:18A0 oppure JMP DWORD PTR ES:[DI],
che vi spedir‡ alla locazione contenuta in ES:DI. Ma sono solo alcuni esempi).
Questa comunque Ë l'istruzione che userete pi˘ spesso (anzi, mi sbilancio:
nel 99% dei casi) nei vostri scopi pirateschi. Difatti, se la vostra
protezione, ad esempio, controlla una locazione e poi f‡ un JNZ che riporta
il programma all'inserimento della password/serialnumber, basta che
sostituiate il jump condizionale con un JMP, e..... et voil‡!
Ora, vi agevolo la lista dei vari jump condizionali, copiata(:O)
dal Cracking Manual di The Cyborg.
Dunque, supponendo un CMP AX,BX, si possono avere i seguenti casi:
(Z,O,S,C,P sono i flags che i jump vanno a controllare)
Istruzione Definizione, condizione, flag
JNZ 030A (Jump if not zero, AX diverso da BX, Z=0)
JNE 030A (Jump if not equal, identico a JNZ)
JZ 030A (Jump if zero, AX=BX, Z=1)
JE 030A (Jump if equal, identico a JNZ)
JB 030A (Jump if below, AX<BX, C=1)
JA 030A (Jump if above, AX>BX, C=0)
JL 030A (Jump if less, AX<BX, S diverso da O)
JNGE 030A (Jump if not greater or equal, AX<=BX, S diverso da O)
JGE 030A (Jump if greater or equal, AX>=BX, S=O)
JNL 030A (Jump if not less, in pratica uguale a JGE)
JLE 030A (Jump if less or equal, AX<=BX Z=1 oppure S=F)
JNG 030A (Jump if not greater, come JLE)
JG 030A (Jump if greater, AX>BX Z=0 oppure S=O)
JNLE 030A (Jump if not less or equal, AX>=BX Z=0 oppure S=O)
JS 030A (Jump if sign, /, S=1)
JNS 030A (Jump if not sign, /, S=0)
JC 030A (Jump if carry, /, C=1)
JNC 030A (Jump if not carry, /, C=0)
JO 030A (Jump if overflow, /, O=1)
JNO 030A (Jump if not overflow, /, O=0)
JP 030A (Jump if parity, /, P=1)
JPE 030A (Jump if parity even, come JP)
JNP 030A (Jump if no parity, /, P=0)
JPO 030A (Jump if no parity odd, come JNP).
[LOOP]..... Indica un ciclo, che si ripete per CX volte (naturalmente, CX
decrementa ogni volta che trova questa istruzione). Per quanto riguarda il
formato, Ë LOOP <indirizzo>, che indica appunto l'inizio del LOOP dove questo
ogni volta ritorna finchË CX non diventa 0. Istruzione piuttosto noiosa da
debuggare, utile in questo caso la funzione "Breakpoint Here" dei debugger,
che permette di settare un breakpoint all'istruzione successiva e ripartire
direttamente da l‡ senza sorbirsi tutto il ciclo (sempre che funzioni).
[REP]..... Repeat. Stesso discorso del loop per quanto riguarda l'uso
della funzione "Here". Indica il ripetersi di istruzioni MOVS, LODS,
STOS (quindi si trover‡ nel formato REP MOVS, REP LODS, REP STOS). Le
istruzioni suddette vengono ripetute CX volte.
[MOVSB]..... Muove un byte dall'indirizzo DS:SI all'indirizzo ES:SI.
[MOVSW]..... Stesso discorso, ma per una word (4 bytes)
[LODSB/LODSW]..... Con queste istruzioni, viene letto un byte o una word
residenti in memoria all'indirizzo DS:SI. Il byte o la word in questione
viene messo in AL (o in tutto AX, naturalmente, se Ë una word)
[STOSB/STOSW]..... Se le istruzioni prima leggevano, queste scrivono.:))
Difatti, scrive il byte (o la word) in AL (o AX se
word) all'indirizzo ES:SI.
[CALL]...... Richiama una subroutine, e dopo l'esecuzione di questa torna
all'indirizzo successivo alla CALL stessa (tramite un RET/RETF).
Esempio:
CALL 68AB ----> esegue la subroutine a CS:68AB
subroutine:
CS:68AB ......
68AE ......
68B0 ......
68B3 RET ----> torna all'istruzione successiva a CALL 68AB
Una call puÚ essere anche nel formato CALL FAR (come anche il JMP),cioË viene
eseguita una subroutine ad un'indirizzo in un altro CS.
Nei vostri primi approcci crakkistici, se avete la fortuna di trovare la CALL
che salta *DIRETTAMENTE E SOLO* alla protezione, potete benissimo togliere
quella. Pi˘ in l‡ sar‡ meglio che impariate a districarvi con i jump e i
compare, identificando e modificando quelli relativi al solo controllo della
protezione. Difatti, se per caso quella CALL chiamasse una subroutine che
contiene la protezione ma anche istruzioni necessarie al buon funzionamento
del programma, eliminandola siete frefati....
[INT]...... Chiama un interrupt (tipo una CALL ma non relativa al programma),
con una specifica funzione assegnata da un valore, di solito mosso in AX.
E' utile ad esempio monitorare l'interrupt 13 con il debugger (nel caso si
voglia sproteggere un programma che accede al floppy), oppure l'interrupt 16
con funzione 10 (AX=10) nel caso il programma attenda la pressione di un
tasto.... Utile ma non indispensabile, si crakka anche senza usare questa
funzione del debugger.....
I registri a 32 bit (i registri di windows) sono EAX, EBX, ECX, ed EDX.
Quest'ultimi sono un'evoluzione dei registri a 16 bit AX, BX, CX, e DX,
i quali a sua volta possono essere divisi in regitri ad 8 bit;
AX puÚ essere infatti diviso in AH (high) e AL (low).
Ricordiamoci che 8 bits sono un byte, quindi AH Ë un byte, AX due bytes,
ed EAX quattro byte.
Questi registri sono usati per manipolare dati e per operazioni
matematiche.
Passiamo ora all'utilizzo del softice.
COMANDI PRINCIPALI
Per fare apparire la finestra del softice si devono usare i tasti CTRL+D (comunque
questa combinazione puo' essere cambiata con il comando ALTKEY).
Una volta dentro al softice, lo schermo sara' diviso in varie finestre. I comandi
vengono inseriti nella finestra piu' bassa. E' consigliabile dare subito il
comando
LINES 60
Per avere un'area maggiore a disposizione.
I tasti per scrollare il contenuto delle finestre sono i seguenti:
Alt+Freccia su Alza di una riga la finestra dati
Alt+Freccia giu Abbassa di una riga la finestra dati
Alt+Pgup Alza di una pagina la finestra dati
Alt+Pgdown Abbassa di una pagina la finestra dati
Ctrl+Freccia su Alza di una riga la finestra codice
Ctrl+Freccia giu Abbassa di una riga la finestra codice
Ctrl+Pgup Alza di una riga la finestra codice
Ctrl+Pgdown Abbassa di una riga la finestra codice
I comandi per visualizzare o nascondere le finestre sono i seguenti:
WC Visualizza/nasconde la finestra del codice
WD Visualizza/nasconde la finestra dei dati
WR Visualizza/nasconde la finestra dei registri
WW Visualizza/nasconde la finestra watch
WF Visualizza/nasconde la finestra dello stack
Un comando molto utile e' il comando:
H
che fornisce un elenco dei comandi riconosciuti dal softice, oppure scrivendo:
H [Comando]
fornisce la sintassi e una breve spiegazione del [Comando] scelto.
Esistono alcuni comandi che servono per controllare il flusso del programma.
Vediamone alcuni.
Il comando X permette di ritornare al programma in esecuzione uscendo dal softice,
che potra' essere richiamato con Ctrl+D.
Il comando G seguito da un indirizzo manda il programma in esecuzione, e si ferma
quando il puntatore del codice arriva all'indirizzo specificato.
Il comando T permette di tracciare il codice. Con questo comando il debugger
esegue un "passo" solo esi ferma all'istruzione successiva
Il comando P e' pressoche' identico al precedente, solo che mentre in caso di una
CALL il comando T "segue" la chiamata, fermandosi di fatto all'indirizzo a cui
punta la CALL, il comando P si ferma all'uscita di essa.
Il comando EXIT forza un'uscita dal programma per ritornare al windows.
Comandi molto importanti per il cracking sono i seguenti:
S [indirizzo] L [lunghezza] [stringa o sequenza di byte]
Ricerca nella memoria a partire dall'indirizzo dato, per la lunghezza data una
certa sequenza di byte. E' molto utile per cercare la locazione di memoria dove
viene memorizzato l'input dell'utente ad esempio quando viene richiesta una
password.
Vediamone alcuni esempi:
S DS:0000 L FFFFFFFF 'aria' Cerca la parola aria nel segmento dati
S CS:0000 L 1000 F3 A6 Cerca nei primi 1000 (esadecimale) byte del segmento
di codice l'istruzione REPZ CMPSB (usata in alcune
protezioni per confrontare la password corretta con
quella inserita o piu' in generale per confrontare
due stringhe, e corrispondente ai byte F3 A6)
D [indirizzo]
Mostra nella finestra dati il contenuto della memoria all'indirizzo specificato.
E' un comando molto semplice, ma vediamone alcuni esempi.
D DS:0 Mostra nella finestra dati il contenuto dell'area di memoria
riservata ai dati (segmento DS)
D $0:0 Mostra nella finestra dati il contenuto dell'area di memoria
riservata ai vettori di interrupt (occorre usare il simbolo $ prima
dello 0 perche' in generale il segmento 0 non e' un segmento
"conosciuto", cioe' nessun registro di segmento vale 0)
CODE [ON|OFF]
Attiva o disattiva la visualizzazione dei byte corrispondenti a ciascun comando
della finestra di codice. E' utile tenere attiva la visualizzazione nell'ultima
parte della procedura di cracking, quando cioe' si vuole andare a modificare il
codice per "confondere" le routine che fanno scattare la protezione, e occorre
capire bene quale sequenza di byte va modificata e come, per poter poi operare con
un debugger sul file eseguibile.
Vediamo ora in dettaglio quali sono i comandi per operare sui breakpoint del
softice.
COS'E' UN BREAKPOINT E COME FUNZIONA
I breakpoint sono la base del cracking. Tramite un uso corretto dei breakpoint si
puo' riuscire a trovare l'istruzione chiave per la protezione in mezzo a svariati
megabyte di roba.
Tramite i breakpoint si puo' dire al softice (come ad un altro qualsiasi debugger)
quando interrompere il programma e riapparire, ad esempio, se sappiamo che la
password da noi inserita viene salvata a partire dall'indirizzo di memoria
1234:5678, possiamo mettere un breakpoint su questo indirizzo e sui successivi in
lettura:
BPR 1234:5678 1234:567F R
Cosi' facendo il softice blocchera' il programma ogni volta che viene letta
quell'area di memoria che va dall'indirizzo 1234:5678 all'indirizzo 1234:567F,
cioe' ogni volta che il programma controlla la nostra password.
Diamo quindi uno sguardo all'uso dei breakpoint, perche' usarli bene vuol dire
crackare meglio e piu' in fretta.
I BREAKPOINT DEL SOFTICE
BPM (-B -W -D) - Breakpoint sulla memoria
Questo breakpoint viene usato su di un indirizzo di memoria, e puo' scattare per
lettura, scrittura o esecuzione.
La sintassi del comando e' questa:
BPM[B,W o D] indirizzo [R,W,RW o X] [condizione] [contatore]
-B,W o D indicano che dimensioni deve avere la memoria coperta dal breakpoint
(byte, word o doubleword).
-indirizzo e' l'indirizzo di memoria su cui agisce il breakpoint.
-R,W,RW o X indicano se il breakpoint deve scattare (rispettivamente) in lettura,
scrittura, sia lettura che scrittura o esecuzione.
-condizione e' una condizione aggiuntiva che si puo' mettere per fare scattare il
breakpoint, solo per breakpoint in lettura e/o scrittura. La condizione puo'
essere del tipo EQ (uguale), NE (diverso), GT (maggiore), LT (minore), seguita da
un numero. Ad esempio:
BPM 1234:5678 W EQ 10
e' un breakpoint che scatta quando all' indirizzo 1234:5678 viene scritto il
valore 10.
-contatore si puo' usare se si vuole che il breakpoint scatti solo alla n-esima
volta ignorando le prime n-1. [sintassi: C=n]
BPX Breakpoint su esecuzione
Questo breakpoint scatta nel momento in cui viene eseguita l'istruzione su cui e'
stato messo. Lo si puo' piazzare con un doppio click del mouse nella finestra di
codice sull'istruzione desiderata, oppure con la seguente sintassi:
BPX indirizzo [contatore]
-indirizzo e' l'indirizzo di memoria su cui agisce il breakpoint.
-contatore si puo' usare se si vuole che il breakpoint scatti solo alla n-esima
volta ignorando le prime n-1. [sintassi: C=n]
BPINT Breakpoint su interrupt
Un breakpoint su interrupt interrompe il programma ogni volta che viene chiamato
un particolare interrupt (gli interrupt sono le fuzioni basilari di ogni sistema,
ad esempio vengono chiamati per leggere un input da tastiera, vedere/modificare la
data e l'ora del sistema, e anche per far scattare un breakpoint).
La sintassi e' la seguente:
BPINT numero_di_interrupt [AL,AH o AX = valore] [contatore]
-numero_di_interrupt e' l'interrupt a cui si vuole associare il breakpoint.
-AL,AH o AX = valore si puo' utilizzare se si vuole che il breakpoint scatti solo
su precise funzioni di un interrupt.
-contatore si puo' usare se si vuole che il breakpoint scatti solo alla n-esima
volta ignorando le prime n-1. [sintassi: C=n]
BPIO Breakpoint su accesso a porte I/O
Questo breakpoint scatta in lettura/scrittura sulle porte di input/output.
BPIO porta [R,W o RW] [condizione] [contatore]
-porta e' il numero della porta di I/O su cui si desidera far agire l'interrupt
-R,W o RW si puo' specificare se si desidera che il breakpoint agisca in caso di
input (R), output (W) o entrambi (RW).
-condizione e' una condizione aggiuntiva che si puo' mettere per fare scattare il
breakpoint, cosi' come avveniva per i breakpoint sulla memoria. La condizione
puo' essere del tipo EQ (uguale), NE (diverso), GT (maggiore), LT (minore),
seguita da un numero.
-contatore si puo' usare se si vuole che il breakpoint scatti solo alla n-esima
volta ignorando le prime n-1. [sintassi: C=n]
BPR Breakpoint memory-range
Questo breakpoint funziona come il breakpoint sull'indirizzo di memoria, solo che
puo' coprire piu' indirizzi consecutivi.
La sintassi e' la seguente:
BPR indirizzo_iniziale indirizzo_finale [R,W,RW,T o TW] [contatore]
-indirizzo_iniziale e indirizzo_finale indicano i limiti dell'area di memoria che
l'interrupt deve coprire.
-R,W o RW indicano se il breakpoint deve scattare (rispettivamente) in lettura,
scrittura o entrambe. T e TW servono per utilizzare il backtrace. Se si usano T
oppure TW, in caso di breakpoint il programma non si blocchera', ma le modifiche
all'area di memoria verranno salvate nel buffer di backtrace, e potranno essere
esaminate in seguito.
-contatore si puo' usare se si vuole che il breakpoint scatti solo alla n-esima
volta ignorando le prime n-1. [sintassi: C=n]
CSIP Setta il raggio di CS:IP
Se si vuole che tutti i breakpoint agiscano solo in una certa area del programma,
o si vuole evitare di essere interrotti da breakpoint che scattano a causa di
funzioni esterne al programma, si puo' settare una determinata zona di valori per
CS:IP al di fuori (o all'interno) della quale verranno ignorati tutti i
breakpoint. Per farlo basta scrivere:
CSIP [NOT] indirizzo_iniziale indirizzo_finale
-indirizzo_iniziale e indirizzo_finale indicano i limiti dell'area di memoria
all'interno della quale i breakpint possono (o non possono se avete messo il NOT)
essere attivati.
Il comando:
CSIP OFF
Disattiva questa verifica sui breakpoint.
BPAND Setta un AND logico tra piu' breakpoint
Questo comando setta un AND logico tra due o piu' breakpoint, con il risultato che
il programma viene interrotto solo se si incontrano le condizioni per far scattare
TUTTI i breakpoint considerati.
Per esempio, se si vuole mettere un AND tra i breakpoint 1,2 e 3 bisogna scrivere:
BPAND 1,2,3
Scrivendo:
BPAND *
Si setta un AND tra TUTTI i breakpoint esistenti.
Per disattivare un AND precedentemente attivato bisogna scrivere:
BPAND OFF
------------------------------------------------------------------
Esistono inoltre alcuni comandi utili per manipolare i breakpoint gia' esistenti.
Vediamo quali sono.
BL Lista breakpoint
Il comando BL fornisce una lista dei breakpoint esistenti, e ci permette anche di
vedere il numero associato a ciascuno di essi. Tutte le operazioni che si
riferiscono ad un breakpoint, infatti (come BPAND che abbiamo gia' visto), devono
fare riferimento al numero corrispondente.
Tramite il comando BL otteniamo quindi una cosa di questo tipo:
00) * BPX #172A:0000198C
01) BPMB #2F85:0C0043D1 R DR3
03) BPMB #2F85:0C0030A2 RW DR2
I numeri a sinistra sono i numeri a cui e' associato ogni breakpoint.
BPE Modifica breakpoint
Questo comando, seguito dal numero di breakpoint, serve a copiare la descrizione
del breakpoint nella riga di comando. Da qui la si puo' modificare e il breakpoint
selezionato verra' modificato di conseguenza.
I comandi successivi dovranno tutti essere associati ad uno o piu' breakpoint.
Per fare cio', e' necessario specificare nella riga di comando uno o piu' numeri,
separati da una virgola, oppure un asterisco per specificare TUTTI i breakpoint
esistenti.
BC Cancella breakpoint
Il comando BC seguito dai numeri dei breakpoint, cancella uno o piu' breakpoint.
Se il breakpoint ci servira' in seguito, pero', e' consigliabile utilizzare i
comandi seguenti.
BE/BD Abilita/disabilita breakpoint
Col comado BD, vengono disattivati uno o piu' breakpoint. I breakpoint resteranno
in memoria, e col comando BL ci verranno mostrati con un asterisco davanti, che
sta a significare che non sono attivi.
Quando verranno incontrate le condizioni per il breakpoint, se questo e'
disattivato verra' ignorato.
Per riattivare breakpoint precedntemente disattivati si usa il comando BE.