***************************************** * * * 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.