Terminal Overdrive 98 by emo

Required tools: Numega's Softice 3.xx
                W32Dasm 8.9 
                Mlotek, przecinak i obcegi ;)

Dzien Dobry! Na dzisiejszych zajeciach dowiemy sie czegos o Terminal Overdrive 98. Jest to program reklamowany jako 'Internet accelerator'. Mozna go spotkac na plycie ze stycznia 1999 magazynu PC World Computer lub pod URL: http://www.digitalrobotics.com Jest to przypadek dosc ciekawy, poniewaz jest to wersja 15-dniowa programu i nigdzie nie ma informacji o tym, ze mozna go zarejestrowac. Dopiero po 15 dniach od zainstalowania (lub po przestawieniu zegara systemowego ;-) po uruchomieniu komputera pojawia sie na ekranie okno :

'The trial period has ended. Please register this software!'

Po czym pojawia sie nastepne:

Please enter the unlock information
Name:
Company Name:
Unlock Code:

Musze sie przyznac, ze nie mialem zbytniej ochoty zajmowac sie tym przypadkiem, ale pewna sprawa poruszyla mnie do zywego. Po wpisaniu falszywych danych wyskoczylo okienko z nastepujaca trescia: 'Would you like to keep using Terminal Overdrive 98?' Po wcisnieciu OK program sie odinstalowal, i zdazyl zakomunikowac: 'Please contact www.digitalrobotics.com', a w dodatku prawie zawiesil mi komputer. (ALT+CTRL+DEL i po 20 sek. pomoglo). Tego juz za wiele! Zrobimy tu 'total unlock code reverse', napiszemy KeyGenerator, a nastepnie wyslemy do DigitalRobotics!

Oczywiscie nie zrobilem tego ostatniego, chociaz bardzo mnie korcilo ;)

Tak jak w poprzednim tutorialu, nie powiem Wam dokladnie co macie robic, a jedynie wyjasnie jak moze wygladac kod przy 'paper protection' (Nie moge sie uwolnic od angielskiego, sorry :)))

Zaczynamy: Po zalozeniu 'bpx Hmemcpy' (nie dziala nic innego) doszedlem do nastepujacego kawalka kodu:

0137:0049FC12  8B45FC              MOV     EAX,[EBP-04] <-- Twój 'unlock code'
0137:0049FC15  E82E3CFDFF          CALL    00473848     <-- ile znaków?
0137:0049FC1A  83F80E              CMP     EAX,0E       <-- porównaj z 0Eh=14
0137:0049FC1D  0F8CEA000000        JL      0049FD0D     <-- mniej = bye, bye
0137:0049FC23  8D55E8              LEA     EDX,[EBP-18]
0137:0049FC26  8B45FC              MOV     EAX,[EBP-04]
0137:0049FC29  E8C268FDFF          CALL    004764F0
0137:0049FC2E  8B55E8              MOV     EDX,[EBP-18]
0137:0049FC31  8D45FC              LEA     EAX,[EBP-04]

Wiemy, ze 'unlock code' musi sie skladac conajmniej z 14 cyfr/liter... to juz cos!

BTW. 1: Na pytanie 'Would you keep using...' zawsze odpowiadaj NIE, wtedy program sie nie odinstaluje (swoja droga, podchwytliwie sformulowane ;)

2:W32Dasm'a uzyjesz tylko wtedy, gdy przestawisz date systemowa i program nie bedzie chcial sie uruchomic (jeden jnz zalatwi sprawe...)

Patrzcie na ten trick:

