UN ESEMPIO DI DLL REVERSING - COME RICONFIGURARE IL COMPORTAMENTO DI EXPLORER MODIFICANDO 
ALCUNE FUNZIONI DELLA LIBRERIA SHELL32.DLL

By -NeuRaL_NoiSE

_______________________________________________________________________________________________


Salve a tutti!!

Quante volte avete pensato "cacchio se solo potessi evitare di far passare i files per il 
cestino di Windows quando li elimino...che rottura dover prima cancellare, poi svuotare il 
cestino, magari anche solo per un file....solo che poi se gli dico di eliminare sempre i files 
a volte mi trovo in difficolta'..." ??? Bene, se rientrate nella folta schiera (me compreso, 
altrimenti questo tute non avrebbe mai visto la luce :) di coloro i quali si pongono il 
problema, beh allora state leggendo il .txt adatto :)

a questo punto permettetemi di spiegarvi sinteticamente un paio di cosette e DISCLAIMARE le mie 
responsabilita':

UNO : Se apporterete le modifiche che vi indichero' in questo tutorial, non ritenetemi 
responsabile per perdite accidentali dei vostri dati (il vostro comando ELIMINA da explorer non 
sara' piu' sicuro come un tempo!! :)

DUE : questo e' un tutorial rivolto al reverse engineering piu' che al cracking. Se avete 
scaricato questo file credendo di poter sproteggere un programma o crackare un gioco, mi 
dispiace deludervi ma non troverete niente di simile qui. Vi consiglio di dare un'occhiata ai 
tutorials su ringzer0.cjb.net - troverete sicuramente qualcosa di vostro gradimento :)

Detto cio'......LET'S GO!!!



