     ___     ___          ___     ___          ___         ___         ___
    /  /\   /__/\        /  /\   /__/\        /  /\       /  /\       /  /\
   /  /:/   \  \:\      /  /::\  \  \:\      /  /::\     /  /::\     /  /::|
  /  /:/     \  \:\    /  /:/\:\  \  \:\    /  /:/\:\   /  /:/\:\   /  /:|:|
 /  /::\ ___  \__\:\  /  /::\ \:\  \__\:\  /  /::\ \:\ /  /::\ \:\ /  /:/|:|__
/__/:/\:\  /\ /  /::\/__/:/\:\ \:\ /  /::\/__/:/\:\ \:/__/:/\:\_\:/__/:/_|::::\
\__\/  \:\/://  /:/\:\  \:\ \:\/://  /:/\:\  \:\ \:\_\\__\/  \:\/:\__\/  /~~/:/
     \__\:://  /:/\ \:\  \:\ \:://  /:/\ \:\  \:\ \:\      \__\::/      /  /:/
     /  /://  /:/  \_\/\  \:\/://  /:/  \_\/\  \:\_\/      /  /:/      /  /:/
    /__/://__/:/        \  \:://__/:/        \  \:\       /__/:/      /__/:/
    \__\/ \__\/          \__\/ \__\/          \__\/       \__\/       \__\/
                                                                 www.htb.prv.pl

Title:    [Kilka slow na temat: crackme_0 by Hallor...........................]
Topic:    [cracking lesson - crackmes.........................................]
Author:   [Tymon^HTB..................]   E-mail: [tymon_crk@wp.pl............]
Packager: [Tymon^HTB..................]   Date:   [14.03.2002.................]
Homepage: [http://www.htb.prv.pl..............................................]

         D  O  N  '  T     T  R  Y     T  O     B  E  A  T     U  S  !
_______________________________________________________________________________

Hello all!

Ostatnio  znalezlem  na  swoim  dysku  wlasnie  to  crackme,  ktore  mialem juz
wczesniej zlamac, ale z blizej nieznanych mi przyczyn calkiem o nim zapomnialem
:) Jak  wszem i  wobec wiadomo  na moim  dysku jest  balagan ktorego nie da sie
opisac :). Oki, ale koniec tych glupich wywodow, czas cos napisac na temat,  bo
sama improwizorka nic nie zdziala :)

Crackme  jest dosyc  specyficzne, bo  napisane jest  przez programiste,  a nie
crackera  ( niby  cracker =  programista, ale  ... :).  Jezeli chodzi  o jezyk
programowanie to ( niestety ) jest  to Delphi, a samo crackme jest  konsola, co
oznacza, za uruchamia sie  pod MS-DOS, ale tylko  w obecnosci windy. Ozacza  to
takze, ze wykorzystywane sa tu zwykle api ( createfilea itd. ).

Chcialbym tu jeszcze powiedziec, ze ten tutor bedzie raczej opisem algorytmu  i
jego rozwiazaniem, a nie dokladnym opisem zlamania. Nie wiem jak was, ale  mnie
nudza tutory w stylu:

bpx ....
5 * F5
6 * F10
...

To chyba nic nie daje...

Oki, czas zaczac...

.Gra WsTepNa :)

Jak widzimy,  razem z  crackme dolaczony  jest pliczek  keys.dat. Warto  by sie
przyjrzec co on posiada, wiec zaladuj go do hex editora i najlepiej spisz sobie
pierwsze  bajty.  Moze  sie  to  przydac, gdy  cm  bedzie  sie  do  tych danych
odwolywalo. Oki,  czas obejrzec  samo crackme.  Jak juz  wiecie napisane jest w
delphi. Dodatkowo program spakowany jest  Aspackiem 2.11. Sam packer w  lamaniu
nie przeszkadza, chyba, ze chcesz  obejrzec crackme pod IDA. Oki,  czas wlaczyc
moje ulubione narzedzie, czyli SoftIce :)

.CzaS na CracKing

