Cracking4neWBies
Lekce č.7
Tajemství výroby ochran - podruhé
Balík ke stáhnutí
zde
Probrali jsme si jeden typ ochrany, a to typu
Nick-s/n.
Nyní si probereme nový typ, a to jen s/n. Nemyslím pevně dané, ale třeba typu
ABC-xxxyyy. Jak takové s/n počítání funguje? Jednoduše. Dám jednoduchý příklad. Známe příkaz Ord. Správné s/n bude typu
ABC-xxyyyy. Kde
xx, jsou dvě náhodná čísla, a první dvě
yy, je ord prvního
x, a druhá dvojice
yy, je druhé ord
x. Dáme si příklad: Víme, že se s/n počítá takto, jak jsem napsal. Dejme tomu, že chceme vytvořit třeba keygen. Máme
ABC-29yyyy. Provedeme:
Ord(‚2‘) = 50
Ord(‚9‘) = 57
Tedy správné s/n by bylo
ABC-295057.
Samozřejmě, pokud chceme ochranu zvýšit, započteme mezi čísla i písmena. Podle stejného vzorce by bylo
ABC-sEyyyy = ABC-sE11569. s/n má ale čísel ‚y‘ pět, ale my chceme aby byly jen čtyři. Zkrátíme tedy na
ABC-sE1156. Samozřejmě že tato ochrana je primitivní. Je to ale podle mě lepší ochana než typ Nick-s/n. Pokud děláte tyto ochrany v Delphi, moc je neochráníte, protože Delphi vše ukládá do proc. registrů. Museli byste použít tzv.vložený ASM. A to takto:
Asm
;asm prikazy, napr:
Mov eax, ebx
Xor eax, eax
End;
Vložený asm, začíná „asm“ a končí „end;“. Jednoduché viďte. Já osobně ale vložený asm nepoužívám. Moc mi to nejde. Lepší je na ochrany vytvořit DLL knihovnu, anebo celý program psát v C++. V aplikacích na bázi .NET FW, uvidíte v DisAsm taky pěkné prt :-), moc se v těchto aplikacích nevyznám, ani v Olly. Víceméně, vyzkoušejte sami… Ale teď uvedu zde source k dalšímu našemu (mému) CMe, které si crackneme:
var
s1,s2,s3,s4,s5,sn:string;
i1,i2,i3,i4,i5:Integer;
begin
s1 := Edit1.Text;
if (s1[1] = 'C') and (s1[2] = 'M') and (s1[3] = 'e') and (s1[4] = '-') and (length(Edit1.Text)=12) then
begin
i1:=ord(s1[5]);
i2:=ord(s1[6]);
i3:=ord(s1[7]);
i4:=ord(s1[8]);
i1:=strtoint(inttostr(i1)[2]);
i2:=strtoint(inttostr(i2)[2]);
i3:=strtoint(inttostr(i3)[2]);
i4:=strtoint(inttostr(i4)[2]);
if Edit1.Text = 'CMe-'+s1[5]+s1[6]+s1[7]+s1[8]+inttostr(i2)+inttostr(i4)+inttostr(i3)+inttostr(i1) then Button4.Click;
end;
end;
Snad chápete, co kontrola provádí. Spustíme si tedy naše CMe, a jako, že jsme tento kód neviděli :-), napíšeme ‚123456‘ a klikneme na Check, a nic se nestalo. Otevřeme si CMe programem PEiD, a co nevidíme, program je packovaný UPXem. Zkoušíme unpacknout přes PEiD – nejde, zkoušíme přes UPX, nejde. Když se podíváte na jednotlivé sekce, jsou přepsané a vlasnosti characteristics jsou také přepsané. Proto nelze provést UnPack. Zkusíme poslední možnost, a to je Generic Unpacker. Bomba! Už to jde! :-)
Nyní jsme si ukázali perfektní ukázku crackování packovaného programu…Když program přetáhneme do eXeScope, tváří se pořád jako packovaný. Zkusíme program natáhnout do DeDe, ať se podíváme, co se děje při kliknutí na „check“… Program ohlásí „Dump sucessfull“ ale v Procedures nic není! Bude to složité… Natáhneme si program do Olly a projedeme si kód. Stringy většinou bývají až na konci, tak se díváme… Nic na konci není. Proč? Protože jsme soubor unpackli a dokonce Genericky, takže kód nemusí být originální, a také, že není. Našli jsme stringy „CMe-“ a „Registration completed sucessfully! :-)“… Podíváme se na to druhé, a stopujeme pozpátku (program nezapínáme), hledáme „to pravé místo pro BP“. Bohužel jsme dostopovali asi jen dva řádky nahoru, našli jsme tam totiž NOP a RETN. Nastavíme tedy BP na NOP (0046C773) a na MOV (0046C774) a skusíme zjistit, odkud sem skáče. Spustíme program, napíšeme blábol, stiskneme „Check“ a…nic…jakto? Protože jsme nastavili BP na funkci, která probíhá po SPRÁVNÉM zaregistrování, což my jsme neudělali. Co teď? Najdeme si ten string „CMe-“ a krokujeme nahoru. Někde by měla být směsice nesmyslných dat, ale my si nastavíme BP předtím. Poslední DB je na adrese 0046C4A9. Potom následuje MOV. Nastavíme si BP na adresu 0046C4B9 (je tam příkaz JNZ) a zkusíme…a hle! Zastavilo se to tam… Vidíme že je to nějaký cyklus, a tak vyčkáme než přestane. Nyní se už jen soustředíme na nalezení s/n… krokujeme, a co nevidíme…:
0046C4DF . 8038 43 CMP BYTE PTR DS:[EAX], 43 //první znak musí být C (43 hex = 67 dec a to je písmeno „C“ (Ord(‚C‘) = 67)
0046C4E2 . 0F85 AC010000 JNZ cme_exe_.0046C694
0046C4E8 . 8B45 FC MOV EAX, DWORD PTR SS:[EBP-4]
0046C4EB . 8078 01 4D CMP BYTE PTR DS:[EAX+1], 4D //Druhé písmeno musí být „M“
0046C4EF . 0F85 9F010000 JNZ cme_exe_.0046C694
0046C4F5 . 8B45 FC MOV EAX, DWORD PTR SS:[EBP-4]
0046C4F8 . 8078 02 65 CMP BYTE PTR DS:[EAX+2], 65 //třetí „e“
0046C4FC . 0F85 92010000 JNZ cme_exe_.0046C694
0046C502 . 8B45 FC MOV EAX, DWORD PTR SS:[EBP-4]
0046C505 . 8078 03 2D CMP BYTE PTR DS:[EAX+3], 2D //čtvrtý znak musí být pomlka „-“
0046C509 . 0F85 85010000 JNZ cme_exe_.0046C694
0046C50F . 8D55 F0 LEA EDX, DWORD PTR SS:[EBP-10]
0046C512 . 8B83 F8020000 MOV EAX, DWORD PTR DS:[EBX+2F8]
0046C518 . E8 CBB6FCFF CALL cme_exe_.00437BE8
0046C51D . 8B45 F0 MOV EAX, DWORD PTR SS:[EBP-10]
0046C520 . E8 E77BF9FF CALL cme_exe_.0040410C
0046C525 . 83F8 0C CMP EAX, 0C //počet znaků musí být 12
0046C528 . 0F85 66010000 JNZ cme_exe_.0046C694
Jinak nás to automaticky háže na Badboy. Nastavíme: CMe-56789012 (max poč. znaků = 12). Tamnějším testem projde v pohodě, a soustředíme se opět na nalezení s/n.
Narazíme na toto:
0046C67E . E8 D57BF9FF CALL cme_exe_.00404258
0046C683 . 75 0F JNZ SHORT cme_exe_.0046C694
Kde v CALLu se porovnává zadané s/n se správným a jnz už jen skočí buď na badboye, nebo ne. Když call vytrasujeme, můžeme si na adrese
0040425F v
EDX najít správné s/n. Tedy
„CMe-56784653“. „CMe-5678xxxx“ jsme napsali pamatujete? Jen se vypočítaly poslední 4 čísla. Zadáme s/n „
CMe-56784653“, a jde to :-). Skusíme si zadat s/n „
CMe-DjH4xxxx“, a nastavíme BP na CALL, který volá porovnávání, abychom si hned přečetli správné s/n… Správné s/n pro prvních 8 znaků (
CMe-DjH4) je „
CMe-DjH40228“… V balíčku najdete Source, CMe (originální), CMe (Packované) a CMe (Genericky UnPackované) + source a exe ke keygenu.
Chtěl bych ještě říct, že tohle zajista nebyl poslední díl :-), ještě jich pár vydám, sám nevím kolik... příště se ale asi mrkneme na výrobu patchů a cracků :-)