*****************************************
                *                                       *
                *         RingZer0   Presents           *
                *                                       *
                *       Win32asm PATCH by PUSILLUS      *
                *                                       *
                *****************************************

Quello che cercherò di illustrare è un template per una patch generica in 
win32asm compilabile con il MASM della Micro$oft

SORGENTI

Per Iniziare:

dal sito: http://www.pbq.com.au/home/hutch/masm.htm scaricatevi: masm32v3.zip,
le "Import Libraries" e l2inc.exe . Sono tutti i tools necessari x la 
compilazione di programilli in win32asm tramite MASM.

manuale del MASM: http://catalyst.intur.net/~Iczelion/files/asm-tools/programmers_guide.zip

Win32.hlp :file guida xle API di window, lo trovate in molti compilatori C++
           oppure lo trovate su molti siti ma è grande 12Mbytes.
UltraEdit :www.ultraedit.com e' un'editor con il sintax highlighting, molto
           utile per i programmatori, oppure usatene uno che vi aggrada di più.
SoftIce   :lo si usa x il debugging.
Un editor di risorse (.rc) si trova insieme ai pacchetti dei compilatori. In 
alternativa potete prelevarne alcuni sulla pagina di Iczelion oppure farvi
i file .rc a mano. 

*OBBLIGATORIA* la lettura dei tutes di Iczelion al sito: 
http://catalyst.intur.net/~Iczelion/win32asm/

come usare il compilatore:
nell'autoexec.bat inserite il path della dyrectory \bin del masm 

COMANDI: 

* ml /c /coff /Cp /Zi patch.asm : ML.EXE, il compilatore, genera il file .obj 
                                  per la lista delle opzioni lanciare ML /?
* rc patch.rc                   : compilatore di risorse viene generato il file
                                  .RES che sara' linkato all'applicazione e
                                  contiene tutte le informazioni relative a
                                  bottoni finestre ecc.
* Link /SUBSYSTEM:WINDOWS /VERSION:4.0 /LIBPATH:c:\masm\lib /DEBUG /DEBUGTYPE:COFF patch.obj patch.res                            
                                : il linker genera l'EXE vero e proprio

in altenativa si può usare un MAKEFILE che esegue la compilazione automaticamente
tramite nmake.exe e nmaker.exe che vedrò di allegare ai sorgenti.
Da notare che nelle righe di comando sono inseriti gli switch per la generazione
delle informazioni di debug che ci permetteranno, una volta dato in pasto al
softice l'eseguibile, di visualizzare riferimenti a labels e variabili con i
nomi da noi assegnati nel sorgente. Eliminando gli switch per il debugging
l'eseguibile avrà dimesioni piu ridotte. 


Schema di principio del prgramma:

                        -----------------
                        |    Winmain    |   tasto "EXIT"
             |--------->|               |----------------> uscita
             |          -----------------
             |                  |
             |                  | tasto "OK"
             |                  |
             |                  | 
             |          -----------------
             |          |               |    errore 1
             |          |    aprifile   |------------------------|
             |          -----------------                        |
             |                  |                                |
             |                  |OK                              |
             |                  |                                |
             |                  |                                |
             |          -----------------                        |
             |          |   controllo   |    errore 2            |
             |          | dim. file     |-------------------|    |
             |          -----------------                   |    |
             |                  |                           |    |
             |                  |OK                         |    |
             |                  |                           |    | 
             |          -----------------                   |    |
             |          |  controllo    |    errore 3       |    |
             |          | corrispondenza|---------------|   |    |
             |          |bytes originali|               |   |    |
             |          -----------------               |   |    |
             |                  |                       |   |    |
             |                  |OK                    ------------
             |                  |                      | Tabella  | 
             |          -----------------              | errori   | 
             |          | Applicazione  |              |          |
             |          |    patch      |              ------------
             |          -----------------                   |
             |                  |                           |
             |                  |<--------------------------|
             |                  |                           
             |------------------- 
 

