Zoom Icon

Xnview

From UIC

Xnview 1.68.1

Contents


Infos
Author: GeO
Email: geuzzo[at]gmail[dot]com
Website: None
Date: 23/03/2005 (dd/mm/yyyy)
Level: Luck and skills are required
Language: Italian Image:Flag_Italian.gif
Comments: Grazie tante Geo



Introduzione

Tipico time trial con la possibilità di essere registrato tramite user/serial...


Tools


Link e Riferimenti

http://www.xnview.com/


Notizie sul Programma

Questo programma è in grado di gestire moltissimi formati ed è anche in grado di controllare dei file alla ricerca di formati conosciuti (in caso vi fosse un file contentente altri file al suo interno) basandosi sull'header...


Essay

Aprendo il programma con olly il debugger mi ha avvertito che era packato... così, Peid alla mano ho scoperto che si trattava di Aspack 2.12. Non avendo voglia di unpackarlo a mano ed ho usato un unpacker (lo so, lo so, la prossima volta faccio a mano :D), precisamente Stripper v2.07

Una volta unpackato, breakando sulla classica getdlgitemtexta, Olly poppa e ci ritroviamo all'interno del codice del programma dove vengono letti user e serial, ecco il codice:


00469570 SUB ESP,168
00469576 LEA EAX,DWORD PTR SS:[ESP+68]
0046957A PUSH ESI // xnview.00560718
0046957B MOV ESI,DWORD PTR SS:[ESP+170]
00469582 PUSH EDI // ntdll.77F4164E
00469583 MOV EDI,DWORD PTR DS:[<&USER32.GetDlgItemTextA>] // USER32.GetDlgItemTextA
00469589 PUSH 100 // /Count = 100 (256.)
0046958E PUSH EAX // |Buffer = NULL
0046958F PUSH 7D0 // |ControlID = 7D0 (2000.)
00469594 PUSH ESI // |hWnd = 00560718
00469595 CALL EDI // \GetDlgItemTextA
00469597 LEA ECX,DWORD PTR SS:[ESP+10]
0046959B PUSH 20 // /Count = 20 (32.)
0046959D PUSH ECX // |Buffer = 0012FFB0
0046959E PUSH 7D1 // |ControlID = 7D1 (2001.)
004695A3 PUSH ESI // |hWnd = 00560718
004695A4 CALL EDI // \GetDlgItemTextA
004695A6 MOV AL,BYTE PTR SS:[ESP+70]
004695AA TEST AL,AL // controlla che non sia vuoto
004695AC JE xnview.004696EC
004695B2 MOV AL,BYTE PTR SS:[ESP+10]
004695B6 TEST AL,AL // come prima
004695B8 JE xnview.004696EC
004695BE LEA EDX,DWORD PTR SS:[ESP+8]
004695C2 LEA EAX,DWORD PTR SS:[ESP+70]
004695C6 PUSH EDX
004695C7 PUSH EAX
004695C8 CALL xnview.0040B410 // calcoli sull'user


[CALL NUMERO 1]:


0040B410 MOV EDX,DWORD PTR SS:[ESP+4] // xnview.0056B804
0040B414 PUSH EBX
0040B415 PUSH EBP
0040B416 PUSH ESI
0040B417 PUSH EDI
0040B418 MOV EDI,EDX
0040B41A OR ECX,FFFFFFFF
0040B41D XOR EAX,EAX
0040B41F REPNE SCAS BYTE PTR ES:[EDI]
0040B421 NOT ECX
0040B423 DEC ECX // numero di char
0040B424 MOV ESI,xnview.0056B798
0040B429 MOV EBP,ECX // num di char in ebp
0040B42B MOV ECX,5
0040B430 MOV EDI,xnview.0058BA08
0040B435 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0040B437 MOV ESI,EAX
0040B439 JE SHORT xnview.0040B45C
0040B43B /MOV CL,BYTE PTR DS:[ESI+EDX] // prende il primo char
0040B43E |MOV BL,CL // lo copia in bl
0040B440 |XOR BL,BYTE PTR DS:[EAX+58BA08] // xora un char con un altro
0040B446 |INC EAX // aumenta eax
0040B447 |CMP EAX,5 // lo confronta con 5
0040B44A |MOV BYTE PTR DS:[ESI+EDX],BL // salva il risultato dello xor
0040B44D |MOV BYTE PTR DS:[EAX+58BA07],CL // salva il primo parametro dello xor
0040B453 |JNZ SHORT xnview.0040B457 // se eax non è 5 salta
0040B455 |XOR EAX,EAX // altrimenti azzera eax...
0040B457 |INC ESI // ...e aumenta esi di 1
0040B458 |CMP ESI,EBP // confronta il num di giri con il num di char
0040B45A \JB SHORT xnview.0040B43B // se è meno del num dei char salta all'inizio
0040B45C XOR EDI,EDI // azzera edi
0040B45E XOR ECX,ECX // azzera ecx
0040B460 TEST EBP,EBP
0040B462 JBE SHORT xnview.0040B48A
0040B464 /MOV BL,BYTE PTR DS:[EDI+58BA0D] // mette il valore da usare per lo xor in bl
0040B46A |MOV ESI,EBP // muove il contenuto di ebp in esi
0040B46C |SUB ESI,ECX // sottrae ecx a esi e stora il risultato in esi
0040B46E |DEC ESI // decrementa esi
0040B46F |MOV AL,BYTE PTR DS:[ESI+EDX] // muove il risultato dello xor precedente in al
0040B472 |XOR BL,AL // xora bl con al
0040B474 |INC EDI // aumenta edi
0040B475 |MOV BYTE PTR DS:[ESI+EDX],BL // salva il risultato dello xor
0040B478 |MOV BYTE PTR DS:[EDI+58BA0C],AL // salva il risultato dello xor del 1° giro
0040B47E |CMP EDI,5 // confronta edi con 5
0040B481 |JNZ SHORT xnview.0040B485 // se è minore di 5 salta a 0040B485
0040B483 |XOR EDI,EDI // altrimenti azzera edi
0040B485 |INC ECX // aumenta di uno ecx
0040B486 |CMP ECX,EBP // se ecx = num di char dell'user esce dal ciclo
0040B488 \JB SHORT xnview.0040B464 // altrimenti salta all'inizio del ciclo
0040B48A XOR ESI,ESI // azzera esi
0040B48C XOR EDI,EDI // azzera edi
0040B48E TEST EBP,EBP
0040B490 JBE SHORT xnview.0040B4B3
0040B492 /MOV AL,BYTE PTR DS:[EDI+EDX] // mette il risultato del 2° xor in al
0040B495 |MOV CL,BYTE PTR DS:[ESI+58BA12] // mette il char per lo xor in cl
0040B49B |XOR CL,AL // xora al e cl e salva il risultato in al
0040B49D |INC ESI // aumenta di uno esi
0040B49E |MOV BYTE PTR DS:[EDI+EDX],CL // salva il risultato del 3° xor
0040B4A1 |MOV BYTE PTR DS:[ESI+58BA11],AL // salva il risultato del 2° xor
0040B4A7 |CMP ESI,5 // confronta esi con 5
0040B4AA |JNZ SHORT xnview.0040B4AE // se non è uguale salta a 0040B4AE
0040B4AC |XOR ESI,ESI // altrimenti azzera esi
0040B4AE |INC EDI // aumenta di uno edi
0040B4AF |CMP EDI,EBP // se ha xorato tutti i char esce dal ciclo
0040B4B1 \JB SHORT xnview.0040B492
0040B4B3 XOR EDI,EDI // azzera edi
0040B4B5 XOR ECX,ECX // azzera ecx
0040B4B7 TEST EBP,EBP
0040B4B9 JBE SHORT xnview.0040B4E1
0040B4BB /MOV BL,BYTE PTR DS:[EDI+58BA17] // mette il valore per lo xor in bl
0040B4C1 |MOV ESI,EBP // num di char in esi
0040B4C3 |SUB ESI,ECX // sottrae ecx a esi
0040B4C5 |DEC ESI // decrementa esi
0040B4C6 |MOV AL,BYTE PTR DS:[ESI+EDX] // mette il risultato del 3° xor in al
0040B4C9 |XOR BL,AL // xora bl e al
0040B4CB |INC EDI // aumenta edi di uno
0040B4CC |MOV BYTE PTR DS:[ESI+EDX],BL // salva il risultato del 4° xor
0040B4CF |MOV BYTE PTR DS:[EDI+58BA16],AL // salva il risultato del 3° xor
0040B4D5 |CMP EDI,5 // se edi = 5 non salta e...
0040B4D8 |JNZ SHORT xnview.0040B4DC // ...azzera edi
0040B4DA |XOR EDI,EDI // qui azzera edi
0040B4DC |INC ECX // aumenta ecx
0040B4DD |CMP ECX,EBP // se ha xorato tutti i char non ripete ed esce
0040B4DF \JB SHORT xnview.0040B4BB
0040B4E1 MOV EDI,DWORD PTR SS:[ESP+18]
0040B4E5 XOR EAX,EAX // azzera eax
0040B4E7 TEST EBP,EBP
0040B4E9 MOV DWORD PTR DS:[EDI],0
0040B4EF JBE SHORT xnview.0040B508
0040B4F1 /MOV ECX,EAX // azzera ecx
0040B4F3 |AND ECX,3
0040B4F6 |MOV BL,BYTE PTR DS:[ECX+EDI] // mette il char da sommare in bl
0040B4F9 |LEA ESI,DWORD PTR DS:[ECX+EDI] // mette l'indirizzo del char da sommare in esi
0040B4FC |MOV CL,BYTE PTR DS:[EAX+EDX] // mette in cl l'altro char da sommare
0040B4FF |ADD BL,CL // li somma
0040B501 |INC EAX // aumenta eax
0040B502 |CMP EAX,EBP // finché non ripete il giro 5 volte loopa
0040B504 |MOV BYTE PTR DS:[ESI],BL // scrive il risultato della somma
0040B506 \JB SHORT xnview.0040B4F1
0040B508 POP EDI // xnview.005913C3
0040B509 POP ESI // xnview.005913C3
0040B50A POP EBP // xnview.005913C3
0040B50B POP EBX // xnview.005913C3
0040B50C RETN

