Questo tutorial concerne l'implementazione della protezione a tempo delle versioni
trial dei sistemi operativi Windows NT. I riferimenti più dettagliati, ed i frammenti di
disassemblato mostrati si riferiscono in particolar modo a Windows 2000 RC2, ma i concetti
esposti sono, almeno fino a questo momento, applicabili a tutte le trial version di tutte
le versioni di Windows NT.
Com'è noto, le alghe sono organismi vegetali, e tra i più semplici; tassonomicamente
si pongono tra i protozoi e le piante superiori, ma molto più simili ai primi (dai quali
si differenziano per la capacità di fotosintesi) che non alle seconde.
Quindi, sono un'organismo estremamente elementare; non aspettatevi troppo da me!
Un lavoro come quello descritto nel testo avrebbe dovuto venire eseguito avvalendosi di
i386kd e due macchine collegate tramite null-modem; ciò avrebbe consentito di scoprire
anche ciò che invece è rimasto inspiegato.
Ma le alghe sono pigre...si lasciano cullare dalle onde senza muovere un dito (soprattutto
perchè - non so se avete mai osservato un'alga da vicino - non hanno dita; non vi dico i
problemi con la tastiera...), e così quanto descritto nel testo è stato realizzato su
una sola macchina, e con "gli attrezzi" descritti nella sezione
"Tools".
L'esecuzione delle operazioni descritte prevede però l'uso di macchina con boot multiplo
di due o più sistemi operativi con file systems compatibili.
NON ESEGUITE ALCUNA OPERAZIONE SU UNA MACCHINA SULLA QUALE SIA INSTALLATO SOLO W2000, O
SULLA QUALE SIANO PRESENTI SISTEMI OPERATIVI CON FILE SYSTEMS INCOMPATIBILI, PRIMA DI AVER
ULTIMATO LA LETTURA DEL TUTORIAL ED AVERE ESEGUITO LE OPERAZIONI E PRESO LE PRECAUZIONI
ELENCATE NELLA SEZIONE "DISCLAIMER".
In caso contrario potreste ritrovarvi con un sistema assolutamente non più riavviabile a
meno che:
1) il volume principale non sia FAT16, o abbiate un convertitore su dischetto (come
quello di System Internals) abilitato in scrittura
2) non abbiate provveduto a fare delle copie di ciò che vi serve
3) non sappiate REALMENTE dove mettere le mani
AVVERTITI!
- Qualcuno di voi è interessato a Windows 2000? Probabilmente sì, se state leggendo
questo tutorial. Oppure siete interessati solamente alla protezione?
PERCHE' LA RAM AUMENTA DI PREZZO?
Inizialmente, quando NT 5 divenne ufficialmente Windows 2000, io non ero interessata né
all'uno, né all'altro aspetto; il mio interesse cominciò a destarsi quando si
verificarono gli improvvisi, inaspettati ed inspiegabili (come sanno anche i sassi, il
terremoto a Taiwan non ha mai avuto nulla a che vedere con ciò) incrementi di prezzo
della RAM.
Poichè lo zio Bill controlla una buona percentuale delle fabbriche di chip, pensai che il
tutto potesse essere scaturito dalla mente di mamma Microsoft.
Perchè, infatti, qualcuno avrebbe dovuto desiderare Windows 2000? Le recensioni
"precoci" che era possibile leggere su alcune riviste (PcPlus in testa)
dicevano, in pratica: fa schifo, NT4 + il Service Pack di turno è molto meglio.
Mi venne allora il sospetto che in realtà W2000 richiedesse meno risorse del suo
predecessore, e questo dovrebbe divenire un buon motivo per acquistarlo; domandai un pò
in giro, ed i soliti bene informati (leggi persona cha ha un amico/a che a sua volta ha un
amico/a che conosce benissimo qualcuno che ha avuto una versione pre-pre-alfa in esclusiva
direttamente dalla moglie di Guglielmo Cancelli) sostenevano che sì, sembrava avesse
bisogno di una minore quantità di RAM.
Da qui nacque la curiosità di verificare se fosse vero.
Così sparsi la voce presso i bene informati riguardo ad una richiesta di una copia di una
qualunque versione (anche pre-pre-pre-alfa) del sistema operativo, ma non ottenni un bel
nulla.
NE AVEVO LE TASCHE PIENE DI WINDOWS 2000!
Così, quando, qualche mese dopo, PC Professionale pubblicò il CD con la versione detta
"RC2" di W 2000, gli amici che sapevano della mia curiosità si affrettarono (la
permanenza in edicola di quel numero di PC Professionale non superò la mezza giornata) ad
acquistarne una copia anche per me. Oltre quella che avevo acquistato io, naturalmente.
Per non creare disparità le accettai tutte, ringraziando.
Quando tornai a casa avevo le tasche ben riempite da 4 CD di Windows 2000 RC2.
ALGA MEDIANICA
Sono in grado di leggere nel pensiero. In questo momento state pensando: e di tutto questo
a noi che ce frega?
Nulla, ovviamente. Ma realmente non sono in grado di raccontare alcunchè senza condire il
tutto con una miriade di particolari stupidi, irrilevanti e non attinenti.
Le alghe, si sa, non hanno cervello.
PEGGIO DEL MILLENNIUM BUG...
Arrivata a casa, mi affrettai a leggere la documentazione acclusa al CD, nella quale
veniva dichiarato che il sistema operativo avrebbe cessato di funzionare dopo 444 giorni;
cioè, il sistema sarebbe rimasto avviabile, ma non avrebbe funzionato per più di un'ora.
Ero esterrefatta! Molto peggio del Millennium Bug! Come era possibile che una casa seria
come Microsoft mettesse in giro un prodotto con un simile difetto? Non erano stati in
grado di produrne uno in grado di funzionare correttamente per più tempo?
In effetti bisogna dire che qualche tempo dopo Microsoft ha immesso sul mercato una
versione (denominata, chissà perchè, "FINAL") in grado di funzionare per più
tempo (in teoria, indefinitamente), ma...costa un sacco di soldi!
Ritengo che ciò sia in relazione alle risorse che hanno dovuto impegnare (ed ai
conseguenti oneri che hanno dovuto sostenere) per eliminare il tremendo bug; l'avessero
chiesto a me, l'avrei fatto gratis...
PUO' UN'ALGA ESSERE DEMORALIZZATA?
Bene, al lavoro, aiutiamo Microsoft a migliorare i suoi programmi.
La prima cosa che feci fu quella di andare a curiosare tra le stringhe di NTDLL.DLL.
Perchè proprio NTDLL.DLL? Perchè non avevo intenzione, per il momento di installare
nulla, e NTDLL.DLL era addirittura già decompresso (pigrissima Alga!).
Tra le stringhe era possibile leggere: "Avviso valutazione di Windows""Il
periodo di valutazione di questa installazione di Windows è terminato..".
Fortissima Alga!, pensai. Senza neanche installare...già trovato!
Caricando NTDLL.DLL in un editor esadecimale era possibile ricavare l'offset della
stringa; dando un'occhiata all'header era possibile verificare che essa si trovasse
effettivamente all'interno della sezione .rsrc.
A questo punto disassemblai e cercai i riferimenti all'interno del disassemblato. Niente.
Beh, dopo tutto W32Dasm è carino, ma non è adatto per questo genere di lavoretti.
Disassemblai con IDA. Niente. Diedi un'occhiata alla sezione .rsrc con un
decompilatore di risorse. Nessun riferimento.
Risultato: Alga demoralizzata (non più fortissima :( )
L'AGO NEL PAGLIAIO
Così, il sistema operativo, dopo la data di scadenza, avrebbe funzionato per un'ora. Ma
quanti millisecondi sono contenuti in un'ora? Tremilioniseicentomila. E come si dice
tremilioniseicentomila in esadecimale? 36EE80. OK, decomprimiamo WINLOGON.EXE e cerchiamo
36EE80 nel disassemblato.
Arrivai ad un segmento di codice che veniva invocato da un salto condizionale dopo una
chiamata a ZWQuerySystemTime e che diceva più o meno :"Fai partire un thread in
background e ponilo in Suspend per 36EE80 millisecondi..".
Ci siamo!, pensai. Installai W2000 dual boot, installai SICE 4.01 in modalità boot (con
ICEPACK, driver di tastiera nuovo, etc. - una pena), misi un break point all'inizio del
segmento di codice in fase di boot, e nulla successe. Durante il riavvio del sistema,
reimpostai la data nel BIOS a due anni più tardi, inserii di nuovo il breakpont e
finalmente...non successe nulla lo stesso! Aspettai un'ora e comparve: "Avviso
valutazione di Windows: il periodo..." etc. etc.
Aspettai un'altra ora. Il sistema si bloccò mostrando un Bug Check; niente logoff e
shutdown comandati dal sistema, solo il blocco totale.
OK, daccapo. Feci ripartire il tutto, brkpoint su ShowWindow, e dopo un'ora ecco la
console di SICE. Con un pò di stack si risale a quello che ha originato la finestra di
messaggio: NTOSKRL.EXE. Evidente. Ma da dove partiva il tutto? Lo stack non forniva alcuna
informazione.
Una buona idea poteva essere quella di cercare 36EE80 in altri files. Quali? La protezione
in teoria poteva essere ubicata ovunque; in un servizio, in un file qualunque utilizzato
da un servizio
si sarebbe potuta eseguire una ricerca in automatico con un programma
Grep
Ok, facciamolo.
Dopo aver letto sulla finestra di dialogo del programma "searching 5160 files for
36EE80
" pensai 'no, grazie, comunque troppo oneroso'.
Ma Microsoft desidera o no che questa protezione venga disattivata, e tutto il mondo usi
W2000, che l'abbia regolarmente acquistato o no? Oppure non ne ha più bisogno (tanto
tutto il mondo lo userà comunque), e vuole soltanto venderlo? Nel primo caso trovare la
protezione (o le informazioni relative) sarebbe facile, nel secondo la protezione sarebbe
difficilissima da disattivare.
Bé, comunque ditelo, e non fate perdere tempo inutile ad un'onesta cracker che ha un
sacco di altre cose da fare...
DEDICATO A COLORO CHE CI CHIAMANO 'PIRATI'
Tanto la risoluzione di un enigma è appassionante (quando la natura dell'enigma è chiara
e definita), quanto è noiosa la ricerca delle informazioni.
Al diavolo Microsoft e i suoi giochetti! Non mi interessava affatto avere una versione
"full" di W2000 RC2; sapevo benissimo che subito dopo la presentazione ufficiale
del prodotto, mi sarebbe stata fornita, in maniera assolutamente gratuita, una versione
"final" originale, con licenza regolare, ed in Inglese, prima che qui
cominciassero a circolare le copie pirata della versione italiana.
Così mi disinteressai del problema, e giorno 18 febbraio pomeriggio la fantasmagorica
etichetta olografica del CD originale occhieggiava dal tavolo da lavoro. Ricambiai lo
sguardo, ed in quel momento decisi che...mai una copia regolare di questo sistema
operativo sarebbe stata installata su una macchina utilizzata da me, a qualunque titolo,
se prima essa non avesse ospitato, anche per un solo giorno, la versione italiana
"RC2 full cracked". Ho detto!
MARK RUSSINOVICH E BRYCE COGSWELL SONO CORRETTI, O CI PRENDONO SOLO IN
GIRO?
La ricerca delle informazioni ricominciava. La sera stessa notavo che sul sito di System
Internals era presente, tra gli altri, un programma denominato "Istrial". Cosa
fa Istrial? Verifica se una versione di NT (qualunque versione) sia full o sia un trial, e
nel secondo caso visualizza la data di scadenza.
Allora System Internals sa! E, cosa più importante, anche io saprò!
Le funzioni importate da Istrial sono essenzialmente le ADVAPI32 che riguardano il
registro di sistema; quindi qualcosa è scritto lì, ed il programma lo legge. Basta
allora utilizzare il RegMon che la stessa System Internals ci mette gentilmente a
disposizione...
Una cosa che avevo notato, ma sulla quale non mi ero soffermata più di tanto, era un
leggero ritardo nella risposta di Istrial all'avvio. Dopo aver chiesto a RegMon di salvare
il log degli accessi al registro di Istrial ed avere avviato quest'ultimo, un'occhiata
alle dimensioni del fle di log generato (2Megs all'incirca) chiarificò istantaneamente le
ragioni della "torpidità" nella risposta all'avvio di Istrial: Istrial legge
tutto il registro, per intero, prima di pronunciarsi su versione e data di scadenza del
sistema operativo.
Ma che bisogno ha di leggere tutto il registro? Mascherare quale fosse la chiave realmente
interessante, supposi.
Allora Russinovich e Cogswell sarebbero estremamente corretti? E ritorniamo all'ago nel
pagliaio, dunque?
Disassemblando Istrial, il segmento di codice nel quale viene stabilito se il sistema
operativo sia o meno una versione trial è di individuazione praticamente immediata: la
locazione di memoria 407A20 (un flag), viene controllata: se il flag è resettato, la
versione è full, se è settato, una data viene calcolata a partire dal contenuto delle
locazioni 407BE0 e seguenti.
.text:00401356 add esp, 0Ch
.text:00401359 xor eax, eax
.text:0040135B mov al, byte_0_407A20 QUESTA QUI
.text:00401360 test eax, eax
.text:00401362 jz loc_0_40142F
.text:00401368 mov ecx, dword_0_407BE4
.text:0040136E mov [ebp+var_8C], ecx
.text:00401374 mov edx, dword_0_407BE0
.text:0040137A mov [ebp+var_90], edx
.text:00401380 mov eax, dword_0_407BE8
.text:00401385 xor ecx, ecx
.text:00401387 push 0
.text:00401389 push 3Ch
.text:0040138B push ecx
.text:0040138C push eax
.text:0040138D call __allmul
.text:00401392 push 0
.text:00401394 push 989680h
.text:00401399 push edx
.text:0040139A push eax
.text:0040139B call __allmul
.text:004013A0 add eax, [ebp+var_90]
.text:004013A6 adc edx, [ebp+var_8C]
.text:004013AC mov [ebp+var_98], eax
.text:004013B2 mov [ebp+var_94], edx
.text:004013B8 lea edx, [ebp+var_88]
.text:004013BE push edx
.text:004013BF lea eax, [ebp+var_98]
.text:004013C5 push eax
.text:004013C6 call ds:FileTimeToLocalFileTime
.text:004013CC lea ecx, [ebp+var_A8]
.text:004013D2 push ecx
.text:004013D3 lea edx, [ebp+var_88]
.text:004013D9 push edx
.text:004013DA call ds:FileTimeToSystemTime
.text:004013E0 push 40h
.text:004013E2 lea eax, [ebp+var_80]
.text:004013E5 push eax
.text:004013E6 push 0
.text:004013E8 lea ecx, [ebp+var_A8]
.text:004013EE push ecx
.text:004013EF push 0
.text:004013F1 push 400h
.text:004013F6 call ds:GetDateFormatA
.text:004013FC push 40h
.text:004013FE lea edx, [ebp+var_40]
.text:00401401 push edx
.text:00401402 push 0
.text:00401404 lea eax, [ebp+var_A8]
.text:0040140A push eax
.text:0040140B push 0
.text:0040140D push 400h
.text:00401412 call ds:GetTimeFormatA
.text:00401418 lea ecx, [ebp+var_40]
.text:0040141B push ecx
.text:0040141C lea edx, [ebp+var_80]
.text:0040141F push edx
.text:00401420 push offset aThisTrialVersi ; "This trial version of NT will expire on"...
.text:00401425 call sub_0_401754
.text:0040142A add esp, 0Ch
.text:0040142D jmp short loc_0_40143C
.text:0040142F loc_0_40142F: ; CODE XREF: sub_0_40121F+143j
.text:0040142F push offset aThisIsTheFullV ; "This is the full version of NT.\n\n"
.text:00401434 call sub_0_401754
.text:00401439 add esp, 4
.text:0040143C loc_0_40143C: ; CODE XREF: sub_0_40121F+20Ej
.text:0040143C xor eax, eax
.text:0040143E loc_0_40143E: ; CODE XREF: sub_0_40121F+4Dj
.text:0040143E mov esp, ebp
.text:00401440 pop ebp
.text:00401441 retn
Il setting viene stabilito in base al valore di una sottochiave letta dal programma:
.text:00401105 call ds:RegEnumValueA
.text:0040110B mov [ebp+var_428], eax
.text:00401111 loc_0_401111: ; CODE XREF: sub_0_401000+C3j
.text:00401111 push offset aQsjpsjuzrvbouv ; "qsjpsjuzrvbouvnnbusjy"
.text:00401116 lea ecx, [ebp+var_424]
.text:0040111C push ecx
.text:0040111D call 004053E0
.text:00401122 add esp, 8
.text:00401125 test eax, eax
.text:00401127 jnz short loc_0_401161
.text:00401129 mov edx, [ebp+var_20]
.text:0040112C mov [ebp+var_4], edx
.text:0040112F mov eax, [ebp+var_4] QUI
.text:00401132 cmp dword ptr [eax+4], 0
.text:00401136 jz short loc_0_40114B
.text:00401138 mov byte_0_407A20, 1
.text:0040113F mov ecx, [ebp+var_4]
.text:00401142 mov edx, [ecx+4]
.text:00401145 mov dword_0_407BE8, edx
.text:0040114B loc_0_40114B: ; CODE XREF: sub_0_401000+136j
.text:0040114B mov eax, [ebp+var_4]
ma il nome della sottochiave è crittato, come si vede, e viene decrittato in 4053E0.
Dobbiamo reversare l'algoritmo di decrittazione allora? In realtà non ce ne importa un
fico secco dell'algoritmo di decrittazione: carichiamo il programma in SICE, inseriamo un
breakpoint in 40112F, facciamo partire il programma ed al break di SICE verifichiamo il
valore della locazione.
Indi, con Notepad o un altro editor a scelta, cerchiamo le occorrenze di tale valore nel
log di RegMon. Ne troviamo una sola. E' stato troppo facile. Per quale parte del corpo (il
cui nome comincia per "C") ci prendono Mark Russinovich e Bryce Cogswell?...Alguzza, sarebbe un problema anzichè no, se riuscissero a prenderti
per quella parte del corpo....Ti chiami Alga, mica
Platinette :))) NdQuequero
IL PERIODO DI TRIAL
La chiave è HKLM/SYSTEM/CurrentControl/Control/Session
Manager/Executive/PriorityQuantumMatrix, che ha un valore binario composto in pratica
da tre campi a 32bit; se il campo centrale è posto a zero, la versione è full, se non lo
è, il campo centrale indica la scadenza.
Verifichiamo sul mio sistema NT4: il campo è zero.
Scriviamo qualcosa nel campo: Istrial sostiene che il mio sistema è una trial version.
Sulla mia installazione di Windows 2000 RC2 il campo centrale è 80 C1 09 00, ovverossia
9C180, e cioè 639360 in decimale, che diviso 1440 (il numero di minuti contenuti in un
giorno) fa per l'appunto 444: il campo centrale è la durata in secondi (pignola
Microsoft!) del periodo di trial.
Proviamo adesso ad azzerare il campo in W2000 RC2: non succede niente. Ma proprio niente,
nel senso che il valore del campo resta invariato. Qualcosa presta attenzione alle
eventuali variazioni della voce nel registro, e ripristina prontamente il valore
originale. La faccenda comincia finalmente a farsi interessante.
Per identificare il nostro avversario, diciamo a RegMon di moniritozzare (originale sto termine...moniritozzare NdQue) soltanto gli accessi
in scrittura alla chiave che ci interessa, e riproviamo a variare il campo. OK, RegMon
rileva che qualcuno ha riscritto il valore della chiave, e questo qualcuno è System.
System vuol dire NTDLL.DLL oppure NTOSKRNL.EXE. Le funzioni del sistema operativo sono
rigorosamente "undocumented"
(almeno per i comuni mortali), e se esse vengono chiamate nell'ambito di API per svolgere
solo una parte dei compiti delle funzioni, capire come e cosa facciano può essere
difficile; ma molte di esse hanno nomi evocativi, ed un comportamento dello stack
straordinariamente simile ad alcune API di sistema (vedi ad esempio NtQuerySystemTime), e
quindi si può avere un'idea riguardo al loro comportamento.
In NTOSKRNL.EXE sono presenti tre funzioni dal nome "interessante":
ZwSetValueKey, ZwNotifyChangeKey e ZwFlushKey. Per le prime due di esse, un maggior numero
di parametri viene passato nello stack, ma possiamo supporre che, in linea di massima,
esse agiscano come le "corrispondenti" funzioni di ADVAPI32. Inoltre, mentre le
occorrenze della prima sono numerose, ZwNotifyChangeKey compare solo due volte. Ponendo un
breakpoint su quest'ultima, e tentando di cambiare il valore del campo centrale della
sottochiave, SICE blocca l'esecuzione in questo punto:
PAGE:004BB4C8 push ebp
PAGE:004BB4C9 mov ebp, esp
PAGE:004BB4CB sub esp, 2Ch
PAGE:004BB4CE push ebx
PAGE:004BB4CF xor ebx, ebx
PAGE:004BB4D1 push dword_0_472AD0
PAGE:004BB4D7 mov [ebp+var_1], bl
PAGE:004BB4DA call ZwClose
PAGE:004BB4DF lea eax, [ebp+var_C]
PAGE:004BB4E2 push offset off_0_4BB400
PAGE:004BB4E7 push eax
PAGE:004BB4E8 call RtlInitUnicodeString
PAGE:004BB4ED lea eax, [ebp+var_C]
PAGE:004BB4F0 mov [ebp+var_2C], 18h
PAGE:004BB4F7 mov [ebp+var_24], eax
PAGE:004BB4FA lea eax, [ebp+var_2C]
PAGE:004BB4FD push eax
PAGE:004BB4FE push 2001Fh
PAGE:004BB503 push offset dword_0_472AD0
PAGE:004BB508 mov [ebp+var_28], ebx
PAGE:004BB50B mov [ebp+var_20], 40h
PAGE:004BB512 mov [ebp+var_1C], ebx
PAGE:004BB515 mov [ebp+var_18], ebx
PAGE:004BB518 call ZwOpenKey
PAGE:004BB51D cmp eax, ebx
PAGE:004BB51F jl short loc_0_4BB59A
PAGE:004BB521 cmp byte_0_472B74, bl
PAGE:004BB527 jnz short loc_0_4BB59A
PAGE:004BB529 cmp byte_0_473AE9, bl
PAGE:004BB52F jnz short loc_0_4BB56C
PAGE:004BB531 lea eax, [ebp+var_14]
PAGE:004BB534 push offset a188 ; "PriorityQuantumMatrix"
PAGE:004BB539 push eax
PAGE:004BB53A call RtlInitUnicodeString
PAGE:004BB53F call sub_0_4600A5 equivalente di LockResource
PAGE:004BB544 push 0Ch
PAGE:004BB546 push offset dword_0_473AF8 ; key value
PAGE:004BB54B push 3
PAGE:004BB54D lea eax, [ebp+var_14]
PAGE:004BB550 push ebx
PAGE:004BB551 push eax
PAGE:004BB552 push dword_0_472AD0
PAGE:004BB558 mov [ebp+var_1], 1
PAGE:004BB55C call ZwSetValueKey
PAGE:004BB561 push dword_0_472AD0
PAGE:004BB567 call ZwFlushKey
PAGE:004BB56C
PAGE:004BB56C loc_0_4BB56C: ; CODE XREF: sub_0_4BB4C8+67_j
PAGE:004BB56C push 1
PAGE:004BB56E push 4
PAGE:004BB570 push offset unk_0_472B80
PAGE:004BB575 push ebx
PAGE:004BB576 push 0Fh
PAGE:004BB578 push offset unk_0_472C00
PAGE:004BB57D push 1
PAGE:004BB57F push offset dword_0_472BD0
PAGE:004BB584 push ebx
PAGE:004BB585 push dword_0_472AD0
PAGE:004BB58B call ZwNotifyChangeKey QUI
PAGE:004BB590 cmp [ebp+var_1], bl
PAGE:004BB593 jz short loc_0_4BB59A
PAGE:004BB595 call sub_0_48DE28 equivalente di UnLockResource
PAGE:004BB59A
PAGE:004BB59A loc_0_4BB59A: ; CODE XREF: sub_0_4BB4C8+57_j
PAGE:004BB59A ; sub_0_4BB4C8+5F_j ...
PAGE:004BB59A pop ebx
PAGE:004BB59B leave
PAGE:004BB59C retn 4
PAGE:004BB59C sub_0_4BB4C8 endp
- La routine è chiamata da una call in 418874, che è all'interno di una procedura
eseguita periodicamente; se una modificazione del valore della sottochiave viene rilevato,
il valore originario, inserito in 473AF8 in fase di caricamento del sistema operativo,
viene utilizzato per ripristinare il valore originario.
La ricerca delle altre occorrenze di 473AF8 (o, più semplicemente, l'analisi della cross
reference table se stiamo usando IDA) non consente di rilevare da dove venga letto il
valore della sottochiave che verrà copiato.
L'evento che scrive il valore nella locazione 473AF8 avviene all'avvio di NTOSKRNL.EXE, e
quindi prima del caricamento di SICE; quest'ultimo non può intercettarlo.
L'aspetto più noioso del reversing di NTOSKRNL.EXE eseguito con SoftICE e su una sola
macchina è appunto questo: gran parte delle attività relative alla protezione vengono
eseguite durante la sequenza di startup, quindi SICE non può intercettarle, ed una volta
avviato NTOSKRNL tutte le modificazioni fatte sul file o sulla sua immagine in memoria non
avranno evidemente alcuna influenza su ciò che è già accaduto. Windows non può
ricaricare NTOSKRNL perchè Windows E' NTOSKRNL!
Ciò comporta il fatto di doversi servire in prevalenza del "dead listing"
(senza documentazione sulle funzioni :( ), e di dover riavviare ogni volta che si voglia
provare l'effetto di una modifica (azione, come vedremo, che può risolversi in
"spiacevoli" eventi)
Dalle informazioni fin qui raccolte però, tre dati fondamentali possono venire
estrapolati:
1) Il valore binario della sottochiave in esame è composto da tre campi a 32 bit, ed il
campo che ci riguarda è il secondo (da ISTRIAL, REGMON e REGEDIT)
2) In 473AF8 inizia l'intero valore della sottochiave, ovvero vi si trovano tutti e tre i
campi (da SICE)
3) Il valore del secondo campo si troverà allora evidentemente in 473AFC, e questa
locazione è referenziata separatamente (si vede nel disassemblato):
.data:00473AF8 dword_0_473AF8 dd 0 ; DATA XREF: sub_0_4BB0FC+77_o I campo
.data:00473AF8 ; sub_0_4BB4C8+7E_o ...
.data:00473AFC*dword_0_473AFC dd 0 ; DATA XREF: sub_0_4BA6F5+B9_r II campo
.data:00473AFC* ; sub_0_4BA6F5+EF_r ...
.data:00473B00 dword_0_473B00 dd 0 ; DATA XREF: sub_0_541342+2A_r III campo
.data:00473B04 db 0 ;
.data:00473B05 db 0 ;
.data:00473B06 db 0 ;
.data:00473B07 db 0 ;
La cross reference table di IDA fornisce sette riferimenti per 473AFC:
4BA7AE
4BA7E4
4BB10D
540DB1
541355
54135B
54138C
di essi, il primo ed il secondo, ed il quinto ed il sesto si trovano nell'ambito della
stessa subroutine; questo segmento di codice è l'inizio della sub che contiene il quinto
ed il sesto riferimento:
INIT:00541342 push ebp
INIT:00541343 mov ebp, esp
INIT:00541345 sub esp, 20h
INIT:00541348 push ebx
INIT:00541349 xor ebx, ebx ; EBX è zero
INIT:0054134B cmp byte_0_473AE9, bl ; questo flag è zero?
INIT:00541351 push esi
INIT:00541352 push edi
INIT:00541353 jz short loc_0_54135B ; si, salta
INIT:00541355 mov dword_0_473AFC, ebx ; no, azzera campo centrale
INIT:0054135B
INIT:0054135B loc_0_54135B: ; CODE XREF: sub_0_541342+11_j
INIT:0054135B cmp dword_0_473AFC, ebx ;campo centrale è zero?
etc.
- Come si può vedere, viene eseguito il check del "flag" alla locazione 473AE9;
se è diverso da zero il valore di EBX (posto a zero in 514349) viene copiato in 473AFC.
Quindi "qualcosa" potrebbe indicare a W2000 RC2 di trasformarsi in versione
"full"? E' probabile, ma non è possibile usare SICE, poichè l'evento
sembrerebbe accadere prima del caricamento del debugger.
La cross reference table relativa a 473AE9 ci mostra che il flag viene resettato in
5408D3, e settato in 5409A8.
Patchamo NTOSKRNL in modo da forzare il flusso del programma sulla locazione 5409A8: non
succede niente. Il segmento di codice non è mai stato eseguito? Il flag è stato settato,
ma un evento non previsto lo ha resettato? Con questa metodica non lo sapremo mai.
Se forzassimo l'inserimento di un 1 in 540D83? Il sistema operativo si blocca in fase di
caricamento, mostrando un Bug Check 0x1E KMODE_EXCEPTION_NOT_HANDLED. Beh, meglio lasciar
perdere questa soluzione, se non si può eseguire il debugging su un'altra macchina, e
passare a soluzioni alternative.
VIOLAZIONE DELLA LICENZA!
Una soluzione sicuramente meno elegante è quella di annullare il salto in 541353. Cosa
succede in questo caso? Il sistema si blocca sempre in fase di caricamento mostrando un
Bug Check software: LICENSE_VIOLATION.
Ci siamo, allora! La subroutine in 541342 è stata eseguita, ma esiste qualche altro
controllo che ha rilevato un'incongruenza e generato il Bug Check. Questo è il listato
completo della subroutine:
INIT:00541342 push ebp
INIT:00541343 mov ebp, esp
INIT:00541345 sub esp, 20h
INIT:00541348 push ebx
INIT:00541349 xor ebx, ebx ; EBX è zero
INIT:0054134B cmp byte_0_473AE9, bl ; questo flag è zero?
INIT:00541351 push esi
INIT:00541352 push edi
INIT:00541353 jz short loc_0_54135B ; si, salta
INIT:00541355 mov dword_0_473AFC, ebx ; no, azzera campo centrale
INIT:0054135B
INIT:0054135B loc_0_54135B: ; CODE XREF: sub_0_541342+11_j
INIT:0054135B cmp dword_0_473AFC, ebx ; campo centrale è zero?
INIT:00541361 jz loc_0_54144A ; si, salta controllo SystemTime e
ZwNotifyChangeKey
INIT:00541367 mov eax, dword_0_473AF8
INIT:0054136C mov ecx, dword_0_473B00
INIT:00541372 cmp eax, ebx
INIT:00541374 jnz loc_0_5414AC
INIT:0054137A cmp ecx, ebx
INIT:0054137C jnz loc_0_5414AC
INIT:00541382 push offset dword_0_472BE8
INIT:00541387 call KeQuerySystemTime
INIT:0054138C
INIT:0054138C loc_0_54138C: ; CODE XREF: sub_0_541342+165_j
INIT:0054138C ; sub_0_541342+175_j
INIT:0054138C mov eax, dword_0_473AFC
INIT:00541391 push ebx
INIT:00541392 imul eax, 3Ch
INIT:00541395 cdq
INIT:00541396 push 989680h
INIT:0054139B push edx
INIT:0054139C push eax
INIT:0054139D call _allmul
INIT:005413A2 add eax, dword_0_472BE8
INIT:005413A8 mov ecx, 0FFDF02C8h
INIT:005413AD push offset aRegistryMach_4 ; "\\Registry\\Machine\\System\\CurrentControl"...
INIT:005413B2 adc edx, dword_0_472BEC
INIT:005413B8 mov dword_0_472B78, eax
INIT:005413BD mov dword_0_472B7C, edx
INIT:005413C3 mov [ecx], eax
INIT:005413C5 mov eax, dword_0_472B7C
INIT:005413CA mov [ecx+4], eax
INIT:005413CD lea eax, [ebp+var_8]
INIT:005413D0 push eax
INIT:005413D1 mov byte_0_472B74, bl
INIT:005413D7 mov dword_0_472BD8, offset sub_0_4BB4C8
INIT:005413E1 mov dword_0_472BDC, ebx
INIT:005413E7 mov dword_0_472BD0, ebx
INIT:005413ED call RtlInitUnicodeString
INIT:005413F2 lea eax, [ebp+var_8]
INIT:005413F5 mov [ebp+var_20], 18h
INIT:005413FC mov [ebp+var_18], eax
INIT:005413FF lea eax, [ebp+var_20]
INIT:00541402 push eax
INIT:00541403 push 2001Fh
INIT:00541408 push offset dword_0_472AD0
INIT:0054140D mov [ebp+var_1C], ebx
INIT:00541410 mov [ebp+var_14], 40h
INIT:00541417 mov [ebp+var_10], ebx
INIT:0054141A mov [ebp+var_C], ebx
INIT:0054141D call ZwOpenKey
INIT:00541422 cmp eax, ebx
INIT:00541424 jl short loc_0_54144A
INIT:00541426 push 1
INIT:00541428 push 4
INIT:0054142A push offset unk_0_472B80
INIT:0054142F push ebx
INIT:00541430 push 0Fh
INIT:00541432 push offset unk_0_472C00
INIT:00541437 push 1
INIT:00541439 push offset dword_0_472BD0
INIT:0054143E push ebx
INIT:0054143F push dword_0_472AD0
INIT:00541445 call ZwNotifyChangeKey
INIT:0054144A
INIT:0054144A loc_0_54144A: ; CODE XREF: sub_0_541342+1F_j
INIT:0054144A ; sub_0_541342+E2_j
INIT:0054144A push ebx
INIT:0054144B mov edi, offset unk_0_472A40
INIT:00541450 push offset loc_0_418628
INIT:00541455 push edi
INIT:00541456 call KeInitializeDpc
INIT:0054145B mov esi, offset unk_0_472BA0
INIT:00541460 mov dword_0_472B28, offset sub_0_4BA6F5
INIT:0054146A push esi
INIT:0054146B mov dword_0_472B2C, ebx
INIT:00541471 mov dword_0_472B20, ebx
INIT:00541477 call KeInitializeTimer
INIT:0054147C push 0FFFFFFF7h
INIT:0054147E mov eax, 9E3B9800h
INIT:00541483 pop ecx
INIT:00541484 mov dword_0_472B08, eax
INIT:00541489 push edi
INIT:0054148A push ecx
INIT:0054148B push eax
INIT:0054148C push esi
INIT:0054148D mov dword_0_472B0C, ecx
INIT:00541493 call KeSetTimer
INIT:00541498 push offset unk_0_46A6C0
INIT:0054149D call ExInitializeResourceLite
INIT:005414A2 pop edi
INIT:005414A3 pop esi
INIT:005414A4 pop ebx
INIT:005414A5 leave
INIT:005414A6 retn
- Tutto appare molto semplice: sembrerebbe che venga eseguito il controllo su una
locazione di memoria (che abbiamo etichettato come "flag") per resettare,
eventualmente, il campo centrale del valore della chiave del registro; se esso risulta
diverso da zero viene calcolato il tempo di utilizzo, altrimenti si salta alla fine della
routine. Bene, allora deve esistere un altro check (se il sistema si blocca), e questo
check deve tenere conto del fatto che abbiamo azzerato la locazione che ci interessa.
Cercando tra le altre occorrenze di 473AFC troviamo facilmente il controllo:
INIT:00540D9E loc_0_540D9E: ; CODE XREF: sub_0_5408BF+4B1_j
INIT:00540D9E ; sub_0_5408BF+4D2_j ...
INIT:00540D9E mov eax, dword_0_473B08
INIT:00540DA3 mov edx, dword ptr unk_0_473B0C
INIT:00540DA9 push 0Dh
INIT:00540DAB pop ecx
INIT:00540DAC call _allshr ; scorrimento a destra di EAX di 13 bit
INIT:00540DB1 mov ecx, dword_0_473AFC ;campo centrale in ECX
INIT:00540DB7 mov [ebp+var_6C], edx ; salva
INIT:00540DBA mov edx, eax ; memorizza in EDX
INIT:00540DBC and edx, 0FFFFFFFh ; maschera il primo byte
INIT:00540DC2 cmp edx, ecx ; confronta con il risultato precedente
INIT:00540DC4 jz short loc_0_540DDC ; continua se uguali
INIT:00540DC6 push ecx
INIT:00540DC7 mov ecx, dword ptr unk_0_473B0C
INIT:00540DCD and ecx, esi
INIT:00540DCF shl ecx, 3
INIT:00540DD2 push ecx
INIT:00540DD3 push eax
INIT:00540DD4 push 1
INIT:00540DD6 push edi
INIT:00540DD7 call KeBugCheckEx ; FATAL SYSTEM ERROR!
INIT:00540DDC
INIT:00540DDC loc_0_540DDC: ; CODE XREF: sub_0_5408BF+505_j
INIT:00540DDC mov esi, 2079654Bh
INIT:00540DE1
INIT:00540DE1 loc_0_540DE1: ; CODE XREF: sub_0_5408BF+41E_j
INIT:00540DE1 push 1
INIT:00540DE3 push 4
INIT:00540DE5 push offset unk_0_472C78
INIT:00540DEA push ebx
INIT:00540DEB push 5
INIT:00540DED push offset unk_0_472CA0
INIT:00540DF2 push 1
INIT:00540DF4 push offset dword_0_472CC0
INIT:00540DF9 push ebx
INIT:00540DFA push dword_0_472CB0
INIT:00540E00 call sub_0_49C13C
INIT:00540E05 cmp eax, ebx
INIT:00540E07 jge loc_0_540ECB
INIT:00540E0D cmp byte_0_473AE9, bl
INIT:00540E13 jnz loc_0_540A61
INIT:00540E19 cmp byte_0_472CD0, bl
INIT:00540E1F jnz loc_0_540A61
INIT:00540E25 push ebx
INIT:00540E26 push ebx
INIT:00540E27 push eax
INIT:00540E28 push 8
INIT:00540E2A jmp loc_0_540A5B
In 473B0C è presente una "copia" del valore, shiftata a sinistra di 13 bit.
Forziamo il salto in 540DC4, copiamo la nuova versione di NTOSKRNL e riavviamo. Il sistema
parte regolarmente. Al logon ci accorgiamo che la scritta "Copia di valutazione"
sul desktop è scomparsa; quindi la 473AFC, rimasta a zero, sembra controllare tutto. Se
cerchiamo di variare il campo centrale del valore binario della sottochiave
HKLM/SYSTEM/CurrentControl/Control/Session Manager/Executive/PriorityQuantumMatrix, il
valore rimane quello che impostiamo. Poniamolo a zero; Istrial ci dirà che la nostra è
una versione full. OK, sembra fatto!
SI, MA DOV'E' UBICATA LA PROTEZIONE A TEMPO?
Qui:
PAGE:004BA795 loc_0_4BA795: ; CODE XREF: sub_0_4BA6F5+3D_j
PAGE:004BA795 ; sub_0_4BA6F5+41_j ...
PAGE:004BA795 cmp byte_0_4706B8, bl
PAGE:004BA79B jz short loc_0_4BA7AE
PAGE:004BA79D call sub_0_48A5C6
PAGE:004BA7A2 push ebx
PAGE:004BA7A3 push ebx
PAGE:004BA7A4 call sub_0_47A8CE
PAGE:004BA7A9 call sub_0_48A5DF
PAGE:004BA7AE
PAGE:004BA7AE loc_0_4BA7AE: ; CODE XREF: sub_0_4BA6F5+A6_j
PAGE:004BA7AE cmp dword_0_473AFC, ebx ;verifica valore campo
PAGE:004BA7B4 jz short loc_0_4BA801 ; salta se è zero
PAGE:004BA7B6 lea eax, [ebp+var_C]
PAGE:004BA7B9 push eax
PAGE:004BA7BA call KeQuerySystemTime ; verifica il tempo se è una trial version
PAGE:004BA7BF mov eax, [ebp+var_8]
PAGE:004BA7C2 cmp eax, dword_0_472B7C ; rimane tempo?
PAGE:004BA7C8 jl short loc_0_4BA801 ; si, continua
PAGE:004BA7CA jg short loc_0_4BA7D7 ; no, procedura di attivazione
PAGE:004BA7CC mov eax, [ebp+var_C] ; è uguale, verifica l'ora
PAGE:004BA7CF cmp eax, dword_0_472B78 ; minore?
PAGE:004BA7D5 jb short loc_0_4BA801 ; sì, vai avanti
PAGE:004BA7D7
PAGE:004BA7D7 loc_0_4BA7D7: ; CODE XREF: sub_0_4BA6F5+D5_j
PAGE:004BA7D7 cmp byte_0_472C08, bl ; flag avviso già visualizzato?
PAGE:004BA7DD jz loc_0_4BA88B ; no, parti
PAGE:004BA7E3 push ebx ; si, shutdown
PAGE:004BA7E4 push dword_0_473AFC
PAGE:004BA7EA push dword_0_472BEC
PAGE:004BA7F0 push dword_0_472BE8
PAGE:004BA7F6 push 98h
PAGE:004BA7FB push ebx
PAGE:004BA7FC call PoShutdownBugCheck
PAGE:004BA801
PAGE:004BA801 loc_0_4BA801: ; CODE XREF: sub_0_4BA6F5+BF_j
PAGE:004BA801 ; sub_0_4BA6F5+D3_j ...
PAGE:004BA801 mov eax, 0FFFFFFFFh
PAGE:004BA806 mov ecx, offset unk_0_472BE0
PAGE:004BA80B xadd [ecx], eax
PAGE:004BA80E dec eax
PAGE:004BA80F cmp eax, ebx
PAGE:004BA811 jnz loc_0_4BA6FF
PAGE:004BA817 push offset unk_0_472A40
PAGE:004BA81C push dword_0_472B0C
PAGE:004BA822 push dword_0_472B08
PAGE:004BA828 push offset unk_0_472BA0
PAGE:004BA82D call KeSetTimer
PAGE:004BA832 pop esi
PAGE:004BA833 pop ebx
PAGE:004BA834 leave
PAGE:004BA835 retn 4
PAGE:004BA838 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA838 jmp loc_0_4BA772
PAGE:004BA83D ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA83D
PAGE:004BA83D loc_0_4BA83D: ; CODE XREF: sub_0_4BA6F5+65_j
PAGE:004BA83D shr esi, 1
PAGE:004BA83F cmp esi, edx
PAGE:004BA841 jnz short loc_0_4BA84B
PAGE:004BA843 test al, 1
PAGE:004BA845 jz loc_0_4BA772
PAGE:004BA84B
PAGE:004BA84B loc_0_4BA84B: ; CODE XREF: sub_0_4BA6F5+6F_j
PAGE:004BA84B ; sub_0_4BA6F5+77_j ...
PAGE:004BA84B xor ecx, ecx
PAGE:004BA84D jmp loc_0_4BA779
PAGE:004BA852 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA852
PAGE:004BA852 loc_0_4BA852: ; CODE XREF: sub_0_4BA6F5+1C_j
PAGE:004BA852 ; sub_0_4BA6F5+28_j
PAGE:004BA852 mov dword_0_472A60, ebx
PAGE:004BA858 mov dword_0_472A64, ebx
PAGE:004BA85E jmp loc_0_4BA795
PAGE:004BA863 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA863
PAGE:004BA863 loc_0_4BA863: ; CODE XREF: sub_0_4BA6F5+10_j
PAGE:004BA863 cmp byte_0_473AE9, bl
PAGE:004BA869 jnz loc_0_4BA795
PAGE:004BA86F cmp byte_0_472CD0, bl
PAGE:004BA875 jnz loc_0_4BA795
PAGE:004BA87B inc dword_0_472AA0
PAGE:004BA881 jmp loc_0_4BA795
PAGE:004BA886 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA886 jmp loc_0_4BA801
PAGE:004BA88B ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA88B
PAGE:004BA88B loc_0_4BA88B: ; CODE XREF: sub_0_4BA6F5+E8_j
PAGE:004BA88B push 0C0000268h
PAGE:004BA890 push offset sub_0_4BB3DA
PAGE:004BA895 push ebx
PAGE:004BA896 push ebx
PAGE:004BA897 push ebx
PAGE:004BA898 lea eax, [ebp+var_4]
PAGE:004BA89B push 1F03FFh
PAGE:004BA8A0 push eax
PAGE:004BA8A1 mov byte_0_472C08, 1 ; partito! Da qui trascorrerà un'ora,
PAGE:004BA8A1 ; indi il flag risulterà settato
PAGE:004BA8A8 call PsCreateSystemThread
PAGE:004BA8AD cmp eax, ebx
PAGE:004BA8AF jl loc_0_4BA801
PAGE:004BA8B5 push [ebp+var_4]
PAGE:004BA8B8 call ZwClose
PAGE:004BA8BD jmp loc_0_4BA801
PAGE:004BA8BD sub_0_4BA6F5 endp
PAGE:004BA8BD
PAGE:004BA8BD ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
PAGE:004BA8C2 db 0CCh
Risulta chiaro il modo di operare di NTOSKRNL: solo se la solita 473ACF è diversa da zero
(e quindi il sistema è una versione trial) verifica se il periodo di trial è scaduto. Se
lo è, verifica un certo flag (472C08). Se esso è resettato, parte e lo setta,
riverificando il tutto dopo un'ora. Se esso risulta già settato, un'ora è già
trascorsa, quindi visualizza l'avviso, e dopo un'altra ora il sistema si inginocchierà
miseramente mostrando un Bug Check.
Anche qui dunque 473AFC è la chiave di tutto, e questo sembrerebbe aprire delle
interessanti possibilità.
LE INTERESSANTI POSSIBILITA'
Istrial è un'utility relativa a tutti i sistem NT. Di fatto sui sistemi NT 4 (Workstation
e Server) esiste la sottochiave verificata da Istrial, mentre la stessa non è presente
sui sistemi W 9x. Come accennavo all'inizio, io non mi ero mai occupata della protezione a
tempo dei sistemi NT; mi sono chiesta allora: oltre alla presenza della sottochiave ed al
significato del suo valore, cos'altro hanno in comune le trial NT4 con quelle W2000? Lo
schema della protezione è lo stesso?
Sì, è identico. Su un vecchio CD-ROM (PC Magazine Gennaio '97) era presente una versione
trial 120 giorni di NT 4 Workstation.
L'equivalente della routine in 4BA795 si trova in 80155686; il controllo relativo alla
violazione della licenza che in W2000 inizia in 540D9E ha il suo corrispettivo in NT4 in
801BEF14, ed infine l'analogo della routine "principale" di W2000 (541342) è in
801BF05E.
Chiarifico, adesso, l'accenno fatto precedentemente alle "interessanti
possibilità".
Consideriamo la routine che inizia in 4BA795. Forzando il solo salto condizionale in
4BA7C8 (oltre, naturalmente, quello in 540DC4, pena il blocco del sistema all'avvio per
generazione del Bug Check LICENSE_VIOLATION), il campo centrale del valore di HKLM/SYSTEM/CurrentControl/Control/Session
Manager/Executive/PriorityQuantumMatrix resterebbe non alterabile, così come immutato
rimarebbe il valore corrispondente in 473AFC; ciò significa che il sistema verrebbe visto
come trial da Istrial (e da qualunque altro programma), la dicitura "Copia di
valutazione" rimarebbe ben visibile sul desktop e verosimilmente (ritengo che anche
questo aspetto sia controllato da 473AFC - ma è solo un'ipotesi) non sarebbero
applicabili i Service Packs.
La copia di W2000 sarebbe una versione trial a tutti gli effetti legali (e legalmente si
sarebbe autorizzati ad usarla - la licenza è acclusa) ma...non si fermerebbe mai.
Stesso discorso vale per la versione trial 120 giorni di NT4 Workstation; qualunque
ispezione legale troverebbe una trial version "legale", e si sarebbe ottenuta la
licensa d'uso di un sistema operativo in maniera assolutamente gratuita. Sarebbe infatti
veramente difficile verificare che la versione di NTOSKRNL.EXE attiva sulla macchina è
diversa da quella presente sul CD di installazione...
Purtroppo però, come vedremo, ciò è attualmente vero solo in (minima) parte, mentre lo
era totalmente ai tempi di NT 4.
I TEMPI STANNO CAMBIANDO
Come già accennato, la versione trial 120 giorni di NT4 workstation in mio possesso era
inserita (gratuitamente, quindi) in un CD ROM accluso ad una rivista.
Anche la RC2 di W2000 era inserita gratuitamente in un CD ROM accluso ad una rivista, e
sembrerebbe assolutamente funzionale; sono riuscita a rilevare solo un ridicolo bug in
WordPad, ed un ben più grave blocco totale del sistema (stallo totale - bisogna
resettare) durante il recupero da suspend mode degli hard disk, ma per il resto non
sembrerebbero esistere altri problemi.
Il periodo di valutazione dura però ben 444 giorni (più di un anno, una
valutazione veramente accurata!), e soprattutto il programma di installazione esegue di
default l'aggiornamento del sistema.
Microsoft Italia fornisce a richiesta delle versioni trial 120 giorni, ma le vende, 50000
lire a copia.
Vi pregherei di notare questi tre fatti salienti:
1) Tre anni addietro le copie trial 120 giorni erano distribuite gratuitamente
2) RC2 è distribuita gratuitamente, ma se non si sta in guardia effettua l'aggiornamento
del sistema; tutto procede magnificamente e poi, più di un anno dopo, quando il vostro
sistema è pieno della roba vostra (di tutto quello che avete potuto inserire in un anno)
il sistema si blocca e vi si chiede di acquistare la licenza. Non volete? Avevate una
magnifica copia di Windows 95 perfettamente funzionante e con licenza e volete continuare
ad utilizzarla? Benissimo, nessun problema! Baste seguire questi semplici passi, ancora
più semplici, per l'utilizzatore medio, del Plug&Play:
-
- a) convertitevi una partizione in FAT16
b) copiatevi tutta la roba che non volete perdere
c) riformattate il volume principale
d) reinstallate Windows 95 dall'inizio
e) reinstallate tutte le vostre applicazioni
f) rimettete a posto tutto ciò contenuto nel backup effettuato in b).
Ah, dimenticavo, naturalmente i passi a) e b) vanno eseguiti nelle due ore che ogni avvio
di RC2 scaduta vi lascia...non sbagliate a calcolarvi il tempo...se andate fuori tempo
Microsoft non vi esegue un logoff forzato, vi manda in crash il sistema...vi conviene
farlo poco per volta riavviando ogni ora e mezza...tutto ciò se non avete letto questo
tutorial, naturalmente! :)
3) Adesso le copie trial 120 giorni vengono vendute
Riparleremo di questi tre punti tra poco.
LA CERTIFICAZIONE VERISIGN DEI FILE DI SISTEMA
Adesso possiamo scrivere un patcher; solo due byte da patchare agli offset 140DC4 e
141354, più altri due in 128 e 129 per il checksum...fatto, funziona, patchato, riavviamo
e...la scritta "copia di valutazione" è sempre lì, ed il registro di sistema
non consente variazioni.
Se scriviamo una patch che disattivi solo il limite di tempo si verifica la stessa cosa.
Le differenze non sarebbero visibili, ma un file compare con la copia originale di
NTOSKRNL.EXE mostra che i file sono comunque uguali.
Se cerchiamo di sovrascrivere NTOSKRNL con una versione patchata il risultato non cambia.
Questo è ciò che mamma Microsoft chiama "Protezione file"; siccome
mamma Microsoft ci vuole bene, e non vuole che il nostro sitema subisca danni se qualche
cattivaccio decide di sovrascrivere i file del sistema operativo, installa in duplice
copia e tiene sotto controllo, regolarmente gli accessi in scrittura a 3427(!) file, e se
il cattivaccio di cui sopra ne sovrascrive uno il sistema operativo verifica innanzitutto
che
-
1) la nuova versione sia dotata della firma digitale; se non lo è
2) preleva una copia del file dalla copia (compressa in %SystemRoot%\Driver
Cache\i386\driver.cab) e
3a) sovrascrive l'attività del cattivaccio, oppure, se anche la copia nella cache
dei file dovesse essere priva di firma digitale
3b) non sovrascrive nulla e segnala che nel sistema è presente un file (ed anche
quale) privo della firma digitale.
Ma, pensava un'Alga qualunque, non sarebbe stato più sensato porre
gli attributi dei file a sola lettura in fase di boot, considerando anche che file come
NTOSKRNL non verranno più caricati da disco dopo l'avvio, anzichè rallentare il sitema
per eseguire ciclicamente tutti questi controlli in background, ed occupare altri 52
Mega(!) per la copia dei file, nonchè altri 6 Mega per cataloghi e chiavi?
No,no,no...assolutamente no! Ormai i processori sono potenti, gli hard disk sono capienti,
e la sicurezza è sicurezza!
Bene, allora se vogliamo patchare il kernel dobbiamo disattivare protezione file. In
realtà la cosa non presenterebbe alcun problema; anche il nostro patcher può eseguire
ciò, rinominando il file driver.cab (ad esempio drivers.cab). In questo caso la patch
sarà applicabile e funzionerà perfettamente, ma...l'utility SIGVERIF.EXE segnalerà che
la versione in uso di NTOSKRNL.EXE è priva di firma digitale.
Così se il nostro sistema dovesse venire sottoposto a qualche "controllo",
sarebbe molto più facile verificare che i file di sistema sono stati alterati. Ed abbiamo
anche identificato il cattivaccio che vuole sovrascrivere, e dal quale mamma Microsoft ci
protegge benevolmente: il cattivaccio siamo noi stessi.
Tutto questo non esisteva per le trial di Windows NT 4, delle quali, se vogliamo possiamo
ancora "usufruire" :)
SCAPPATOIA!
E se noi (monelli!) volessimo ugualmente mantenere una
copia "pseudolegale" ma funzionante di RC2 (o di qualunqua altra trial, purchè
legalmente posseduta)?
Bene, rinominiamo DRIVER.CAB, patchamo NTOSKRNL, ripristiniamo DRIVER.CAB e viviamo
tranquilli; nell'ipotesi di un controllo o qualcos'altro basterà tentare di rinominare
NTOSKRNL.EXE e Protezione File ripristinerà prontamente il file originale, munito di
firma digitale. Attenzione però a non variare assolutamente il campo centrale del valore
di HKLM/SYSTEM/CurrentControl/Control/Session Manager/Executive/PriorityQuantumMatrix!
Diversamente, al riavvio successivo al ripristino il sistema si bloccherà visualizzando
il Bug Check LICENSE_VIOLATION e, a meno che non abbiate preso le precauzioni di cui parlo
alla fine, o non abbiate un sistema multiple boot, sarete costretti a reinstallare.
SI, MA QUANTO DURERA'?
Poco, ritengo. Fino al prossimo NT, comunque si chiamerà.
Dopodichè, penso diverrà estremamente difficile e soprattutto "pericoloso"
aggirare Protezione File.
Perchè la strada imboccata è a senso unico, ed ormai la diffusione del sistema comincia
ad essere tale che esso verrà praticamente imposto.
Tra l'altro, diviene così possibile rispondere ad una delle domande poste all'inizio:
Microsoft vuole o no che la protezione venga disattivata?
Ieri, voleva.
Oggi, forse.
Domani, non avrà più alcuna importanza.
Ah, e la RAM? Sembra che le cose stanno in maniera assolutamente opposta a come avevo
immaginato.
Microsoft ha altre frecce al suo arco per "costringere" all'acquisto di W2000.
Questo sembra adottare una serie di accorgimenti che diano l'illusione di una maggiore
rapidità nel logon (ma appare solo una diversa sequenza nell'esecuzioni di operazioni di
Phase 4 - dopo la comparsa del desktop e di tutte le icone il sistema diviene non
rispondente agli input di mouse e tastiera per una ventina di secondi almeno - bella
trovata, no? - ma non ho approfondito più di tanto), ma dalle prove fatte necessita di
più RAM per essere più veloce di un NT4 con Service Pack 6a (anche Protezione File avrà
il suo ruolo in questo, probabilmente).