0137:0049FC54  B901000000          MOV     ECX,00000001
0137:0049FC59  BA02000000          MOV     EDX,00000002
0137:0049FC5E  E8293EFDFF          CALL    00473A8C
0137:0049FC63  8D45FC              LEA     EAX,[EBP-04]
0137:0049FC66  B901000000          MOV     ECX,00000001
0137:0049FC6B  BA04000000          MOV     EDX,00000004
0137:0049FC70  E8173EFDFF          CALL    00473A8C
0137:0049FC75  8D45FC              LEA     EAX,[EBP-04]
0137:0049FC78  B901000000          MOV     ECX,00000001
0137:0049FC7D  BA04000000          MOV     EDX,00000004
0137:0049FC82  E8053EFDFF          CALL    00473A8C
0137:0049FC87  33C0                XOR     EAX,EAX
0137:0049FC89  8AC3                MOV     AL,BL 

Powiedzmy, ze jako Unlock Code wpiszesz '123456789abcdef'. Powyzsze 3 CALLs przeksztalcaja go na '134789abcdef' - zniknela 2, 5 i 6 litera. Co to za obyczaje? Patrz ponizej, co robi z druga i piata litera:

0137:0049FC87  33C0                XOR     EAX,EAX        <-- czysc EAX
0137:0049FC89  8AC3                MOV     AL,BL          <-- druga litera
0137:0049FC8B  83E841              SUB     EAX,41         <-- odejmij od niej 41
0137:0049FC8E  6BC01A              IMUL    EAX,EAX,1A     <-- mnozymy
0137:0049FC91  33D2                XOR     EDX,EDX        
0137:0049FC93  8A55EF              MOV     DL,[EBP-11]    <-- piata litera
0137:0049FC96  83EA41              SUB     EDX,41         <-- odejmowanie
0137:0049FC99  03C2                ADD     EAX,EDX        <-- dodaj wynik z 49fc8e
0137:0049FC9B  8B5508              MOV     EDX,[EBP+08]
0137:0049FC9E  8902                MOV     [EDX],EAX
0137:0049FCA0  33DB                XOR     EBX,EBX
0137:0049FCA2  8D55F0              LEA     EDX,[EBP-10]
0137:0049FCA5  A184574A00          MOV     EAX,[004A5784]
0137:0049FCAA  E84168FDFF          CALL    004764F0 

Na co i po co? A co z szósta litera? Jesli chcesz sie dowiedziec, czytaj dalej... A raczej obserwuj kod ;)

0137:0049FCD9  8B45E4              MOV     EAX,[EBP-1C]
0137:0049FCDC  8D4DE8              LEA     ECX,[EBP-18]
0137:0049FCDF  8BD3                MOV     EDX,EBX
0137:0049FCE1  E8BA070000          CALL    004A04A0
0137:0049FCE6  8B55E8              MOV     EDX,[EBP-18]        <-- twój szczerbaty kod :-)
0137:0049FCE9  8B45FC              MOV     EAX,[EBP-04]        <-- poprawny szczerbaty kod
0137:0049FCEC  E8673CFDFF          CALL    00473958            <-- porównaj...
0137:0049FCF1  7506                JNZ     0049FCF9            <-- czyzby rózne?!?
0137:0049FCF3  8B45F4              MOV     EAX,[EBP-0C]
0137:0049FCF6  C60001              MOV     BYTE PTR [EAX],01
0137:0049FCF9  8B4508              MOV     EAX,[EBP+08]        <-- (*)
0137:0049FCFC  833800              CMP     DWORD PTR [EAX],00
0137:0049FCFF  750C                JNZ     0049FD0D
0137:0049FD01  807DEE43            CMP     BYTE PTR [EBP-12],43<-- (**)
0137:0049FD05  7406                JZ      0049FD0D
0137:0049FD07  8B45F4              MOV     EAX,[EBP-0C]
0137:0049FD0A  C60000              MOV     BYTE PTR [EAX],00
0137:0049FD0D  33C0                XOR     EAX,EAX             

