Zabezpieczenie prgramu przed kopiowaniem

WIDMO

Witam ze wzgledu na duze zaiteresowanie tematem zabezpieczenia programu przed kopiowaniem, postanowilem napisac WAM,to co ja zastosowalem w swojej aplikacji i co jak do tej pory zdalo egzamin :)

Najwazniejsze to zastanowic sie, jak by to mialo wygladac???
Ja uzylem tutaj metody, ktora porownuje serial dysku C: z serialem zapisanym w pliku. Zeby nie byc goloslownym zachecam WAS do zapoznania sie z ponizszymi instrukcjami. Wykonywanie ich krok po kroku pozwoli WAM poznac zasade dzialania i rozsadnie wykorzystac ten sposob.

Zasada dzialania jest taka :
Osobie ktora chce kupic (uzywac) twojego programu, dajesz jej swoj program do pobierania serialu z dysku C: serial ten bedzie dodatkowo zakodowany aby nie kojarzyl sie z niczym szczegolnym. Nastepnie ona przesyla ci zakodowany SERIAL. Ty zacierajac rece odkodowujesz go i zakodowujesz powiedzmy kluczem 10 i umieszczasz w pliku TEST.TXT plik ten umieszczasz na dysku C: nastepnie w programie ktory jemu wysylasz ustawiasz tez klucz na 10 i wysylasz mu APLIKACJE + PLIK (TEST.TXT) nazwy plikow oraz ich lokalizacja jest oczywiscie dowolna i zalezy od ciebie.
Osoba ktorej dlaes program otwiera GO i jesli znajduje sie plik to pobiera serial z jego kompa i porownuje z serialem z pliku jesli sie zgadza to program przechodzi w FULL VERSION jesli serial sie nie zgadza badz nie ma pliku to program przechodzi w SHAREWARE :) proba przeniesienia Twojej aplikacji razem z plikiem TEST.TXT na inny komputer nie zda egzaminu poniewaz bedzie inny serial dysku.

To cala geneza. wiem ze to dla niektorych proste zabezpieczenie, ale wierzcie zdaje egzamin. DODATKOWO mozesz wprowadzic timer badz co jakies wydarzenie w aplikacji by sprawdzal serial z oryginalem. np. przy nacisnieciu okreslonych buttonow :) itd

Program pierwszy pobiera i szyfruje serial pobrany od osoby ktora chce kupic nasz program.

wstaw
EDIT1
BUTTON1

W sekcji VAR wpisz:

  var
    dl_textu, nr, k : integer;
    zn : char;
    de, df : string;

...
...
...

implementation

{$R *.DFM}

function ID: string;
var
   VolumeSerialNumber : DWORD;
   MaximumComponentLength : DWORD;
   FileSystemFlags : DWORD;
   SerialNumber : string;
begin

  //zmien literke dysku na jaka tylko chcesz ;)

  GetVolumeInformation ( 'C:', nil, 0, @VolumeSerialNumber, MaximumComponentLength, FileSystemFlags, nil, 0 );
  SerialNumber := IntToHex( HiWord( VolumeSerialNumber ), 4 ) +  IntToHex( LoWord( VolumeSerialNumber ), 4 );
  Result := SerialNumber;
  form1.edit1.text := result;

end;


procedure TForm1.Button1Click(Sender: TObject);
begin
 
  k:=19;
  id;
  dl_textu := length( edit1.text );

  for nr := 1 to dl_textu do
  begin
    zn := edit1.text[ nr ];
    df := df + chr( ord( zn ) xor ord( k ) );
  end;

  for nr := 1 to dl_textu do
  begin
    zn := df [nr ];
    de := de + chr( ord( zn ) xor ord( k ) );
  end;

  if ( edit1.text = de ) then 
    form1.caption := 'status - OK'
  else
    df := df + '--';
    
  edit1.text := df;
  button1.Enabled := false;

end;

k:=19
to klucz wedlug ktorego przesowamy bity nazwijmy go KLUCZ KODOWANIA zazwyczaj bierz wartosci od 5 do 30 nie wieksze. Jesli zmienna 'df' po zakodowaniu i zdekodowaniu bedzie miala inne wartosci to jako serial na koncu dodane zostanie '--' czyli postac zakodowana serialu bedzie wygladala pzykladowo tak: 8I<6%379-- Dwie kreski na koncu oznaczaja blad. Przy xorowaniu podanie duzej liczby jako KLUCZA KODOWANIA w polaczeniu z niektorymi znakami moze spowodwoac blad podczas odkodowywania bledu wtedy nie mozemy uzyc takiego zabezpieczenia dlatego prosze o stosowanie wartosci z przexzialu 5..30 ;) to i tak nie ma wiekszego znaczenia dla bezpieczenstwa ktore jest w takim samym stopniu jak przy wartosci 5 jak i przy wartosci 25

Nastepny program bedzie odkodowywal serial przeslany od klienta zainteresowanego naszym programem.