allora....come avrete certamente capito dall'intro, in questo tute faremo in modo che quando 
scegliete una determinata opzione, il vostro fido explorer di Window$ ELIMINERA' fisicamente i 
files dal disco, senza farli passare dal cestino. "Bella novita'", starete pensando..."lo posso 
fare pure selezionando l'opzione 'Non spostare i files nel cestino, elimina direttamente' nelle 
proprieta' del cestino"....ed invece ecco la novita'....che ne direste di un bel dialog box con 
tre opzioni, UNO=SPOSTA NEL CESTINO, DUE=ELIMINA DAL DISCO e TRE=ANNULLA L'OPERAZIONE ?
Esatto....sto parlando di combinare, in qualche arcano modo, le tre cose senza smanettare con 
le opzioni del cestino (IMPORTANTE: PER SEGUIRE QUESTO TUTE, E SUCCESSIVAMENTE, *DOVETE* 
LASCIARE L'OPZIONE "SPOSTA NEL CESTINO", NIENTE "ELIMINA DIRETTAMENTE").
Ok, basta chiacchiere....

Contrariamente a quello che qualcuno potrebbe pensare, *NON* e' EXPLORER.EXE che regola le 
operazioni come cancellare i files, copiarli ecc., ma queste funzioni sono svolte da una DLL 
(Dynamic Link Library, ovvero un insieme di funzioni che vengono sfruttate da un programma, nel 
nostro caso EXPLORER.EXE) chiamata SHELL32.DLL e situata sotto WINDOWS\SYSTEM. Niente di grave, 
tratteremo la DLL come un qualsiasi eseguibile, e i tools saranno gli stessi di sempre:

* W32Dasm v8.93
* SoftICE v3.24
* HIEW v6.01

Bene...ci dovreste essere.
Aprite Shell32.dll con W32dasm....noterete la differenza di image base....non piu' 40000000h 
come i classici .exe ma 7FDB0000h. Bene, ora aprite Explorer.exe (Gestione Risorse) e create 
una directory temporanea, riempendola di files inutili copiati da altre dirs. MI RACCOMANDO NON 
OPERATE CON DIRECTORY GIA' PRESENTI SUL VOSTRO HARD DISK, PERCHE' LE POSSIBILITA' DI PERDERNE I 
DATI CONTENUTI E' MOLTO ALTA!
Allora...prendete un file a caso della vostra dummy dir e scegliete ELIMINA dal menu FILE (o 
dal context menu che appare premendo il tasto destro del mouse). Noterete un simpatico dialog 
che vi chiede se volete spostare xxxx.xxx nel cestino.....benissimo, ecco trovato il nostro 
hook per accedere al codice. Ad una prima occhiata, e' intuibile che la API su cui breakare e' 
DialogBoxParamA. E cosi' fate....scegliete NO, entrate in SoftICE, e scrivete 
"BPX DialogBoxParamA".
Riselezionate "elimina" e sice vi poppera' sullo schermo. premete F12 e sarete di nuovo in 
pista, stavolta con il dialog sullo schermo. Selezionate SI...Sice ri-poppera', e sarete alla 
riga successiva al caller del Dialog Box, che e' questa:


* Reference To: USER32.DialogBoxParamA, Ord:0084h
                                  |
:7FDE2505 FF15E83DE17F            Call dword ptr [7FE13DE8]


Date un'occhiata ad EAX, che come saprete contiene il valore di ritorno di OGNI funzione API.
Notate che e' 6. Ora premete F5, e il vostro file verra' spostato nel cestino. Adesso riprovate 
a scegliere ELIMINA. Noterete che, scegliendo NO, il return value in EAX successivamente al 
DialogBoxParamA e' = 7. Ripete l'operazione, ma stavolta lasciate perdere il mouse e premete 
ESC. Il return value sara' 2. quindi possiamo tracciare un semplice schema:


VALORE DI RITORNO DALLA CALL DEL DIALOGBOX | TASTO/BUTTON SELEZIONATO |  ** SIGNIFICATO **
___________________________________________|__________________________|________________________
                                           |                          |
          00000006                         | BUTTON "SI" SUL DIALOG   | SPOSTA FILE NEL CESTINO
___________________________________________|__________________________|________________________
                                           |                          |
          00000007                         | BUTTON "NO" SUL DIALOG   | ANNULLA L'OPERAZIONE
___________________________________________|__________________________|________________________
                                           |                          |
          00000002                         | TASTO "ESC" DA TASTIERA  | ANNULLA L'OPERAZIONE
___________________________________________|__________________________|________________________



Hmm.....cio' che salta all'occhio qui e' un'inutile ripetizione.....due valori di ritorno 
svolgono la stessa funzione...sarebbe molto meglio se potessimo modificare il significato del 
button "NO" sul dialog box....magari redirezionandolo verso l'ELIMINAZIONE FISICA del file 
selezionato dall'hard disk...In tal modo, senza grosse modifiche al codice avremmo una 
situazione molto piu' interessante: "SI" sposterebbe il file nel cestino, "NO" lo eliminerebbe 
fisicamente e "ESC" annullerebbe l'operazione. Vediamo che si puo' fare :)

Cominciamo a tracciare con F10, finche' non arriviamo qui

* Referenced by a JUMP at Addresses:
|:7FDE24ED(U), :7FDE2519(C), :7FDE2524(U)
|
:7FDE252B 83FE06                  cmp esi, 00000006         ; ESI CONTIENE IL RETURN VALUE
:7FDE252E 751E                    jne 7FDE254E              ; SE NON SI E' SCELTO "SI"
:7FDE2530 8B452C                  mov eax, dword ptr [ebp+2C]  
:7FDE2533 8B00                    mov eax, dword ptr [eax]   ; BYTE INIZIALE DESCRITTORE OBJECT
:7FDE2535 A810                    test al, 10                ; CONTROLLA SE L'OBJECT E' UNA DIR
:7FDE2537 7515                    jne 7FDE254E               ; SE SI (10=DIR, 20=FILE) SALTA
:7FDE2539 A805                    test al, 05                ; SE E' UN FILE....
:7FDE253B 7411                    je 7FDE254E                ; SALTA COMUNQUE :)
:7FDE253D 85FF                    test edi, edi
:7FDE253F 7503                    jne 7FDE2544
:7FDE2541 8B7D20                  mov edi, dword ptr [ebp+20]

Stop! Abbiamo quanto basta a capire che la continuazione naturale della procedura e' a 
7FDE254E...dove troviamo questa parte di codice:

:7FDE254E 8BC6                    mov eax, esi