[FINE CALL NUMERO 1]


004695CD LEA ECX,DWORD PTR SS:[ESP+18] // mette il serial in ecx
004695D1 PUSH ECX // e lo mette nello stack
004695D2 CALL xnview.00473553 // calcoli sul serial


[CALL NUMERO 2]:


00473553 PUSH EBX
00473554 PUSH EBP
00473555 PUSH ESI // xnview.0056B804
00473556 PUSH EDI // xnview.005913C3
00473557 MOV EDI,DWORD PTR SS:[ESP+14]
0047355B /CMP DWORD PTR DS:[576AD8],1 // sempre 1 quindi salta sempre
00473562 |JLE SHORT xnview.00473573
00473564 |MOVZX EAX,BYTE PTR DS:[EDI]
00473567 |PUSH 8
00473569 |PUSH EAX
0047356A |CALL xnview.00473BD6
0047356F |POP ECX // xnview.0040B5DB
00473570 |POP ECX // xnview.0040B5DB
00473571 |JMP SHORT xnview.00473582
00473573 |MOVZX EAX,BYTE PTR DS:[EDI] // mette il 1° char del serial in eax
00473576 |MOV ECX,DWORD PTR DS:[5768CC] // xnview.005768D6
0047357C |MOV AL,BYTE PTR DS:[ECX+EAX*2] // 5768D6+31*2
0047357F |AND EAX,8
00473582 |TEST EAX,EAX
00473584 |JE SHORT xnview.00473589
00473586 |INC EDI // xnview.005913C3
00473587 \JMP SHORT xnview.0047355B
00473589 MOVZX ESI,BYTE PTR DS:[EDI] // primo char del serial in esi
0047358C INC EDI // legge il char dopo
0047358D CMP ESI,2D // confronta il char con 2D
00473590 MOV EBP,ESI // copia il char in ebp
00473592 JE SHORT xnview.00473599 // se è 2D salta
00473594 CMP ESI,2B // confronta il char con 2B
00473597 JNZ SHORT xnview.0047359D // se non è 2B salta
00473599 MOVZX ESI,BYTE PTR DS:[EDI] // se è 2B lo scarta e legge il char dopo
0047359C INC EDI // considera il char ancora dopo in edi
0047359D XOR EBX,EBX // azzera ebx
0047359F /CMP DWORD PTR DS:[576AD8],1 // sempre 1 quindi salta sempre
004735A6 |JLE SHORT xnview.004735B4
004735A8 |PUSH 4
004735AA |PUSH ESI // xnview.0056B804
004735AB |CALL xnview.00473BD6
004735B0 |POP ECX // xnview.0040B5DB
004735B1 |POP ECX // xnview.0040B5DB
004735B2 |JMP SHORT xnview.004735BF
004735B4 |MOV EAX,DWORD PTR DS:[5768CC]
004735B9 |MOV AL,BYTE PTR DS:[EAX+ESI*2]
004735BC |AND EAX,4
004735BF |TEST EAX,EAX // legge finché non finisce il serial
004735C1 |JE SHORT xnview.004735D0 // salta solo se c'è il terminatore nullo
004735C3 |LEA EAX,DWORD PTR DS:[EBX+EBX*4]
004735C6 |LEA EBX,DWORD PTR DS:[ESI+EAX*2-30]
004735CA |MOVZX ESI,BYTE PTR DS:[EDI] // mette il char dopo in esi
004735CD |INC EDI // legge il char successivo
004735CE \JMP SHORT xnview.0047359F
004735D0 CMP EBP,2D // se il primo char è 2D inverte il segno ad<br/> // eax, frutto dei calcoli
004735D3 MOV EAX,EBX // sposta il risultato dei calcoli da ebx a eax
004735D5 JNZ SHORT xnview.004735D9 // se non è 2D salta
004735D7 NEG EAX // altrimenti inverte il segno
004735D9 POP EDI // xnview.0040B5DB
004735DA POP ESI // xnview.0040B5DB
004735DB POP EBP // xnview.0040B5DB
004735DC POP EBX // xnview.0040B5DB
004735DD RETN


