Memori peccing

Data

by "PiPsqueak"

 

29/07/2002... ma spediscilo oggi spediscilo domani... 02/09/2002

UIC's Home Page

Published by Quequero



Vedo che oggi hanno riscosso successo i tutorial sul memory patching, grazie tante Pip

 

D'altronde

E-mail: ilmionick(at)libero(dot)it
Nick, UIN, canale IRC/EFnet frequentato

il mare fa le onde
la merda puzza
e le donne hanno i segreti.

Difficoltà

(X)NewBies ( )Intermedio ( )Avanzato ( )Master

 

Per tutti gli scansafatiche che non hanno nessuna voglia di dampare e aggiustare IT varie o che comunque non ne hanno il tempo ecco un tutz veloce di memory patching .…


Memori peccing
Written by PiPsqueak

Introduzione

bENE... azz... Bene,bene,bene, dato che questo corso e' gia' stato risolto piu' volte col manual upacking vi propongo in alternativa il memory patching (mp) che, a mio parere, e' mooolto piu' divertente.

Tools usati


Softice
UltraEdit
Giusto per controllare....
PEditor
WDasm

URL o FTP del programma

Sezione lezioni UIC...

Notizie sul programma

E' un crackme criptato non paccato ...

Essay

Dunque... Immaginate di aver corretto un bug in una vostra applicazione, magari di un solo byte, e di dover 
distribuire la patch. Purtroppo per voi le vostre manie di grandezza vi hanno portato a creare applicazioni inutilmente
enormi, per poi comprimerle con i vari UPX, NeoLite, Aspack eccetera... Cosa fare? Unpaccate correggere, 
ripaccate e create la patch comparando i file? Mi spiace ma non funziona proprio cosi’, creereste patch da svriati Mb 
e basta....E allora? Allora il m.p. ci viene in aiuto... Ecchee’ sto memmoripaccing? La stronzata piu’ stupida che 
sia mai esistita...Ovvero facciamo cambiare i byte che ci interessano dal programma stresso... Come? In due modi: 
o inserendo direttamente nel programma il codice modificante oppure, in mancanza di spazio o nel caso di un 
CRC-check (bastardi!!!), con un launcher che launcia il programma e gli applica le modifiche... 

Ma andiamo a incominciare....
Mettiamo un BPX MessageBoxA, usciamo dalla lib e sopra la call che visualizza il messaggio di errore un salto 
sospetto...

:00401500 cmp dword ptr [00403020], 00000001
:00401507 jne 0040151B          ; 75 12 che deve diventare je ... 74 12
:00401509 push 00000010         ; 6A 10 

* Possible StringData Ref from Data Obj ->"Sorry..."
          |
:0040150B push 00403088

* Possible StringData Ref from Data Obj ->"Non sei registrato" 
          |
:00401510 push 00403074
:00401515 call 00401762
:0040151A ret

* Jump at Address:
 |:00401507(C)
	|
:0040151B push 00000040

* Possible StringData Ref from Data Obj ->"Ben Fatto..."
            |
:0040151D  push 00403064

* Possible StringData Ref from Data Obj ->"Ce l'hai fatta!"
            |
:00401522 push 00403024
:00401527 call 00401762
:0040152C ret

Come e’chiaro cambiando il jne in je si ottiene la messagebox giusta... 

Proviamo... Infatti...

 2. Scriviamo il codice 

Due righe, ma proprio due di numero, in asm che cambiano un byte: 

mov     eax,00401507 h         ; oddio non e’ che sia ottimizzato al massimo        
mov     [eax],10126474 h       ; con mov bl,74 - mov [eax],bl rispamierei 2 byte... 

ovvero B8 07 15 40 00 - C7 00 74 12 6A 10 
11 Byte che vanno inseriti da qualche parte nel codice... 

Caso 1 : C’e’ spazio e se non c’e’ si cancella di qua e di la’ e lo facciamo saltare fuori  

Ma dove? Boooo... Nel loader sarebbe il top perche’ 1° e’ il suo lavoro 2° non si rischia che il 
nostro codice venga spacchettato o decrittato mandando a pu#[]n[ tutto 3° c’e’ sempre... Nella sezione 
.Geddone! non so proprio dove metterlo... Vediamo se si puo’ segare qualcosa dal loader 
Peditor - > sections - > .Geddone! - > copy the section to HD - > Wdasm

Ed eccoci qui...

:00407000 pushfd

............ Qui ci sono I due cicli di decript... magari dopo ............

:00407071 jne 0000005F

 :00407073 mov eax, dword ptr [ebp+0000014C]

............non ci interessa............

:00407112 mov ebx, eax

:00407114 mov dword ptr [ebx], 00000000     
:0040711A mov [ebx+0C], 00000000  
:00407121 mov [ebx+08], 00000000  

:00407128 mov eax, dword ptr [ebp+00000154] 	recupera entry point originale (rva)
:0040712E mov ebx, dword ptr [ebp+00000158]	imagebase
:00407134 add eax, ebx                        tadhan!!! Ecco l’ entry point 004017D0
:00407136 jmp eax

Per inserire le istruzioni del nostro complicatissimo m.p. ci servono 11 byte ma se osserviamo bene ne abbiamo 
molte di piu’... le tre istruzioni da 407114 a 407127 sono inutili per il corretto funzionamento del programma in 
quanto vanno a modificare la IT solo per crearci problemi, quindi via, noppiamo tutto da 407114 a 407136 e 
otteniamo uno spazio enorme dove possiamo sbizzarrirci nelle cose piu’ disparate... Ma anche no... 
dopo aver controllato dove inizia la sezione Geddone! apriamo Ultra-edit e sostituiamo i byte del loader con i 
nostri: Il Virtual Offset della sezione .Geddone! (che palle non poteva chiamarsi G e basta) e’ 7000 mentre il 
Raw O. e’ 3800 bene, apriamo Ultra-edit andiamo all’ind. 3800+114= 3914 e sostituiamo con il nostro codice...

 

