Windasm reversing
da oggi supporta anche il wheel mouse!!!

Data

by "ZaiRoN"

 

29-12-2oo2

UIC's Home Page

Published by Quequero

"Dì di no, dì di no!
Si.
Doh!"

Qualche mio eventuale commento sul tutorial :)))

Que, se indovini chi ha detto queste due bellissime frasi potrai scrivere qua dentro :ppp

Attivazione motore euristico in corso... Deduzione delle signature... Elaborando, elaborando, Bill Clinton -> Scartato, Moana Pozzi -> Scartato, Jessica Rizzo -> Scartato, Silvia Saint (gnam, dove va la y? ;p) -> Scartato, Homer Simpson -> Probabilita' 101%, evvai ho riguadagnato il mio spazio personale ;p, chiusura motore euristico. (Potrei dirti anche gli episodi, non lo faccio per non fare la sborona ;p)

Beh cazzate a parti ti meriti davvero un complimento perche' il tutorial e' molto interessante e cmq e' utilissimo se usare il windasm, grazie zai

"gas frena clacson,
gas frena clacson,
clacson clacson pugno,
gas gas gas"

....

Home page se presente: macchè...
E-mail: ZaiRoNcrk(at)hotmail.com
Nick, canale IRC frequentato:
ZaiRoN su irc: #crack-it
ZaiRoN su efnet: #cracking4newbies e #win32asm

....

Difficoltà

(Z)NewBies ()Intermedio ( )Avanzato ( )Master

 

Aggiungiamo una piccola feature al nostro caro e amato Windasm :)


Windasm reversing
da oggi supporta anche il wheel mouse!!!
 
Written by ZaiRoN
 

Introduzione

Ecco qua un piccolo esempio di 'adding functionality project'. Il programma vittima è Windasm e gli daremo la possibilità di gestire i wheel mouse (quelli con la rotella per capirsi :p) per fare lo scroll del file disassemblato.
Il reversing è molto semplice e il tutto sarà reso ancora più semplice da uno dei tool che utilizzerò: Code Snippet Creator.

Tools usati

- W32Dasm v8.93
- Code Snippet Creator (compreso di codice sorgente!!!)
- Un compilatore masm o tasm
- Win32 Programmer's Reference, una guida indispensabile!
 
musica: Aghora (www.aghora.org)

URL o FTP del programma

UIC - Sezione TOOL

Notizie sul programma

Non sapete cos'è Windasm??? Non ci credo...

Essay

Preambolo: approccio al problema.
Solitamente, quando devo modificare un programma, scrivo dei semplici programmini asm ad hoc per testare il codice che dovrò inserire; in questo caso ho provato a simulare l'utilizzo della rotella all'interno di un controllo di tipo ListBox. Perchè proprio questo tipo di controllo? Perchè l'output prodotto da Windasm viene visualizzato all'interno di un controllo di tipo ListBox.
 
L'idea di base per risolvere il problema è quella di catturare e gestire il messaggio generato quando viene mossa la rotella del mouse. Il messaggio che viene prodotto è: WM_MOUSEWHEEL e questa è la sua sintassi:
 
WM_MOUSEWHEEL
fwKeys =         LOWORD(wParam);    // key flags
zDelta = (short) HIWORD(wParam);    // wheel rotation
xPos   = (short) LOWORD(lParam);    // horizontal position of pointer
yPos   = (short) HIWORD(lParam);    // vertical position of pointer
 
Vediamo quali informazioni contengono i due parametri.
- wParam: è una double word la cui parte alta indica il "passo" effettuato dalla rotella (quanto la giro), espresso in multipli o divisori della costante WHEEL_DELTA (che è 120). Un valore positivo indica che la rotella è stata mossa in avanti mentre un valore negativo indica che la rotella è stata mossa all'indietro. La parte bassa del wParam ci dice se e quale altro tasto è stato premuto; tra tutti quelli possibili, noi siamo interessati soltanto ad uno di essi: MK_SHIFT che indica se il tasto SHIFT è premuto (capirete tra un pò perchè siamo interessati soltanto a questo).
- lParam: anche questo è una double word la cui parte alta e bassa rappresentano rispettivamente la coordinata y e x del puntatore del mouse. Le coordinate sono espresse relativamente all'angolo in alto a sinistra dello schermo. Ovviamente, lParam non verrà minimamente preso in considerazione nel resto del tutorial.
 