Il return value viene rimesso in eax, molto bene....siamo sulla strada giusta...il check 
precedente serviva quindi solo a verificare problemi di memoria o di invalid handle....se 
c'erano problemi in eax veniva lasciato un dummy value e le operazioni successive non sarebbero 
andate in esecuzione. Come vedrete shell32.dll e' PIENA di checks di questo tipo...potete pure 
chiamarlo Good Old Micro$oft Redundant Code (TM) :)

Continuiamo il tracing con SoftICE fino al ret 028...ci ritroveremo qui:

:7FDE4093 E810E1FFFF              call 7FDE21A8         ;<-- TORNIAMO DA QUESTA CALL
:7FDE4098 8BF8                    mov edi, eax

* Referenced by a JUMP at Address:
|:7FDE4064(C)
|
:7FDE409A 83FF06                  cmp edi, 00000006    ; DI NUOVO...CHECK SE ABBIAMO PREMUTO SI
:7FDE409D 7540                    jne 7FDE40DF             ; ALTRIMENTI ELABORA DI CONSEGUENZA
:7FDE409F 8B442434                mov eax, dword ptr [esp+34] 
:7FDE40A3 8B08                    mov ecx, dword ptr [eax] ; BYTE INIZIALE DESCR. OBJ. IN ECX
:7FDE40A5 F6C110                  test cl, 10              ; ABBIAMO UN FILE QUI??
:7FDE40A8 7435                    je 7FDE40DF              ; SI! SALTA !
:7FDE40AA 81FD00010000            cmp ebp, 00000100        ; O UNA DIR?? (100=DIRECTORY)
:7FDE40B0 7408                    je 7FDE40BA
:7FDE40B2 81FD00030000            cmp ebp, 00000300        ; (300=FILE)
:7FDE40B8 7525                    jne 7FDE40DF        

Benissimo.....ulteriori checks (uff! :)...ora il nostro jne a 409D non saltera' perche' abbiamo 
scelto "SI", mentre prenderemo quello a 40A8 per ovvi motivi (abbiamo scelto un file:)...ora 
una premessa e' d'obbligo. Poiche' quello che stiamo per fare e' MOLTO pericoloso per i vostri 
dati, ho deciso di trattare in questo tutorial SOLO la modifica del codice relativo 
all'eliminazione di UN SOLO FILE ALLA VOLTA. In altre parole, il file verra' distrutto SOLO 
quando verra' cancellato DA SOLO. Se decidete di cancellare directories intere, o piu' file 
alla volta, dovrete servirvi del cestino. Comunque, se siete intenzionati a modificare anche il 
codice relativo alla cancellazione di piu' files o di una dir intera, vi do un piccolo 
consiglio...il dialog box e' diverso per quando dovete cancellare piu' files...quindi, un bpx 
su DialogBoxParamA vi fara' poppare in un altro punto, e troverete semplice orientarvi nello 
stesso modo in cui stiamo agendo qui. (consiglio nel consiglio ;) : Quando cancellate piu' 
files potete provare a noppare il mov eax,2 che viene eseguito SIA quando premete ESC SIA 
quando premete il button "NO"...noppando il mov, avrete la dovuta differenziazione (7 o 2) nel 
return value, che vi serve a ridirezionare le funzioni anche in tal caso...l'unico problema e' 
che poi dovrete appendere del codice se questo non e' gia' presente nella dialog procedure, 
quindi magari dovrete ingrandire l'ultima sezione del pe e...ma hey! questo e' un altro 
discorso :)

Ritorniamo a noi! :)
I checks ci fanno intuire che la prossima zona di codice per l'elaborazione dei return values, 
nel caso in cui si e' scelto un file (insomma proprio cio' che ci interessa :) e' a 7FDE40DF.
Ecco qui....

:7FDE40DF 83FF02                  cmp edi, 00000002
:7FDE40E2 741A                    je 7FDE40FE
:7FDE40E4 83FF07                  cmp edi, 00000007
:7FDE40E7 7415                    je 7FDE40FE
:7FDE40E9 837C241C00              cmp dword ptr [esp+1C], 00000000
:7FDE40EE 740E                    je 7FDE40FE
:7FDE40F0 FF742424                push [esp+24]
:7FDE40F4 56                      push esi
:7FDE40F5 FF742434                push [esp+34]
:7FDE40F9 E845EEFFFF              call 7FDE2F43