Ten 'szczerbaty' kod to twój 'unlock code' bez drugiej, piatej i szóstej litery... Bardzo wazna jest linia (*). Porównywana jest wartosc w EAX i 0. Gdy nie sa sobie równe, a szczerbaty kod sie zgadza, twój 'unlock code' jest tzw. 'extended evaluation'- mozesz korzystac dluzej z programu, ale nie jest to wersja w pelni zarejestrowana. W EAX znajduje sie wynik operacji na drugiej i piatej literze, co jest opisane powyzej... Trzeba sie zastanowic, jakie maja byc wartosci tych liter.

Nic trudnego, wymyslilem to po 3 sekundach... przedstawie to jeszcze raz:

Niech x=2 litera, y=5 litera:

      1.x-41h  = z
      2. y-41h=n
      z*z*1a = m            

Z 1 i 2 'm+n' musi sie równac 0. Najprosciej gdy m i n sa równe 0... zatem: x=41h i y=41h. 41h jest symbolem litery 'A', wiec 2 i 5 litera zawsze beda 'A' - mam nadzieje, ze zrozumieliscie :-)

Linia (**) sprawdza, czy szósta litera to 'C' (a wiec tu to schowali...)

Teraz zajmiemy sie procedura kodujaca: (to bedzie jeszcze trudniejsze) :->

Oto I-sza czesc:

0137:004A04DB  8D45F4              LEA     EAX,[EBP-0C]
0137:004A04DE  33D2                XOR     EDX,EDX
0137:004A04E0  8AD3                MOV     DL,BL             
0137:004A04E2  8B4DFC              MOV     ECX,[EBP-04]
0137:004A04E5  8A5411FF            MOV     DL,[EDX+ECX-01]  <-- kolejne litery twojego Name
0137:004A04E9  0FB7CE              MOVZX   ECX,SI           
0137:004A04EC  C1E908              SHR     ECX,08
0137:004A04EF  32D1                XOR     DL,CL
0137:004A04F1  E87A32FDFF          CALL    00473770
0137:004A04F6  8B55F4              MOV     EDX,[EBP-0C]
0137:004A04F9  8BC7                MOV     EAX,EDI
0137:004A04FB  E85033FDFF          CALL    00473850
0137:004A0500  33C0                XOR     EAX,EAX
0137:004A0502  8AC3                MOV     AL,BL
0137:004A0504  8B17                MOV     EDX,[EDI]
0137:004A0506  0FB64402FF          MOVZX   EAX,BYTE PTR [EAX+EDX-01]
0137:004A050B  6603F0              ADD     SI,AX
0137:004A050E  6669C603D9          IMUL    AX,SI,D903
0137:004A0513  6605672B            ADD     AX,2B67
0137:004A0517  8BF0                MOV     ESI,EAX
0137:004A0519  43                  INC     EBX
0137:004A051A  FE4DFB              DEC     BYTE PTR [EBP-05]
0137:004A051D  75BC                JNZ     004A04DB

Bede sie streszczal:

1. si=016Ch (jest jedno przeliczenie wczesniej na podstawie stalego ciagu liczb A7B9C6) (wskazówka - dodaj hexy...)

2. mov dl,[EDX+ECX-01]; w przypadku Name: MateMagik, najpierw 'M', potem 'a' itd.

3. mov ecx, si;

4. shr ecx,08;

5. xor cl,dl = A;

6. A + si = B;

7. A * B * D903 + 2B67 = C;

8. goto 1 - w SI sa wstawiane kolejne wartosci C

W moim przypadku z "MATEMAGIK'99" (c) ;) normalnie w postaci hex'owej:

4d,41,54,45,5d,41,47,49,4b,27,39,39 powstalo4c,69,8a,fd,bd,06,06,5a,3b,c1,31,b7 <-- nazwijmy to 'abecadlo'

A oto II czesc - kilkanascie procedur dalej :->