cominciamo a dare una spiegazione del sorgente:
+++++++++
.386
.model FLAT, STDCALL
include    winicz2.inc          ; includefile di Iczelion modificato da me
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
+++++++++

In ordine vengono specificati il tipo di processore (.386) e il tipo di modello
di memoria da usare FLAT, l'unico disponibile in win32. STDCALL indica che i 
parametri nelle call vengono passati da destra a sinistra. vengono di seguito
specificati il file di include e le librerie usate.
Non mi soffermo molto su queste cose perche i tutes di Iczelion sono molto più
autorevoli delle mie spiegazioni!

++++++++++
UpdateBuffer   PROTO :DWORD,:DWORD
log            PROTO :DWORD,:DWORD
Patch          PROTO :DWORD,:DWORD,:DWORD

PDWORD TYPEDEF PTR DWORD
++++++++++

Vengono definite i prototipi delle procedure e PDWORD che e' un puntatore a 
una DWORD

++++++++++
.data
DlgName        db "MyDialog",0              ; riferimento alla dialogbox

;---------Valori modificabili-----------------------------
AppName        db "Patch template By Pusillus ",0

TestString     db "E' possibile inserire dei  ",0dh,0ah
               db "commenti come ad esempio   ",0dh,0ah
               db "il nome del progrmma da    ",0dh,0ah
               db "patchare ed altre info     ",0dh,0ah
               db "cracker, release ecc.      ",0dh,0ah,0dh,0ah,0
;--------Dati x la Patch
FileName       db "prova.exe",0             ;nome del File da patchare  
FileSize       dd 3096                      ;dimensioni del file da patchare

Offset1         dd 020h,021h,022h,024h, 0   ;Offsets del file
Original1       db 00h,00h,00h,00h          ;bytes del file originale   
Patch1          db 011h,022h,033h,044h      ;bytes x la modifica del file    
;---------------------------------------------------------


;---messaggi x la log window
opening        db "Opening File %s... ",0
checkingSize   db "Checking File Size... ",0
checkingCRC    db "Checking CRC... ",0
Patching       db "Patching... ",0
MsgOk          db "OK",0dh,0ah,0
TuttoOk        db "File PATCHED !! ",0dh,0ah,0

;----messaggi di errore
errFileNotFound db 0dh,0ah,"FILE NOT FOUND !!! ",0dh,0ah,0
errBadFileSize  db 0dh,0ah,"BAD FILE SIZE !!!  ",0dh,0ah,0
errBadCRC       db 0dh,0ah,"BAD CRC or alredy patched !!!  ",0dh,0ah,0
;----puntatore ai messaggi di errore
Perr PDWORD  errFileNotFound
     PDWORD  errBadFileSize
     PDWORD  errBadCRC
++++++

La sezione .DATA non merita particolari spiegazioni, soltanto "Perr" che e' 
un'array di tipo PDWORD, precedentemente definito, a cui vengono assegnati gli 
indirizzi che contengono i messaggi di errore.

++++++
.data?

hInstance1 HINSTANCE ?          ; Hanle della dialogbox
hInstButt  HINSTANCE ?          ; Handle del bottone "Ok"
CommandLine LPSTR ?
buffer         db 512 dup(?),0  ; buffer per il log
ReadBuffer     db ?             ; buffer per la memorizz. del byte letto dal file
ptbuffer       dd ?             ; puntatore al buffer del log
hFile          dd ?             ; handle del file da patchare
byteWriRead    dd ?             ; numero di bytes scritti/letti
++++++

nella sezione .DATA? vengono dichiarate le variabili.

++++++
.const

IDC_EXIT                 equ     3003
IDC_BUTTON               equ     3002
IDC_STATIC               equ       -1
IDC_EDIT1                equ     3004
++++++

queste costanti sono gli id degli elementi della dialogbox assegnate dal 
resource editor

++++++
.code