* Referenced by a JUMP at Addresses:
|:7FDE40E2(C), :7FDE40E7(C), :7FDE40EE(C)
|
:7FDE40FE 8BC7                    mov eax, edi
:7FDE4100 5D                      pop ebp
:7FDE4101 5F                      pop edi
:7FDE4102 5E                      pop esi
:7FDE4103 5B                      pop ebx
:7FDE4104 83C418                  add esp, 00000018
:7FDE4107 C22400                  ret 0024


Altri tre checks....se abbiamo scelto ESC o "NO", il programma esce dalla call (con il ret 024 
a 4107) conservando tale valore nel registro, altrimenti esegue una zona di codice, allo scopo 
di rilevare i dati necessari alla cancellazione del file (con la call a 40F9).
Continuiamo a tracciare con SoftICE, e ci ritroveremo al caller....

:7FDE4952 E8A3F6FFFF              call 7FDE3FFA    ; <--NOI TORNIAMO DA QUESTA CALL
:7FDE4957 83F802                  cmp eax, 00000002 ; HAI PREMUTO "ESC" ?
:7FDE495A 0F847F080000            je 7FDE51DF        
:7FDE4960 83F806                  cmp eax, 00000006 ; HAI SCELTO "SI" ?
:7FDE4963 743F                    je 7FDE49A4
:7FDE4965 83F807                  cmp eax, 00000007 ; HAI SCELTO "NO" ?
:7FDE4968 0F8486070000            je 7FDE50F4

* Referenced by a JUMP at Addresses:
|:7FDE48D1(U), :7FDE50AF(U)
|
:7FDE496E 8945FC                  mov dword ptr [ebp-04], eax ; SORRY, MA QUI C'E' QUALCOSA CHE
                                                              ; NON VA...SE EAX NON CONTIENE
                                                              ; NESSUNO DEI 3 VALORI DI CUI 
                                                              ; SOPRA, ABBIAMO UN INVALID
                                                              ; HANDLE! MESSAGGIO DI ERRORE!

Wohho! Ecco il codice che ci interessa....il gioco si fa interessante :D
La fortuna ci assiste....abbiamo tre ramificazioni per tre eventuali opzioni...adesso tutto sta 
a ridirezionare il je relativo alla pressione del button "NO" in una zona di codice diversa, 
che ELIMINERA' il file dall'hard disk....non avremo bisogno di perdere tempo con le raw sizes e 
le virtual sizes delle sezioni del pe, e questo e' un bel vantaggio!

Per ora continuiamo a tracciare, per renderci un po' conto di come funzionano le cose...la 
nostra corsa deviera' a 4963 perche' in questo caso abbiamo scelto "SI"...
e ci ritroveremo qui:

:7FDE49A4 8B4DF4                  mov ecx, dword ptr [ebp-0C]
:7FDE49A7 8B01                    mov eax, dword ptr [ecx]
:7FDE49A9 0B45F8                  or eax, dword ptr [ebp-08]
:7FDE49AC 3D01020000              cmp eax, 00000201
:7FDE49B1 7725                    ja 7FDE49D8
:7FDE49B3 0F8402020000            je 7FDE4BBB
:7FDE49B9 3D01010000              cmp eax, 00000101
:7FDE49BE 0F848E000000            je 7FDE4A52
:7FDE49C4 3D02010000              cmp eax, 00000102
:7FDE49C9 0F84FA000000            je 7FDE4AC9
:7FDE49CF 3D03010000              cmp eax, 00000103
:7FDE49D4 7447                    je 7FDE4A1D
:7FDE49D6 EB3E                    jmp 7FDE4A16

Non fatevi spaventare dal numero dei jumps, se tutto va bene prenderete sempre il JA a 49B1 
(non lo prendete se state cancellando un folder, ma gia' al primo file dello stesso saltera'), 
che vi portera' qui:

:7FDE49D8 3D02020000              cmp eax, 00000202
:7FDE49DD 743E                    je 7FDE4A1D
:7FDE49DF 3D03020000              cmp eax, 00000203
:7FDE49E4 0F84D1010000            je 7FDE4BBB
:7FDE49EA 3D01030000              cmp eax, 00000301
:7FDE49EF 0F84F0030000            je 7FDE4DE5
:7FDE49F5 3D02030000              cmp eax, 00000302
:7FDE49FA 0F843C020000            je 7FDE4C3C
:7FDE4A00 3D03030000              cmp eax, 00000303
:7FDE4A05 0F8444030000            je 7FDE4D4F          ; JUMP CHE VERRA' PRESO SE TUTTO VA BENE
:7FDE4A0B 3D04030000              cmp eax, 00000304
:7FDE4A10 0F8499030000            je 7FDE4DAF

Hmmm....sembrano a colpo d'occhio ulteriori checks sulle caratteristiche dei files...lasciamoli 
stare....il jump che prendera' sempre e' quello a 4A05. Ecco dove conduce:

:7FDE4D4F 8B4730                  mov eax, dword ptr [edi+30] 
:7FDE4D52 85C0                    test eax, eax
:7FDE4D54 741C                    je 7FDE4D72
:7FDE4D56 53                      push ebx
:7FDE4D57 8D4DFC                  lea ecx, dword ptr [ebp-04]
:7FDE4D5A 6A00                    push 00000000
:7FDE4D5C 8D95E4FDFFFF            lea edx, dword ptr [ebp+FFFFFDE4]
:7FDE4D62 50                      push eax
:7FDE4D63 51                      push ecx
:7FDE4D64 52                      push edx
:7FDE4D65 E815690000              call 7FDEB67F        ; CALL DI CONTROLLO OPZIONE "CESTINO ON"
:7FDE4D6A 85C0                    test eax, eax        ; EAX E' *ZERO* SE CESTINO E' OFF
:7FDE4D6C 0F85ABFCFFFF            jne 7FDE4A1D         ; HAI IL CESTINO "ON", SALTA E SPOSTA
                                                       ; I FILES
* Referenced by a JUMP at Address:
|:7FDE4D54(C)
|
:7FDE4D72 8D85E4FDFFFF            lea eax, dword ptr [ebp+FFFFFDE4] ; ALTRIMENTI PROCEDI CON
:7FDE4D78 50                      push eax                          ; L'ELIMINAZIONE FISICA DEL
* Reference To: SHELL32.Ordinal:00A4                                ; FILE DALL'HD !!
                                  |
:7FDE4D79 E8C7C3FFFF              call 7FDE1145
:7FDE4D7E 85C0                    test eax, eax
:7FDE4D80 7409                    je 7FDE4D8B
:7FDE4D82 C745FC00000000          mov [ebp-04], 00000000
:7FDE4D89 EB09                    jmp 7FDE4D94


Eh....sembra che ci siamo :)
Tutto viene giostrato da quella call di controllo opzione a 4D65...se il risultato di quella 
call e' ZERO, i files verranno cancellati fisicamente, altrimenti verranno spostati nel 
cestino. Io personalmente ci sono arrivato tracciando passo per passo la call, e segnandomi le 
differenze nell'esecuzione che si verificano con le due opzioni di cestino "on" e "off".
Se vi puo' interessare, la zona di codice in cui viene decisa la sorte di eax in quella call e' 
quella dei tre jumps agli indirizzi B660, B666 e B66C. Lo xor azzerera' eax e ci restituira' il 
valore zero, evitando per altro di eseguire una buona parte del codice della call (che serve a 
preparare lo spostamento del file nel cestino).
Ora quindi sappiamo che, per ELIMINARE fisicamente i files, il nostro programma deve eseguire 
il codice che parte a 4D72...hey ma cosa vedo?? un jump che porta li'?? hmm, mettiamo un bpx su 
questo jump (7FDE4D54)...strano, non salta mai....nemmeno quando abbiamo il cestino ad 
"OFF"...ah! dimenticavo....il solito Redundand Code (TM) della Micro$oft :)))
Ora pero' devo dire che questo jump inutile (vabbeh, saltera' una volta ogni dieci millenni:) 
mi ha fatto pensare una cosa....se c'e' un jump che evita tutta la zona di codice precedente, 
non dobbiamo preoccuparci di inserire una flag e farla controllare dopo la call di controllo...
si puo' accedere a quel codice anche EVITANDO tutto il check...lo dimostra il fatto che i 
programmatori hanno inserito nel codice un jump che fa proprio questo....evitare il codice...
e' solo una questione di intuizione e logica (chiamiamolo ZEN che mi fa sembrare piu' cool ;)
la soluzione a questo punto e' semplicissima......modificheremo il jump relativo al tasto "NO" 
in modo che esegua DIRETTAMENTE il codice a 7FDE4D72, invece che eseguire le sue inutili 
funzioni ! Pertanto il primo passo da seguire e' fare un BACKUP del file shell32.dll, 
chiamandolo ad es. shell32.bak. Poi copiamolo anche su un file temporaneo che andremo a 
patchare fisicamente (non possiamo patchare shell32.dll perche' non viene scaricato dalla 
memoria, nemmeno quando chiudiamo explorer.exe). Adesso abbiamo 3 files, shell32.dll, 
shell32.bak e, diciamo, shell32.new. 

