------------------------------------------------------------------------
              Szyfrowanie danych by bEANUS^CookieCrK
-----------------------------------------------------------------------

Szyfrowanie jest doskonalym sposobem ochrony informacji przed
zinterpretowaniem
ich przez osoby niepowolane.

Rodzaje szyfrow:
* szyfry przestawieniowe
* szyfry podstawieniowe (monograficzne,polialfabetyczne)
* zlozenie szyfrow podstawieniowych polialfabetycznych
* szyfry oparte na generatorach pseudolosowych
* szyfry oparte na roznicy symetrycznej

Legenda:
A - alfabet - zakladamy ['A'...'Z'] czyli 65-106 ASCII + spacja '_'
A* - skonczony lancuch z alfabetu A

                     Czyli prosta metoda
                        F:A*xA*=>A*
przyporzadkowujaca lancuchowi do zaszyfrowania i kluczowi lancuch
zaszyfrowany.

I.Szyfr przestawieniowy - idea tego jest bardzo prosta.Text zaszyfrowany
jest permutacja textu wejsciowego.
W lancuchu zaszyfrowanym znaki zmieniane zostaja w pewien okreslony
sposob.
* przyklad     OSIOLKOWI_W_ZLOBIE_DANO_W_JEDNYM_OWIES_W_DRUGIM_SIANO
lancuch zaszyfrowany bedzie wygladal tak:
               ONAIS_MIGURD_W_SEIWO_MYNDEJ_W_ONAD_EIBOLZ_W_IWOKLOISO
Innym sposobem szyfrowania mozy byc zamiana parami liter k i k+1 ( gdzie
k jest
liczba nieparzysta).Jezeli lancuch ma nieparzysta dlugosc, to ostatni
znak
pozostaje na pierwotnym miejscu czyli:
               SOOIKLWO_I_WLZBOEID_NA_O_WEJNDMYO_IWSEW_D_URIG_MISNAO
Mozna rowniez stworzyc szyfr przestawieniowy, ktory bedzie zmienial
kolejne grupy trzyznakowe wedlug permutacji

                         ( 1 2 3 )
                         ( 2 3 1 )

Jezeli dlugosc slowa nie jest podzielna przez 3, to ostatnie znaki, w
ilosci
rownej reszcie z dzielenia, pozostaja na swoich miejscach - czyli
               SIOLKOWIW__LOZIEBDA_O_N_JWDNEM_YWIOS_E_DWUGRM_IIASNO
Oto program:
function Szyfruj(Tekst:string):string;
var strpom:string;
i:byte;
begin
strpom:='';
for i;=length(tekst) downto 1 do
strpom:=strpom + tekst[i] ;
szyfruj:=strpom;
end;

function szyfruj_2(tekst:string):string;
var strpom:string;
i:byte;
begin
strpom:='';
for i;=1 to length(tekst) div 2 do
strpom:=strpom+tekst[2*i] + tekst[2*i-1];
if length(tekst) mod 2 ) <> 0 then
strpom:=strpom+tekst[length (tekst)];
szyfruj_2:=strpom;
end;

II. Szyfry podstawieniowe.
1. dzielimy na :
* szyfry monograficzne
* szyfry polialfabetyczne
Cala idea tych szyfrow polega na tym, iz kazda litera alfabetu jest
zamieniana
na podstawie pewnego klucza na inna.Sposob zamiany moze byc funkcja
litery
szyfrowanej i klucza, lub tez litery szyfrowanej, jej pozycji w lancuchu
i klucza

a) szyfr monograficzny
- mamy alfabet ABCDEFGHIJKLMNOPQRSTUVWXYZ_
Przeciwdzieczina tej funkcji bedzie pewna permutacja tego zbioru:
               _QWERTYUIOPASDFGHJKLZXCVBNM
               W ten sposob otzymujemy przporzadkowanie wzajemne
jednoznaczne, zwanej dalej kluczem
               Nasz klucz to :
               ABCDEFGHIJKLMNOPQRSTUVWXYZ_
               _QWERTYUIOPASDFGHJKLZXCVBNM

        Nasza wiadomosc , ktora bedziemy szyfrowali :
        OSIOLKOWI_W_ZLOBIE_DANO_W_JEDNYM_OWIES_W_DRUGIM_SIANO
Robi sie t w taki sposob, ze w dziedzinie klucza szuka sie kolejnych
liter i do
tekstu zaszyfrowanego przepisuje sie ich odpowiedniki  z
przeciwdziedziny.
I wynik tej operacji:
              FKIFAPFCIMCMNAFQIRME_DFMCMOREDBSMFCIRKMCMEJZYISMKI_DF
