Music Match 10
Keyfish e keygen

Data

by "Pnluck"

 

27/09/2005

UIC's Home Page

Published by Quequero

Si prega di fare donazioni anche minime x la UIC.

Grazie pn, anche per il monito a fare donazioni alla UIC :)

Si prega di fare donazioni anche minime x la UIC.

....

 

....

Difficolt�

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

 


Introduzione

MusicMatch Jukebox ha una routine di protezione presente in una dll, basata su md5 .Poi Mmj è il miglio player disponibile sul mercato. Info su MD5: ZaiRon's tute, rfc-editor

Tools usati

Tools usati:
Ollydbg.
 

URL o FTP del programma

!google musicmatch :P

Essay

Il programma fortunatamente non è protetto con nessuno packer, guindi non ci resta che fare direttamente il keyfishing.
Apriamo la finestra di registrazione e mettiamo una key a casaccio, ci apparirà un MsgBox di errore quasi sicuramente(senno che cazzo di mazzo extraterrestre), in olly a questo punto carichiamo Mmj. Vediamo che si verificano un paio di eccezioni, passiamole con shift+F9, e poi aggiungiamo quest'eccezioni tra quelle da ingnorare, affinchè in futuro non ci rompino.
Apriamo la dialog di registrazione, e settiamo dei bp a: MessageBoxExA e MessageBoxExW, in questo modo ci fermeremo anche su MessageBoxA\W. Ora inseriamo una key a casaccio e premiamo invio: olly ci ferma su MessageBoxExW, ora risaliamo al codice del progie e ci troviamo all'interno del modulo "EnforceR".
Avrete certamente capito che Mmj utilizza quest'api per il controllo della keyinserita, quindi settiamo dei bp su tutte le export di questa dll: Premiamo alt+e, poi selezioniamo il modulo EnforceR e poi mettere bp su ogni export. Riclicchiamo nella dialog su ok, ed olly ci fermerà qui:


 