start:
     
     mov eax,offset buffer
     mov ptbuffer, eax
     invoke WinMain, NULL,NULL,NULL, SW_SHOWDEFAULT
     invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
        mov   eax, OFFSET DlgProc
        invoke DialogBoxParam, hInst, ADDR DlgName,NULL,eax,NULL
        ret
WinMain endp
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
     mov eax,hWnd
     mov hInstance1,eax
     mov   eax,uMsg
        .IF eax==WM_INITDIALOG
                
                invoke GetDlgItem, hWnd,IDC_BUTTON
                mov hInstButt,eax
                invoke SetWindowText, hWnd, addr AppName
                invoke log, addr TestString,NULL
                invoke SetFocus,eax
        .ELSEIF eax==WM_CLOSE
                invoke EndDialog, hWnd,NULL
        .ELSEIF eax==WM_COMMAND
                mov eax,wParam
                        .IF ax==IDC_BUTTON
                                shr eax,16
                                .IF ax == BN_CLICKED
                                    ;se viene premuto il tasto "OK" viene chiamata la routine x la patch                                
                                    invoke Patch,addr Offset1 ,addr Original1,addr Patch1
                               
                                .ENDIF
                        .ELSEIF ax == IDC_EXIT
                                shr eax,16
                                .IF ax==BN_CLICKED
                                    invoke EndDialog, hWnd,NULL
                                .ENDIF
                        .ENDIF
        .ELSE
                mov eax,FALSE
                ret
     .ENDIF
        mov eax,TRUE
     ret
DlgProc endp

++++++

Questa parte di codice usa una dialogbox come main window; scopiazzata, lo
devo ammettere, dai tutes di Iczelion e ripulita delle cose che non servivano.

Qui sotto c'e' la routine principale del programma :


++++++
;Routine principale x la patch 
Patch proc aPatchAddr:DWORD,aOriginalData:DWORD, aPatchData:DWORD
     invoke log, addr opening, addr FileName ;log iniziale
     ;-----apertura del file---
     invoke CreateFile,addr FileName,GENERIC_READ + GENERIC_WRITE, 0,0,OPEN_EXISTING,0,0
     cmp eax,-1                         ; la funzione restituisce -1
     jz  @@exit                         ; se non e' riuscita ad aprire il file.
     mov hFile, eax                     ; salva l'handle del file. 
     invoke log, addr MsgOk,NULL        ; 
     invoke log, addr checkingSize,NULL ; messaggi x la log
     invoke GetFileSize, hFile,NULL     ; 
     cmp eax,[FileSize]                 ; confronta le dim. del file  
     je  @@read                         ; se le dimensioni sono ok salta a @@read 
     mov eax, -2                        ; altrimenti salva il valore -2 in EAX
     jmp @@exit                         ; e salta a @@exit 
;    routine di controllo dei bytes del file non patchato       
@@read:                                 
     invoke log, addr MsgOk,NULL        ;
     invoke log, addr checkingCRC,NULL  ; messaggi x la log window
        mov edi, aPatchAddr             ; in EDI viene caricato l'indirizzo degli offsets
        mov esi, aOriginalData          ; in ESI l'indirizzo dei dati da confrontare
        xor ebx,ebx
@@loop1:        
        mov edx,[edi+ebx*4]             ; EDX valore dell'offset, EBX indicizza
        test edx,edx                    ; se EDX e' 0 termina il controllo. Notare
        je @@finecomp                   ;  che l'array 'Offset1' e' terminato con 0
        invoke SetFilePointer, hFile, edx, 0, FILE_BEGIN  ; si sposta all'offset indicato da EDX nel file
        invoke ReadFile,hFile,addr ReadBuffer,1,addr byteWriRead,0 ;legge un byte
        mov al, ReadBuffer              ; sposta in AL il byte letto
        cmp al,[esi+ebx]                ; confronta AL con il contenuto dell'indirizzo puntato da ESI indic. EBX
        jnz    @@errorecomp             ; i due bytes non sono uguali
        inc ebx                         ; incrementa l'indice
        jmp @@loop1                     ; 
