Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС СФМЭИ.doc
Скачиваний:
22
Добавлен:
17.09.2019
Размер:
1.37 Mб
Скачать

8.2.2 Неявная загрузка dll

Рассмотрим неявную загрузку DLL на примере вызова процедуры HelloFromLib.

Последовательность действий:

  1. Создадим приложение, экранная форма которого изображена на рисунке 8.1:

  2. П рограммный код модуля имеет следующий вид:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Edit1: TEdit;

Label1: TLabel;

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

// неявная загрузка DLL

procedure HelloFromLib(k:Integer); external 'mess.dll';

procedure TForm1.Button1Click(Sender: TObject);

begin

HelloFromLib(StrToInt(Edit1.Text));

end;

end.

Примечание: Процедура HelloFromLib объявлена как внешняя.

8.2.3 Явная загрузка dll

Рассмотрим явную загрузку DLL на примере вызова процедуры HelloFromLib и функции fy.

Последовательность действий:

  1. Создадим приложение, экранная форма которого изображена на рисунке 8.2.

  2. П рограммный код модуля имеет следующий вид:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Label1: TLabel;

Edit1: TEdit;

Button1: TButton;

Edit2: TEdit;

Edit3: TEdit;

Button2: TButton;

Label2: TLabel;

Label3: TLabel;

Edit4: TEdit;

Label4: TLabel;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

// определение переменной – указателя на процедуру

HelloFromLibM:procedure (k:Integer);

// определение переменной – указателя на функцию

fyM:function(x:real;n:Integer):Real;

public

{ Public declarations }

end;

var

Form1: TForm1;

instance:LongWord;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

begin

// явная загрузка DLL

instance:=LoadLibrary('D:\Lab_OS\DLL\mess.dll');

If instance<>0 then

Begin

// Получаем адрес требуемой функции

HelloFromLibM:=GetProcAddress(instance,'HelloFromLib');

// вызов функции из внешней DLL

HelloFromLibM(StrToInt(Edit1.text));

FreeLibrary(instance);

end;

end;

procedure TForm1.Button2Click(Sender: TObject);

Var y:Real;

begin

instance:=LoadLibrary('D:\Lab_OS\DLL\mess.dll');

If instance<>0 then

begin

fyM:=GetProcAddress(instance,'fy');

y:=fyM(StrToFloat(Edit2.text),StrToInt(Edit3.Text));

Edit4.Text:=FloatToStr(y);

FreeLibrary(instance);

end;

end;

end.

8.2.4 Внедрение dll в адресное пространство другого процесса

Одним из методов внедрения DLL в адресное пространство другого процесса является использование ловушек. Для создания ловушек используется функция

SetWindowsHookEx(idHook:Integer; lpfn: Pointer; hMod:DWORD; dwThreadId:DWORD):hHook;

где

idHook - тип ловушкиl

lpfn - адрес процедуры, которая обрабатывает ловушку

hMod - дескриптор приложения

dwThreadId - идентификатор потока.

Механизм, позволяющий внедрять DLL в адресное пространство другого процесса, работает следующим образом:

Процесс A устанавливает ловушку WH_GETMESSAGE и наблюдает за сообщениями, которые обрабатываются окнами в системе. Ловушка устанавливается вызовом SetWindowsHookEx:

hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hinstDll,0);

Аргумент WH_GETMESSAGE определяет тип ловушки, а параметр GetMsgProc — адрес функции (в адресном пространстве процесса), которую система должна вызывать всякий раз, когда окно собирается обработать сообщение. Параметр hinstDll идентифицирует DLL, содержащую функцию GetMsgProc. В Windows значение hinstDll для DLL фактически задаст адрес в виртуальной памяти, по которому DLL спроецирована на адресное пространство процесса. И, наконец, последний аргумент, 0, указывает поток, для которого предназначена ловушка. Поток может вызвать SetWindowsHookEx и передать ей идентификатор другого потока в системе. При передаче 0 системе сообщается, что ловушка ставится для всех существующих в ней GUI-потоков.

Перехват работает следующим образом::

  1. Поток процесса B собирается направить сообщение какому-либо окну.

  2. Система проверяет, не установлена ли для данного потока ловушка WH_GETMESSAGE.

  3. Затем выясняет, спроецирована ли DLL, содержащая функцию GetMsgProc, на адресное пространство процесса B.

  4. Если указанная DLL еще не спроецирована, система отображает ее на адресное пространство процесса B.

  5. Вызывается GetMsgProc в адресном пространстве процесса B.

Причем, когда система внедряет или проецирует DLL, содержащую функцию фильтра ловушки, проецируется вся DLL, а не только эта функция. А значит, потокам, выполняемым в контексте процесса B, теперь доступны все функции такой DLL.

Для отключения DLL от адресного пространства процесса достаточно вызвать:

UnhookWindowsHookEx(HOOK: hHook):Boolean;