wstaw
EDIT1,EDIT2,BUTTON1

w VAR dodaj

VAR
  nr, k : integer;
  zn : char;
  de : string;

...
...
...

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin

  k := strtoint( edit1.text );

  for nr := 1 to length( edit2.text ) do
  begin
    zn := edit2.text[ nr ];
    de := de + chr( ord( zn ) xor ord( k ) );
  end;

  edit2.text := de;
  de := '';

end;

I to wszystko. Po odpaleniu programu w edit 1 wpisujemy wartosc klucza jaka dales w poprzednim programie czyli 19 bo k:=19 i w edit2 wpisz serial ktory przeslal ci klient i wciskamy dekoduj mamy teraz jego oryginalny serial.
Nastepnie zmien sobie klucz kodowania na dowolny inny np: 10 i wcisnij znowu BUTTON1 Oryginalny serial zostanie zakodowany KLUCZEM 10 i taki serial wstaw do pliku TEST.TXT i plik ten umiesc na dysku C:

Ostatni program to twoja glowna aplikacja

dla przykladu w VAR wstaw

VAR
  plik : textfile;
  znak, zn : char;
  serial, de, dysknr : string;
  k, nr : integer;

wstaw label1, label2, label3, label4

wklej ponizszy kod


implementation

{$R *.DFM}

function ID: string;
var
   VolumeSerialNumber : DWORD;
   MaximumComponentLength : DWORD;
   FileSystemFlags : DWORD;
   SerialNumber : string;

begin

   // zmien literke dysku na jaka tylko chcesz ;)

   GetVolumeInformation( 'C:', nil, 0, @VolumeSerialNumber, MaximumComponentLength, FileSystemFlags, nil, 0 );
   SerialNumber := IntToHex( HiWord( VolumeSerialNumber ), 4 ) +  IntToHex( LoWord( VolumeSerialNumber ), 4 );
   Result := SerialNumber;
   dysknr := result;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin

  id;

  try

    assignfile( plik, 'C:/test.txt' );
    reset( plik );

    repeat
    begin
      read( plik, znak );
      serial := serial + znak;
    end
    until EOF( plik ) = true;

    except on EInOutError do
    begin

      form1.text := 'brak pliku';

      { ewentualnie dajecie
         demo:=true;
         wtedy oznacza to ze program dialac bedzie w wersji demo
         to juz wasza dowolna kombinacja
      }

      exit;

    end;

  end;

  de := '';
  k := 10; // pamietaj ten klucz wpisz taki jaki zakodowales oryginal 

  // w poprzednim programie :)

  for nr := 1 to length( serial ) do
  begin

    zn := serial[ nr ];
    de := de + chr( ord( zn ) xor ord( k ));

  end;

  form1.caption := de;
  label4.caption := dysknr;
  label1.caption := de;

  if (dysknr = de) then
    form1.caption := 'OK'

    { ewentualnie dajecie tu zamoast procedury
       np.   demo=flase  wylaczacie tu opcje programu demo
    }

  else
    form1.caption:='BUUU';

    { tutaj dajecie demo=true
       i wetdy prz y wykonywaniu opcji Jesli demo=true
       to wtedy opcja.enabled := false
      itd badz kierujecie do odpowiedniej procedury
    }

end;

Najwazniejsze to zebys pamietal jaki miales klucz ten kod sprawdza czy istnieje plik TEST.TXT na dysku C: jesli NIE istnieje program ustawia sie w tryb SHAREWARE ( czy DEMO) jesli plik istnieje nastepuje odczytanie seriala z dysku 'C' zakodowanego z pliku TEST.TXT serial ten jest odkodowany i porownywany z oryginalem jesli sie zgadzaja to program jest w FULL VERSION jesli nie to SHAREWARE (DEMO)

We wszytskich aplikacjach mozesz ustawic kodowanie klucza na wartosc okreslona i potem rozsylasz pliki z zakodowanym serialme do osob ktore zapalcily ci kase. np dajesz im demo jak nie zaplaca nie moga uzywac jak zaplaca to OK a ty nic nie tracisz. Mozesz dodawac fukcje destrukcji programu, lub losowo wybierac klucze kodowania mozna sporo dodac jescze roznych algorytmow nie tylk oxorowanie.

To wsyztsko co chcialem zaprezentowac. to szkielet procedury zabezpieczenia, moze to byc jeden z elementow zabezpieczen w Twojej aplikacji.

pamietaj KLUCZ KODOWANIA w programie glownym musi byc taki sam jak w programie ktorym go zakodowales:)

gotowe kody do pobrania:
pobierz gotowe kody

22 komentarzy

Bardzo ubogie. Gdyby ktoś wiedział jak to działa, mógłby skopiować ten plik i wysłać go razem z programem. Gdyby to miał być faktycznie nie do obejścia to ja bym zrobił tak, że skompilowałbym program z już wpisanym ip kompa, lub inną wartością która jest niezmienna (czyli unikatowa i nie da się jej zmienić).