Aby moc odszyfrowac ta wiadomosc nalezy stworzyc funkcje odwrotna do
klucza, czyli:

                KluczOdwrotny(Klucz(Haslo))=Haslo
gdzie
Haslo - szyfrowany tekst ['A'...'Z']
Klucz - funkcja szyfrujaca wzajemnie jednoznaczna , ktorej dziedzina
jest alfabetA
KluczOdwrotny - funk.deszyfrujaca,czyli
               ABCDEFGHIJKLMNOPQRSTUVWXYZ_
               LYWNDOPQIRST_ZJKBEMFHXCVGUA
Powstaje ona przez zmiane dziwdziny i przeciwdziedziny klucza , z
pozostawionymi
wszystkimi powiazaniami.

const liczbaznakowalfabetu=27;
type typalfabetowy=array [1...liczbaznakowalfabetu] of char;
const
alfabet:typalfabetowy=('A','B','C','D','E','F','G','H','I','J','K','L'
,'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ');
klucz:typalfabetowy = ('
','Q','W','E','R','T','Y''U','I','O','P','A','S','D','F'
,'G','H','J','K','L','Z','X','C','V','B','N','M');

Teraz funkcja szukajaca pozycje znaku

function kpos(c:char;t:typalfabetowy):integer;
var i:word;
begin
kpos:=0;
for i:=0 to sizeof(t) do
if t[i];=c then kpos;=i;
end;
procedure kluczodwrotny(var k:typalfabetowy);
var i:byte;
begin
for i:=1 to liczbaznakowalfabetu do
k[i]:=alfabet[kpos (alfabet[i],klucz)];
end;

Oto funkcja szyfrujaca i deszyfrujaca:

function szyfr(tekst:string;klucz:typalfabetowy):string;
var
strpom:string;
i:byte;
begin
strpom:='';
for i;=1 to length(tekst) do
strpom:=strpom +klucz [kpos (tekst[i],alfabet)];
szyfr:=strpom;
end;

Wada tego szyfru:
* mozna odkryc powiazania miedzy literami (funkcje szyfrujaca) dzieki
analizie wystepowania
poszczegolnych znakow w tekscie zaszyfrowanym
b) szyfr polialfabetyczny
Alfabet pozostaje taki jak w poprzednim przykladzie.Okreslamy na
alfabecie
dzialanie zwane dodawaniem znakow.
    Jezeli Poz(C) okresla pozycje znaku C w alfabecie to
     C1= C2 + C3 <=> Poz(C1)=((Poz(C2)+Poz(C3)-1) Mod
LiczbaZnakowAlfabetu+1

Teraz odejmowanie:
     C1= C2 - C3 <=> Poz(C2)-Poz(C3)+LiczbaZnakowAlfabetu-1) Mod
LiczbaZnakowAlfabetu+1
czyli nad naszym przykladowym alfabetem:
A+B=C  => Poz(A)=1  , Poz(B)=2   Poz(C)=3  (1+2-1)+1=3     , 3  Mod
27+1=3
X+Z=W  => Poz(X)=24 , Poz(Z)=36  Poz(W)=23 (24+26-1)=49    , 49 Mod
27+1=23
C-B=A  => Poz(C)=3  , Poz(B)=2   Poz(A)=1  (3-2+27-1)=27   , 27 Mod
27+1=1
W-X=Z  => Poz(W)=23 , Poz(X)=24  Poz(Z)=26 (23-24+27-1)=25 , 25 Mod
27+1=26

Niech bedzie dany tekst do szaszyfrowania C1 C2 C3 ... Cn i klucz H1 H2
H3 ...Hn
Kazdej literze Ci tekstu przyporzadkowujemy litere klucza Hj taka, ze
                           i=(j-1) Mod m+1
Szyfrowanie:

Dla kazdej litery Ci ciagu wykonywujemy dzialanie Ki= Ci + Hj
Otrzymamy nowy ciag Ki (i=1..n) bedacy zaszyfrowanym ciagiem Ci

Deszyfrowanie:
Dla kazdej litery zaszyfrowanego tekstu: K1 K2 K3 ... Kn wykonywujemy
dzialanie
                              Ci=Ki - Hj
Otrzymamy ciag Ci (i=1..n) jest zdeszyfrowany ciagiem Ki
                             Oto przyklad:

       OSIOLKOWI_W_ZLOBIE_DANO_W_JEDNYM_OWIES_W_DRUGIM_SIANO

                             Klucz : GLOD