0137:004A0403  33DB                XOR     EBX,EBX
0137:004A0405  8A5C02FF            MOV     BL,[EAX+EDX-01] <-- podobnie jak wyzej, brana jest
0137:004A0409  C1EB04              SHR     EBX,04              po kolei litera z 'abecadla' 
0137:004A040C  80C331              ADD     BL,31           
0137:004A040F  80FB39              CMP     BL,39        
0137:004A0412  7603                JBE     004A0417
0137:004A0414  80C307              ADD     BL,07
0137:004A0417  8D45F4              LEA     EAX,[EBP-0C]   ; niewazne
0137:004A041A  8BD3                MOV     EDX,EBX; tu jest tylko przepisywanie
0137:004A041C  E84F33FDFF          CALL    00473770      ; kodu do innych obszarów
0137:004A0421  8B55F4              MOV     EDX,[EBP-0C]; pamieci
0137:004A0424  8BC6                MOV     EAX,ESI; nie interesuje nas to
0137:004A0426  E82534FDFF          CALL    00473850; przeciez ....
0137:004A042B  33C0                XOR     EAX,EAX;
0137:004A042D  8A45FB              MOV     AL,[EBP-05]
0137:004A0430  8B55FC              MOV     EDX,[EBP-04]
0137:004A0433  8A5C02FF            MOV     BL,[EAX+EDX-01]
0137:004A0437  80E30F              AND     BL,0F
0137:004A043A  80C331              ADD     BL,31
0137:004A043D  80FB39              CMP     BL,39
0137:004A0440  7603                JBE     004A0445
0137:004A0442  80C307              ADD     BL,07
0137:004A0445  8D45F4              LEA     EAX,[EBP-0C]
0137:004A0448  8BD3                MOV     EDX,EBX
0137:004A044A  E82133FDFF          CALL    00473770
0137:004A044F  8B55F4              MOV     EDX,[EBP-0C]
0137:004A0452  8BC6                MOV     EAX,ESI
0137:004A0454  E8F733FDFF          CALL    00473850
0137:004A0459  FE45FB              INC     BYTE PTR [EBP-05]
0137:004A045C  807DFB07            CMP     BYTE PTR [EBP-05],07 <-- juz 7 liter?
0137:004A0460  7599                JNZ     004A03FB

Znowu sie streszczam - tym razem kazda litera 'abecadla' jest przerabiana dwukrotnie, powyzej siódmej litery Name jest bez znaczenia - równie dobrze moge wpisac: Name : MateMagik'99 lub Name : Matemagik ma sie dobrze ;)

Schemat :

1. mov bl, Z; gdzie Z to kolejna litera 'abecadla'

2. shr ebx,04;

3. add bl, 31h;

4. if bl > 39h then bl=bl+9;

5. bl = X;

6. mov bl, Z;

7. and bl, 0fh;

8. add bl, 31h;

9. if bl > 39h then bl=bl+9;

10. bl = Y;

11. goto 1

Powinien powstac kod postaci: XYXYXYXYXY..., który jest niczym innym, jak szczerbatym, poprawnym 'Unlock Code', który ostatecznie powinien miec postac:

      X  A  Y  X  A  C  X  Y  X  Y  X  Y  X  Y
        _  _  _  _  _  _  _  _  _  _  _  _  _  _  

np.   1  A  2  3  A  C  5  6  7  8  9  8  7  6

No, to juz chyba wszystko, co powinno wystarczyc do napisania KeyGeneratora. Na koncu znajdziecie listing procedury w Delphi. Nie jest to zbyt dobry sposób, bo program wyjdzie ok.200kb, podczas gdy w assemblerze ok.4kb. Trzeba sie tylko tego nauczyc :-) Delphi jest zreszta 'user friendly' i mozna go latwo zrozumiec.

Jak widzicie, opisywany program jest doskonalym przykladem tego, ze nie zawsze znajdziesz porównanie eax, ebx i to wystarczy... Tutaj usunieto kilka liter, które sa sprawdzane pod koniec, ale widzialem juz wieksze manewry (o ile dobrze pamietam, spróbuj WEBZipa, wygenerowanie numeru zajelo mi troche czasu...)

