PC-cillin 2003 |
||
Data |
by "M@GiStR" |
|
23/02/2003 |
Published by Quequero |
|
Bravo
magi hai fatto proprio un bel tute per essere la tua prima volta, complimenti |
||
.... |
irc.azzurranet.org / irc.tin.it #crack-it |
.... |
Difficoltà |
(x)NewBies ( )Intermedio ( )Avanzato ( )Master |
PC-cillin 2003
Reversing the update client
Written by
M@GiStR.
Introduzione |
Vedremo come eliminare il check della License Key dell'antivirus PC-cillin 2003 ogni volta che si effettua un update da programma. PC-cillin utilizza il proprio server per validare la licenza dell'utente che cerca di aggiornare il programma on-line. Se questo check dà esito negativo (sempre a meno che non abbiate pagato e siate registrati sul sito) il cillin non permette l'aggiornamento e fornisce una messagebox di errore..
Tools usati |
Un disassembler qualsiasi, tipo win32dasm o IDA
Filemon
Un Hex-editor
URL o FTP del programma |
www.trendmicro.com
Notizie sul programma |
La prima cosa che ho fatto è stato cercare di capire come avvenisse questo scambio di dati con il server. Solitamente in questi tipi di programmi il server invia un file al client con dentro la risposta alla richiesta del client. Allora ho runnato filemon e mi sono accorto che all'atto dell'update viene utilizzato il processo "PCCClient" (il file è pccclient.exe). Che dite lo disassembliamo?? evvai! mano al dasm e via!
Essay |
Come prima cosa dò un'occhiata alla string reference e subito mi balza all'occhio la stringa "RESPONSE". Potrebbe essere la risposta del server alla richiesta del client?? Per saperlo portiamoci sul codice e cosa vediamo? una call all'API GetPrivateProfileIntA. Questa si occupa di prelevare dati dai file .ini (in questo caso un intero).
Ecco la descrizione dell'API:
UINT GetPrivateProfileInt(
LPCTSTR lpAppName, // address of section name
LPCTSTR lpKeyName, // address of key name
INT nDefault, // return value if key name is not found
LPCTSTR lpFileName // address of initialization filename
);
...e questo è il codice che vediamo:
:00408220 51 push ecx <--- pusha il nome del file
:00408221 6A00 push 00000000 <--- pusha il valore di ritorno di default
* Possible Reference to Dialog:
:00408223 68DC524400 push 004452DC <--- pusha il nome della chiave da ricercare nel file
* Possible StringData Ref from Data Obj ->"RESPONSE"
:00408228 68E0524400 push 004452E0 <--- pusha il nome della sezione da ricercare nel file ([RESPONSE])
* Reference To: KERNEL32.GetPrivateProfileIntA, Ord:017Fh
:0040822D FF1510C34300 Call dword ptr [0043C310] <--- invoca l'API GetPrivateProfileIntA
:00408233 8945EC mov dword ptr [ebp-14], eax
:00408236 8D8DE4FEFFFF lea ecx, dword ptr [ebp+FFFFFEE4]
:0040823C E88F6B0000 call 0040EDD0
:00408241 C745FC00000000 mov [ebp-04], 00000000
:00408248 8D4DF0 lea ecx, dword ptr [ebp-10]
:0040824B E8806B0000 call 0040EDD0
:00408250 C645FC01 mov [ebp-04], 01
* Possible Reference to String Resource ID=57351: "Trend Micro PC-cillin"
:00408254 6807E00000 push 0000E007
:00408259 8D4DF0 lea ecx, dword ptr [ebp-10]
:0040825C E82EAE0200 call 0043308F
:00408261 8B55EC mov edx, dword ptr [ebp-14]
:00408264 8995B8FEFFFF mov dword ptr [ebp+FFFFFEB8], edx <---- l'intero prelevato dal file ce lo troviamo qui
:0040826A 81BDB8FEFFFF9A010000 cmp dword ptr [ebp+FFFFFEB8], 0000019A <-- viene confrontato con 19Ah=410
:00408274 7F3A jg 004082B0 <-- se è > salta a 4082B0
:00408276 81BDB8FEFFFF9A010000 cmp dword ptr [ebp+FFFFFEB8], 0000019A <-- viene confrontato con 19Ah=410
:00408280 0F8463010000 je 004083E9 <-- se è = salta a MessageBox("Expire DB connection error")
:00408286 83BDB8FEFFFF64 cmp dword ptr [ebp+FFFFFEB8], 00000064 <-- viene confrontato con 64h=100
:0040828D 7446 je 004082D5 <-- se è = salta verso la fine della call
:0040828F 81BDB8FEFFFFD2000000 cmp dword ptr [ebp+FFFFFEB8], 000000D2 <-- viene confrontato con D2h=210
:00408299 7458 je 004082F3 <-- se è = salta a MessageBox("Your license has expired")
:0040829B 81BDB8FEFFFF36010000 cmp dword ptr [ebp+FFFFFEB8], 00000136 <-- viene confrontato con 136h=310
:004082A5 0F84C3000000 je 0040836E <-- se è = salta a MessageBox("Your license key format is invalid")
:004082AB E9AA020000 jmp 0040855A <-- salta a MessageBox ("Unknown error")
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 00408274(C)
:004082B0 81BDB8FEFFFFA4010000 cmp dword ptr [ebp+FFFFFEB8], 000001A4 <-- viene confrontato con 1A4h=420
:004082BA 0F84A4010000 je 00408464 <-- se è = salta a MessageBox ("No database error")
:004082C0 81BDB8FEFFFFAE010000 cmp dword ptr [ebp+FFFFFEB8], 000001AE <-- viene confrontato con 1AEh=430
:004082CA 0F840F020000 je 004084DF <-- se è = salta a MessageBox ("Unknown error")
:004082D0 E985020000 jmp 0040855A salta a MessageBox ("Unknown error")
Dunque adesso siamo sicuri che è proprio questo il check che ci interessa, infatti abbiamo visto che avviene prelevando la risposta da un file .ini inviato dal server. L'unica risposta che non fornisce un errore è all'indirizzo 40828D dove se l'intero ricercato è "100" salta verso la fine della call. Usciamo allora dalla call e ci ritroviamo all'indirizzo 408CF7. Si vede che lo stesso check sul file viene ripetuto altre 2 volte:
:00408CF2 E838F4FFFF call 0040812F
:00408CF7 8985E4EAFFFF mov dword ptr [ebp+FFFFEAE4], eax
:00408CFD 83BDE4EAFFFF64 cmp dword ptr [ebp+FFFFEAE4], 00000064 <-- 2° check
:00408D04 750B jne 00408D11
:00408D06 8B8D10F3FFFF mov ecx, dword ptr [ebp+FFFFF310]
:00408D0C E8130E0000 call 00409B24
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 00408C92(U), :00408CEA(C), :00408D04(C)
:00408D11 8B8DE4EAFFFF mov ecx, dword ptr [ebp+FFFFEAE4]
:00408D17 51 push ecx
* Possible Reference to Dialog:
:00408D18 686C5A4400 push 00445A6C
:00408D1D 6A28 push 00000028
:00408D1F 683C040000 push 0000043C
* Possible StringData Ref from Data Obj ->"D:\Pcc10\src\modules\PCCClient\MainFrm.cpp"
:00408D24 68A05A4400 push 00445AA0
:00408D29 E8EC670100 call 0041F51A
:00408D2E 83C414 add esp, 00000014
:00408D31 83BDE4EAFFFF64 cmp dword ptr [ebp+FFFFEAE4], 00000064 <-- 3° check
:00408D38 7422 je 00408D5C
La prima cosa che mi viene da fare è forzare i jump condizionali di tutti e tre i check con dei jump fissi in modo tale che il valore intero prelevato dal file sia sempre riconosciuto come "100", quindi:
1° check :0040828D 7446 je 004082D5 -----> EB46 salto fisso
2° check :00408D04 750B jne 00408D11 -----> 7500 nessun salto
3° check :00408D38 7422 je 00408D5C -----> EB22 salto fisso
Prima di salvare con il nostro bell'hex-editor terminiamo il processo "PCCClient" con il task manager, salviamo e facciamolo ripartire di nuovo. Adesso lanciamo l'updater e magicamente l'update viene fatto!!! Bene...potreste pensare che a questo punto abbiamo finito, ma invece NO! Mica vogliamo che il nostro bel seriale taroccato e magari qualche altra bella informazione venga inviata al server del Cillin??? ASSOLUTAMENTE NO!!!!!!!!Allora...scordatevi le modifiche che abbiamo fatto perchè non ci serviranno +. Tutto questo è servito per capire come funziona, ma ora passiamo al crackaggio vero e proprio.Vediamo se riusciamo a saltare tutta la procedura di check. Poco prima della call incriminata (quella a 408CF2) si notano altre 2 chiamate all'API: GetPrivateProfileStringA che è uguale alla precedente, eccetto per il fatto che restituisce una stringa invece di un intero. Soffermiamoci su quella all'indirizzo 408C71 e cerchiamo di capire cosa fa:
:00408C61 51 push ecx <--- pusha il nome del file
* Possible Reference to Dialog:
:00408C62 68FC2F4500 push 00452FFC <--- pusha il valore di ritorno di default
* Possible StringData Ref from Data Obj ->"LastCheckDate"
:00408C67 682C5A4400 push 00445A2C <--- pusha il nome della chiave da ricercare nel file
* Possible StringData Ref from Data Obj ->"UPDATE"
:00408C6C 683C5A4400 push 00445A3C <--- pusha il nome della sezione da ricercare nel file
* Reference To: KERNEL32.GetPrivateProfileStringA, Ord:0185h
:00408C71 FF1590C24300 Call dword ptr [0043C290] <--- invoca l'API GetPrivateProfileStringA
:00408C77 C785E4EAFFFF64000000 mov dword ptr [ebp+FFFFEAE4], 00000064
:00408C81 8D95B0E0FFFF lea edx, dword ptr [ebp+FFFFE0B0]
:00408C87 52 push edx
:00408C88 E8B39A0100 call 00422740 <--- questa call verifica se alla sezione UPDATE la chiave "LastCheckDate" è vuota o contiene una stringa (in questocaso è la data dell'ultimo check effettuato)
:00408C8D 83C404 add esp, 00000004
:00408C90 85C0 test eax, eax
:00408C92 747D je 00408D11 <--- se la stringa è vuota salta ben oltre la procedura di check e va direttamente alla procedura di update!!
:00408C94 8D8514F4FFFF lea eax, dword ptr [ebp+FFFFF414]
:00408C9A 50 push eax
:00408C9B 6804010000 push 00000104
:00408CA0 8D8DB0E0FFFF lea ecx, dword ptr [ebp+FFFFE0B0]
:00408CA6 51 push ecx
:00408CA7 6800304500 push 00453000
Beh! a questo punto tutto è chiaro! Il PC-Cillin fornisce un'unica possibilità di aggiornamento all'utente TRIAL. Una volta effettuata inserisce in pc-cillin.ini alla sezione UPDATE e alla voce "LastCheckDate" la data in cui è stato effettuato l'aggiornamento. Quindi quando questo campo è vuoto vuol dire che non abbiamo mai aggiornato il programma e quindi ce lo fa fare, viceversa quando trova una data inserita, vuol dire che abbiamo già aggiornato una volta e quindi lancia la procedura di check del serial e torniamo a tutto quello che abbiamo visto prima. Come risolviamo questo problema?? Beh...a questo punto anche un muflone saprebbe la risposta! Modifichiamo all'indirizzo 408C92 mettendo un jump fisso, quindi:
:00408C92 747D je 00408D11 ---> EB7D
Note finali |
Basta quindi modificare un solo byte per saltare tutta la procedura di check e aggiornare ogni volta che vogliamo!! Carino no?
Un saluto a...Quequero che ha pubblicato il mio primo tute per la UIC, _Blackdeath_, crazykiwi, DJK, Pincopall e tutti i membri della UIC!
byez e alla prossima!!
Disclaimer |
Qui inserirete con questo carattere il vostro piccolo disclaimer, non è obbligatorio però è meglio per voi se c'è. Dovete scrivere qualcosa di simile a: 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.