[ Pobierz całość w formacie PDF ]
/*
Alokacja bloku pamięci XMS wielkości 'numberBytes'
Zwraca 1, gdy zakończona poprawnie
0 w przypadku błędu
*/
_DX = (int)(numberBytes / 1024);
_AH = 9;
(*XMSFunc)();
if (_AX==0)
{
return FALSE;
}
XMSHandle=_DX;
return TRUE;
}
void XMS_free(void)
{
/*
Zwolnij pamięć XMS
*/
_DX=XMSHandle;
_AH=0x0A;
(*XMSFunc)();
}
char XMS_write(unsigned long loc, char far *val, unsigned length)
{
/*
Zaokrąglij długość do kolejnej wartości parzystej
*/
length += length % 2;
XMSParms.sourceHandle=0;
XMSParms.sourcePtr=val;
XMSParms.destHandle=XMSHandle;
XMSParms.destPtr=(void far *) (loc);
XMSParms.blockLength=length; /* Musi być liczbą parzystą! */
_SI = FP_OFF(&XMSParms);
_AH=0x0B;
(*XMSFunc)();
if (_AX==0)
{
return FALSE;
}
return TRUE;
}
void *XMS_read(unsigned long loc,unsigned length)
{
/*
Zwraca wskaznik do danych
D:\KISIU\PDFy\Chudy\Ksią\ki\Hack_Wars_Tom_1\Hack_Wars_Tom_1\06.doc 287
288 Hack Wars. Tom 1. Na tropie hakerów
lub NULL w przypadku błędu
*/
/*
Zaokrąglij długość do kolejnej wartości parzystej
*/
length += length % 2;
XMSParms.sourceHandle=XMSHandle;
XMSParms.sourcePtr=(void far *) (loc);
XMSParms.destHandle=0;
XMSParms.destPtr=XMSBuf;
XMSParms.blockLength=length; /* Musi być liczbą parzystą */
_SI=FP_OFF(&XMSParms);
_AH=0x0B;
(*XMSFunc)();
if (_AX==0)
{
return NULL;
}
return XMSBuf;
}
/*
Przykładowy program
Zapisuje ciągi ró\nej długości
do pojedycznego bloku XMS(EMB)
i odczytuje je
*/
int main()
{
int kbAvail,largestAvail;
char buffer[80];
char *p;
long pos;
long end;
if (XMS_init() == 0)
printf("Pamięć XMS dostępna ...\n");
else
{
printf("Pamięć XMS nie jest dostępna\n");
return(1);
}
XMSSize(&kbAvail,&largestAvail);
printf("Wielkość dostępnej pamięci XMS: %d; Largest block:
1 %dK\n",kbAvail,largestAvail);
if (!AllocXMS(2000 * 1024L))
return(1);
pos = 0;
do
{
p = fgets(buffer,1000,stdin);
if (p != NULL)
{
288 D:\KISIU\PDFy\Chudy\Ksią\ki\Hack_Wars_Tom_1\Hack_Wars_Tom_1\06.doc
Rozdział 6. f& 289
f& Podstawy programowania dla hakerów
f&
f&
XMS_write(pos,buffer,strlen(buffer) + 1);
pos += strlen(buffer) + 1;
}
}
while(p != NULL);
end = pos;
pos = 0;
do
{
memcpy(buffer,XMS_read(pos,100),70);
printf("%s",buffer);
pos += strlen(buffer) + 1;
}
while(pos
/*
Zwolnienie pamięci XMS jest BARDZO wa\ne!
*/
XMS_free();
return 0;
}
Tworzenie programów TSR
Ostatnim tematem w naszym omówieniu podstaw języka C, mającym zarazem
szczególne znaczenie dla zagadnień zabezpieczeń, są wszechstronne programy
rezydentne, określane równie\ skrótem TSR (terminate and stay resident, zakończ i
pozostań w pamięci). Programy takie pozostają aktywne w pamięci, w trakcie gdy na
pierwszym planie pracują inne programy. Tworzenie programów rezydentnych to
ulubione zajęcie wielu programistów i hakerów.
Trudność w tworzeniu programów TSR wynika z ograniczeń DOS-u, który nie jest
wielozadaniowym systemem operacyjnym i nie współpracuje dobrze z kodem
wielowątkowym, przede wszystkim gdy pojawiają się wzajemne wywołania funkcji
systemowych (przerwań). Teoria programów rezydentnych jest dość prosta. Program
taki kończy pracę funkcją DOS-u keep (przerwanie 27h), a nie przy u\yciu
standardowej funkcji terminate. Zapewnia to zarezerwowanie w pamięci obszaru
wykorzystywanego przez program. Nie jest to skomplikowane, koniecznie trzeba
jednak podać, jaka ilość pamięci ma zostać zarezerwowana.
Głównym zródłem problemów jest brak mo\liwości korzystania z wywołań funkcji
DOS-u od momentu przyjęcia przez programu statusu programu rezydentnego.
Poni\ej przedstawiamy kilka podstawowych zasad, których przestrzeganie pomo\e
uniknąć problemów z programami TSR.
1. Unikanie wywołań funkcji DOS-u.
2. Monitorowanie znacznika zajętości DOS-u (busy flag). Gdy ma on wartość
niezerową, oznacza to, \e DOS wykonuje właśnie funkcję 21h i nie mo\na
mu przeszkadzać!
D:\KISIU\PDFy\Chudy\Ksią\ki\Hack_Wars_Tom_1\Hack_Wars_Tom_1\06.doc 289
290 Hack Wars. Tom 1. Na tropie hakerów
3. Monitorowanie przerwania 28h. Sygnalizuje ono, \e DOS jest zajęty
oczekiwaniem na dane wejściowe z konsoli. W tym czasie mo\na wykonywać
ró\ne operacje bez względu na stan znacznika zajętości.
4. Sprawdzanie, czy program jest ju\ uruchomiony, aby uniknąć jego wielokrotnego
ładowania do pamięci.
5. Nie wolno zapominać, \e równie\ inne programy TSR mogą przechwytywać
przerwania. Konieczne jest więc tworzenie łańcucha po wywołaniu własnej
funkcji wywołujemy funkcję określoną wektorem zastanym przy uruchamianiu
programu.
6. Program TSR musi korzystać z własnego stosu, a nie stosu uruchomionego
procesu.
7. Programy TSR nale\y kompilować, wybierając model pamięci small i wyłączając
sprawdzanie stosu.
8. Po przejęciu kontroli program TSR musi poinformować DOS o zmianie procesu
aktywnego.
Przedstawione poni\ej trzy moduły kodu stanowią kompletny program rezydentny.
Jest to prosta baza danych typu ksią\ka adresowa , aktywowana w trakcie pracy
innych programów wciśnięciem kombinacji klawiszy ALT i kropki (.). Je\eli praca
systemu operacyjnego nie mo\e zostać przerwana, program nie reaguje na
kombinację klawiszy. Wówczas nale\y spróbować ponownie.
/*
Przykładowy program TSR (wyskakująca ksią\ka adresowa)
Kompilować z modelem pamięci 'small' i
wyłączonym sprawdzaniem stosu (stack checking)
*/
#include
#include
#include
#include
static union REGS rg;
/*
Rozmiar programu pozostającego jako rezydentny
Aby określić wielkość minimalną, konieczne są eksperymenty
*/
unsigned sizeprogram = 28000/16;
/* Aktywacja kombinacją 'Alt+.' */
unsigned scancode = 52; /* . */
unsigned keymask = 8; /* ALT */
char signature[]= "POPADDR";
char fpath[40];
/*
Prototypy funkcji
*/
void curr_cursor(int *x, int *y);
int resident(char *, void interrupt(*)());
290 D:\KISIU\PDFy\Chudy\Ksią\ki\Hack_Wars_Tom_1\Hack_Wars_Tom_1\06.doc
Rozdział 6. f& 291
f& Podstawy programowania dla hakerów
f&
f&
void resinit(void);
void terminate(void);
void restart(void);
void wait(void);
void resident_psp(void);
void exec(void);
/*
Punkt wejścia z DOS-u
*/
void main(int argc, char *argv[])
{
void interrupt ifunc();
int ivec;
/*
Dla uproszczenia zakładamy, \e plik danych jest w
katalogu głównym dysku C:
*/
strcpy(fpath,"C:\\ADDRESS.DAT");
if ((ivec = resident(signature,ifunc)) != 0)
{
/* Ju\ jest */
if (argc > 1)
{
rg.x.ax = 0;
if (strcmp(argv[1],"quit") == 0)
rg.x.ax = 1;
else if (strcmp(argv[1],"restart") == 0)
rg.x.ax = 2;
else if (strcmp(argv[1],"wait") == 0)
rg.x.ax = 3;
if (rg.x.ax)
{
int86(ivec,&rg,&rg);
return;
}
}
printf("\nKsią\ka adresowa jest ju\ uruchomiona");
}
else
{
/* Załadowanie programu TSR */
printf("Ksią\ka adresowa została uruchomiona.\nWciśnij 'Alt+.',
aby
1 wywołać...\n");
resinit();
[ Pobierz całość w formacie PDF ]