Archivio storico · Reverse engineering · Spiegazione dettagliata

Lezione 5: caricatori e protezioni su floppy

Come un programma intermedio può intervenire all'avvio di un altro e come funzionavano i dischi originali con settori anomali.

In breve

La quinta lezione unisce due temi. Nella prima parte l'autore presenta i caricatori, piccoli programmi che avviano un altro programma e intervengono mentre il sistema lo carica. Poi passa alle protezioni basate su dischi floppy formattati in modo anomalo: il programma funzionava solo se trovava sul disco originale settori che le copie normali non riproducevano.

La pagina spiega il funzionamento e il contesto storico. Il documento contiene codice e indirizzi per modificare giochi specifici; non li riporto. La spiegazione resta sul piano dei meccanismi, delle nozioni sui dischi e dei limiti del testo.

1. Il caricatore: intervenire prima che il programma parta

Alcune protezioni agganciano un vettore di interruzione, cioè deviano una richiesta al sistema verso una propria routine. In casi del genere l'autore propone un programma intermedio. Funziona così, in termini generali:

  1. salva il punto in cui il sistema gestisce una certa richiesta;
  2. lo sostituisce con una propria routine;
  3. carica il programma bersaglio;
  4. osserva le richieste che il bersaglio invia e, a un certo punto, interviene sul suo codice già in memoria;
  5. ripristina la situazione originale e termina.

Il vantaggio concettuale è che il file originale resta intatto sul disco: la modifica avviene solo in memoria. Per questo il testo lo considera utile contro programmi capaci di controllare il proprio codice.

Dal punto di vista della sicurezza, la lezione è severa per chi progetta protezioni. Un controllo di integrità fatto dal programma stesso viene eseguito sullo stesso computer, con gli stessi privilegi, di chi può intercettare le sue richieste. Il testo cita due giochi come esempi e mostra che il caricatore individua il momento giusto riconoscendo una richiesta precisa e un contenuto noto in memoria. Non riporto quei dettagli.

Due affermazioni da non prendere alla lettera

Il camuffamento delle modifiche

Il testo consiglia di non sostituire le istruzioni con una serie evidente di «non fare nulla», ma con una sequenza di istruzioni che si annullano a vicenda, perché i controlli più recenti diffidano delle sequenze troppo regolari. È un esempio di corsa tra protezione e aggiramento. La pagina lo registra come fatto storico e non ne spiega l'applicazione.

2. Come funzionavano le protezioni su floppy

Un floppy PC standard registrava dati in tracce e settori. Il formato più comune da 5,25 pollici aveva 40 tracce, 9 settori per traccia e settori da 512 byte; il controllo di ogni settore era affidato a un valore di verifica. Una copia normale riproduce i dati ma non i difetti voluti del formato, per esempio:

Il programma originale chiedeva al sistema di leggere proprio quel punto del disco. Se la risposta era quella prevista, il disco era considerato originale; se i dati erano normali, la copia veniva respinta. Il testo cita come esempio un'antica versione di VisiCalc, in cui mancherebbe un settore su una traccia. Non ho modo di verificare quell'esempio specifico.

Le capacità dei formati

FormatoCalcoloByte
5,25 pollici, un lato, 8 settori40 × 8 × 512163.840
5,25 pollici, un lato, 9 settori40 × 9 × 512184.320
5,25 pollici, due lati, 8 settori40 × 8 × 512 × 2327.680
5,25 pollici, due lati, 9 settori40 × 9 × 512 × 2368.640
5,25 pollici ad alta densità80 × 15 × 512 × 21.228.800

I calcoli del testo sono corretti. Per i dischi da 3,5 pollici l'autore cita le capacità nominali: 720, 1.440 e 2.880 KiB. Il conteggio usa multipli di 1.024 byte, anche se il documento adopera le sigle K e M in modo informale.

3. I parametri del floppy e l'interruzione 13h

Il vettore 1Eh contiene l'indirizzo di una tabella di parametri del dischetto. Il vettore si trova all'indirizzo 0000:0078 (0x1E × 4 = 0x78). Il testo spiega che la tabella contiene tempi del motore, testina e attese e, soprattutto, quattro campi che riguardano il formato: la dimensione del settore, l'ultimo settore della traccia, la lunghezza degli intervalli e quella dei dati.

Il codice della dimensione del settore è 0 per 128 byte, 1 per 256, 2 per 512 e 3 per 1024. Un riferimento tecnico moderno conferma questa codifica. Lo stesso riferimento chiarisce che il campo «lunghezza dati» conta solo quando il codice della dimensione è 0, mentre l'autore lo collega al byte 4 invece che al byte 3: è una svista nel testo.

Un'altra differenza riguarda il secondo byte: il documento parla di «metà destra» per la modalità DMA, mentre la descrizione tecnica assegna il bit 0 alla modalità DMA e i bit superiori al tempo di caricamento della testina. Per questa lezione non cambia il senso, ma conviene non trattare la tabella come riferimento definitivo.

Le funzioni usate

L'interruzione 13h si trova al vettore 0000:004C (0x13 × 4).

Il CRC

Quando un settore viene scritto, il controllore calcola un valore di controllo e lo scrive insieme ai dati. In lettura lo ricalcola e lo confronta. Una protezione può creare di proposito un settore il cui valore non corrisponde: la lettura segnala l'errore 10h, e proprio quell'errore è la «firma» del disco originale. Il codice 10h è confermato da un riferimento tecnico indipendente.

4. Errori da interpretare con cautela

