Cracking4neWBies - Lekce č.19

Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: DjH
Datum: 20.10.2007
Hodnocení/Hlasovalo: 2.29/24

Cracking pro začátečníky...podevatenácté :-)

Cracking4neWBies

Lekce č.19

Keygenning Crueheadova CrackMe



Balík zde

No tak vidíte, dočkali jste se nového CrackMe :). Tentokráte si vezmeme do latě Crueheadovo CrackMe. Já si myslím, že můžeme hned začít :). CrackMe si otevřte a vidíte, že máte před sebou jen menu, tak zvolte „Help“ -> „Register“ a trochu si ho můžete omakat :). Pokud ze zeptáme pana PeiDa, co na CrackMe říká, odpoví Vám MASM32/TASM32. Žádný crypter, žádný packer, můžeme jít na věc a natáhnout prográmek do Ollyho. CrackMe je velmi jednoduché, krátké, kód si můžete celý projet, máte to celé na dlani :). Na adrese 004012B5 můžete vidět, jak nám začíná funcke GetDlgItemTextA a pod ní je tato funkce další. Můžeme tedy určit, že se zde bere Name a Serial. Nastavíme BP na výše uvedenou adresu a zkusíme si spustit CMe. Do editu name napíšeme třeba „DjH2oo7“ a do editu serial „123456“ a stiskneme OK. Pokud budeme krokovat, program kamsi skočí, a dostaneme se sem:

004011E6 > 5B POP EBX
004011E7 . |5F POP EDI
004011E8 . |5E POP ESI
004011E9 . |C9 LEAVE
004011EA . |C2 1000 RETN 10