La logica ci direbbe di segnarci i due offsets (del je relativo a "NO" e del punto in cui 
vogliamo che salti), aprire HIEW e patchare come in ogni altro caso...e invece NO! Se tentate 
questo approcio, al riavvio di Windows con la nuova shell32.dll, premendo "NO" avrete l'amara 
delusione di un misero GPF...perche'?? La spiegazione e' molto semplice, il motivo purtroppo 
no....ho pensato ad una differenza di image base, ma gradirei se qualcuno mi spiegasse con 
certezza il perche' di questo problema. Quando patchiamo con HIEW, e' vero che l'offset a cui 
diciamo di saltare cambia in 34172h, ma purtroppo, all'esecuzione del jump nella "vita reale:)", 
la dll saltera' alla RIGA DI CODICE 34172h, NON all'offset 34172h (che e' relativo alla riga di 
codice 7FDE4D72)....hmmm problemuccio fastidioso eh?? Su, basta un po' di logica....non 
dimenticatevi MAI della potenza di SoftICE...entrateci e scrivete CODE ON (se non l'avete gia' 
nella init string)...questa opzione vi permettera' di visualizzare i bytes relativi alle varie 
istruzioni del codice...adesso mettete un bel bpx su 7FDE4968 (il je relativo alla pressione del 
button "NO")...per entrare nel codice della dll basta il solito bpx DialogBoxParamA. ora premete 
"NO" alla richiesta di spostamento del file nel cestino, e vi troverete fermi sulla riga del je 
su cui abbiamo piazzato il bpx. Se continuate con l'esecuzione causerete un GPF, ma se invece 
premete A (Assemble instruction), Sice vi dara' un simpatico prompt in cui potrete inserire il 
codice che volete, relativo alla riga in cui vi trovate. Non dovete far altro che inserirvi 
"JE 7FDE4D72", e noterete un cambiamento dei bytes a fianco all'istruzione. Prendete un pezzo 
di carta, e segnatevi per filo e per segno quei bytes. Dovrebbero essere questi: 0F8404040000.
Detto cio', uscite da tutto e aprite HIEW con il vostro file temporaneo shell32.new...andate 
all'offset 33D68h, premete F3 e inserite l'ESATTA sequenza di bytes che vi ha dato SoftICE. 
Salvate il file, riavviate in modalita' MsDos, andate sotto windows\system e copiate 
SHELL32.NEW in SHELL32.DLL (che adesso e' sovrascrivibile, perche' non c'e' Windows in 
esecuzione). Mi raccomando la copia di Backup del file. adesso riavviate Windows.....aprite 
explorer e provate "elimina" su di un file che non vi interessa...se premete ESC, il file resta 
li'.....se premete "SI" viene spostato nel cestino...e se premete "NO" il file scompare 
dall'hard disk!! E' FATTA! :D

__________

Con questo tutorial ho voluto dimostrare come puo' essere semplice fare un po' di sano 
reversing, e spero che qualcuno abbia imparato qualcosa da questo txt. Se avete problemi a 
seguire il tutorial o volete chiedermi o comunicarmi qualcosa, il mio indirizzo e' 
neural_noise@hotmail.com

Detto cio', saluto tutti gli amici da #cracking4newbies, #crack-it e RingZ3r0...e colgo 
l'occasione per dare il benvenuto ad ALoR nel gruppo!!! :)

till next time......

-NeuRaL_NoiSE 1999