L'errore 09h, secondo l'autore, nasce quando un indirizzo che termina con tre zeri cade dentro l'area di un settore. La descrizione è imprecisa. Il limite riguarda il confine fisico di 64 KB del trasferimento DMA: un buffer non può attraversare un indirizzo fisico come 0x10000. L'esempio di Wikipedia, 4 settori a 0FC0h:0000h, mostra proprio un trasferimento che arriva a 0x10400 e supera quel confine. Un indirizzo qualsiasi che termina per 1000 non produce l'errore.

La tabella dei bit dell'errore, inoltre, appare sovrapposta nella trascrizione. Il significato dei codici più noti coincide invece con i riferimenti indipendenti: 04h settore non trovato, 03h disco protetto da scrittura, 10h errore CRC, 40h errore di posizionamento, 80h dispositivo non pronto.

Alcuni esempi di debug nel testo sono incoerenti: l'indirizzo letto prima è 0000:0070, mentre il vettore 1Eh sta a 0000:0078, e il blocco successivo viene mostrato a un indirizzo diverso. Possono essere errori di trascrizione. Non ho eseguito quei comandi.

5. Quando l'interruzione non si vede

Un modo ovvio di trovare una protezione su disco è cercare nel programma i due byte di una chiamata all'interruzione 13h. L'autore elenca tre modi per rendere inutile questa ricerca:

  1. simulare la chiamata, preparando lo stato del processore e saltando direttamente alla routine del sistema;
  2. scrivere un'interruzione apparentemente innocua e cambiarla al volo prima dell'uso;
  3. copiare nel proprio codice il comportamento dell'interruzione, così che nessuna istruzione contenga il numero cercato.

Il principio generale vale ancora: una ricerca di una sequenza nota trova solo ciò che il programma non nasconde. Per capire il comportamento bisogna osservare ciò che avviene, non soltanto leggere ciò che c'è scritto.

Leggere settori con DEBUG

Il testo ricorda che il vecchio DEBUG può caricare settori assoluti: si indica l'indirizzo di destinazione, l'unità, il primo settore logico e il numero di settori. Se si verifica un errore, parte dei dati può essere già stata trasferita. È una nozione di recupero dati, utile anche fuori dal contesto delle protezioni.

6. L'esempio del 1985

L'ultimo caso tecnico è un simulatore di volo del 1985. Sul disco c'è un piccolo programma che prepara lo stato del processore, installa una routine inutile per un vettore e legge un solo settore da una posizione descritta nel testo come non standard. Il listato mostra poi un salto ai dati appena letti, senza un controllo esplicito dell’esito in quel breve frammento.

La struttura è ingegnosa per l'epoca: il codice importante non sta in un file visibile, ma in un punto del disco che una copia comune non riproduce. Il testo dice che per analizzarlo basta osservare le chiamate all'interruzione 13h e recuperare i dati. L'autore anticipa che schemi simili compaiono in protezioni più recenti, che saranno trattate nella lezione seguente.

La frase conclusiva del blocco fa un confronto: le protezioni antiche sarebbero spesso ancora in uso e difficili da aggirare, mentre quelle dei programmi Windows con numero di serie sarebbero noiose. L'ultimo blocco ripete l'idea già vista nella lezione 3: osservare cosa succede ai dati inseriti dall'utente e risalire alla routine che li controlla.

7. Chiavi generate e chiavi legate al nome

Nel finale il testo distingue due tipi di registrazione. Nel primo la validità dipende solo da una relazione matematica sul numero: in quel caso un generatore potrebbe produrre un numero valido per qualunque nome. Nel secondo il codice è legato al nome, tramite una trasformazione delle lettere.

Per un progettista la distinzione è utile: legare il codice al nome impedisce di riutilizzare lo stesso numero per altri utenti, ma non rende segreta la regola, se la regola sta nel programma distribuito. Non descrivo come costruire un generatore, perché questo sarebbe uno strumento per ottenere licenze non pagate.

8. Il lungo passaggio finale

La fine del documento esce dal tema tecnico. L'autore scrive una requisitoria contro il consumismo, la pubblicità, le automobili, la televisione, Windows 95 e la democrazia rappresentativa. Sostiene che le persone siano «schiave», e arriva a dire che a volte rimpiange bombe che uccidano le persone lasciando intatti libri e vodka.

Quest'ultima frase è un'espressione estrema di disprezzo per le persone, anche se la presenta come sfogo. La pagina la riporta come testimonianza del tono del documento e non la condivide. Non aggiunge nulla alla comprensione delle tecniche.

Il testo si chiude con l'invito a scrivere all'autore, tramite un indirizzo anonimo, per ottenere le altre lezioni: chi invia nuovi trucchi o un buon lavoro riceve il materiale mancante. È un meccanismo di scambio tipico di quella comunità e non c'è modo di verificare qui se la procedura fosse ancora attiva o sicura.

9. Che cosa resta di valido

Glossario

Caricatore
Programma che ne avvia un altro e può intervenire sul suo avvio.
Vettore di interruzione
Indirizzo della routine che gestisce una certa richiesta al sistema.
Traccia e settore
Suddivisioni fisiche di un disco: ogni traccia contiene più settori.
CRC
Valore di controllo scritto insieme ai dati di un settore per rilevare errori.
DMA
Trasferimento diretto tra dispositivo e memoria, senza passare per ogni byte dal processore.
FDPB
Tabella di parametri del dischetto, indicata dal vettore 1Eh.

Fonti e verifiche

Il testo è stato ricevuto in due blocchi incollati dall'utente. Il secondo blocco termina con l'invito a scrivere all'autore. I calcoli sulle capacità dei floppy e sui vettori sono stati ricontrollati. Per i codici di errore, la lettura dei settori e la tabella dei parametri ho usato riferimenti tecnici indipendenti, tra cui INT 13H su Wikipedia e una descrizione della tabella dei parametri. Non ho eseguito programmi né applicato modifiche.

Leggi il documento originale: ORC_5.DOC