Adesso sappiamo che cosa andare a cercare ma ci manca ancora una cosa fondamentale per completare l'approccio iniziale: cosa facciamo quando riceviamo questo particolare messaggio?
Dobbiamo dire a Windasm di fare lo scroll della pagina; questo si risolve semplicemente mandando un particolare messaggio a Windasm. Il messaggio che utilizzeremo è WM_VSCROLL. Vediamo in dettaglio la sintassi:
 
WM_VSCROLL
nScrollCode   = (int)       LOWORD(wParam);   // scroll bar value
nPos          = (short int) HIWORD(wParam);   // scroll box position
hwndScrollBar = (HWND)      lParam;           // handle of scroll bar
 
I parametri che ci interessano sono hwndScrollBar che rappresenta l'handle dello scroll bar e nScrollCode che rappresenta la modalità di scrolling. Sono possibili svariati tipi di scroll ma per l'occasione ne vedremo soltanto due:
- SB_LINEDOWN/SB_LINEUP per scrollare di una linea in basso/alto
- SB_PAGEDOWN/SB_PAGEUP per scrollare di una pagina in basso/alto
 
Queste sono tutte le informazioni necessarie e sufficienti per aggiungere la nuova feature!
 
Identificazione di un possibile punto d'attacco.
E' arrivato il momento di iniziare il lavoro *sporco*. Andremo infatti alla ricerca di un possibile punto d'attacco, ovvero di un punto in cui poter inserire il jump al nostro codice. Visto e considerato che dobbiamo lavorare con dei messaggi, la cosa ovvia da fare è quella di cercare la routine di gestione dei messaggi ricevuti da Windasm.
Come facciamo a trovarla? Esistono vari metodi; spesso, quando come ora non ho caricato SoftIce (e non ho voglia di riavviare:p), utilizzo un metodo bruttino ma funzionante. Aprite Windasm con Windasm (ehhe utilizziamo Windasm per reversare se stesso :)) e andate alla ricerca di '00000111'. Perchè questa strana ricerca? 111h è il valore associato al messaggio WM_COMMAND che viene sicuramente processato dal programma e '00000111' è il modo in cui Windasm lo riconosce.
La ricerca si interrompe la prima volta all'indirizzo 004478BE ma non mi sembra proprio la routine che stiamo cercando quindi...riproviamo e la ricerca si interrompe di nuovo a 0045262E. Hmmm...mi sembra che ci siamo:
 
:00452617 mov [ebp-18], 004C1F26
:0045261E mov eax, dword ptr [esi+04]   <-- [esi+04] è il messaggio ricevuto, [esi] è l'handle del controllo che ha ricevuto il messaggio
:00452621 cmp eax, 00000121   <------------ WM_ENTERIDLE, qui metteremo il jump alla nostra routine
:00452626 jg 00452669
:00452628 je 004533D1
:0045262E cmp eax, 00000111   <------------ è stato ricevuto un WM_COMMAND ?
:00452633 jg 00452650
:00452635 je 0045269A
Ok, un'altro tassello è stato aggiunto al nostro puzzle!
 
Utilizziamo Code Snippet Creator per aggiungere la nuova routine.
Siamo finalmente arrivati alla parte più importante di tutto il tutorial!
Come vi ho già detto utilizzeremo CSC, un piccolissimo programma scritto da Iczelion. Cosa fa realmente questo strumento? Noi scriviamo la nostra nuova routine in assembly, lui la compila e se non ci sono errori inserisce i nuovi byte nel programma da reversare. Ecco perchè è necessario avere un compilatore assembly (sia esso masm o tasm).
 
Bando alle ciance e lanciamo il CSC. Iniziamo a prendere confidenza con questo tool. Il form principale presenta soltanto un menù, un paio di pulsanti e un RichEdit control. Il RichEdit control è il posto dove andremo ad inserire il nostro codice, il pulsante 'Assemble' provvederà a compilare il codice, il bottone 'Exit' a chiudere il tutto e il menù...c'è molto poco da vedere, è tutto disabilitato; non vi preoccupate, ogni cosa a suo tempo!
 
La prima cosa da fare è settare a dovere le poche opzioni presenti -in realtà è soltanto una...- per cui clickate su Action-Options.
Selezionate il compilatore che utilizzate solitamente: MASM o TASM; dopodichè settate i path corretti nei campi 'Assembler', 'Linker' e 'Project Directory'. I parametri di compilazione potete anche lasciarli così come sono; nulla e nessuno però vi vieta di modificarli come vi pare e piace :p.
 
