Cel     : Uniwersalny Instalator v???
URL     : http://www.doktorx.prv.pl/
Opis    : Program do tworzenia instalatorow
Tools   : DeDe(http://www.crackpltools.prv.pl)

Prog po starcie wyswietla paskudny nag-screen, trzeba czekac nastepnie
chyba 10 razy wyswietlany jest box z textem, ze to wersja niezarejestrowana
deko sie wnerwilem juz myslalem, ze sie zawiesil ale jednak nie to, tylko
taki "bajer" z tymi boxami.

Prog po wstepnych ogledzinach wyglada na exeka z delphi a do analizy
tego typu progow najskuteczniejsza okazuje sie IDA ale mimo mocy i
zalet IDA jest wolna jak cholera wiec postanowilem siegnac po prog
roku wg mnie czyli DeDe.DeDe jest specjalnie zaprojektowany do analizy
(jak to ladnie brzmi) programow skompilowanych w Delphi oraz BCC, dzieki
DeDe mamy wglad w budowe programu, widzimy jakie procedury sa wywolywane
na okreslone zdarzenia(np. OnMouseMove).Ok ladujemy proga do DeDe
idziemy do zakladki "Procedures", w oknie ponizej widzimy(kolumna Unit
Name):

Unit Name | Class Name
----------------------
about     | TForm3
main      | TForm1
postep    | TForm2

Program na starcie juz sie rzuca, ze jest niezarejestrowany tzn. ze zanim
pojawi sie forma zostaja wykonane jakies operacje sprawdzajace, w Delphi
aby cos zrobic tuz przed pokazaniem formy wystarczy wstawic kod w eventa
FormCreate lub FormShow, jest to najlepszy punkt zaczepny.Ok dalej
klikamy na "about" bo jest to okienko ktore pojawia sie na starcie.
Po prawej pojawia sie lista procedur ktore sa wywolywane z tej formy

FormCreate
Timer1Timer
checkreje
FormShow

Normalnie sprawdzalbym FormCreate ale moja uwage zwrocila procka
"checkreje" (no bo jak nie zwrocic na cos takiego uwagi), klikamy na
nia 2 razy, pojawia sie okno z deadlistingiem tejze procki, jej
poczatek wyglada tak:

***** TRY
|
00464BD5   64FF30                 push    dword ptr fs:[eax]
00464BD8   648920                 mov     fs:[eax], esp
00464BDB   A18C754600             mov     eax, dword ptr [$46758C]
00464BE0   C60000                 mov     byte ptr [eax], $00

* Possible String Reference to: 'licensed.dat'
|
00464BE3   B8884D4600             mov     eax, $00464D88

* Reference to: Sysutils.FileExists(System.AnsiString)
|
00464BE8   E81738FAFF             call    00408404
00464BED   84C0                   test    al, al
00464BEF   0F8458010000           jz      00464D4D

* Possible String Reference to: 'licensed.dat'
|
00464BF5   BA884D4600             mov     edx, $00464D88
00464BFA   8D8530FEFFFF           lea     eax, [ebp+$FFFFFE30]
|
00464C00   E8350AFAFF             call    0040563A
00464C05   8D8530FEFFFF           lea     eax, [ebp+$FFFFFE30]

Widzimy, ze sprawdzane jest czy plik "licensed.dat" istnieje w biezacym
katalogu.Jesli plik nie istnieje nastepuje wyjscie z procki, aby program
przeszedl dalej nalezy stworzyc plik "licensed.dat" w katalogu naszego
programu, wpisujemy do niego jakas 1 linijke np.987654321 i lecimy dalej:

* Reference to: System..ResetText()
|
00464C0B   E8570EFAFF             call    00405A67

* Reference to: System.._IOTest()
|
00464C10   E8AFDBF9FF             call    004027C4
00464C15   8D55FC                 lea     edx, [ebp-$04]
00464C18   8D8530FEFFFF           lea     eax, [ebp+$FFFFFE30]

* Reference to: System..ReadLString()
|
00464C1E   E8B1F3F9FF             call    00403FD4
00464C23   8D8530FEFFFF           lea     eax, [ebp+$FFFFFE30]

* Reference to: System..ReadLn()
|
00464C29   E8820DFAFF             call    004059B0

* Reference to: System.._IOTest()
|
00464C2E   E891DBF9FF             call    004027C4
00464C33   8D8D2CFEFFFF           lea     ecx, [ebp+$FFFFFE2C]
00464C39   B203                   mov     dl, $03
00464C3B   8B45FC                 mov     eax, [ebp-$04]
|
00464C3E   E879ABFFFF             call    0045F7BC
00464C43   8B852CFEFFFF           mov     eax, [ebp+$FFFFFE2C]

* Possible String Reference to: 'zarejestrowany'
|
00464C49   BAA04D4600             mov     edx, $00464DA0

* Reference to: System..LStrCmp()
|
00464C4E   E819F1F9FF             call    00403D6C
00464C53   0F85E4000000           jnz     00464D3D

Funkcja ResetText otwiera plik "licensed.dat" nastepnie poprzez ReadLn
odczytywana jest pierwsza linijka z pliku rejestracyjnego, potem widzimy

00464C33   8D8D2CFEFFFF           lea     ecx, [ebp+$FFFFFE2C]
00464C39   B203                   mov     dl, $03
00464C3B   8B45FC                 mov     eax, [ebp-$04]
|
00464C3E   E879ABFFFF             call    0045F7BC

Call nie posiada zadnego komentarza co moze oznaczac, ze nie jest to
wywolanie zadnego api tylko wywolanie wlasnej procedury, klikamy na
call-u i ladujemy w:


0045F7E6   64FF30                 push    dword ptr fs:[eax]
0045F7E9   648920                 mov     fs:[eax], esp

* Possible String Reference to: 'C:\temp.loc'
|
0045F7EC   BA7CF94500             mov     edx, $0045F97C
0045F7F1   8D8524FEFFFF           lea     eax, [ebp+$FFFFFE24]
|
0045F7F7   E83E5EFAFF             call    0040563A

* Possible String Reference to: 'C:\temp2.loc'
|
0045F7FC   BA90F94500             mov     edx, $0045F990
0045F801   8D8558FCFFFF           lea     eax, [ebp+$FFFFFC58]
|
0045F807   E82E5EFAFF             call    0040563A
0045F80C   8D8524FEFFFF           lea     eax, [ebp+$FFFFFE24]

* Reference to: System..RewritText()
|
0045F812   E85762FAFF             call    00405A6E

Program tworzy tymczasowy plik na c:\ do ktorego wpisuje zawartosc 1
linijki textu nastepnie odczytuje kolejno bajty z tego tymczasowego
pliku(super algo):

0045F872   BE01000000             mov     esi, $00000001
0045F877   8D8524FEFFFF           lea     eax, [ebp+$FFFFFE24]

* Reference to: System..ReadChar()
|
0045F87D   E82260FAFF             call    004058A4

* Reference to: System.._IOTest()
|
0045F882   E83D2FFAFF             call    004027C4
0045F887   33DB                   xor     ebx, ebx
0045F889   8AD8                   mov     bl, al
0045F88B   33C0                   xor     eax, eax
0045F88D   8A45FB                 mov     al, byte ptr [ebp-$05]
0045F890   2BD8                   sub     ebx, eax
0045F892   7105                   jno     0045F899

* Reference to: System..IntOver()
|
0045F894   E8FB33FAFF             call    00402C94
0045F899   2BDE                   sub     ebx, esi
0045F89B   7105                   jno     0045F8A2

* Reference to: System..IntOver()
|
0045F89D   E8F233FAFF             call    00402C94
0045F8A2   8BD3                   mov     edx, ebx
0045F8A4   8D8558FCFFFF           lea     eax, [ebp+$FFFFFC58]

* Reference to: System..Write0Char()
|
0045F8AA   E8E463FAFF             call    00405C93

* Reference to: System..Flush()
|
0045F8AF   E8015EFAFF             call    004056B5

* Reference to: System.._IOTest()
|
0045F8B4   E80B2FFAFF             call    004027C4
0045F8B9   46                     inc     esi
0045F8BA   4F                     dec     edi
0045F8BB   75BA                   jnz     0045F877

Pod 0045F87D odczytywane sa kolejno bajty (1 linijka z "licensed.dat")
nastepnie pod 0045F890 od kazdego bajtu odejmowana jest wartosc spod [ebp-5]
a pod 0045F899 dodatkowo odejmowana jest wartosc rejestru esi ktorej wartosc
startowa wynosi 1(look na poczatek petli) i jej wartosc jest inkrementowana
(0045F8B9) co kolejna iteracje.Ilosc powtorzen petli jest rowna dlugosci 1
linijki textu z pliku "licensed.dat".Pod [ebp-5] znajduje sie wartosc 03h
ale skad ona sie tam wziela?Spojrzmy once more na wywolanie tej procki:

00464C33   8D8D2CFEFFFF           lea     ecx, [ebp+$FFFFFE2C]
00464C39   B203                   mov     dl, $03
00464C3B   8B45FC                 mov     eax, [ebp-$04]
|
00464C3E   E879ABFFFF             call    0045F7BC

Tak te mov dl,$03 to jest to, delphi stosuje nieco inny system wywolywnia
wlasnych pseudo api, tzn. ze np. pierwszy parametr dla procki jest
zapisywany do rejestru eax, drugi do edx, trzeci do ecx, nastepne zapisywane
sa na stosie.Po takiej transformacji kolejne zmienione bajty sa zapisywane
do tymczasowego pliku, nastepnie jest z niego odczytywana jedna linijka
a plik tymczasowy zostaje skasowany i tak zamieniona pierwsza linijka trafia
do bufora ktorego adres wskazuje parametr przekazany w rejestrze ecx czyli
[ebp+0FFFFFE2Ch].Po tym malym szyfrowaniu(i wyjsciu z tej procki) widzimy:

00464C43   8B852CFEFFFF           mov     eax, [ebp+$FFFFFE2C]

* Possible String Reference to: 'zarejestrowany'
|
00464C49   BAA04D4600             mov     edx, $00464DA0

* Reference to: System..LStrCmp()
|
00464C4E   E819F1F9FF             call    00403D6C
00464C53   0F85E4000000           jnz     00464D3D

Do eax idzie adres bufora gdzie zostala odczytana zaszyfrowana 1 linijka
textu z "licensed.dat", do edx adres "zarejestrowany", nastepnie jest
wywolywana funkcja LStrCmp ktorej dzialania chyba nie trzeba nikomu
tlumaczyc.Jesli ciagi sa rozne nastepuje wyjscie z glownej procki
sprawdzajacej, jesli sa takie same:

00464C59   8D55FC                 lea     edx, [ebp-$04]
00464C5C   8D8530FEFFFF           lea     eax, [ebp+$FFFFFE30]

* Reference to: System..ReadLString()
|
00464C62   E86DF3F9FF             call    00403FD4
00464C67   8D8530FEFFFF           lea     eax, [ebp+$FFFFFE30]

* Reference to: System..ReadLn()
|
00464C6D   E83E0DFAFF             call    004059B0

* Reference to: System.._IOTest()
|
00464C72   E84DDBF9FF             call    004027C4

Odczytywana jest 2 linijka textu i wywolywana jest znana nam juz funkcja:

00464C77   8D8D28FEFFFF           lea     ecx, [ebp+$FFFFFE28]
00464C7D   B203                   mov     dl, $03
00464C7F   8B45FC                 mov     eax, [ebp-$04]
|
00464C82   E835ABFFFF             call    0045F7BC

Czyli szyfrowanie(a moze deszyfrowanie?) tejze linijki pliku.

Skrotowo co program robi
- czyta 1 linijke z pliku "licensed.dat"
- deszyfruje ja
- jesli po zdeszyfrowaniu jest to text "zarejestrowany"
  - odczytywana jest 2 linijka z "licensed.dat"
  - text z 2 linijki jest deszyfrowany wg. tego samego algo co 1 linijka
    i pojawia sie jako imie zarejestrowanego usera w oknie About

Jak nalezy wiec zrobic plik klucz?
Program deszyfruje text wg. banalnego algorytmu, tzn. od kolejnych
znakow odejmuje bajt podany jako parametr(w naszym wypadku 3) i dodatkowo
odejmuje wartosc licznika ktorego wartosc na poczatku rowna sie 1 i jest
zwiekszana o 1 co przejscie do szyfrowania nastepnego znaku.Aby po
zdeszyfrowaniu 1 linijka to byl text "zarejestrowany" nalezy ten string
zaszyfrowac tzn. przepuscic przez algorytm odwrotny do deszyfrowania.
Procka deszyfrujaca wyglada tak w C++:

void decrypt(char *input)
{
for (int t=0;t<strlen(input);t++)
input[t]-=t+1+3; // od kolejnych bajtow odejmij wartosc licznika(t+1 bo
                 // t na poczatku jest rowne 0) oraz wartosc 3
}

Procka szyfrujaca:

void crypt(char *input)
{
for (int t=0;t<strlen(input);t++)
input[t]+=t+1+3; // do kolejnych bajtow dodaj wartosc licznika i magiczna
                 // liczbe 3
}

Kompletny keygen a wlasciwie keymaker:

#include <windows.h>
#include <stdio.h>

int userlen;
char user[0x128],keydata[0x256];
int hFile;

void decrypt(char *input)
{
        for (int t=0;t<strlen(input);t++)
        input[t]-=t+1+3;
}

void crypt(char *input)
{
        for (int t=0;t<strlen(input);t++)
        input[t]+=t+1+3;
}

int main()
{
        printf("Uniwersalny Instalator keymaker by bart^CrackPl\n");
        printf("===============================================\n");
        printf("Wpisz imie :");

        gets(user);             // pobierz dane usera

        userlen=strlen(user);   // dlugosc imienia
        if (userlen)
        {
                                // 1 linijka pliku
                strcat(keydata,"zarejestrowany");

                crypt(keydata); // zaszyfruj 1 linijke
                crypt(user);    // zaszyfruj imie usera

                                // dolacz znak konca linii do keydata
                strcat(keydata,"\r\n");
                                // dolacz imie usera
                strcat(keydata,user);

                                // stworz plik klucz
                hFile=_lcreat("licensed.dat",0);
                                // zapisz dane
                _lwrite(hFile,keydata,strlen(keydata));
                                // zamknij plik
                _lclose(hFile);

                printf("Plik klucz zostal zapisany na dysku");
        }
        else
        {
        printf("Nic nie wpisales!");
        }



return 0;
}


bart^CrackPl
cryogen@box43.pl
www.cryogen.prv.pl
