Zpět na seznam článků     Číst komentáře (1)     Verze pro tisk

Cracking4neWBies - Lekce č.13

Autor: DjH   
19.10.2007

Cracking pro začátečníky...potřinácté :-)


Cracking4neWBies

Lekce č.13

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



Balík zde

Znáte dUP? Je to diablo2oo2’s Ultimate Patcher. Pomocí tohoto prográmku si vytvoříte svůj vlastní patch. Do programu zadáte pár dat, ten vytvoří kdovíkam *.asm soubor, který se náhle zkompiluje pomocí MASM. Diablo2oo2 je proslavený jako „velkej cracker“ a „čaroděj MASMu“, tak není co divu, že i samotný dUP je vyvíjený v MASMu.
O co tedy vlastně jde? Dejme tomu, že PATCHUJETE 5MB program, patchnete 1 byt (třeba JZ za JMP) a chcete vyrobit patch. Minule jsem Vám ukazoval, jak to udělat pomocí pevného zadání offsetu přímo do zdrojového kódu, ale s&r engine pracuje úplně jinak… Jak?
Dejme tomu, že jsme v OllyDbg a crackujeme opět to naše CMe z lekce 1 (resp. 2), a jsme na adrese 00401185 kde je instrukce JNZ, kterou my chceme zaměnit, třeba vyNOPovat. My tak učiníme, odzkoušíme a bingo, udělá to to, co my chceme (vždycky goodboy). Každá instrukce je složená z nějakých bytů, ale to vy už snad víte… Označíme si v Olly TEN úsek, kde se nachází instrukce, označíme ho však tak dostatečně dlouhý, abychom si mohli být jistí, že se takový kousek kódu nikde jinde v programu nevyskytuje, ale ne zase tak dlouhý aby to byla půlka z celé binárky… Dejme tomu že označíme toto:

0040117E . F7F3 DIV EBX
00401180 . 35 86140000 XOR EAX, 1486
00401185 . 75 1E JNZ SHORT crackme.004011A5 ;TOTO CHCEME ZAMENIT!
00401187 . 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401189 . 68 CC304000 PUSH crackme.004030CC ; |Title = "Zpráva"



Nyní si instrukci změníme (vynopujeme, nebo si patchnutí v Olly obnovíme v okně [/]), a vybereme ten stejný počet bytů, vlastně ten stejný úsek:

0040117E . F7F3 DIV EBX
00401180 . 35 86140000 XOR EAX, 1486
00401185 90 NOP ;ZMENENO
00401186 90 NOP ;ZMENENO
00401187 . 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401189 . 68 CC304000 PUSH crackme.004030CC ; |Title = "Zpráva"

Tudíž změnili jsme byty 751E za 9090. No jo, jenže takových se v kódu může vyskytovat několik, proto jsme vybrali větší kousek :-). Nyní si odstraníme patchnutí z5 na „JNZ“ a označíme si ten kousek co je výše, a klikneme na kód pravým myšítkem, klikneme na Binary->Binary Copy… vyhodí nám to do ClipBoardu toto:
F7 F3 35 86 14 00 00 75 1E 6A 00 68 CC 30 40 00
Opět to patchneme, vybereme opět tu část a opět dáme Binary copy a máme toto:
F7 F3 35 86 14 00 00 90 90 6A 00 68 CC 30 40 00
Po takovém rozepsání snad už začínáte chápat, co to je ten s&r engine. Jde o to, že v prográmku dUP zadáte v políčku „Find bytes:“ toto:
F7 F3 35 86 14 00 00 75 1E 6A 00 68 CC 30 40 00
A v políčku „Replace with:“ toto:
F7 F3 35 86 14 00 00 90 90 6A 00 68 CC 30 40 00
A výsledný crack bude při patchovací proceduře dělat toto:
Vezmi byte -> je byte F7? Ne? Tak popojdi o byte dál…
Vezmi další byte -> je byte F7? Ano? 
Vezmi další byte -> je byte F3? Ne? Popojdi dále…
Vezmi další byte -> je byte F7? Ano? 
Vezmi další byte -> je byte F3? Ano?
Vezmi další byte -> je byte 35? Ano?
………………
Vezmi další byte -> je byte 40? Ano?
Vezmi další byte -> je byte 00? Ano?
Vrať se o 15 bytů z5 a podle zadaných dat „Replace with“ přepiš data…


Je to jednoduché, co říkáte? :) Prográmek dUP verze 1 a zatím poslední v této době (2.16) je v balíku. Program má pro výrobu patchu ohromné množství možností a obrovská výhoda je ta, že je výsledný patch v MASMu, tzn. malá binárka. Můžete vytvořit i Loader, nebo si do patchu přidat XM písničku… je toho opravdu moc :)…