E' arrivato il momento di creare un nuovo progetto: clickate su File-NewProject. Date un nome al progetto e selezionate il file da modificare (che ovviamente sarà il windasm); vi consiglio di crearvi una copia di windasm su cui lavorare, non si sa mai! Il progetto è creato e tutte le informazioni relative ad esso verranno salvate nella sottodirectory <nome_progetto> che inizialmente contiene soltanto il file <nome_progetto.ini>.
 
Molte voci di menù si sono abilitate, dategli un'occhiata.
La voce 'PE info' vi permette di esplorare il file mostrandovi praticamente tutte le informazioni di cui avete bisogno: informazioni sull'header del PE, informazioni sulle sezioni, funzioni importate e il classico Data Directories.
La voce 'Action' vi permette di modificare il file caricato aggiungendo nuove funzioni, patchando il file e così via.
 
Adesso che tutto è configurato e il progetto è stato creato, torniamo al nostro problema originale: come aggiungiamo del codice utilizzando CSC?
Bene, procediamo con calma: clickate su Action-ProjectOptions.
Andiamo subito alla sezione 'Patch Options'; qui diciamo a CSC dove inserire il codice compilato: in una nuova sezione o in una già esistente. Potete scegliere l'opzione che più vi piace; personalmente preferisco fargli creare una nuova sezione così non mi sbatto a cercare una zona libera dove inserire il codice e a controllare che effettivamente non venga utilizzata dal programma che sto reversando.
Prossimo passo: scegliere una delle opzioni nella sezione 'Address to Redirect Control to The Snippet'; qui dite a CSC dove volete effettuare il jump al vostro codice. Visto che abbiamo deciso di jumpare all'istruzione all'indirizzo 452621, siamo obbligati a scegliere la terza voce 'Redirect Control From Code Section'; in questo modo, CSC modifica la cmp all'indirizzo 452621 con due nuove istruzioni: una push e una ret. Ma, come fa a sapere che deve patchare proprio a 452621? Glielo diciamo noi! Come vedete, poco sotto c'è un edit box vuoto con label "Virtual Address"; inserite il valore 452621 e il gioco è fatto.
Prima di proseguire, fermiamoci un attimo perchè questo passo necessita di una ulteriore spiegazione. Come vi ho già detto, la cmp a 452621 viene sostituita con due nuove istruzioni; nel nostro caso il codice assumerà la seguente forma (direttamente dal programma finale reversato):
 
:00452617 mov [ebp-18], 004C1F26
:0045261E mov eax, dword ptr [esi+04]
:00452621 push 00500000   <-- la nuova push. 500000 è l'indirizzo dove risiede la nostra nuova routine
:00452626 ret   <------------ e la nuova ret
:00452627 inc ecx   <-------- questa è consequenza della modifica :)
:00452628 je 004533D1   <---- da qui in poi le istruzioni sono le originali di Windasm
:0045262E cmp eax, 00000111
Confrontate questo snippet con l'originale e segnatevi le istruzioni che sono state sovrascritte; sono 3 e precisamente sono quelle agli indirizzi 452621, 452626 e 452628. Questo è necessario perchè, nel nuovo codice dovremmo ri-inserirle per mantenere il normale flusso del programma. Inutile dire che questo è un ragionamento che dovete fare a priori e non a posteriori come abbiamo fatto questa volta, per cui state attenti e fate bene i conti con i vari byte che sovrascrivete ;).
Passiamo alla sezione 'Return Control to Program'; cosa selezioniamo? Ovviamente 'Don't Return to Program'. In realtà, la cosa più logica sembrerebbe quella di tornare ad uno specifico indirizzo ma, se ci pensate un attimo vi accorgerete subito che non è così. Infatti, dobbiamo tornare ad un indirizzo se la rotella non è stata girata e ad un altro indirizzo se invece è stata ruotata. Saremmo noi a decidere dove e quando tornare al programma!
Resta un'ultima sezione: 'Restore Original Instruction'. Se settiamo questa opzione, CSC provvede a ripristinare i byte originali a partire dall'indirizzo 452621 e la modifica funzionerebbe soltanto per il primo messaggio WM_MOUSEWHEEL ricevuto per cui lasciamo il box non settato e premiamo OK.
 
Buono, tutto è pronto e configurato e finalmente è arrivato il momento di scrivere qualche linea di codice!
Come scriviamo? Esiste una sintassi particolare?
Bhè, questo dipende dal tipo di compilatore che usate. Io uso masm e in masm, ad esempio, dovete seguire questo schema:
 