Szyfrowanie:
   OSIOLKOWI_W_ZLOBIE_DANO_W_JEDNYM_OWIES_W_DRUGIM_SIANO
 +
   GLODGLODGLODGLODGLODGLODGLODGLODGLODGLODGLODGLODGLOD
  -------------------------------------------------------
   WDXSTWC_QLKDFXCEQQOGIZCDDLYILZMQG_KMMDO_GPEYPUAP_UPRW

Deszyfrowanie:
   WDXSTWC_QLKDFXCEQQOGIZCDDLYILZMQG_KMMDO_GPEYPUAP_UPRW
 -
   GLODGLODGLODGLODGLODGLODGLODGLODGLODGLODGLODGLODGLOD
  --------------------------------------------------------
   OSIOLKOWI_W_ZLOBIE_DANO_W_JEDNYM_OWIES_W_DRUGIM_SIANO

Program:
const LiczbaZnakowAlfabetu=27;
LiczbaZnakowKlucza=4;
type
TypAlfabetowy = Array [1..LiczbaZnakowAlfabetu] of Char;
TypKluczowy   = Array [1..LiczbaZnakowKlucza] of Char;
const
Alfabet : TypAlfabetowy=('A','B','C','D','E','F','G','H','I','J','K','L'

,'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ');
Klucz   : TypKluczowy = ('G','L','O','D');

function Dodawanie (C1,C2:char):char;
begin
Dodawanie:=Alfabet [(Kpos (C1,Alfabet) + KPos(C2,Alfabet) -1 ) Mod
LiczbaZnakowAlfabetu +1];
end;

function Odejmowanie (C1,C2:char):char;
begin
Odejmowanie:=Alfabet [(KPos (C1,Alfabet) - KPos(C2,Alfabet) +
LiczbaZnakowAlfabetu -1) Mod LiczbaZnakowAlfabetu +1];
end;