A RETN nás hodí do knihovny USER32.DLL (můžete vyčíst ze stacku: 
0012F4B8 77AB1A10 RETURN to USER32.77AB1A10
A tam už bysme se asi nevyznali, proto si najdeme adresu, kde už se pracuje se stringem. Popojedeme nahoru a vidíme:

00401223 . 83F8 00 CMP EAX, 0
00401226 .^ 74 BE JE SHORT CRACKME1.004011E6
00401228 . 68 8E214000 PUSH CRACKME1.0040218E
; ASCII "DjH2oo7"
0040122D . E8 4C010000 CALL CRACKME1.0040137E
; vypocet cisla z [name]
00401232 . 50 PUSH EAX
00401233 . 68 7E214000 PUSH CRACKME1.0040217E
; ASCII "123456"
00401238 . E8 9B010000 CALL CRACKME1.004013D8
; vypocet cisla z [sn]
0040123D . 83C4 04 ADD ESP, 4
00401240 . 58 POP EAX
00401241 . 3BC3 CMP EAX, EBX
; hodnoty se porovnaji


nastavíme BP na adresu 00401223 a krokujeme. Call na adrese 0040122D vytracujeme pomocí [F7] a skočíme sem:
0040137E /$ 8B7424 04 MOV ESI, DWORD PTR SS:[ESP+4] ; CRACKME1.0040218E
00401382 |. 56 PUSH ESI
00401383 |> 8A06 /MOV AL, BYTE PTR DS:[ESI]
; tato procedurka zajisti,
00401385 |. 84C0 |TEST AL, AL
; ze v editboxu pro
00401387 |. 74 13 |JE SHORT CRACKME1.0040139C
; [name] budou jen velka pismena
00401389 |. 3C 41 |CMP AL, 41
0040138B |. 72 1F |JB SHORT CRACKME1.004013AC
0040138D |. 3C 5A |CMP AL, 5A
0040138F |. 73 03 |JNB SHORT CRACKME1.00401394
00401391 |. 46 |INC ESI
00401392 |.^ EB EF |JMP SHORT CRACKME1.00401383
00401394 |> E8 39000000 |CALL CRACKME1.004013D2
00401399 |. 46 |INC ESI
0040139A |.^ EB E7 \JMP SHORT CRACKME1.00401383
0040139C |> 5E POP ESI
0040139D |. E8 20000000 CALL CRACKME1.004013C2
; pokud jsou, skoc...
004013A2 |. 81F7 78560000 XOR EDI, 5678
004013A8 |. 8BC7 MOV EAX, EDI
004013AA |. EB 15 JMP SHORT CRACKME1.004013C1
004013AC |> 5E POP ESI
004013AD |. 6A 30 PUSH 30
; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013AF |. 68 60214000 PUSH CRACKME1.00402160
; |Title = "No luck!"
004013B4 |. 68 69214000 PUSH CRACKME1.00402169
; |Text = "No luck there, mate!"
004013B9 |. FF75 08 PUSH [ARG.1]
; |hOwner
004013BC |. E8 79000000 CALL <JMP.&USER32.MessageBoxA>
; \MessageBoxA
004013C1 \> C3 RETN


Zde jsme zjistili, že v EditBoxu name, musí být jen písmena. Jak jsme k tomu došli?
Takto: AL, tedy aktuální znak, který tam přiřadila funkce MOV AL, BYTE PTR DS:[ESI] (z cyklu) se porovnává s hodnotou 41h, tedy 65 dec. což je v ASCII „A“ a hodnota 5Ah je 90 dec, což je „Z“, a pokud není v tomto rozhraní, CMe skočí sem:
004013D2 /$ 2C 20 SUB AL, 20
004013D4 |. 8806 MOV BYTE PTR DS:[ESI], AL
004013D6 \. C3 RETN

Tím se zajistí, že kdyby náhodou přišlo na malý znak, odečtením hodnoty 20h (32 dec) dostaneme znak velký, a podprogram skočí zpět. Tam pokračuje v kontrole, a pokud i po „akci podprogramu“ není znak v tomto rozmezí, CMe skočí na badboi. Tedy číslice nepřipadají v úvahu…
Takže necháme CMe projet, a nastavíme jméno „DJH“ a s/n necháme na „123456“
Nyní si dáme breakpoint na adresu 0040139D protože už jsme si jistí, že k tomuto skoku dojde. Cyklus necháme proběhnout [F9] a Olly se zastaví na tomto BreakPointu. Ten my vytracujeme [F7] a skočíme sem:
004013C2 /$ 33FF XOR EDI, EDI ; tato procedurka vypocita
004013C4 |. 33DB XOR EBX, EBX
; ordinalni soucet ASCII znaku
004013C6 |> 8A1E  /MOV BL, BYTE PTR DS:[ESI]
; v editu [name]
004013C8 |. 84DB  |TEST BL, BL
004013CA |. 74 05 |JE SHORT CRACKME1.004013D1
004013CC |. 03FB  |ADD EDI, EBX
004013CE |. 46    |INC ESI
004013CF |.^ EB F5\JMP SHORT CRACKME1.004013C6
004013D1 \> C3 RETN
Myslím že kód je dostatečně popsaný. Cykl sečte ordinální hodnoty ASCII znaků. Je to něco jako:
For i:=1 to Length(Edit1.Text) do
begin
soucet := soucet + ord(Edit1.Text[i]);
end;
Až cyklus skončí, a dorazí na „RETN“, opíšeme si (třeba do poznámkového bloku) hodnotu z EDI. To je vlastně ta hodnota. Převeďte si ji (třeba pomocí Win kalkulačky) na decimální hodnotu, a tu si taky zapište. Se jménem „DJH“ by v EDI mělo být D6h. Super, vše máme, krokujeme tedy dále:
0040139D |. E8 20000000 CALL CRACKME1.004013C2 ; pokud jsou, skoc...//program se nam vlastne vrati…
004013A2 |. 81F7 78560000 XOR EDI, 5678
; soucet vyxoruj s 5678h
004013A8 |. 8BC7 MOV EAX, EDI
; a uloz do EAX
004013AA |. EB 15 JMP SHORT CRACKME1.004013C1

Po xoru EDI s 5678h si EDI znovu někam zapište (v hex. i v dec.). Po skoku se dosaneme zpět sem:
00401232 . 50 PUSH EAX
00401233 . 68 7E214000 PUSH CRACKME1.0040217E
; ASCII "123456"
00401238 . E8 9B010000 CALL CRACKME1.004013D8
; vypocet cisla z [sn]


A call na adrese 00401238 vytracujeme a dostaneme se sem:
004013D8 /$ 33C0 XOR EAX, EAX
004013DA |. 33FF XOR EDI, EDI
004013DC |. 33DB XOR EBX, EBX
004013DE |. 8B7424 04 MOV ESI, DWORD PTR SS:[ESP+4]
004013E2 |> B0 0A /MOV AL, 0A
; prevedeni cisla v [sn] na hex tvar
004013E4 |. 8A1E |MOV BL, BYTE PTR DS:[ESI]
; ktery se ulozi do registru EDI
004013E6 |. 84DB |TEST BL, BL
004013E8 |. 74 0B |JE SHORT CRACKME1.004013F5
004013EA |. 80EB 30 |SUB BL, 30
004013ED |. 0FAFF8 |IMUL EDI, EAX
004013F0 |. 03FB |ADD EDI, EBX
004013F2 |. 46 |INC ESI
004013F3 |.^ EB ED \JMP SHORT CRACKME1.004013E2
004013F5 |> 81F7 34120000 XOR EDI, 1234
; cislo se vyxoruje s cislem 1234h
004013FB |. 8BDF MOV EBX, EDI
; a presune do EBX
004013FD \. C3 RETN

Myslím že není co dodat. Cyklus na adrese <004013E2 až 004013F3> vypočítá ze zadaného SN platné číslo, tedy z „123456“ vytvoří v EDI „1E240h“, což je vlastně oněch 123456 v dec. tvaru. Toto EDI se ovšem zase XORuje, tentokráte s hodnotou 1234h a vyxorovaná hodnota se přesune do EBX. RETN nás vrátí sem:
0040123D . 83C4 04 ADD ESP, 4
00401240 . 58 POP EAX
00401241 . 3BC3 CMP EAX, EBX
; hodnoty se porovnaji
00401243 . 74 07 JE SHORT CRACKME1.0040124C


A to už je jasné :). Takže to co nám vzniklo po xoru 5678h se musí rovnat číslu v editboxu serial. Toto číslo ale musí být zase vyxorováno hodnotou 1234h a převedeno na dec. Zní to složitě, ale opět je opak pravdou… Možná to pochopíte takto:
For i:=1 to Length(Edit1.Text) do
begin
    soucet := soucet + ord(Edit1.Text[i]);