Jenomže mě MASM moc nesedí, tak mi vrtalo hlavou… Co si takhle přepsat s&r engine do Delphi? Proč ne, trvalo mi to sice asi hoďku ale poradil jsem si, výsledný engine v pascalu je zde:
begin
    //0F 8C 01 02 00 00 8B 86 84 A3 02 00 85 C0 EB 31 8B 86 E8 A4 02 00 8B 96 F0 A4 02 00
        maxL := 7; //in array is declared max value 128...

        rasd[1] := $0F; rawd[1] := $0F;
        rasd[2] := $8C; rawd[2] := $8C;
        rasd[3] := $01; rawd[3] := $01;
        rasd[4] := $02; rawd[4] := $07;
        rasd[5] := $00; rawd[5] := $00;
        rasd[6] := $00; rawd[6] := $00;
        rasd[7] := $8B; rawd[7] := $8B;
        //rasd=search byte, rawd=byte to replace(write)
end;

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

        lopS:
            if bfr = rasd[l] then //Compare with „search for“ byte
            begin
                if l = maxl then //if all „search for“ bytes are equals
                begin
                SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'Bytes at address ' + inttohex(n,2) + ' equals to the "find data"! Now Replacing...')); ScrollText; //id_proces = Memo :), process info
                goto lopR;
            end else
            begin
                FileSeek (FlHandle, (n + l), 0);
                FileRead (FlHandle, Bfr, 1);
                inc (l);
                goto lopS;
            end;
    end;
goto end2;


        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
                FileSeek (FlHandle, (n - 1 + m), 0);
                FileWrite(FlHandle, rawd[m], 1);
                inc (m);
                goto lopR;
            end;
        end2:
    inc(n);
end;

Jelikož po nějaké slušné době, mě přestalo bavit psát (deklarovat) ty byty ručně, vymyslel jsem si na to prográmek, do kterého prostě zkopčíte byty z Ollyho a vyflusne Vám to rovnou deklaraci, kterou pastnete do zdrojáku v Delphi :). Zatím se mi nějak nechtělo to řešit, dělám to takto, možná se na to někdy pořádně mrknu, a možná vymyslím i něco takového, jako je dUP :).

Takže teď Vám napíšu, jak by asi vypadal patch s použitím s&r na to CMe z lekce 1 a 2(CMe from Programujte.com =)):
Spustím si můj superprográmek a zadám do něho ty čísla bytů z Ollyho, vyplivne mi toto:
//Created by DjH's BTP4C v0.5
    MaxL := 16;
    rasd[1] := $F7; rawd[1] := $F7;
    rasd[2] := $F3; rawd[2] := $F3;
    rasd[3] := $35; rawd[3] := $35;
    rasd[4] := $86; rawd[4] := $86;
    rasd[5] := $14; rawd[5] := $14;
    rasd[6] := $00; rawd[6] := $00;
    rasd[7] := $00; rawd[7] := $00;
    rasd[8] := $75; rawd[8] := $90;
    rasd[9] := $1E; rawd[9] := $90;
    rasd[10] := $6A; rawd[10] := $6A;
    rasd[11] := $00; rawd[11] := $00;
    rasd[12] := $68; rawd[12] := $68;
    rasd[13] := $CC; rawd[13] := $CC;
    rasd[14] := $30; rawd[14] := $30;
    rasd[15] := $40; rawd[15] := $40;
    rasd[16] := $00; rawd[16] := $00;
Když odstraníme veškeré zbytečnosti (ovládání oken, různé deklarace a procedury), zbude nám asi toto:

procedure Declare;
begin
    if o= 1 then
    begin
        //Created by DjH's BTP4C v0.5
        MaxL := 16;
        rasd[1] := $F7; rawd[1] := $F7;
        rasd[2] := $F3; rawd[2] := $F3;
        rasd[3] := $35; rawd[3] := $35;
        rasd[4] := $86; rawd[4] := $86;
        rasd[5] := $14; rawd[5] := $14;
        rasd[6] := $00; rawd[6] := $00;
        rasd[7] := $00; rawd[7] := $00;
        rasd[8] := $75; rawd[8] := $90;
        rasd[9] := $1E; rawd[9] := $90;
        rasd[10] := $6A; rawd[10] := $6A;
        rasd[11] := $00; rawd[11] := $00;
        rasd[12] := $68; rawd[12] := $68;
        rasd[13] := $CC; rawd[13] := $CC;
        rasd[14] := $30; rawd[14] := $30;
        rasd[15] := $40; rawd[15] := $40;
        rasd[16] := $00; rawd[16] := $00;
    end;
end;

function CrackIt: string; //Search and Replace engine, Delphi Code, by DjH2oo7
    label lopS;//loop in search...
    label lopR;//loop in replace...
    label end2;//jmp
    begin
        HowManyCrkd := 0;
        j:=0;
        n:=1; //WE CAN'NT USE "J", I DON'T KNOW WHY??!!!

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