609B1E7A / >PUSH EBP <--Olly breaka qui
609B1E7B |>MOV EBP,ESP
609B1E7D |>PUSH ECX
609B1E7E |>AND DWORD PTR SS:[EBP-4],0
609B1E82 |>LEA EAX,DWORD PTR SS:[EBP-4]
609B1E85 |>PUSH EAX
609B1E86 |>PUSH DWORD PTR SS:[EBP+8]
609B1E89 |>CALL EnforceR.?GetStringFromID
609B1E8E |>TEST EAX,EAX
609B1E90 |>JNZ SHORT EnforceR.609B1EAB
609B1E92 |>PUSH DWORD PTR SS:[EBP-4]
609B1E95 |>MOV ECX,DWORD PTR SS:[EBP+C]
609B1E98 |>CALL DWORD PTR DS:[<&MFC71U.#776>] ; MFC71U.7C25ED29
609B1E9E |>PUSH DWORD PTR SS:[EBP-4] ; /block
609B1EA1 |>CALL <JMP.&MFC71U.#764> ; \free
609B1EA6 |>POP ECX
609B1EA7 |>XOR EAX,EAX
609B1EA9 |>JMP SHORT EnforceR.609B1EAE
609B1EAB |>OR EAX,FFFFFFFF
609B1EAE |>LEAVE
609B1EAF \>RETN 8

Steppiamo fino al ret un paio di volte fino a tornale alla procedura principale che sarebbe a 609b7146, qui analiziamo il codice(alt+a) e ritorniamo a steppare finchè non troviamo qualcosa di utile:
 
609B721B >PUSH EDI
609B721C >PUSH EAX
609B721D >MOV BYTE PTR SS:[EBP-4],4
609B7221 >CALL EnforceR.?SetUpgradeKey <--Più interesante di così :D
 
Steppiamo dentro e poi continuiamo fino ad arrivare ad arrivare ad un call(a 609b60f8)con successivo je, steppiamo dentro e ci troveremo il seguente codice:

...
609B5EC9 |>PUSH EBX
609B5ECA |>PUSH EnforceR.609BD000 ; pusha ASCII "XO3-54368-bEi7 *L;d/bang"
609B5ECF |>LEA ECX,DWORD PTR SS:[EBP-80]
609B5ED2 |>MOV DWORD PTR SS:[EBP-4],EBX
609B5ED5 |>CALL DWORD PTR DS:[<&MSVCP71.?c_str@?$basic_string@DU?$char_traits@D@std>;
609B5EDB |>PUSH EAX ; pusha key inserita da noi
609B5EDC |>CALL EnforceR.609B4BDE ;call della verifica del key
609B5EE1 |>ADD ESP,0C
609B5EE4 |>CMP EAX,1
609B5EE7 |>JNZ SHORT EnforceR.609B5EF4

Steppiamo per l'ennesima volta dentro, dopo vario codice spazzatura, ecco qualcosa di interessante:

609B4C0F |>>PUSH DWORD PTR SS:[EBP+74] ; copia key inserita
609B4C12 |.>LEA EAX,DWORD PTR SS:[EBP+40]
609B4C15 |.>PUSH EAX                 ; in un nuovo buffer con
609B4C16 |.>CALL <JMP.&MSVCR71.strcpy> ; strcpy
609B4C1B |.>LEA EAX,DWORD PTR SS:[EBP+28]
609B4C1E |.>PUSH EAX
609B4C1F |.>LEA EAX,DWORD PTR SS:[EBP+40]
609B4C22 |.>PUSH EAX           ; Pusha la key inserita e controlla se ci sono i
609B4C23 |.>CALL EnforceR.609B4B3E ;char_giusti[]="234579AGHJKLQRUW"(nella key ovviamente)
609B4C28 |.>ADD ESP,10
609B4C2B |.>TEST EAX,EAX
609B4C2D |.>JNZ EnforceR.609B4CEF ; se non è così ci vancullizza
609B4C33 |.>TEST ESI,ESI
609B4C35 |.>JE SHORT EnforceR.609B4C8F
609B4C37 |.>LEA EAX,DWORD PTR SS:[EBP-30] ;se no
609B4C3A |.>CALL EnforceR.609B49DB            ; inizializza md5 buffer

Cmq si può notare, qui il codice inizia a farsi interessante, e non è tutto qui:

609B4C3F |. 8D45 40 LEA EAX,DWORD PTR SS:[EBP+40]
609B4C42 |. 50 PUSH EAX
609B4C43 |. 6A 08 PUSH 8
609B4C45 |. 58 POP EAX
609B4C46 |. 8D4D D0 LEA ECX,DWORD PTR SS:[EBP-30]
609B4C49 |. E8 B1FDFFFF CALL EnforceR.609B49FF ; copia i primi 8 char della psw nel md5 Padding 609B4C4E |. 56 PUSH ESI ; /s = "XO3-54368-bEi7 *L;d/bang" (questa è una stringa static)
609B4C4F |. E8 9A340000 CALL <JMP.&MSVCR71.strlen>
609B4C54 |. 56 PUSH ESI
609B4C55 |. 8D4D D0 LEA ECX,DWORD PTR SS:[EBP-30]
609B4C58 <>|. E8 A2FDFFFF CALL EnforceR.609B49FF ; ,poi ci aggiunge nel pad quella stringa
609B4C5D |. 8D45 58 LEA EAX,DWORD PTR SS:[EBP+58]
609B4C60 |. 50 PUSH EAX
609B4C61 |. 8D75 D0 LEA ESI,DWORD PTR SS:[EBP-30] ; per poi eseguire la
609B4C64 |. E8 54FEFFFF CALL EnforceR.609B4ABD ; procedura che genera l'output md5


Questo pezzo di codice configura il buffer di 0x40byte di cui ha bisogno md5 Process Message in 16-Word Blocks (prensente nella call a 609b4c61 che finisce, tralaltro, di impostare il md5padding) per generare appunto i 16byte dell'output. Quindi il buffer sarà strutturato in questo modo: primi 8 char della nostra psw inseriti + quella stringa statica + 0x80 + ultimi 8byte per l'append lenght; cioè sarà di 0x40 (60d)byte, dai quali avremo md5output. Continuiamo l'analisi:

609B4C69 |>ADD ESP,10
609B4C6C |>XOR EAX,EAX ; Esegue controllo su psw:
609B4C6E |>/MOVZX ECX,BYTE PTR SS:[EBP+EAX+58] ; prende md5output[eax]
609B4C73 |>|MOV EDX,ECX ; ne fa una copia in edx
609B4C75 |>|SAR EDX,4 ;lo shifta aritmeticamente a destra
609B4C78 |>|XOR EDX,ECX ; quindi edx = md5output[eax]^(md5output[eax]>>4)
609B4C7A |>|MOV CL,BYTE PTR SS:[EBP+EAX+2F] ;prende psw_iserita[8+eax]
609B4C7E |>|AND EDX,0F ; edx &= 0xF;
609B4C81 |>|CMP CL,BYTE PTR DS:[EDX+609C52FC] ;compara cl con char_giusti[edx]
609B4C87 |>|JNZ SHORT EnforceR.609B4CEF ; se non uguali ti manda a fanculo
609B4C89 |>|INC EAX ;altrimenti continua e ci registra
609B4C8A |>|CMP EAX,6
609B4C8D |>\JL SHORT EnforceR.609B4C6E
609B4C8F |>TEST EDI,EDI
609B4C91 |>JE SHORT EnforceR.609B4CEA

Questa è la procedura per il controllo della psw: prende md5output appena generato, ci fa delle operazioni sopra e poi controlla se pswinserita[8+eax] = char_giusti[numero calcolato dai calcoli su md5output], per 6 volte se tutto va bene ci registra altrimenti, ci fancullizza.
Ora possiamo fare il keyfish: cmq avrete certamente notato anche se inserite la key senza "-", ci penserà Mmj tramite le sue api a metterli ogni 5 char, per poi controllare se i char della psw sono gli stessi che ci sono in un array formato da questi elementi: 234579AGHJKLQRUW. Cmq Io ho agito in questo modo: cm key ho inserito: 23457-9aghj-klqru-w2345, e ho settato un bp a 609b4c81; poi ho preso il valore che usciva dal cmp con [EDX+609C52FC], ho preso questo valore e l'ho messo al posto di key_inserito[8+eax], cioè se da quel compare usciva "h" al primo confronto, l'ho presa e messa al posto della "g", questo per sei volte, cioè mi è uscita sta key : 23457-9ag5h-5lkru-w2345. Ora inseriamo di nuovo questa key, e vediamo che non caompre + la MsgBox, ma una nag che ci dice che non siamo ancora registrati. A questo punto tracciamo il progie, fino ad arrivare a questo punto, che si trova subbito dopo la procedura principale, sulla quale steppando sopra farà apparire il nag (ci chiede di farci collegare ad internet prima per controllare la key, fatelo):

...
609B6160 >CALL EnforceR.609B5806 <-- steppiamo dentro
-------
609B58A9 |>TEST BL,BL <-- azzeriamo ebx per non far apparire la nag
609B58AB |>POP EDI
609B58AC |>JNZ SHORT EnforceR.609B58C9
609B58AE |>CALL EnforceR.609B21C6 <-- genera i certificati buoni;P
609B58B3 |>TEST AL,AL
609B58B5 |>JNZ SHORT EnforceR.609B58BE <-- non dovrebbe farci saltare
609B58B7 |>XOR BL,BL
609B58B9 |>JMP EnforceR.609B5951

I certificati generati sono: Certificate.mmc, ProvvisionalCert.mmc. Dopo il jmp possiamo runnare il progie per e vedremo che uscirà una dialog che ci dice che siamo registrato. A questo punto, il Mmj può controllare i Certificati ogni qual volta siamo online(io ho controllato ed ho visto che apre anche tempcert.mmc, anche all'avvio del progie),quindi per non farli modificare metteteli readonly(tutti e tre). Ora chiudiamo Mmj in olly e lanciamolo normalmente, e possiamo vedere che siamo registrati :D
                                                                                             Pnluck

Note finali

Bhe Nt, Quake2, ZaiRon, evilcry, ,|dM|, active85k, quequero, ged, alfa, 0x87k sbiru, e tutti gli altri di #crack-it e #pmode

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 che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.