Caso 2: Il Launcer
 
In alcuni casi non e’ possibile, o non conviene, modificare direttamente l’eseguibile. Percio’ sono stati inventati 
i launcer. Il launcer e’ un semplicissimo programma che lancia l’eseguibile da "correggere" e quando questo e’ 
bello decrittato in memoria lo cambia...
Il l. e’ uno strumento malleabile e comodo da usare e una volta scritto lo potrete riciclare piu’ e piu’ volte...
Un bellissimo articolo sull’argomento e’ "Memory Patcher in pratika"di T3X lo trovate su RingZ3r0 
mi raccomando  andatevelo a leggere...A quelli piu’ pigri (aridaje) propongo una soluzione in C che potrete inserire 
nella GUI che volete...

le funzioni principali sono 2: 

BOOL CreateProcess(  
LPCTSTR lpApplicationName, // name of executable module  
LPTSTR lpCommandLine,                      // command line string  
LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD  
LPSECURITY_ATTRIBUTES lpThreadAttributes,  // SD  
BOOL bInheritHandles,                      // handle inheritance option  
DWORD dwCreationFlags,                     // creation flags 20h  
LPVOID lpEnvironment,                      // new environment block  
LPCTSTR lpCurrentDirectory,                // current directory name  
LPSTARTUPINFO lpStartupInfo,               // startup information  
LPPROCESS_INFORMATION lpProcessInformation // process information); 

Questa funzione lancia il programma da patchare...
I parametri che ci interessano per i nostri malvagi scopi sono: il 2° che non e’ niente popo’ di meno che il 
nome del programma (con o senza percorso), e l’ultimo che ritorna la struttura _PROCESS_INFORMATION 

typedef struct _PROCESS_INFORMATION { 
    HANDLE hProcess; 
    HANDLE hThread; 
    DWORD dwProcessId; 
    DWORD dwThreadId; 
} PROCESS_INFORMATION;

Il primo campo e’ l’handle del processo creato... Avuto l’handle della finestra possiamo chiamare la 

BOOL WriteProcessMemory(  
HANDLE hProcess,                // handle to process  
LPVOID lpBaseAddress,           // base of memory area  
LPCVOID lpBuffer,               // data buffer  
SIZE_T nSize,                   // count of bytes to write  
SIZE_T * lpNumberOfBytesWritten // count of bytes written); 

Che si occupera’ di scrivere i Byte in memoria.

Nel nostro caso:

    // VCC

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory( &si, sizeof(si) ); // Riempe la zona di memoria di zero.
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi) );
    LPTSTR str;
    CreateProcess( NULL, "nono.exe", NULL, NULL, NULL, 32, NULL, NULL, &si, &pi);
    WriteProcessMemory(pi.hProcess,(LPVOID) 0x401507,
			"/x74", // nel caso di piu’ byte "/x74 /x00 /x ..." e cosi’ via
			1,   //questo e’ il n° dei byte da scrivere.
			NULL); 

 Nella maggior parte dei casi vi conviene pero' inserire un test per vedere se il programma e’ quello giusto:

 BOOL ReadProcessMemory(
  HANDLE hProcess,              // handle to the process
  LPCVOID lpBaseAddress,        // base of memory area
  LPVOID lpBuffer,              // data buffer
  SIZE_T nSize,                 // number of bytes to read
  SIZE_T * lpNumberOfBytesRead  // number of bytes read
); 

Il funzionamento e’ uguale controllate se in lpBuffer ci sono i byte originali e poi sovrascrivete ...

Se poi siete pignoli potete inserire una routine di ritardo dopo la CreateProcess in modo tale da aspettare 
che tutto sia presente in memoria prima di patchare sono fatti vostri...


Caso 3: Non  c’e’ spazio ma il file non e’ compresso.

E chi ha detto che i programmi criptati non si possono patchare? Basta sapere cosa cambiare...Dato che 
il programma e’ solo criptato possiamo criptare i byte da sostituire e inserirli nell’eseguibile in modo tale che, 
durante l’esecuzione, vengano tradotti dal loader del programma...Vediamo il decripter della sezione .text 

:00407037 dec ecx
:00407038 mov bl, byte ptr [eax+ecx]  ; prende il byte da decriptare
:0040703B not bl                       \
:0040703D xor bl, 37h                   } Qui l’istruzione viene decriptata...
:00407040 rol bl, 03h                  /
:00407043 mov byte ptr [eax+ecx], bl  ; ... e qui rimessa al suo posto
:00407046 cmp ecx, 00000000h
:00407049 jne 00407037h 

a noi interessano le tre istruzioni centrali: 

:0040703B not bl                              
:0040703D xor bl, 37h
:00407040 rol bl, 03h

 Con queste tre istruzioni possiamo scrivere un cripter per la nostra istruzione:

	mov bl,74h
	ror bl,3h
	xor bl,37h
	not bl 

lo spariamo nel tasm e lo carichiamo nel Symbol Loader del sice steppiamo fino alla fine del prog leggiamo 
il byte tradotto in bl ... 66. 
Non resta che calcolarci dove metterlo...
VA 401507 - image base - V.O. (1000) + R.O. (400) = 907h E patchare il file... 

Note finali


Un saluto al mio gatto Droga che e' ormai da sei mesi disperso... Droga, se mi stai leggendo ti prego torna!!!

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.