function szyfruj(lancuch:string):string;
var strpom:string;
i:byte;
begin
strpom:='';
for i:=1 to length(lancuch) do
strpom:=strpom + Dodawanie(Lancuch [I] , Klucz [(I-1) Mod SizeOf(Klucz)
+1);
szyfrowanie:=strpom;
end;

function deszyfruj(lancuch:string):string;
var
   strpom:string;
   i:byte;
    begin
strpom:='';
for i:=1 to length(lancuch) do
strpom:=strpom + Odejmowanie(Lancuch [I] , Klucz [(I-1) Mod
SizeOf(Klucz) +1);
szyfrowanie:=strpom;
end;

Zalety:
* prosta analiza szyfru czestotliwosci wystepowania liter ani grup liter
nic nie da
Szyfr dla tych samych liter daje rozne wyniki w zaleznosci od ich
pozycji.Im
dluzsze slowo kluczowe tym szyfr jest trudniej zlamac

c) szyfry oparte na generatorach liczb pseudolosowych
Generator liniowy: produkuje on ciag liczb losowych T1...Tm .. przy
pomocy
funkcji rekurencyjnej;
                        Ti+1:=(aTi+c) Mod m.
przy ustalonej wartosci poczatkowej T1.Liczby a i c to stale.Jako m
wezmy
liczbe znakow naszego alfabetu.Zostalo udowodnione, ze ciag ma okres
m (czyli najdluzszy z mozliwych) <=>
1. c jest nieparzyste
2. a mod 4 =1
3. m jest potega dwojki

Gdy m nie jest potega dwojki otrzymujemy klucze o krotszych okresach.
Alfabet, ktory bedzie wykorzystany w praktycznych zastosowaniach to
znaki ASCII (0..255)
Jego moc jest potega dwojki.Bedziemy wiec otzymywac klucze o dlugosci
256 , rozne
w zaleznosci od pierwszej litery szyfrowanego tekstu.

Jest wiele metod wyboru odpowiednich wartosci a , c i T1.Jedna z nich
moze byc:
1. Jako T1 przyjmuje sie pierwsa litere szyfrowanego tekstu
2. Jezeli pierwsza litera zaszyfrowanego tekstu ma kod neiparzysty,
przyjmujemy
go jako c. W przeciwnym razie za pomoca dosolnej funkcji rekurencyjnej
tworzymy ciag S2...Si,
az do uzyskania pierwszej liczby nieparzystej.Jako pierwszy wyraz ciagu
S obieramy pierwsza
liczbe ciagu
3. Liczbe a obieramy tak, by byla to pierwsza liczba , ktora podzielona
przez
4 taje reszte 1 , wieksza od c. Jezeli jest wieksza od m , obieramy
pierwsza
liczbe mniejsza od c i podzielna przez 4 z reszta 1.Poniewaz prze
podstawieniu
polialfabetycznym, przy kluczu zdefinowanym jako ciag T1...Ti (Ti
ostatnia nie
powtorzona litera) , pierwsza litera nie ulega zmianie, wiec funkcja
deszyfrujaca potrafi bez klopotu odnalez klucz.

Program:
const LiczbaZnakowAlfabetu=32;
type
TypAlfabetowy = Array [1..LiczbaZnakowAlfabetu] of Char;
const
Alfabet : TypAlfabetowy=('A','B','C','D','E','F','G','H','I','J','K','L'

,'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ');

procedure Klucz (pierwszaL :Char,var K:TypAlfabetowy );
var M,C,A,I,j:Byte;
    Cpom:Char;
    begin
    FillChar (K,SizeOf(K) , #0);
    M:=LiczbaZnakowAlfabetu;
    K[1]:=PierwszaL;
    C:=KPos (PierwszaL,Alfabet);
    J:=2;
    if not Odd(C) then
    if C+1<=M then C:=C+1 else C:=C-1;
    if ((C div 4 ) +1 )*4+1<=M then A:=((C div 4 )+1)*4+1 else A:=(C div
4)*4+1;
    for i:=2 to M do begin
    Cpom:=alfabet [(A*(KPos ([K[I-1],Alfabet)-1)+C) Mod M+1];
    if KPos(Cpom,K)=0 then begin
    K[J]:=Cpom;
    inc(j);
    end;
    end;
    end;

d) szyfry oparte na roznicy symetrycznej
                      f(f(x,y),y)=x
   dla dowolnego x zachodi => x XOR y XOR y= x

1.Na kazdy znak tekstu nakladamy operacje XOR X, gdzie X jest znakiem
szyfrujacym.
Kod jest bardzo prosty do zlamania.
2.Lancuch szyfrujemy za pomoca klucza K podobnie jak w szyfrze
polialfabetycznym.
Zamiast funkcji dodawania i odejmowania uzywamy XOR-a
3.Pierwszy znak pozostawiamy bez zmian.Drugi znak dodujemy jako roznice
symetryczna znaku drugiego i
pierwszego.Trzeci znak staje sie roznica symetryczna znaku trzeciego i
drugiego itd
4. Kolejne znaki kodujemy podobnie jak w pkt.3 lecz uzywajac XOR i
klucza nakladamy na to jeszcze
szyfrowanie polialfabetyczne

function szyfrdeszyfr(tekst,klucz:string):string;
var i:byte;
begin
for i:=1 to length(tekst) do
tekst[i]:=char(byte(tekst[i] xor byte (klucz[(i-1) mod
length(klucz)+1));
szyfrdeszyfr:tekst;
end;

                        Ochrona przed modyfikacja
A.Programy samosprawdzajace sie.
- dlugosc programu,
- data i czas ostatniej modyfikacji,
- atrybuty
- rozne sumy kontrolne wszystkich lub czesci bajtow programu

Program:
uses Dos;
const nazwaPliku:String='program.exe';
function dlugoscpliku:longint;
var
   f:file of byte;
begin
assign(f,nazwapliku);
reset(plik);
dlugoscpliku:=FileSize(F);
close(f);
end;

function DataICzas:longint;
var f:file of byte;
t:longint;
begin
assign(f,nazwapliku);
reset(plik);
GetTime(f,t);
close(f);
dataiczas:=t;
end;
function atrybuty:word;
var f:file of byte;
a:word;
begin
assign(f,nazwapliku);
reset(plik);
Getfattr(f,a);
close(f);
end;
Function roznica:byte;
const rozmiarbufora=32767;
type bufor = array [1..RozmiarBufora] of Byte;
var f:file;
    r:byte;
    buf:^bufor;
    przeczytano,i:Integer;
begin
r:=0;
new(buf);
assign(f,nazwapliku);
reset(plik,1);
repeat
blockread(f,buf^,rozmiarbufora,przeczytano);
for i:=1 to przeczytano do r:=r xor buf^[i];
until przeczytano<rozmiarbufora;
roznica:=r;
end;
{$D-}
Program zabezpiecz;
{tutaj nalezy umiescic wczesniejsze funkcje}
const :longint=0;
pom :byte=0;
dataiczaszapisu:longint=0;
attr:word=0;
begin
if boolean (pom) then;
if (rozmiar=dlugoscpliku) and (attr=attrybuty) and
(dataiczaszapisu=dataiczas) and (roznica=0) then
begin
{tutaj tresc programu}
end
else
begin
{zgloszenie modyfikacji programu}
end;
end.

Atrybuty
  ReadOnly = $01
  Hidden   = $02
  System   = $04
  Volume   = $08
  Directory= $10
  Archive  = $20

Aby uzyskac rozmiar pliku wystarczy napisac dir program.exe
Aby uzyskac atrybuty attrib program.exe, jezeli plik jest tylko do
odczytu,
czyli ma atrybut ReadOnly i Archive powinno byc: $01+$20=$21=33
Problem jest natomiast z uzyskaniem zmiennej DataICzasZapisu i Pom.W tym
celu
nalezy zlokalizowac mijsce przechowywania watosci tych zmiennych  w
zbiorze .exe
Kapilujemy powyzszy program dwukrotnie, do zbiorow p1.exe i p2.exe.Przed

kapilacja zbioru p2.exe  nalezy zmienic wartosc poczatkowa zmiennej pom
z 0 na 1
czyli spisac pom:byte=1; oraz zmiennej DataICzasZapisu z 0 na 1.
Otrzymujemy dwa zbiory p1.exe i p2.exe rozniace sie od siebie dwoma
bajtami.
Aby odnazesc te miejsca uzyjemy polecenia fc z parametrem /b
Czyli fc /b p1.exe p2.exe program pokaze nam
offset_xxxx: 00 01
offset_yyyy: 00 01
W ten sposob okreslilismy miejsce, w ktorym znajduje sie zmienna Pom-xxx

(zmienna 1 bajtowa) , oraz polozenie zmiennej DataICzasZapisu(4 bajty) -
yyyy
yyyy+1,yyyy+2,yyyy+3
Napiszmy program, ktory wstawi do programu program.exe odpowiednie
wartosci
zmiennych Pom i DataICzasZapisu.
- zmienna DataICzasZapisu musi byc spakowana postacia daty i czasu
ostatniej
modyfikacji
- zmienna Pom musi byc tak dobrana by roznica symetryczna wszystkich
bajtow byla rowna
0
Niech wynik wynosi x.Jezeli w porgramie wartosc POm (0) zastapimy liczba
x ,
 to roznica symetryczna wyniesie 0 => a xor 0 xor b =0 , a xor x xor b
=a itd..
 Program zmienne;
 uses dos;
{tu nalezy wstawic zdefiniowane uprzednio deklaracje oraz funkcje
Roznica}
 const
    pocz1=wartosc xxxx
    pocz2=wartosc yyyy
type arr= array [1..4] of byte;
var
f:file of byte;
dataiczaszapisu:longint;
i:byte;
roznicasymetryczna:byte;
begin
assign(f,nazwapliku);
reset(f);
seek(f,pocz2);
for i:=1 to 4 do
write(f,arr(dataiczaszapisu) [i]);
close(f);
roznicasymetryczna:=roznica;
reset(f);
seek(f,pocz1);
write(f,roznicasymetryczna);
setftime(f,dataiczasxzapisu);
close(f);
end.

                        Ochrona danych przed sledzeniem

1.Badanie czasu realizacji procedur
Metoda bardzo prymitywna.Zasada jest prosta nastepuje dwukrotne czytanie

zegara systemowego.Pierwszy odczyt bedzie nastepowal przed wywolaniem
pewnej
procedury , drugi zas po jej zakonczeniu.Program sledzony zostanie
wykryty
na podstawie stwierdzenia, ze czas wywolania procedury byl wiekszy od
zalozonego.
program antydebug;
Var
timer:longint aboslute $0:$046c; {bios tick counter ..licznk :)) }
czasod,czasdo:word;
procedure resetuj;
begin
inline($ea/$f0/$ff/$00/$f0);    {jump f000:fff0}
end;
procedure pozaczasem(limit:real);
var roznica:real;
begin
raznica:=(czasdo-czasod)*55/1000; {zmienna zegar zlicza ilosc 55
milisekundowych "tikow" zegara czyli co 1/8 sekundy zwieksza swa wartosc
o 1}
if roznica> limit then resetuj;
end;

begin
czasod:=timer;
writeln('welkome ble ble ble beanus');
czasdo:=timer;
pozaczasem(1.0);
{trest porgramu}
end.

2.Przechwycenie przerwania.
Implementacja tej metody jest bardzo prosta.Program przejmuje przerwanie
3h,
wy wypadku jego wywolania dzialanie programu zostanie zakonczone.
program antydebug2;
uses dos;
var starywektor3h:pointer;
{$F+}
procedure int3h;interrupt;
begin
resetuj;
end;
{$F-}
begin
getintvec($3,starywektor3h);
setintvec($3,@int3h);
{trest programu}
setintvec($3,starywektor3h)
end.
A ten program sprawdza czy Softice jest aktyualnie zaladowany....
Program Is_Sice_Loaded;

Const
   Loaded      : string[18]='SoftICE is loaded$';
   Not_Loaded  : string[22]='SoftICE is NOT loaded$';

Begin
   ASM
      mov   ah,43h
      int   68h
      cmp   ax,0f386h
      jnz   @no_SICE
      lea   dx, loaded+1
      jmp   @DisplayIt
@no_SICE:
      lea  dx, Not_Loaded+1
@DisplayIt:
      mov   ah, 09h
      int   21h
   end;
end.
Inna metoda wykrycia softica

    mov     ebp, 04243484Bh        ; 'BCHK'
    mov     ax, 04h
    int     3
    cmp     al,4
    jnz     SoftICE_Detected

Inna metoda wykrycia softica

    xor     di,di
    mov     es,di
    mov     ax, 1684h
    mov     bx, 0202h       ; VxD ID of winice
    int     2Fh
    mov     ax, es          ; ES:DI -> VxD API entry point
    add     ax, di
    test    ax,ax
    jnz     SoftICE_Detected

_______________________________________________________________________________________________

Inna metoda wykrycia softica

    xor     di,di
    mov     es,di
    mov     ax, 1684h
    mov     bx, 7a5Fh
    int     2fh
    mov     ax, es          ; ES:DI -> VxD API entry point
    add     ax, di
    test    ax,ax
    jnz     SoftICE_Detected

__________________________________________________________________________________________________

Inna metoda wykrycia softica

int41handler2 PROC
    iret
int41handler2 ENDP


    mov     bx, cs
    lea     dx, int41handler2
    xchg    dx, es:[41h*4]
    xchg    bx, es:[41h*4+2]
    mov     ax,4fh
    int     41h
    xchg    dx, es:[41h*4]
    xchg    bx, es:[41h*4+2]
    cmp     ax, 0f386h
    jz      SoftICE_detected

________________________________________________________________________________________

Inna metoda wykrycia softica

int41handler PROC
    mov     cl,al
    iret
int41handler ENDP


    xor     ax,ax
    mov     es,ax
    mov     bx, cs
    lea     dx, int41handler
    xchg    dx, es:[41h*4]
    xchg    bx, es:[41h*4+2]
    in      al, 40h
    xor     cx,cx
    int     41h
    xchg    dx, es:[41h*4]
    xchg    bx, es:[41h*4+2]
    cmp     cl,al
    jnz     SoftICE_detected

________________________________________________________________________________________

Inna metoda wykrycia softica

    mov     ah,43h
    int     68h
    cmp     ax,0F386h
    jz      SoftICE_Detected

___________________________________________________________________________________________

Inna metoda wykrycia softica

    mov     ah, 25h
    mov     al, Int_Number (01h or 03h for FrogsICE)
    mov     dx, offset New_Int_Routine
    int     21h

===============================================================================================

" MeToDa ] :
                              Wykrywanie VXD drivers
[ AnTy - DeBuG ] :
                              SoftIce for Win/Win95


Oglnie znan metod wykrywania obecnoci SI jest wykrywanie sterownikw
VXD uywanych przez niego. S to SICE.VXD
(win95), NTICE.VXD (WinNT) i sterownik grafiki SIWVID. Prost metod
wykrycia sterownika w pamici jest prba otwarcia lub
zapisu do pliku o nazwie uywanej przez ten sterownik w wyniku czego
generowany jest bd dostpu do pliku przy nie zezwoleniu na
jego wspuytkowanie. Moemy wykorzysta do tego funkcje API
CreateFileA

HANDLE CreateFile(      LPCTSTR lpFileName,     // address of name of
the file
                                        DWORD dwDesiredAccess,    //
access (read-write) mode
                                        DWORD dwShareMode,    // share
mode
                                        LPSECURITY_ATTRIBUTES
lpSecurityAttributes,    // address of security descriptor
                                        DWORD dwCreationDistribution,
// how to create
                                        DWORD dwFlagsAndAttributes,
// file attributes
                                        HANDLE hTemplateFile     //
handle of file with attributes to copy );

gdzie istotnym parametrem jest dwShareMode, przy ustawieniu 0 chroni
przed wspuytkowaniem pliku. Przykad procedury
wykorzystujcej ten sposb w 32bit asm (na podstawie Stone'a)   i C++
(by D.Eriksson)

.DATA
lpSICE9x db "\\.\SICE",0

.CODE

CALL    CreateFileA, OFFSET lpSICE9x, FALSE, FALSE, NULL,
FALSE,OPEN_EXISTING, NULL
CMP    EAX, -1
JZ    NiemaSI
........................

BOOL IsSoftIce95Loaded()
{
    HANDLE hFile;

    // "\\.\SICE" without escape stuff
    hFile = CreateFile( "\\\\.\\SICE",
                        GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);

    if( hFile != INVALID_HANDLE_VALUE )
    {
        CloseHandle(hFile);
        return TRUE;
    }

    return FALSE;
}

Analogicznie moemy sprawdzi NTICE, SIWVID i wogle obecno innych
sterownikw w pamici komputera. Nalezy jednak
zaznaczy, e sposb ten jest do znany i atwy do usunicia. Wystarczy
bowiem zmieni nazwy starownikw w SoftIce na inne i ju
program nam nie wykryje jego obecnoci.


[ MeToDa ] :
                              IDT - Sprawdzenie Interrupt Descriptor
Table
[ AnTy - DeBuG ] :
                              SoftIce for Win/Win95


Interrupt Descriptor Table jest tablic w ktrej przechowywane s
informacje o przerwaniach. Wymaga tego sposb pracy systemu w
trybie chronionym. Windows tworzy IDT dla 255 wektorw przerwa. Aby
podgldnc t tablice moemy uy SoftIce i komenda 'idt'
co da nam nastpujce informacje :

:idt
Int Type Sel:Offset Attributes Symbol/Owner
IDTbase=8009F000 Limit=02FF
0000 IntG32 0028:C0001200 DPL=0 P VMM(01)+0200
0001 IntG32 0028:C0001210 DPL=3 P VMM(01)+0210
0002 IntG32 0028:C0004054 DPL=0 P Simulate_IO+01CC
0003 IntG32 0028:C0001220 DPL=3 P VMM(01)+0220
0004 IntG32 0028:C0001230 DPL=3 P VMM(01)+0230
..........

IDTbase jest adresem, gdzie przechowywana jest ta tablica. Mozemy sobie
ja wyswietlic w okienku danych, czyli d 8009F000:

0030:8009F000 00 12 28 00 00 8E 00 C0-F7 30 28 00 00 EE 03 C0
0030:8009F010 06 31 28 00 00 8E 03 C0-15 31 28 00 00 EE 03 C0
0030:8009F020 30 12 28 00 00 EE 00 C0-40 12 28 00 00 EE 00 C0
0030:8009F030 24 31 28 00 00 8E 03 C0-60 12 28 00 00 8E 00 C0

Strukuta elementw tej tablicy przedstawia si tak :

IDTGATE {
    WORD    gateOffsetLow;
    WORD    gateSelector;
    WORD    gateFlags;
    WORD    gateOffsetHigh;}

Wemy wic np. przerwanie INT0 czyli pierwsze 8 bajtw (4 * word) i mamy
wg struktury adres ( C0 00 12 00) + selector (00 28)
co daje nam 0028:C0001200 no i jeszcze gateFlags (8E i 00) co ustawia
nam poziom uprzywilejowania DPL=3.

Jak widzimy mamy adresy obsugi przerwa INT1 i INT3 poniewa
zainstalowany mamy SoftIce. Ich obecno w IDT moe pozwoli
nam wykry SI przez nasz program. Ston'e zaproponowa np. nastpujc
metod wykrycia obecnoci SI :

     pobieramy z tablicy IDT adresy gateOffsetLow dla INT1 (30F7h) i
INT3 (3115h)
     odejmujemy adresy 3115h-30F7h  --> =1Eh
     jeeli rwne 1Eh to SI zainstalowany

    sidt   fword ptr pIDT          ; Pobranie IDT
    mov    eax, dword ptr [pIDT+2] ; eax -> IDT
    add    eax,8                   ; eax -> int 1 "vector"
    mov    ebx, [eax]              ; ebx == int 1 "vector"
    add    eax, 16                 ; eax -> int 3 "vector"
    mov    eax, [eax]              ; eax == int 3 "vector"
    and    eax, 0ffffh             ; bez selektora
    and    ebx, 0ffffh             ;
    sub    eax, ebx                ; znajdz roznice addrr
    cmp    eax, 01eh               ; jezeli 1eh to SI :-)



                              Wykorzystano materiay Stone'a, D.
Eriksson i fravia.org.



                                          @CrackPL by GustawKit"

"
Comment % Stone's APIHook - Detector :)


   Detecting an API-Spy real simple in a TASM/TLINK compiled program.
   This program will detect any API spy that hooks MessageBoxA api
          by modifying the IAT. (Ofcause provided the HOOK doesn't come
up
   with counter meassures)....

   NOTICE: THIS PROGRAM STRONGLY HINGES ON THE WAY BORLAND MAKES
          API-CALL'S... THE JUMP-TABLE APPROACH. NOTICE ALSO THAT IT
HINGES
          ON THE "DETECT" CALL TO BE COMPILED AS A SHORT (RELATIVE
CALL)...

    For a MS Convertion replace the first 4 lines of code with:
   mov eax, dword ptr [Detection+2]
   mov eax, [eax]
          ...

          To change detection from the MessageBoxA api to another just
change
          the call in detection accordingly.

    2nd&mi
    Stone / UCF & F4CG 1998
    email: stone@one.se
 %




.386P
Locals
jumps
.Model Flat ,StdCall
extrn VirtualQuery : PROC

UNICODE=0
include w32.inc
;

.Data
Mem_Structure:
pvBaseAddress  dd 0
pvAllocBase    dd 0
dwAllocProt    dd 0
dwRegionSize   dd 0
dwState        dd 0
dwProtect dd 0
dwType  dd 0

lpUser32  db "USER32.DLL",0
Tittle  db "Stone's ApiHook Detect",0
Detected db 13,"                 FOUND!!",13,0
NotHere  db 13,"No ApiHook Installed on MessageBoxA",13,0
.Code
;

Main:
 mov eax, dword ptr [Detection+1] ; Find IAT:
      ; eax = JMPtable-entry's displacement
      ; from Detection
 add eax, offset Detection+5+2  ; eax->IAT-Entry in jump instruction
      ; E8(ADDRESS)=5, 2= FF25 of jump
 mov eax, [eax]    ; eax->IAT-Entry

 mov eax, [eax]    ; eax = IAT-entry

 call VirtualQuery, eax, offset Mem_Structure, 4*7 ; Which module owns
this?

 call GetModuleHandleA, Offset lpUser32 ; Get USER32's baseaddress
 cmp eax, [pvAllocBase]   ; do they compare?
        jnz  SpyDetected

 call MessageBoxA, 0, offset NotHere, offset Tittle, 0
exit:
 Call ExitProcess, LARGE-1

SpyDetected:
 call MessageBoxA, 0, offset Detected, offset Tittle, 0
 jmp  exit

Detection:
 call MessageBoxA

;

End Main
"

                      Ochrona programu przed kopiowaniem
1.Pamietanie fragmentu biosu.
- w czasie instalacji programu na dysk bedzie odczytywany fragment biosu
i
zapisywany w zbiorze
- w trakcie kazdego uruchomienia programu bedzie odczytywal zbior
pomocniczy i p
prownywal z biosem komputera , na ktorym aktulanie jest zainstalowany
- w zaleznosic od wynikow porownania bedzie decycja co do legalnosci
oprogramowania..etc..

Przykladowym fragmentem BIOS-u moze byc 40 bajtow poczawszy od adresu
$F:$E874.

Type ZbiorPom= file od byte;
procedure czytaj;
const segment=$f;
ofset=$e874;
nazwapli='bios.dat';
var f:zbiorpom;
i:byte;
assign(f,nazwapli);
rewrite(f);
for i;=1 to 40 do
write(f,mem[segment:ofset+i-1]);
close(f);
end;
function sprawdz:boolean;
const
 segment=$f;
 ofset=$e874;
 nazwapli='bios.dat';
 var
 f:zbiorpom
 i:byte;
 b:byte;
 begin
 sprawdzbios:=false;
 assign(f,nazwapli);
 {$I-} reset(F);
 if ioresult=0 then begin
 if filesize(f)=40 then begin
 sprawdzbios:=true;
 for i;=1 to 40 do
 read(f,b);
 if b<>mem[segment:ofset+1-1] then sprawdzbios:=false;
 end ;
 end;
 close(f);
 end {$I+}
 end;
 I juz...:)))
--------------------------------------------------------------------------
CookieCrK
http://www.cookiecrk.z.pl/
e-mail: cookiecrk@z.pl