andreony
[admin]
Din: bucharest
Inregistrat: acum 18 ani
Postari: 1062
|
|
Un micro-tutorial, pentru cei neinitiati in cracking INTRO Este vorba de un program care trimite e-mailuri la mai multe adrese de odata (spamming ,indeed :) ), dar versiunea neinregistrata, are o limita de 3 adrese.
B O D Y Exista doua solutii la problema ta: 1) Se inregistreaza programul 2) Se patchuieste proramul ca sa trimita oricat de multe mesaje, chiar fiind neinregistrat.
Sigur, metoda mai simpla este metoda 2. Metoda mai frumoasa si mai utila, insa, este metoda 1 (poate mai are niste nag screenuri, care dispar la inregistrare, etc).
Voi incerca sa descriu pe scurt metoda de inregistrare generala, care lucreaza la 90% din programele shareware.
La crackuiala unui program (inregistrarea), planul negru de actiune este urmatorul: 1. Se incearca inregistrarea cu un cod de inregistrare aiurea 2. Se gaseste functia care face inregistrarea in program: 2.1. Se gaseste punctul unde se citeste codul introdus 2.2. Se gaseste punctul in care se face compararea codului cu 3.1 Daca este codul corect, se inregistreaza programul cu codul corect 3.2 Daca este un cod generat din codul nostru introdus, se gaseste in program metoda de transformare a codului introdus 3.2.1. Se scrie o functie generala pentru efectuarea acestei transformari 3.2.2. Se extrapoleaza functia cu parametrul , pentru a gasi codul corect de inregistrare.
Voila, nici 4 pasi :). Ei, acesti pasi necesita ceva cunostinte si resurse: cunoasterea limbajului de asamblare si NuMega Soft-Ice instalat. Eventual si Borland Pascal sau C sau alt limbaj de nivel inalt, pentru a putea scrie functia de transformare a codului (si extrapolarea), functie care poate fi scrisa si in assembler, sau chiar in debug.exe, daca nu ai nici un compilator prin zona. Voi incerca sa descriu pe scurt pasii pe rand, straduindu-ma sa fiu cat mai inteles si lipsit de aiureli si greseli :).
Pasul 1: Este clar: Vom incerca sa inregistram programul cu un cod invalid. Deobicei, cand selectam 'Register', ne apare un dialog, unde introducem acest cod [si numele, adresa, etc].
Pasul 2: Pentru a gasi functia care face inregistrarea, trebuie in primul rand sa gasim unde se afla parametrii acesteia, sau codul nostru introdus (alti parametri, ca adresa, etc, nu ne intereseaza, sau ne intereseaza mai tarziu, in cazul in care acestia participa in transformarea codului nostru introdus). Dar, ca sa nu ma intind pe 100 de pagini, sa consideram ca suntem in cazul cel mai simplu, adica programul jertva va compara codul nostru introdus cu un cod pe care il are scris in el, adica ceva de genul: if cod_introdus<>cod_corect then mesaj('Dute-n dracu!') else mesaj('Thanks for paying $500 for our program'); Ceea ce trebuie sa aflam ca if-ul acesta sa fie false, este constanta cod_corect. Pentru a putea sa-l aflam, trebuie mai intai sa gasim in program punctul unde se executa acest if. Ar fi o idee grozava, daca am putea impune soft-ice-ul sa se opreasca atunci cand se face vreo operatie cu codul nostru (ca, de exemplu, acest if). Pentru aceasta, in soft-ice exista notiunea de breakpoint. Ei,aceste break-pointuri se pot pune cu o sumedenie de conditii, ca, de exemplu, executia unei functii API, citirea sau scrierea din/in vreun port, citirea/scrierea unei adrese din memorie, etc.
Acum, daca am sti adresa variabilei noastre (codul) in memorie, am putea pune un breakpoint pe accesarea acestei adrese, oprindu-ne chiar la if-ul multdorit :). Asfel, problema ar fi rezolvata. Cum aflam, insa adresa codului introdus ??? Iarasi, printr-un breakpoint. Si anume, vom pune un breakpoint pe functia windows de citire din dintr-un control. In cele mai multe cazuri, aceasta se realizeaza prin urmatoarele functii: GetWindowTextA GetDlgItemTextA Iar in soft-ice, pentru a ne opri atunci cand se executa aceasta functie, se utilizeaza comanda BPX (Breakpoint on execution): BPX Ei, noi nu stim care din aceste doua functii este utilizata in program, deci, vom pune breakpoint pe ambele. Dar cand? Pai, anume atunci cand am introdus codul invalid in dialogul de registrare, dar inainte de a apasa pe OK. Deci, dupa ce am scris tot ce a vrut programul in dialogul de registrare, nu apasam OK, ci apasam Ctrl-D, pentru a intra in softice. Aici vom scrie: BPX GetWindowTextA BPX GetDlgItemTextA Cu Ctrl-D iesim din softice inapoi in proramul nostru. Cand apasam pe OK, ne vom trezi in softice, la inceputul unei din aceste doua functii, sa zicem, GetWindowTextA. Ce facem mai departe? *********************************************************************** Sa facem o abatere si sa analizam aceasta functie. Declaratia ei in Win32 API este urmatoarea:
int GetWindowText(int wndhandle, char *buffer, int maxstrLen);
Pentru a chema aceasta functie in C, vom folosi comanda: result=GetWindowText(myWndHandle, *MyBuffer, 32); Aceasta inseamna, sa ne dea textul inscris in fereastra cu ID=myWndHandle, sa-l puna in MyBuffer si sa ia doar 32 de caractere. Dar cum se cheama aceasta functie in assembler? Parametrii pe care ii transmitem la functie intr-un limbaj de nivel inalt, se pun pe stack, care este un segment de memorie, in care se stocheaza date "una peste alta". Adresa ultimei bucatele de date aflata pe stack, se afla in registrul ESP (extended stack pointer). Cand executam comanda push, procesorul decrementeaza automat valoarea acestui registru cu marimea operandului de la push (eg, push EAX, va pune valoarea din EAX, pe stack la adresa SS:ESP, iar ESP=ESP-4, pentru ca registrul EAX este de 32 biti, deci 4 bytes). Comanda POP va incrementa registrul ESP cu marimea operandului... Bine, sa ne intoarcem la chemarea GetWindowTextA. Pentru a chema aceasta functie in assembler, va trebui sa executam urmatoarele instructiuni: Push 20 ; lungimea stringului in hexazecimal lea eax,myBuffer ; eax = adresa myBuffer Push eax ; punem adresa pe stack Push dword ptr [esi+1D1] ; punem pe stack ID-ul (sau handle-ul) ferestrei, aflat in memorie la esi+1D1h CALL USER32!GetWindowTextA ; luam textul...
***********************************************************************
Pasul 2.1
Acum am inteles (sper) cum este chemata functia in assembler, sa ne intoarcem deci in softice (unde ne-am oprit), cand suntem la inceputul functiei GetWindowTextA, in USER32.DLL. Nu avem nevoie sa vedem cum se citeste valoarea acesetei functii de catre Windows, deci, ca sa ne intoarcem in programul nostru, apasand tasta F11. Acum suntem la urmatoarea instructiune dupa CALL USER32!GetWindowTextA. Sa examinam putin cu ce parametri a fost chemata aceasta functie (sa vedem ce s-a pus pe stack), vom vedea ceva de genul: Push 20 ; lungimea stringului * Lea eax, [ebp-3C] ; Eax=ebp-3c mov ecx, dword ptr [esi+2D] ;... push eax ; adresa buferului push ecx ; handle-ul... CALL USER32!GetWindowTextA ; cheama functia.. push 00000000 ; adaoga un zero pe stack...etc .... cu (*) am marcat punctul interesant. Acum am aflat unde este buferul nostru, deci unde a fost luat textul nostru: la ebp-3C. Daca scriem comanda D EBP-3C (Display Memory at), vom vedea in fereastra de date din softice codul pe care l-am introdus. S-ar putea sa nu fie chiar codul, ar putea fi numele sau adresa pe care a mai cerut-o. In acest caz, apasam Ctrl-D pentru a ne opri la urmatoarea chemare a functiei GetWindowText, pana cand D EBP-3C=codul nostru.
Pasul 2.2
Acum, pentru a vedea ce face programul cu aceasta variabila, va trebuia punem un breakpoint pe citirile/scrierile din/in aceasta adresa de memorie. In Soft-Ice, aceasta se face cu comanda BPM (Breakpoint on Memory access): BPM In cazul nostru adresa este ebp-3c, deci vom scrie: BPM (EBP-3C) Apasand Ctrl-D, ne vom opri in momentul in care se manipuleaza datele de la adresa EBP-3C, si anume la instructiunle (de exemplu): 0234C001 DEC CX INC EDI INC ESI MOV AL,Byte ptr [EDI] * ; AL=[EDI] MOV BL,Byte ptr [ESI] ; BL=[ESI] CMP AL,BL ; if AL<>BL then JNZ 0234CA4D ; goto 0234CA4D CMP CX,0 ; If CX<>0 then JNZ 0234C001 ; goto 0234C001 ....
Pentru mine aceasta inseamna urmatoarea comparatie: again: CX:=CX-1 EDI:=EDI+1; ESI:=ESI+1; If var1[EDI]<>var2[ESI] then goto abort_loop If CX<>0 then goto again Pentru ca SoftIce s-a oprit la *, inseamna ca codul nostru se compara cu ceva. Ceva inseamna, de fapt codul corect. Care se afla la adresa ESI.
Pasul 3.1.
Deci, pentru a-l vedea, este suficient sa scriem comanda: D ESI Scriem pe-o hartiuta codul, scoatem toate breakpointurile pe care le-am pus: BC * (clear breakpoint *), iesim din SoftIce, cu Ctrl-D si mai facem o data registrarea cu acelasi nume si adresa, dar cu codul corect.
Uite ca am si crackuit programul.
Doar ca sa ma exprim corect: Ceea ce am descris eu aici este cazul ideal, adica metoda cea mai simpla de protectie (care, totusi, este utilizata in 80% din cazuri). Exista metode foarte complicate de protectie, dar diferenta de complexitate pentru un cracker adevarat este doar ceva timp in plus petrecut la crackuirea programului.
Iar daca vreai sa continuam tema, trimite-mi programul, sau spune-mi unde se poate gasi pe net, si voi scrie aici cum se poate crackui, aratand exact ce si unde trebuie facut. Sper ca nu v-am zapacit si indus in eroare pe toti.
CLOSE In rest, noroace la toti patsanii.
_______________________________________ ------ eVoLuTiOn ------
|
|