Cracking4neWBies - Lekce č.14

Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: DjH
Datum: 19.10.2007
Hodnocení/Hlasovalo: 3.5/4

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

Cracking4neWBies

Lekce č.14

Patch - Search&Replace engine v Delphi DÍL[2]



Balík zde

Minule již jsme nakousli s&r, dnes doděláme poslední nedostatky :)
Co když třeba budu chtít nějaký byt ignorovat? V dUPu tato možnost je, byt ignorujete tak, že místo hex. Hodnoty bytu, zadáte ‚??‘. Poupravil jsem mou šablonu a úplně jsem předělal „engine“ (lol) programu, co generuje kód :), promiňte, nevím jak ho mám nazvat, říkejme mu třeba BTDP4C :). Nyní Vám i v balíčku přenechávám zdrojové kódy…
Kdybych nechal program BTDP4C „tak, jak je“, po zadání ‚??‘ by mi vyplivl ‚… := $??‘ , což je kravina a Delphi nám to nesežere :), proto, když narazí v EditBoxu na ‚??‘, přidá ‚… := $FFF‘ což bude v mé šabloně taková „identifikace“, že se má byte ignorovat :).
Jak jsem šablonu přeměnil, Vám teď ukážu, žádné velké štrachy jsem neudělal:

for j := 1 to FileSeek (FlHandle, 0, 2) do
begin
    l:=1;
    m:=1;
    FileSeek (FlHandle, n, 0); //Seek the offset "address" from Begin (0)
    FileRead (FlHandle, Bfr, 1);

    lopS:
        if (bfr = rasd[l]) or (rasd[l] = $FFF) then //if read byte = "search byte" or search byte = '??' ($FFF)
        begin
            if l = maxl then //If all bytes equals...
            begin
                SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'Bytes at address ' + inttohex(n,2) + ' equals to the "find data"! Now Replacing...')); ScrollText;
                goto lopR; //Now replace...
            end else
            begin
                FileSeek (FlHandle, (n + l), 0); //read byte and increase l
                FileRead (FlHandle, Bfr, 1);
                inc (l);
                goto lopS; //loop...
            end;
        end;
        goto end2; //We found nothing...


        lopR:
            if m = (maxl + 1) then
            begin
                SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'Bytes at address ' + inttohex(n,2) + ' sucessfully patched!')); ScrollText;
                Inc(HowManyCrkd);
                Inc(CrkdProc);
                goto end2;
            end else
            begin
                if (rawd[m] = $FFF) then goto ignore; //If replace byte eqals to $FFF, ignore (increase and loop)
                FileSeek (FlHandle, (n - 1 + m), 0);
                FileWrite(FlHandle, rawd[m], 1);
                ignore:
                    inc (m);
                    goto lopR;
            end;
        end2:
    inc(n);
end;


K čemu je používání ‚??‘, a vůbec, celého Search&Replace dobré? Možná jsem to už říkal, ale pro jistotu to řeknu ještě jednou :), v minulé lekci v balíku jste měli přidaný soubor ‚how.to.make.nice.search.and.replace.patches.pdf‘ ve kterém to bylo všechno pěkně popsáno, ale anglicky… Zkusím aspoň kousek z toho článku přeložit:


Proč s&r?
Odpověď je jednoduchá: když použijete patchování přesně zadaných offsetů, patch Vám poběží jen na verzi, kterou zrovna chcete patchnout, ale s&r patch, může při troše štěstí (a zacházení) fungovat i do budoucích (minulých) verzí programu. Ovšem, jak jsem řekl, musí se to udělat dobře :)
Pár pravidel…
Je ovšem pár pravidel, které musíte dodržet, aby jste dosáhli dobrého s&r patchu. Hlavně potřebujete velké znalosti assembleru a hexadecimálních instrukcí (třeba co je za instrukci 75h?! Přece JNZ =))
Při zadávání šablony, podle které se bude patchovat, si vlastně uvědomme, z čeho vlastně se jednotlivé příkazy v hex. podobě skládají. Při zavolání (CALL) je vždy po instrukci CALL (většinou ‚E8‘) napsány 4 byty, které znamenají, jak daleko je od aktuálního offsetu instrukce, na kterou se volá. Stejně tak je na tom i JZ nebo JNZ. Vždy po bytu 75 nebo 74 následují 4 byty, které znamenají, jak daleko je instrukce, na kterou by se skákalo. Pokud je instrukce, na kterou JNZ nebo JZ ukazuje, blízko, označuje se JNZ SHORT popř. JZ SHORT. V tom případě je za bytem 74 nebo 75 jen jeden byte. Třeba instrukce vzdálená 14 bytů směrem nahoru by vypadala takto: 75 F1 (směrem nahoru 14 znaků, tj. „-14“ což je FFh – F1h = Eh = 14d :)). Pokud stále nechápete, podívejte se na následující…(‚??‘ je to, co může být jakékoliv):

CALLy
ASM: CALL
?? ?? ?? ??
HEX: E8
?? ?? ?? ??

Memory Addresses
ASM: CMP BYTE PTR [
?? ?? ?? ??],1
HEX: 80 3D
?? ?? ?? ?? 01

Long Jumps
ASM: JE LONG
?? ?? ?? ??
HEX: OF 84
?? ?? ?? ??


To jsou asi nejběžnější instrukce…

Uvedu příklad:


To co nám je „ukradený“, je označeno červeně. Tyto hodnoty se můžou měnit (třeba podle verze), proto nás zajímají jen ostatní instrukce (cally, přesuny atp. ale číslo, na které JE volá, nás vážně nezajímá, protože podle verze se může změnit i délka, na kterou JE skáče)
Vlevo je zápis v HexaBytech, v pravo v assembleru…

Dejme tomu, že chceme, aby skok na adrese 0040B27D nikdy neskočil :)

0040B27D |. /74 43 JE SHORT 0040B2C2
0040B27D |. /74 00 JE SHORT 0040B27F



Vybereme si delší kus kódu před a po instrukci:

PUSH 2
PUSH -1
PUSH 100C
PUSH DWORD PTR DS:[?? ?? ?? ??]
CALL <?? ?? ?? ??>
CMP EAX,-1
JE SHORT ??
MOV DWORD PTR DS:[ ?? ?? ?? ?? ],EAX
MOV DWORD PTR DS:[ ?? ?? ?? ?? ],1
MOV DWORD PTR DS:[ ?? ?? ?? ?? ],5555
MOV DWORD PTR DS:[ ?? ?? ?? ?? ],0


A kus hexkódu, podle kterého budeme chtít hledat byty, bude vypadat asi takto: 
6A 02 6A FF 68 0C 10 00 00 FF 35 ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 F8 FF 74 ?? A3 ?? ?? ?? ?? C7 05 ?? ?? ?? ?? 01 00 00 00 C7 05 ?? ?? ?? ?? 55 55 00 00 C7 05 ?? ?? ?? ?? 00 00 00 00
A nahradit tímto:
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??

Snad jste si všimli, proč jsem to označil a podtrhl :)…
Snad jsem to už dostatečně polopaticky vysvětlil, je to opravdu jednoduché, měl by to pochopit opravdu každý :)
Co se týče mé šablony, poupravil jsem ji, víceméně jste to mohli i postřehnout, když jsem Vám ten nový s&r engine v Delphi ukazoval :), ale pokud to stále nechápete, přidal jsem do balíku zdrojové kódy opět ke cracku na hru 3D Live Pool, s využitím ‚??‘ ($FFF).
A co se týče BTP4C, uvolnil jsem zdroje, tudíž BTP4C je OpenSource =), ale základní úpravy jsem mu dodal, jako je třeba to, že text, který zadáváte do EditBoxů (binary data) se Vám minule vlezly jen na ten řádek, nyní můžou být binary data nekonečně dlouhá :). A vlastně ještě úprava ta, že podporuje konvertování ‚??‘ na $FFF, které engine v šabloně chápe jako „ignore byte“ :)…