Ja przejalem kontrole nad cm, lapiac  je na api CreateFileA. Oki, juz  na samym
poczatku dowiadujemy sie, ze serial powinien miec 11 znakow. Dalej jak na  tacy
cala procka :)


                mov     eax, _serial
                call    sub_408A08              ; ten call tworzy unikalny
                                                ; numer z twojego seriala
                mov     eax, offset dword_40B718
                call    sub_4089BC              ; tutaj ten numer jest
                                                ; przerabiany do formatu
                                                ; 64 bit
                mov     ax, ds:word_40B720
                push    eax
                push    ds:dword_40B71C
                push    ds:dword_40B718
                call    sub_408D88              ; a tutaj drobne porownanie ;)
                test    al, al
                jz      short loc_408F78        ; bye bye!


Hmm.. Cala procka. Moze po koleji obejrzymy sobie odpowiednie call'e.

_next:
                mov     eax, [ebp+var_4]        ; do eax offset seriala
                mov     al, [eax+ebx-1]         ; odpowiedni znak
                mov     edx, ebx
                call    sub_408A70              ; procka liczaca odpowiednia                                                                                                                                                                                                                                                         ; wartosc
                inc     ebx
                dec     esi
                jnz     short _next             ; itd.

Oki, co mozna powiedziec o tym? Hmm... Po koleji pobierane sa znaki s/n,  ktore
po odpowiednim przerobieniu  generuja jakas wartosc.  Bardzo ciekawy jest  call
sub_408A70.  Jest  to jakby  serce  calego cm.  Znajduje  sie tam  cala  procka
generujaca. Nie bede  tu przytaczal jej  listingu, bo to  raczej nie ma  sensu,
opisze tylko jej dzialanie. Oki, w tym call'u cm sprawdza jaki znak wpisalismy.
Jezeli jest to 1 to steruje  nas do odpowiedniej procki, liczacej jakas  sume i
nadpisuje poprzednia wartosc  ( oczywiscie ta  wartosc tez bierze  udzial w tym
procesie ).  Jezeli naszym  znakiem jest 0 to  cm kieruje nas do  jeszcze innej
procki. A teraz najslabszy punkt cm. Jezeli aktualny znak nie jest 0, ani 1, to
program omija cala procke  generujaca, a stala liczona  z seriala ma wartosc  z
poprzednich obliczen.  Warto tu  powiedziec, ze  jezeli serial  bedzie zawieral
znaki inne niz 0 i 1 to procka ta wyliczy zawsze stala wartosc!!! By latwiej to
zrozumiec, looknij na to:

 if znak == 0 than proc1
 if znak == 1 than proc2
 else   
    ret :)

Niby w cm sa jeszcze inne procki, ale program chyba z nich nigdy nie korzysta.

Oki, czas  przejsc dalej  i zobaczyc  call'a przerabiajacego  nasza wartosc  do
64bit.

                mov     eax, ds:_wartosc        ; wartosc z seriala do eax
                cdq
                xor     eax, edx
                sub     eax, edx                ; drobne modyfikacje
                mov     [esp+4+var_4], eax
                fild    [esp+4+var_4]           ; wartosc na stos
                fld     ds:tbyte_4089FC         ; liczba Pi na stos
                fmulp   st(1), st               ; Pi * wartosc
                fstp    ds:tbyte_40B60C         ; zdejmij ze stosu

Oki, tu jak widac jeszcze kilka  modyfikacji i sprawa zajmuje sie koprocesor
( zeby widziec jak dzialaja instrukcje FPU, uzyj komendy  'wf' w sice ).  Nasza
wartosc zostaje  pomnozona przez  liczbe Pi  i zdjeta  ze stosu.  Co dalej? Jak
pamietasz zostalo porownanie.

                mov     edx, offset keyfile
_next2:
                fld     [ebp+arg_0]             ; nasza wartosc
                fld     tbyte ptr [edx]         ; wartosc z keys.dat
                fcompp  st(1), st               ; porownanie
                fnstsw  ax
                sahf
                jnz     short loc_408DA6        ; jezeli rowne to...
                mov     bl, 1                   ; zapisz w bl 1