Ja robię tak: program łączy się ze stroną www, skrypt php sprawdza ip i useragent, jeśli dobre pokazuje coś tam, potem to w programie sprawdza. Dodatkowo program jest pakowany upx i szyfrowanie moim EXE Protectorem. Dodatkowo jeśli program wykryje takie procesy jak np. DeFixed.exe, itp. to się zamyka.

To zabezpieczenie jest kiepskie. Może jakiś ExE Protector w połączeniu z tym byłby nie do rozbicia, ale na 'sucho', wystarczy tylko odczytać co jest w zmiennej K i już po zabezpieczeniu.

spoko wiem jak zabezpieczyc ale np jakbym miał taki program zabezpieczony przez kogoś to co trzeba zrobic ;> ?!

No dzieki, zes nam udostepnil swoja metode! ;)
Przejdz na cos lepszego niz txt i serial dysku c :)

Mówicie, że to łatwo złamać. Dobry Exe Protector i wszyscy leżycie [;
...ale mógł to bardziej namieszać, a nie tylko porównanie...

Mówicie, że to łatwo złamać. Dobry Exe Protector i wszyscy leżycie [;
...ale mógł to bardziej namieszać, a nie tylko porównanie...

literówka w naziwe arta, nieczytelnie napisane, zdania z małych liter i w ogóle jakoś mi się dziwnie czyta :|

Kod może ewentualnie służyć jako "crackme" dla początkujących crackerów, znalezienie seriala(SoftIce), edycja binarki(W32DSM, Hiev), czyli zmiana warunków lub nopowanie i po robocie całe 5 min! poczytaj sobie chociaż o podstawach crackingu! Już lepsze jest kodowanie seriala po nazwisku, przynajmniej nie trzeba prosić o nowy serial po formatce!

To jest fajne ale jezeli dobrze zrozumiałem wcześniej to najpierw pobiera volumin a po sformatowniu dysku volumin sie zmienia i program bedzie działał jako demo.
Lepszym zastosowaniem jest nagranie na cd programu i vol z cd ale to jest tez do przejscia

No może i dobry system, ale niestety zmiana dysku, czy wymiana kompa to spory problem. Z kolei szyfrowanie serialu z WWW i podanie loginu i hasła to nonsens. Ktoś udostępni swoje hasło i już każdy będzie mógł sobie wygenerować. Poza tym - tak jak pisał Marooned. Pojedyncze porównanie to pestka dla cracera. Jakbym się przyłożył, może samemu bym taki programik potrafił scracować, mimo, że moja wiedza na temat ASM'a jest niewielka...

Fajna sprawa tylko zamienisz przy jednym ofsecie jakas wartosc na 90 i juz porownanie bedzie "dobre" i program sie uruchamia ...

a dlaczego offset 40 ???

Pozostaje właśnie wspomniany poroblem, że kod trzeba znowu generować po zmianie dysku... Choć można by generowanie zrobić w PHP i udostępniać na stronie WWW (np. po podaniu loginu i hasła)...

Ogólnie pomysł z serialem nie jest głupi, bo nawet skuteczny, ale ja osobiście nawet jak miałbym taki legalnie to bym poszukał cracka - wątpie by potencjalna firma była na tyle miła, że po zmianie dysku twardego bez żadnych opłat by jeszcze raz wygenerowała numer itd.

Marooned ma rację - funkcja powinna być trochę bardziej zawiła, gdyż jedno porównanie na dodatek rozkodowanych seriali to... może nie tyle prosta, co nie-dość-czasochłonna zabawa.

aha - mam nadzieję, ze nazwa pliku to tylko taki przykład ;] inna sprawa, że dzięki programom takim jak choćby Ashampoo Uninstaller namierzy się każdy plik - lepiej zatem np. wydac wersję programu bundled do choćby dyskietki, albo płyty CD odpowiednio nagranej [funkcja sprawdzałaby dane na płycie jak i jej numer ]

Hm.. choć w zasadzie wszystko da się scrackować - kwestia chęci i czasu :)

troche nagmatwane :)

if dysknr=de then form1.caption:='OK'....

tego typu porównania sprawiają, że cały wysilek idzie na marne... Jak chcesz mieć dobre zabezpieczenie, to musisz np. użyć seriala jako danej jakiejś funkcji, a nie tylko do porównania.

przecież masz możliwość poprawy - na dole ołówek przy Twoim nicku.

to nie ejst dla oceny tylko dla was. napisalem soobie tak i myslalem ze jak wcisne DODAJ bede mial mozliwosc poprawy bo chcialem TAGI i pogrubione elementy ale niec z tego :(

Zapomnialem dopisac ze program dodatkowo mozna zabezpeieczyc sprawdzeniem sumy kontrolnej :)

nie wiem kto to na piątke ocenił ale używaj tagów i wcięć