Nie zawsze nalezy sie poddawac i robic od razu patch'a - ja stosuje to tylko w ostatecznosci.

Trzeci sposób to zrobienie pliku 'x.reg', na przyklad tego: ;)

REGEDIT4

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OptionalComponents\ClipBrd]
@="Ēüé:gk?jmlEoutsvCJlōöLlSsÖÜTtL×cįķóśAaŽžEeyÄóö}lÖtc\\opĀES¦»cózLÄ"

dzieki któremu program jest automatycznie zarejestrowany... Widzicie teraz co mozna zrobic, gdy jakis program was zdenerwuje ;) Ja mialem prawdopodobnie wersje BETA i dlatego musialem walczyc, aby nie zawiesilo mi komputera. Odwiedzilem ostatnio specjalnie strone www.digitalrobotics.com i sciagnalem najnowsza wersje - wszystko dziala nadal.

Mam nadzieje, ze czegos sie nauczyles, a jezeli nie, to nic nie szkodzi - teoria teoria, tylko praktyka czyni mistrza.

<<EMO>>emo@viper.pl

!UWAGA - Tekst powstal tylko w celach edukacyjnych i autor nie ponosi odpowiedzialnosci za szkody wynikle z niewlasciwego stosowania porad tu zamieszczonych. W przypadku uzywania programu przez dluzszy czas nalezy go zarejestrowac.

Greetings : Sir_THomasRE, Monter, MAX, CrackPL za inspiracje

A oto i KeyGen. Moze nie byc zrozumialy, bo uzywalem wstawek w assemblerze i dziwnych oznaczen, ale dziala...

procedure TForm1.button1click(Sender: TObject);
var   si,eax,ebx,dl,ter,numer:longint;
                     rd,dobrze:byte;
                         temp:dword;
                        temp2:word;
   comp,     name,sn,wynik,wynik2:string;
                          i,j:byte;

begin
  name:=edit1.text;
  comp:=edit2.Text;
  name:=uppercase(name);
     j:=1;
    sn:='                  ';
 wynik:='                  ';
wynik2:='                  ';
  temp:=$016c;
 for i:= 1 to length(name) do
begin;
      rd:=ord(name[i]);
      ter:=temp;
      temp:=temp shr $08;
      asm
      mov eax, temp
      mov dobrze, al
      end;
      numer:=dobrze xor rd;
      sn[i] := chr(numer);
      temp:=ter;
      asm
      xor eax, eax
      mov eax, numer
      mov ecx, temp
      add cx, ax
      imul al,ecx,$d903
      mov temp, eax
      end;
      temp:=temp+$2b67;
      temp2:=temp;
      asm
      mov ax, temp2
      mov temp2, ax
      end;
      temp:=temp2;
      end;
 {------------------------------part2------------------}
 si:=1;
 for i:=1 to 6 do
     begin;
     dl:=ord(sn[i]);
     eax:=dl shr $04;
     ebx:=eax+$31;
     if ebx > $39 then ebx:=ebx+7;
     wynik [si] := chr(ebx);
     si:=si+1;
     eax:=dl and $f;
     ebx:=eax+$31;
     if ebx > $39 then ebx:=ebx+7;
     wynik[si]:=  chr(ebx);
     si:=si+1;
     end;
     { ----------- teraz dodamy 2,5 i 6 litere -------- }
     for i:=1 to 12 do
     begin;
     dl:=ord(wynik[i]);
     wynik2[j]:=chr(dl);
     if j=1 then begin; j:=j+1; wynik2[j]:=chr(65); end;
     if j=4 then begin; j:=j+1; wynik2[j]:=chr(65); end;
     if j=5 then begin; j:=j+1; wynik2[j]:=chr(67); end;
     j:=j+1;
     end;
     edit3.text:= sn;
     edit4.text:= wynik2;
end;