@@finecomp:
        mov eax,0                       ; flag x esito POSITIVO della comparazione
        jmp @@exit
@@errorecomp:
        mov eax,-3                      ; flag esito NEGATIVO della comparazione
@@exit:
     cmp eax,0                          
     je @@modifica                      ; salta a @@modifica se il flag e' 0
        neg eax                         
        dec eax                         ; viene spostato l'indice in modo da
        mov esi,dword ptr Perr[eax*4]   ;  puntare ESI al messaggio di errore
        invoke log,esi,NULL             ;  indicato da EAX
        jmp @@close

@@modifica:                             ; routine x la modifica del file
     invoke log, addr MsgOk,NULL
     invoke log, addr Patching,NULL
     mov edi, aPatchAddr                ; in EDI l'indirizzo degli offsets
     mov esi, aPatchData                ; in ESI l'indirizzo dei bytes della Patch
     xor ebx,ebx
@@loop2:     
     mov edx,[edi+ebx*4]                ; routine analoga a quella di comparazione
     test edx,edx
     je @@finescrittura
     invoke SetFilePointer, hFile, edx, 0, FILE_BEGIN
     invoke WriteFile,hFile,esi,1,addr byteWriRead,0
     inc ebx
     inc esi
     jmp @@loop2

@@finescrittura:                        ; la patch e' stata applicata
     invoke log, addr MsgOk,NULL
     invoke log, addr TuttoOk,NULL
@@close:                                ;
    invoke EnableWindow,hInstButt,FALSE ; viene disabilitato il button "OK"
    invoke CloseHandle,hFile            ; chiusura del file
     ret
Patch endp
+++++++

spero che i commenti inseriti siano abbastanza esaurienti.


+++++++
;routine x l'aggiornamento del buffer del log
UpdateBuffer proc aMessage:DWORD,addiction:DWORD
     invoke    wsprintfA, ptbuffer,aMessage,addiction
     add  esp, 12
     add ptbuffer, eax 
     ret
UpdateBuffer endp 
+++++++ 
UpdateBuffer si occupa di aggiornare il buffer della log window aggiungendo
il testo indicato da "aMessage" e spostando ptbuffer alla fine del testo
memorizzato in modo che alla prossima chiamata di UpdateBuffer il testo sia
aggiunto alla coda di stringhe.

++++++++
;routine x l'aggiornamento della finestra di log
log proc aTesto,optional:DWORD
    invoke UpdateBuffer,aTesto,optional
    invoke SendDlgItemMessage,hInstance1,IDC_EDIT1,WM_SETTEXT,0,addr buffer
    invoke SendDlgItemMessage,hInstance1,IDC_EDIT1,EM_LINESCROLL,0,10
    ret
log endp
     

end start
+++++++++
"log" è la routine che 'spara' il contenuto del buffer nella log window con
id IDC_EDIT1, prima di fare questo però chiama la routine di aggiornamento
del buffer passandogli come parametri "aTesto", che e' l'indirizzo della
stringa da scrivere e "optional" che serve come parametro supplementare x la
funzione wsprintf.

Files:

patch.rc                : risorse
afxres.h                : include x le risorse
MAKEFILE                : makefile x nmake.exe
resource.k              : altro include per le risorse
patch.exe               : patch
patch.asm               : sorgente della patch .asm
WinICZ2.inc             : file di include di Iczelion con alcune modifiche
readme.txt              : questo file
prova.exe               : file sul quale verrà applicata la patch
Copia di prova.exe      : copia di prova.exe
NMAKER.EXE              : utility x i Makefile
NMAKE.EXE               :    "  "       "


Non lanciate prova.exe perchè non fa nulla serve solo x applicare la patch.
ne ho fatta anche una copia, perchè una volta patchato l'originale patch.exe
non riapplicherà la patch sul file già patchato.

Grazie Iczelion, Kill3xx e a tutti i membri di RingZer0!
happy CrAkInG... Pusillus.