< dichiarazione dei file .inc inclusi >
< dichiarazione dei file .lib inclusi >
jmp @inizio
< dichiarazione di variabili >
@inizio:
< codice in stile masm >
 
Purtroppo non conosco tasm per cui tutti quelli che lo usano dovranno fare riferimento all'help del programma (Capitolo: Create Snippet).
Ecco qua il codice (commentato) per la gestione della rotella del mouse:
 
; direttive di inclusione
include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
 
jmp @start                               ; salto necessario anche se non è prevista nessuna dichiarazione
; nessuna dichiarazione...
@start:                                  ; inizio del codice
.IF eax == WM_MOUSEWHEEL                 ; controllo se è stata usata la rotella del mouse
   ; si, la rotella è stata usata
   pushad                                ; è sempre meglio salvare almeno i registri
   mov ebx, 3                            ; mi sposto di 3 linee ogni volta che viene ruotata la rotella
   .IF sword ptr [esi+0ah] < 0           ; se la parte alta del wParam è negativa allora mi sposto in basso
                                         ; ho utilizzato sword perchè ho bisogno del segno della word
      .IF word ptr [esi+8] == MK_SHIFT   ; la parte bassa del wParam mi dice se lo SHIFT è premuto
         ; lo SHIFT è premuto e mi sposto di una pagina in basso
         invoke SendMessage, dword ptr [esi], WM_VSCROLL, SB_PAGEDOWN, 0
      .ELSE
         ; SHIFT non premuto e mi sposto di 3 linee in basso
         .WHILE ebx != 0
            invoke SendMessage, dword ptr [esi], WM_VSCROLL, SB_LINEDOWN, 0
            dec ebx
         .ENDW
      .ENDIF
   .ELSE                                 ; la parte alta del wParam è positiva quindi mi sposto in alto
      .IF word ptr [esi+8] == MK_SHIFT   ; il tasto SHIFT è premuto???
         ; si e mi sposto di una pagina in alto
         invoke SendMessage, dword ptr [esi], WM_VSCROLL, SB_PAGEUP, 0
      .ELSE
         ; SHIFT non premuto e mi sposto di 3 linee in alto
         .WHILE ebx != 0
            invoke SendMessage, dword ptr [esi], WM_VSCROLL, SB_LINEUP, 0
            dec ebx
         .ENDW
      .ENDIF
   .ENDIF
   popad          ; ripristino i registri salvati precedentemente
   push 453889h   ; pusho l'indirizzo dell'istruzione a cui ritornare
   retn           ; ritorno al codice del Windasm
.ELSE
; non è stata usata la rotella del mouse quindi devo ripristinare il normale flusso
; di Windasm riscrivendo le istruzioni che sono state sovrascritte a partire da 452621
   cmp eax, 121h
   jg @452669
   jz @4533D1
   push 45262Eh
   retn
  @452669:
   push 452669h
   retn
  @4533D1:
   push 4533D1h
   retn
.ENDIF
; game over...
 
Che ci crediate o no, questo è tutto il codice utile per implementare la nuova feature. Compiliamo premendo il tasto 'Assemble', nessun errore :).
 
Siamo quasi alla fine, dobbiamo soltanto dire a CSC di patchare il file. Clickate su Action-PatchTargetFile: il programma vi chiede di impostare le caratteristiche della nuova sezione che verrà aggiunta in fondo al file originale. Le caratteristiche più comuni sono già selezionate; potete fidarvi e premere 'OK' oppure modificare qualcosa e dopo premere 'OK'.
Windasm è finalmente patchato!!!
 
Postambolo: due paroline finali.
Siamo arrivati alla fine. Come vedete, la modifica è veramente semplice ma di grande effetto.
Cosa ne pensate di CSC? Non sembra essere molto usato ma personalmente lo ritengo uno dei tool più potenti in circolazione. Spero di averti incuriosito e invogliato almeno a provarlo...poi ognuno dirà la sua :)
Ho testato e provato a lungo il nuovo Windasm e sembra non avere problemi; se riscontrate qualsiasi problema (di qualsiasi tipo) non esitate a contattarmi!
 
bona!
 
                                        ZaiRoN
 

Note finali

 
Saluto tutti gli amici della UIC e tutti i frequentatori di #crack-it.
Un ringraziamento particolare va a Kayaker, con il quale ho condiviso questo simpatico progetto all'RCE forum.

Disclaimer

Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
 
Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly...Davvero!?! ganzo abbestia!!!