lopS:
    if bfr = rasd[l] then
    begin
        if l = maxl then
        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;
        end else
        begin
            FileSeek (FlHandle, (n + l), 0);
            FileRead (FlHandle, Bfr, 1);
            inc (l);
        goto lopS;
    end;
end;
goto end2;


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
            FileSeek (FlHandle, (n - 1 + m), 0);
            FileWrite(FlHandle, rawd[m], 1);
            inc (m);
            goto lopR;
        end;
end2:
    inc(n);
    end;
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'Cracked ' + inttostr(HowManyCrkd) + ' same procedures!')); ScrollText;
end;

//#########################################################################//

function GetInfo: string;
begin
    crkdproc:=0; //Kolik bylo cracknuto procedur...porovna se to s tim, kolik jich cracknuto melo byt a pokud se sobe cisla rovnaji (tedy bylo vsechno cracknuto), crack vy\hodnoti akci za uspesnou :), nekdy je i vsak mozne, ze se crackne procedur vice (je jich deklarovano 3 a cracknou se 4, proc? Protoze treba kusu kodu jako je deklarace 2 muze byt v programu vice... nekdy to muze byt umysl, nekdy vsak ne...)
if not FileExists(FlName) then
begin
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'File ' + FlName + ' not found, please, find it manually ;)')); ScrollText;
    OpenDlg;
    FlName:=Opn.lpstrFile;
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'File ' + FlName + #13#10 + '[LOADED]')); ScrollText;

begin
    IsBkuped; //Kontrola, jestli je zaskrtly CheckBox pro zalohovani
//---------------------------------------------------\\
    FlHandle := FileOpen (FlName, fmOpenReadWrite); //nyni oteverme soubor a zjistime jeho handle
//---------------------------------------------------\\
for o := 1 to nop do //nop je "number of procedures" :), tudiz kolik procedur se mam cracknout, je to deklarovano uplne dole :)
begin
    Declare; //Deklarovani bytu pro "search" a pro "write"
    CrackIt; //Spusteni s&r enginu, cracknuti
end;
//---------------------------------------------------\\
    FileClose(FlHandle); //zavreni handle, souboru
//---------------------------------------------------\\
end;

    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + '[JOB COMPLETED]'));
if (crkdproc >= nop) then
begin
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + inttostr(crkdproc) + ' procedures cracked of ' + inttostr(nop) + #13#10 + '[:' + product + ':] sucessfully cracked!! ;)')); ScrollText;
    MessageBox(mwnd,pchar(product + ' sucessfully cracked ;)'), pchar('Cracked ;)'), 0);
end else
begin
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + product + ' - ERROR! ' + inttostr(crkdproc) + ' procedures cracked of ' + inttostr(nop) + '!! (Maybe yet cracked, or you cracking update (or other) version)'));     ScrollText;
    MessageBox(mwnd,pchar(product + ' - ERROR! ' + inttostr(crkdproc) + ' procedures cracked of ' + inttostr(nop) + '!! (Maybe yet cracked, or you cracking update (or other) version)'), pchar('NOT Cracked !!'), 0);
end;
end else

//To same, akorat ze patch zjisti, ze program (v tomto pripade CMe) je ve stejne slozce jako je patch, tudiz nemusime nic hledat a okamzite se crackuje :)
begin
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + 'File ' + FlName + #13#10 + '[LOADED]')); ScrollText;
begin
    IsBkuped;
//---------------------------------------------------\\
FlHandle := FileOpen (FlName, fmOpenReadWrite);
//---------------------------------------------------\\
for o := 1 to nop do
begin
    Declare;
    CrackIt;
end;
//---------------------------------------------------\\
    FileClose(FlHandle);
//---------------------------------------------------\\
end;
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + '[CRACKED]'));
if (crkdproc >= nop) then
begin
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + product + ' sucessfully cracked ;)')); ScrollText;
    MessageBox(mwnd,pchar(product + ' sucessfully cracked ;)'), pchar('Cracked ;)'), 0);
end else
begin
    SetDlgItemText(mwnd, id_process, Pchar(GetText + #13#10 + product + ' - ERROR! NOTHING CRACKED! (Maybe yet cracked)')); ScrollText;
    MessageBox(mwnd,pchar(product + ' - ERROR! NOTHING CRACKED! (Maybe yet cracked)'), pchar('NOT Cracked !!'), 0);
end;
end;
end;

Kde ScrollText je moje vlastnoručně napsaná procka, která posunuje scrollbar v Memu (který informuje o procesu :))


Kompletní kód je samozřejmě v balíku :)

Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.63/8

1  2  3  4  5    
(známkování jako ve škole)