|
CORSO 5 NEWBIES
(Si disassembla allegramente) |
|
30/07/2000 |
by "GuZuRa" |
|
|
UIC's Home Page |
Published by Quequero |
| Meglio vivere da vecchi con due belle pensioni... |
Beh, un complimento meritatissimo a
Guzura che ha spiegato fin nei minimi dettagli il funzionamento di questo crackme, bravo
Guzu, continua così |
Che tirare a campare con una sola...(Renzo Arbore) |
| UIC's form |
- E-mail: guz_ura@yahoo.com
- #crack-it
|
UIC's form |
Difficoltà |
(X)NewBies ( )Intermedio ( )Avanzato ( )Master
|
|
- NEWBIES5
(Oggi si disassembla)
Written by GuZuRa
- Devo proprio farla?.....Tecnicamente si, ne vale la chiarezza del
tute :)))) NdQue
IDA e Sice (basterebbe anche solo il Sice) e una tabella dei caratteri ASCII con
equivalenti in Hex
UIC
Crackme by Andreageddon
- Lanciare il programma mi sembra il primo passo da fare...mmhhhhhmmmmm...
- Ci chiede un nome di 6 lettere e una password (non resisto devo provare un nome di 5
lettere...e becco del leim ignorante un pò la storia della mia vita)
- Dato che oggi sono svogliato e non ho voglia di usare solamente Sice decido di usarlo
solo per individuare dove si trova lo schema di protezione e poi andare a studiarmi il
disassemblato quindi digito il mio nick che è giusto di sei caratteri e una password a
caso;apro Sice e imposto un bel BPX HMEMCPY esco e schiaccio Check; Sice salta fuori , F11
, F12 fino a che non vi trovate a Kernel.alloc (solitamente l' F12 successivo vi riporta
al programma che ha generato il bpx, nel nostro caso il crackme), in realtà finite in una
DLL del C++ (esattamente la MFC42) due F10 per uscire dalla ret e siete nel codice del
crackme esattamente alla locazione :4017C0. In pratica il crackme chiama una funzione di
questa DLL per prendere nome e password, ora abbiamo il punto da dove partire.
- Disassembliamo con IDA e andiamo a vedere la locazione per vedere quale funzione è
stata utilizzata per prendere le stringhe e troviamo:
- :004017BB call j_?GetDlgItemTextA@CWnd@@QBEHHPADH@Z ;
CWnd::GetDlgItemTextA(int,char *,int)
:004017C0...
Bene abbiamo informazioni su cosa fà questa call e sappiamo che il secondo parametro è
il buffer che riceverà i caratteri letti
- Un pò più sotto ci stà un'altra GetDlgItemTextA ovviamente per il seriale.
- La domanda da porsi è, da dove arriva il tutto (cioè questa è una call solitaria o è
stata chiamata da un'altra che ha già fatto dei conti e altre pippate), possiamo
aspettarci che sia solitaria perchè se guardate bene il codice sotto è chiaro che lo
schema di protezione è tutto lì ma questo è un caso voluto solo dalla bontà d'animo di
ANDRE' (per esempio avrebbe potuto innestarla in un'altra routine e quindi avremmo dovuto
fare del backtrace, le possibilità sono infinite)
- In pratica ci basta risalire il codice fino a che non troviamo l'inizio della
routine e iniziare l'analisi del codice, morale della favola troviamo questa roba (che
vado a commentare):
- 00401622 align 10h
00401630 push ebp
00401631 mov ebp, esp
00401633 sub esp, 0D0h ; mi preparo dello spazio disponibile
per metterci dei valori
00401639 push ebx
0040163A push esi
0040163B mov esi, ecx
0040163D push edi
0040163E mov [ebp-64h], esi
00401641 mov byte ptr [ebp-40h], 10h
- ...
; metto nelle varie locazioni dei valori che utilizzero dopo
- 0040176D mov byte ptr [ebp-51h], 0DCh
00401771 mov al, 0CEh
; muove in al CE
00401773 push 1Eh ; nello stack 1E (max numero di caratteri che
verranno letti)primo parametro della getdlgitemtext
00401775 mov [ebp-4Dh], al
00401778 mov [ebp-49h], al
0040177B lea eax, [ebp-88h] ; carico in eax C3F79C che riceverà la
stringa del nick
00401781 mov byte ptr [ebp-50h], 0DBh
00401785 push eax
; nello stack questa locazione secondo parametro
00401786 push 3EBh
; terzo parametro della getdlgitemtext (dovrebbe essere l'handle alla edit
box dove si scrive il nome)
0040178B mov byte ptr [ebp-4Fh], 0DAh
- ...
;metto nelle varie locazioni dei valori
che utilizzero dopo
- 004017B3 mov byte ptr [ebp-43h], 0BBh
004017B7 mov byte ptr [ebp-1], 0
004017BB call j_?GetDlgItemTextA@CWnd@@QBEHHPADH@Z ; CWnd::GetDlgItemTextA(int,char *,int)
PIGLIA IL NICK INSERITO E LO METTE NELLA LOCAZIONE INDIVIDUATA DAL
SECONDO PARAMETRO
-
- 004017C0 lea ecx, [ebp-0D0h] ; in
ecx 63F754 ci finirà il seriale
004017C6 push 1Eh ;come sopra
004017C8 push ecx ;come sopra
004017C9 push 3EAh ;come sopra
004017CE mov ecx, esi
004017D0 call j_?GetDlgItemTextA@CWnd@@QBEHHPADH@Z ; CWnd::GetDlgItemTextA(int,char *,int)
004017D5 xor esi, esi ; azzera esi si inizzializza è ANDRE' ;)
004017D7 xor edi, edi ; e due
004017D9 loc_4017D9: ; CODE XREF: .text:0040182Dj
004017D9 mov al, [ebp+esi-88h] ; ebp-88 contiene la locazione che
punta al nick in pratica ciclerò fra tutti i char del nick
perchè esi verrà incrementato di volta in volta
di volta in volta in eax c'è l'equivalente in byte dle char in
esame
004017E0 cmp al, 0
004017E2 jz short loc_40184A ;salta se è uguale a zero il carattere in esame in pretica salto quando
ho esaurito i char del nick e incontro 00 che funge da terminatore della stringa del nick
004017E4 mov cl, [ebp+esi-40h] ; muovo in cl un valore che avevamo
inizzializzato sopra
004017EB xor al, cl ; xoro al con questo
004017ED mov cl, [ebp+esi-20h] ; come due righe sopra
004017F4 xor al, cl
; come due righe sopra
004017F6 mov cl, [ebp+esi-60h]
004017FD xor al, cl
; terzo xor
004017FF mov bl, [ebp+edi-0D0h] ; muovo in bl il primo valore ASCII
del seriale alla prima ciclata poi il terzo alla seconda poi
il quinto e così via
00401806 sub bl, 30h ; sottraggo un 30h
00401809 cmp bl, 9
0040180C jle short loc_401811 ; se è superiore a 9h il
valore in bl salto
0040180E sub bl, 7
; se non salto tolgo ancora un 7h
- 00401811 loc_401811: ; CODE XREF: .text:0040180Cj
00401811 mov dl, [ebp+edi-0CFh] ; muovo in dl il secondo valore
ASCII del seriale alla prima ciclata poi il quarto alla
seconda poi il sesto e così via
00401818 sub dl, 30h
;come sopra
0040181B cmp dl, 9
0040181E jle short loc_401823
00401820 sub dl, 7
00401823 loc_401823: ; CODE XREF: .text:0040181Ej
00401823 shl bl, 4
; shifta a sinistra bl di 4 aggiungendo degli zeri esempio se prima in bl c'è 0Ah dopo l'istruzione c'è A0h; se prima c'era
B3h dopo c'è 30h (vale solo shiftando di 4 altrimenti avrei altri valori) in pratica
aggiungo uno zero alla fine occhio che se bl è B3h, dopo averlo shiftato di 4 non è B30h
ma solo gli ultimi due byte quindi 30h
00401826 add dl, bl ; aggiungo a dl il
valore di bl
00401828 inc esi ;
incremento esi solo una volta perchè del nick valuto un carattere alla volta
00401829 inc edi
0040182A inc edi ;
incremento edi in totale due volte perchè voglio valutare terzo e quarto valore del
seriale al secondo giro e quinto e sesto al terzo ciclo di valutazione
0040182B cmp al, dl ; se
il valore contenuto in al (che di volta in volta è il valore hex del carattere del nick
xorato) è uguale a dl salto sopra e ricomincio con il char del nick seguente
0040182D jz short loc_4017D9 ; io qua voglio sempre saltare
0040182F mov byte ptr [ebp-1], 0FFh ; muovo in ebp-1 FF se scazzo il
serial
00401833 loc_401833: ; CODE XREF: .text:0040183Dj
00401833 mov al, [ebp+esi-88h] ; questo pezzo di codice
serve a contare il numero dei caratteri del nick quando
scazzo il seriale
0040183A inc esi
0040183B cmp al, 0
0040183D jnz short loc_401833
0040183F cmp esi, 6
00401842 jge short loc_401857 ; se non
supero i 6 char col nik sono fuori a beccare del leim
00401844 mov byte ptr [ebp-1], 0DDh ; se supero i
6 vado a beccare serial errato
00401848 jmp short loc_401857
0040184A loc_40184A: ; CODE XREF: .text:004017E2j
0040184A mov byte ptr [ebp-1], 0CCh ; qua ci arrivo se tutti i check
sono giusti
0040184E cmp esi, 6
; questa mi è piaciuta e la spiego dopo
E' ora del riassuntino: in pretica si prende il primo carattere del nick,
lo si xora con tre valori diversi, e si tiene il valore in al, si prendono il primo e il
secondo val del seriale li si manipolano e si mette il tutto in dl, si compara al con dl
se tutto è ok si ricomincia con il secondo char del nick e il terzo e quarto valore del
seriale (per i char del nick bisogna ricordarsi che cambiano i tre valori con cui si xora
di volta in volta), se tutto va bene si controlla se il nick era lungo almeno 6 char
(all'istruzione :0040184E) e qui sta una cosa che non mi aspettavo, si fa prima tutto
l'algoritmo e poi si controlla se il nick era abbastanza lungo (dovreste aver capito che
le verifiche si fanno in base ai valori in ebp-1 che possono essere CC,FF,DD e che vi
indirizzano alle tre possibile MBoxA : giusto, sbagliato, corto), per inciso potreste
mettere un nick lungo tre char, la password corrispondente, azzeccare tutti i controlli e
alla fine cmq essere sbattuti fuori...
- Si vede bene che la password deve essere lunga il doppio del nick
-
- Bien ora ci resta solo da trovare un algoritmo che dal nick ci permetta di risalire alla
password
- Prima cosa, a ben guardare l'elaborazione fatta sui caratteri del nome è totalmente
indipendente da quella fatta sul seriale quindi se il nostro scopo è trovare una password
adeguata per il nostro nick possiamo sbattercene dei vari xor e segnarci soltanto il
valore che via via sta in al prima del cmp della locazione :40182B (basta un bpx con
Sice...)
- Con il mio nick "GuZuRa" vengono generati i seguenti valori :
- per la G in al ho B9
- per la u in al ho 8A
- per la Z in al ho A6
- per la u in al ho 88
- per la R in al ho A8
- per la a in al ho 9A
- Bene, ora devo fare in modo che le elaborazioni sui primi due numeri del seriale diano
in dl B9 e così via
- Per comodità riporto il pezzo di codice che manipola il seriale
-
- mov bl, HexPrimoCharSeriale
sub bl, 30h
cmp bl, 9
- jle short loc_401811
sub bl, 7
- loc_401811:
mov dl, HexSecondoCharSeriale
sub dl, 30h
cmp dl, 9
jle short loc_401823
sub dl, 7
loc_401823:
shl bl, 4
add dl, bl
- cmp al, dl
- Incominciamo a reversare e consideriamo di voler trovare quei due primi caratteri del
seriale che generano B9 (il ragionamento è identico per gli altri valori)
- Dobbiamo subito notare una cosa la shl bl,4 impone che dopo
l'istruzione bl sia uno dei seguenti valori : 00 (nel caso bl fosse 10),10 (nel caso bl
fosse 01), 20, 30, 40, 50, 60, 70, 80, 90 e basta quindi siamo per forza obbligati ad
avere dl uguale a 09; come lo otteniamo?
- Dl è ottenuto sottraendo al valore ASCII del secondo char del seriale il valore 30
quindi il char che mi interessa sarà caratterizzato dal rispettivo hex 39h che guardacaso
è il carattere 9 ma c'è un piccolo inghippo che non ci permette di usare il carattere 9
come secondo nel seriale; una volta sottratto 30 viene fatto un cmp con 09 (nostro caso)
quindi non saltiamo e di conseguenza togliamo ancora un 7 al valore: tenendo presente
questo il char che ci interessa sarà caratterizzato da 09+30+07=40h che corrisponde al
carattere "@" (carino no?) e così abbiamo risolto il secondo carattere ma anche
tutti i 9 che sono presenti tra i vari valori di al
- Vediamo ora il primo char del seriale, ricordando la shl bl,4 possiamo optare per uno tra i seguenti valori da avere prima
dell'istruzione stessa: 0B, 1B, 2B, 3B, ...,9B teorici ma se guardate bene il programma
non vi permette di usare le minuscole nel seriale quindi solo alcuni delle possibili
scelte sono utilizzabili ma noi cerchiamo la strada più breve da percorrere...
- E' ora abbastanza chiaro che il char che mi serve come primo ha equivalente hex uguale a
0B+30+07=42h (lo 07 ci va ancora perchè se avete capito cosa succede sapete
che nell'algoritmo non viene tolto 07 solo se il char è 0,1,..., 8 ; da 9 in su tolgo 7);
a 42h corrisponde nella tavola ASCII proprio il carattere "B" maiuscolo (tutto
torna); quindi i miei primi due caratteri del seriale saranno B@
- Analogamente i secondi due saranno 8A il primo generato da 08+30 (07 non viene tolto
nell'algoritmo) che corrisponde al char "8" e il secondo da 0A+30+07 che
corrisponde proprio ad "A" maiuscolo
- In questa maniera il gioco è fatto perchè
- il primo al = B9h a cui corrispondono i due char B @
- il secondo al = 8Ah a cui corrispondono i due char 8 A
- il terzo al = A6h a cui corrispondono i due char A 6
- il quarto al = 88h a cui corrispondono i due char 8 8
- il quinto al = A8h a cui corrispondono i due char A 8
- il sesto al = 9Ah a cui corrispondono i due char @ A
- Be il giochino è chiaro quindi a GuZuRa corrisponde la password B@8AA688A8@A
-
- Vale la pena (almeno per me) di fare un'ulteriore nota, password e nick sono elaborati
in parti di codice separate che non interferiscono tra loro (nel senso che non xoro un
valore coi valori dell'altro o cose simili) quindi il crackme è attaccabile anche in un
altra maniera partendo dalla password per risalire poi ad un nick che genera proprio
quella password (anche perchè i valori con cui xorate i char del nick sono noti)
- Per far questo bisogna tenere presente alcune accortezze: 1) password di partenza lunga
almeno 12 char e pari (per avere un nick di sei caratteri almeno), 2) tenere presente che
non è detto che il char a cui si risale sia un carattere alfanumerico (potrebbe essere un
* o un ? o qualsiasi altro char ASCII), 3)se prima potevo sbattermene degli xor (mi
segnavo solo il valore di al finale) ora devo xorare 3 volte, 4) è molto più facile se
la password contiene solo questi char 1,2,3,4,5,6,7,8,@,A,B,C,D,E,F perchè in al
troveremo sempre dei numeri Hex (anche se questa non è una limitazione effettiva)
-
- Vediamo un esempio per chiarire; scelgo la password C@D1CEC@D1CE:
- in al dovremo avere al primo giro C9 (al posto della @ l'algoritmo mette 9), al secondo
giro D1, al terzo CE e così via
- Diamo un'occhiata al codice e segnamoci i valori con cui viene xorato ogni char del nick
e vediamo che
- il primo char del serialeè xorato con 10h poi con 11h e poi con FFh
- il secondo char invece con 12h,13h,FEh
- il terzo con 14h,15h,FDh
- il quarto con 16h,17h,FCh
- il quinto con 18h,19h,FBh
- il sesto con 20h,21h,FAh (per password più lunghe dovreste segnarvi anche i valori
seguenti...)
-
- Eravamo rimasti a volere al = C9: questo valore viene ottenuto nell'algoritmo dopo tre
xor con i rispettivi valori (sopra) e come ci insegna il buon Que per ottenere il valore
originale ci basta rixorare per gli stessi valori quindi prendiamo C9 e lo xoriamo per 10h
poi 11h poi FFh ottenendo il valore 37h a cui corrisponde il carattere ASCII "7"
che sarà il primo char del nick (al contrario infatti 37 xorato con 10, 11, FF da C9 ce
farà il paio con C@ del seriale...)
- Alla stessa maniera ottenete gli altri 5 char del nick e quindi ottenete il seguente
nick "7.24+5" a cui corrisponde la password C@D1CEC@D1CE
- Con questo vi saluto Byez GuZuRa
-
- Ultima cosa il KeyGenerator: può essere compilato con il tasm5 e funziona in questa
maniera: intanto va bene solo per nick lunghi 6 caratteri (ma se guardate è facilmente
estendibile a patto che vi cerchiate i valori con cui si xorano i char dopo il sesto...);
prende un singolo carattere alla volta e vi da fuori i rispettivi due caratteri del
seriale però al posto dei 9 del seriale dovrete inserire @; l'output di uscita è questo:
-
- Nick (di 6 caratteri)
- G B9 u 8A Z A6 u 88 R A8 a 9A ;quindi
dopo ogni lettera vi appaiono i due caratteri del seriale corrispondenti
Non vi spaventate della lunghezza del programma perchè sono solo istruzioni ripetute 6
volte cambiando i valori di xor
;KeyGen5Newbies (Non lo commento perchè se avete letto questo
tut e quelli di BONU$ sul tasm è una cazzata)
.MODEL small
.STACK 100h
.DATA
messaggio DB "Nick (di 6 caratteri)",13,10,'$'
variabile DB 5
.CODE
inizio:
mov ax,SEG messaggio
mov ds,ax
mov dx,OFFSET messaggio
mov ah,09h
int 21h
;elaborazione primo char
mov ah,01h ;legge un car dalla tastiera
int 21h
xor al,10h
xor al,11h
xor al,-1h
mov dl,al
shr dl,4h
cmp dl,9h
jle a1
add dl,7h
a1: add dl,30h
mov variabile[0],' '
mov variabile[1],dl
mov dl,al
shl dl,4h
shr dl,4h
cmp dl,9h
jle a2
add dl,7h
a2: add dl,30h
mov variabile[2],dl
mov variabile[3],' '
mov variabile[4],'$'
mov ax,SEG variabile
mov ds,ax
mov dx,OFFSET variabile
mov ah,09h
int 21h
;elaborazione secondo char
mov ah,01h ;legge un car dalla tastiera
int 21h
xor al,12h
xor al,13h
xor al,-2h
mov dl,al
shr dl,4h
cmp dl,9h
jle b1
add dl,7h
b1: add dl,30h
mov variabile[0],' '
mov variabile[1],dl
mov dl,al
shl dl,4h
shr dl,4h
cmp dl,9h
jle b2
add dl,7h
b2: add dl,30h
mov variabile[2],dl
mov variabile[3],' '
mov variabile[4],'$'
mov ax,SEG variabile
mov ds,ax
mov dx,OFFSET variabile
mov ah,09h
int 21h
;elaborazione terzo char
mov ah,01h ;legge un car dalla tastiera
int 21h
xor al,14h
xor al,15h
xor al,-3h
mov dl,al
shr dl,4h
cmp dl,9h
jle c1
add dl,7h
c1: add dl,30h
mov variabile[0],' '
mov variabile[1],dl
mov dl,al
shl dl,4h
shr dl,4h
cmp dl,9h
jle c2
add dl,7h
c2: add dl,30h
mov variabile[2],dl
mov variabile[3],' '
mov variabile[4],'$'
mov ax,SEG variabile
mov ds,ax
mov dx,OFFSET variabile
mov ah,09h
int 21h
;elaborazione quarto char
mov ah,01h ;legge un car dalla tastiera
int 21h
xor al,16h
xor al,17h
xor al,-4h
mov dl,al
shr dl,4h
cmp dl,9h
jle d1
add dl,7h
d1: add dl,30h
mov variabile[0],' '
mov variabile[1],dl
mov dl,al
shl dl,4h
shr dl,4h
cmp dl,9h
jle d2
add dl,7h
d2: add dl,30h
mov variabile[2],dl
mov variabile[3],' '
mov variabile[4],'$'
mov ax,SEG variabile
mov ds,ax
mov dx,OFFSET variabile
mov ah,09h
int 21h
;elaborazione quinto char
mov ah,01h ;legge un car dalla tastiera
int 21h
xor al,18h
xor al,19h
xor al,-5h
mov dl,al
shr dl,4h
cmp dl,9h
jle e1
add dl,7h
e1: add dl,30h
mov variabile[0],' '
mov variabile[1],dl
mov dl,al
shl dl,4h
shr dl,4h
cmp dl,9h
jle e2
add dl,7h
e2: add dl,30h
mov variabile[2],dl
mov variabile[3],' '
mov variabile[4],'$'
mov ax,SEG variabile
mov ds,ax
mov dx,OFFSET variabile
mov ah,09h
int 21h
;elaborazione sesto char
mov ah,01h ;legge un car dalla tastiera
int 21h
xor al,20h
xor al,21h
xor al,-6h
mov dl,al
shr dl,4h
cmp dl,9h
jle f1
add dl,7h
f1: add dl,30h
mov variabile[0],' '
mov variabile[1],dl
mov dl,al
shl dl,4h
shr dl,4h
cmp dl,9h
jle f2
add dl,7h
f2: add dl,30h
mov variabile[2],dl
mov variabile[3],' '
mov variabile[4],'$'
mov ax,SEG variabile
mov ds,ax
mov dx,OFFSET variabile
mov ah,09h
int 21h
fine:
mov ah,4Ch
int 21h
END inizio
- Con questo vi saluto Byez GuZuRa
La morale è sempre quella fai merenda con i tarallucci che sono sempre i più buoni...
Ringraziamenti particolari vanno a tutti quelli che su #crack-it rispondono alle mie
domande (un pò leim certe volte, scusatemi cercherò di migliorare)
- 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.
- Capitoooooooo????? Bhè credo di si ;))))