[FINE CALL NUMERO 2]


004695D7 MOV ECX,DWORD PTR SS:[ESP+14] // mette i calcoli sull'user in ecx
004695DB ADD ESP,0C
004695DE CMP ECX,EAX // se i calcoli serial/user coincidono ok
004695E0 JE SHORT xnview.0046963F
004695E2 MOV EAX,DWORD PTR DS:[5913A0] // se non sono uguali registrazione non valida
004695E7 LEA EDX,DWORD PTR SS:[ESP+30]
004695EB PUSH 40 // /Count = 40 (64.)
004695ED PUSH EDX // |Buffer = 7FFE0304
004695EE PUSH 1393 // |RsrcID = STRING "Invalid registration"
004695F3 PUSH EAX // |hInst = NULL
004695F4 CALL DWORD PTR DS:[<&USER32.LoadStringA>] // \LoadStringA
004695FA PUSH 10 // /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004695FC LEA ECX,DWORD PTR SS:[ESP+34] // |
00469600 PUSH xnview.0058B9FC // |Title = ""
00469605 PUSH ECX // |Text = ".döwÄ.æwþ...\t"
00469606 PUSH ESI // |hOwner = 00560718
00469607 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] // \MessageBoxA
0046960D PUSH 7D0 // /ControlID = 7D0 (2000.)
00469612 PUSH ESI // |hWnd = 00560718
00469613 CALL DWORD PTR DS:[<&USER32.GetDlgItem>] // \GetDlgItem
00469619 PUSH EAX // /hWnd = NULL
0046961A CALL DWORD PTR DS:[<&USER32.SetFocus>] // \SetFocus
00469620 PUSH xnview.0058B9FC // /Text = ""
00469625 PUSH 7D1 // |ControlID = 7D1 (2001.)
0046962A PUSH ESI // |hWnd = 00560718
0046962B CALL DWORD PTR DS:[<&USER32.SetDlgItemTextA>]// \SetDlgItemTextA
00469631 POP EDI // kernel32.77E614C7
00469632 MOV EAX,1
00469637 POP ESI // kernel32.77E614C7
00469638 ADD ESP,168
0046963E RETN
0046963F LEA EDX,DWORD PTR SS:[ESP+70] // se coincidono la registrazione è ok
00469643 PUSH 100
00469648 PUSH EDX
00469649 PUSH 7D0
0046964E PUSH ESI // xnview.00560718
0046964F CALL EDI // ntdll.77F4164E
00469651 LEA EAX,DWORD PTR SS:[ESP+10]
00469655 PUSH 20
00469657 PUSH EAX
00469658 PUSH 7D1
0046965D PUSH ESI // xnview.00560718
0046965E CALL EDI // ntdll.77F4164E
00469660 LEA ECX,DWORD PTR SS:[ESP+70]
00469664 PUSH ECX
00469665 PUSH xnview.0056B840 // ASCII "LicenseName"
0046966A PUSH 0
0046966C CALL xnview.0043E040
00469671 LEA EDX,DWORD PTR SS:[ESP+1C]
00469675 PUSH EDX
00469676 PUSH xnview.0056B830 // ASCII "LicenseNumber"
0046967B PUSH 0
0046967D CALL xnview.0043E040
00469682 MOV EAX,DWORD PTR DS:[5913A4]
00469687 ADD ESP,18
0046968A MOV DWORD PTR DS:[5913C8],1
00469694 PUSH 1 // /Flags = MF_BYCOMMAND|MF_GRAYED|MF_STRING
00469696 PUSH 0DE // |ItemID = DE (222.)
0046969B PUSH EAX // |/hWnd = NULL
0046969C CALL DWORD PTR DS:[<&USER32.GetMenu>] // |\GetMenu
004696A2 PUSH EAX // |hMenu = NULL
004696A3 CALL DWORD PTR DS:[<&USER32.EnableMenuItem>] // \EnableMenuItem
004696A9 MOV EDX,DWORD PTR DS:[5913A0]
004696AF LEA ECX,DWORD PTR SS:[ESP+30]
004696B3 PUSH 40 // /Count = 40 (64.)
004696B5 PUSH ECX // |Buffer = 0012FFB0
004696B6 PUSH 1394 // |RsrcID = STRING "Registration succesfull"
004696BB PUSH EDX // |hInst = 7FFE0304
004696BC CALL DWORD PTR DS:[<&USER32.LoadStringA>] // \LoadStringA
004696C2 PUSH 40 // /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004696C4 LEA EAX,DWORD PTR SS:[ESP+34] // |
004696C8 PUSH xnview.0058B9FC // |Title = ""
004696CD PUSH EAX // |Text = NULL
004696CE PUSH ESI // |hOwner = 00560718
004696CF CALL DWORD PTR DS:[<&USER32.MessageBoxA>] // \MessageBoxA
004696D5 PUSH 0 // /Result = 0
004696D7 PUSH ESI // |hWnd = 00560718
004696D8 CALL DWORD PTR DS:[<&USER32.EndDialog>] // \EndDialog
004696DE POP EDI // kernel32.77E614C7
004696DF MOV EAX,1
004696E4 POP ESI // kernel32.77E614C7
004696E5 ADD ESP,168
004696EB RETN
004696EC MOV EDX,DWORD PTR DS:[5913A0]
004696F2 LEA ECX,DWORD PTR SS:[ESP+30]
004696F6 PUSH 40 // /Count = 40 (64.)
004696F8 PUSH ECX // |Buffer = 0012FFB0
004696F9 PUSH 1393 // |RsrcID = STRING "Invalid registration"
004696FE PUSH EDX // |hInst = 7FFE0304
004696FF CALL DWORD PTR DS:[<&USER32.LoadStringA>] // \LoadStringA
00469705 PUSH 10 // /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00469707 LEA EAX,DWORD PTR SS:[ESP+34] // |
0046970B PUSH xnview.0058B9FC // |Title = ""
00469710 PUSH EAX // |Text = NULL
00469711 PUSH ESI // |hOwner = 00560718
00469712 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] // \MessageBoxA
00469718 POP EDI // kernel32.77E614C7
00469719 MOV EAX,1
0046971E POP ESI // kernel32.77E614C7
0046971F ADD ESP,168
00469725 RETN


In sintesi:

Il programma compie vari xor sui char dell'username e poi all'ultimo per evitare che i numeri del serial siano troppi li somma con questo criterio: ((numero di char dell'user + (5 * n)) + ((numero di char dell'user + (5 * n)) etc; dove n aumenta di uno ogni 5 char dell'user. Es: se l'user ha 15 caratteri il risultato dello xor del 1° char, del 6° (1 + 5) e dell'11° char (1 + (5 * 2)) vengono sommati. Una volta ricavato questo numero calcolato dall'user lo confronta con il serial, se sono uguali registra il programma, altrimenti segnala che c'è qualcosa che non va.

A questo punto basta "pescare" il serial qui:

004695D7 MOV ECX,DWORD PTR SS:[ESP+14] // mette i calcoli sull'user in ecx

Una volta che avete il serial in esadecimale (da ecx) non dovete far altro che trasformarlo in decimale e inserirlo in fase di registrazione =).

|GeO|


Note Finali

Saluto tutte le persone su #crack-it e #asm e ringrazio Quequero per il vop su #crack-it :D


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.