end;
    soucet := soucet xor $5678;
    soucet := soucet xor $1234;
    Edit2.Text := IntToStr(Soucet);


Kde Edit1 je EditBox pro jméno a Edit2 pro serial. Vlastně máte před sebou už keygen v Delphi :). Takže když už keygen, tak procedura by po úplném zkrácení měla vypadat takto:
procedure ProcGen;
var

   
sName:string; //sName - String Name...
  
  sz,j:integer; //sz = soucet ord znaku, i = docasna promenna
begin
    sName := GetName;
    sz := 0;
    for j := 1 to i do
    begin
        sz := sz + ord(sName[j]);
    end;

    //sz := sz xor $5678;
    //sz := sz xor $1234;
    //5678h xor 1234h = 444Ch
    sz := sz xor $444C;
    SetDlgItemText(mWnd,id_serial,pchar(IntToStr(sz)));
end;


Takto to je v API, keygen je přiložený i se zdrojáky v Delphi bez VCL. Vzhledem k tomu, že plánuju do budoucna více keygenů, rozhodl jsem se i pro šablonu na keygeny v Delphi. Stačí si jen pozměnit proceduru pro výpočet a nějaké stringy, víceméně podívejte se sami do zdrojových kódů :)

Myslím si, že dnes byl díl jeden z nejzajímavějších, hlavně pro nováčky. Kód, co jsme projížděli v Olly jsem vysvětloval jen jednou protože si myslím, že kód byl pochopitelný velmi snadno. Kdyby náhodou jste pořád něco nechápali, pročtěte si článek ještě jednou, nebo tolikrát než to pochopíte. Vězte, že po delším začtení to pochopit musíte :)…