loc_408DA6:
                add     edx, 0Ah
                dec     ecx
                jnz     short _next2            ; a jezeli nie, to sprawdz
                                                ; kolejna wartosc z pliku
                                                ; keys.dat

I tutaj porownanie naszej wartosci z wartosciami z pliku keys.dat. Jezeli  nasz
'key' nie jest rowny to ladowana jest koleja wartosc z pliku itd. Jak latwo sie
domyslec, gdy  nasza wartosc  nie bedzie  rowna zadnej  z wartosci  pobranych z
keys.dat to bad password.

Teraz warto sie zastanowic nad rozwiazaniem tego cm. Ja wpadlem na pomysl,  aby
wpisac wartosc generowana na  podstawie seriala bez 0  i 1, do pliku  keys.dat.
Wtedy  kazdy  serial,  ktory  nie zawiera  0  i  1  bedzie prawidlowy.  Takiego
rozwiazania  nie  przyjal jednak  autor  cm, wiec  trzeba  obliczyc serial  dla
orginalnego keys.dat.

Hmm...  Po kilku  chwilach wiemy,  ze ta  procka (  mieszjaca twoj  sn )  jest
nieodwracalna. Dlaczego? To  proste, jezeli nie  wiesz jaki jest  aktualny znak
sn, to skad bedziesz wiedzial  jakiej  odwroconej procki uzyc? Zobaczmy  jednak
jeszcze raz na charset. Wlasciwie crackme przyjmuje tylko 3 wartosci: 1, 0  lub
dowolny inny znak. Z tego wynika, ze, skoro liczba znakow s/n jest rowna 11,  a
liczba mozliwych  znakow do  wpisania to  praktycznie 3  ( bo  wszystkie znaki,
ktore nie sa 0 albo 1 traktowane  sa tak samo ), to liczba mozliwych  sn wynosi
3^11  = 177147.  Jak widac  zarabiscie malo.  Co wiec  mozna zrobic.  Tak, tak
spokojnie  mozesz  napisac  bruta.  Ja, jako  charset  dalem  0,  1  oraz  2  (
reprezentujace  pozostale liczby  ) i  wyszlo mi  ( po  kilku sekundach  ), ze
poprawny s/n to:

                                  22222122022

Oczywiscie teraz pod 2, mozemy wstawic dowolne  znaki, czyli prawidlowy  serial
to, np.  Tymon1xx0qE. Zdziwilo  mnie tylko  to, ze  brutal znalazl  tylko jedno
prawidlowe ustawienie 0 i 1 ( takie jak powyrzej ), dla ktorych wyliczana  jest
wartosc rowna pierwszej wartosci ladowanej  z keys.dat. Czyzby inne wartosci  z
tego pliku nie mialy rozwiazania? Odpowiedz jest prosta, albo spapralem  bruta,
albo to prawda :)

.No_I_kOniEc

Nastepne  crackme  padlo.  Teraz  z  latwoscia  mozna  napisac  juz  keymakera.
Wlasciwie  algorytm  wcale nie  byl  taki zly,  jednak  przy tak  malej  ilosci
mozliwych seriali wlasciwie kazde algo mozna pociagnac brutem. Jakby tak troche
to rozbudowac, wiecej mozliwych procek, jakies dodatkowe sprawdzenie. Jednak  i
tak  dluzej  by   zajelo  wyliczenie,  np.   poprawnego  hasha  MD5,   niz  tej
jednokierunkowej procki. Wada jednak takiego zabezpieczenia jest to, ze  jezeli
zarejestrowany user pusci serial do netu  to bye bye dolary :) Oki,  jak zawsze
na koniec: opinie i inne duperele slac na adres: tymon_crk@wp.pl

.Greetz

Zakonna, Ged_, Smola, Czajnick, Kwasek, Veneta, all people from HTBteam, AAoCG,
                                  Xt, UnderPL

 
