А также исполнение своего кода в удаленном процессе через CreateRemote

 

Code:

////////////////////////////////////////////////////////////////////////////////

//

//  ****************************************************************************

//  * Project   : Inject/Eject Library Demo

//  * Unit Name : HookDLL

//  * Purpose   : Демонстрационный пример внедрения библиотеки через CreateRemoteThread

//  * Author    : Александр (Rouse_) Багель

//  * Version   : 1.00

//  ****************************************************************************

//  

 

Library HookDLL;

{©Drkb v.3}

 

uses

Windows,

Messages,

SysUtils;

 

procedure DLLEntryPoint(dwReason: DWORD);

begin

case dwReason of

   DLL_PROCESS_ATTACH:

   begin

     MessageBox(0, 'DLL_PROCESS_ATTACH', 'DLL_PROCESS_ATTACH', MB_OK);

     ExitThread(0);

   end;

end;

end;

 

begin

DLLProc := @DLLEntryPoint;

DLLEntryPoint(DLL_PROCESS_ATTACH);

end.

 

 
 
Приложение:

Code:

////////////////////////////////////////////////////////////////////////////////

//

//  ****************************************************************************

//  * Project   : Inject/Eject Library Demo

//  * Unit Name : main

//  * Purpose   : Демонстрационный пример внедрения библиотеки через CreateRemoteThread

//  * Author    : Александр (Rouse_) Багель

//  * Version   : 1.00

//  ****************************************************************************

//

 

unit main;

{©Drkb v.3(2007): www.drkb.ru}

 

interface

 

uses

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

Dialogs, StdCtrls;

 

resourcestring

BTN_INJECT = 'Inject';

BTN_EJECT  = 'Eject';

 

const

DLLName = 'hooklib.dll';

 

type

TfrmMain = class(TForm)

   btnInjectEject: TButton;

   GroupBox: TGroupBox;

   lbStatus: TListBox;

   procedure btnInjectEjectClick(Sender: TObject);

private

   function InjectLib(const ProcessID: DWORD): Boolean;

   function EjectLib(const ProcessID: DWORD): Boolean;

end;

 

// Декларация функций при помощи которых будет происходить выгрузка билиотеки

TGetModuleHandle = function (lpModuleName: PChar): HMODULE; stdcall;

TFreeLibrary = function (hLibModule: HMODULE): BOOL; stdcall;

 

// Структура передаваемая потоковой функции при выгрузке библиотеки

PEjectLibStruct = ^TEjectLibStruct;

TEjectLibStruct = record

   hGetModuleHandle: TGetModuleHandle;

   hFreeLibrary: TFreeLibrary;

   lpModuleName: PChar;

end;

 

var

frmMain: TfrmMain;

 

implementation

 

{$R *.dfm}

 

{ TfrmMain }

 

//  Обработчик кнопки на внедрение/выгрузку библиотеки

// =============================================================================

procedure TfrmMain.btnInjectEjectClick(Sender: TObject);

begin

TComponent(Sender).Tag := TComponent(Sender).Tag + 1;

if (TComponent(Sender).Tag mod 2) = 1 then

begin

   btnInjectEject.Caption := BTN_EJECT;

   if InjectLib(GetCurrentProcessID) then

     lbStatus.Items.Add('Library injected succes.')

   else

     lbStatus.Items.Add('Library injected fail.');

end

else

begin

   btnInjectEject.Caption := BTN_INJECT;

   if EjectLib(GetCurrentProcessID) then

     lbStatus.Items.Add('Library ejected succes.')

   else

     lbStatus.Items.Add('Library ejected fail.');

end;

end;

 

//  Пока наш процесс не получит отлабочные привилегии,

//  весь этот код работать не будет

// =============================================================================

function SetDebugPriv: Boolean;

var

Token: THandle;

tkp: TTokenPrivileges;

ReturnLength: DWORD;

begin

Result := false;

// Получаем токен текущего процесса

if OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then

begin

   // Получаем Luid привилегии

   if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), tkp.Privileges[0].Luid) then

   begin

     // Заполняем необходимые параметры

     tkp.PrivilegeCount := 1;

     tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;

     // Включаем привилегию

     Result := AdjustTokenPrivileges(Token, false, tkp, 0, nil, ReturnLength);

   end;

end;

end;    

 

//  Функция внедряет библиотеку в удаленный процесс с PID равным ProcessID

//  Для успешного внедрения нужно передать адрес функции LoadLibraryA

//  и путь к загружаемой библиотеке.

//  Строку с путем необходимо разместить в алресном пространстве удаленного процесса

// =============================================================================

function TfrmMain.InjectLib(const ProcessID: DWORD): Boolean;

var

Process: HWND;

ThreadRtn: FARPROC;

DllPath: String;

RemoteDll: Pointer;

BytesWriten: DWORD;

Thread: DWORD;

ThreadId: DWORD;

ExitCode: DWORD;

begin

// Устанавливаем отладочные привилегии для нашего процесса

Result := SetDebugPriv;

if not Result then Exit;

Process := 0;

Thread := 0;

try

   // Открываем процесс

   Process := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or

     PROCESS_VM_WRITE, True, ProcessID);

   if Process = 0 then Exit;

   // Выделяем в нем память под строку

   DllPath := ExtractFilePath(ParamStr(0)) + DLLName;

   RemoteDll := VirtualAllocEx(Process, nil, Length(DllPath),

     MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);

   if RemoteDll = nil then Exit;

   // Пишем путь к длл в его адресное пространство

   if not WriteProcessMemory(Process, RemoteDll, PChar(DllPath),

     Length(DllPath), BytesWriten) then Exit;

   if BytesWriten <> DWORD(Length(DllPath)) then Exit;

   // Получаем адрес функции из Kernel32.dll

   ThreadRtn := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA');

   if ThreadRtn = nil then Exit;

   // Запускаем удаленный поток

   Thread := CreateRemoteThread(Process, nil, 0, ThreadRtn, RemoteDll, 0, ThreadId);

   if Thread = 0 then Exit;

   // Ждем пока удаленный поток отработает...

   if (WaitForSingleObject(Thread, INFINITE) = WAIT_OBJECT_0) then

     if GetExitCodeThread(Thread, ExitCode) then

       Result := ExitCode = 0;

finally

   // Удаленный поток свою задачу выполнил и загрузил нашу библиотеку,

   // можно освобождать занятую память...

   if RemoteDll <> nil then

     VirtualFreeEx(Process, @RemoteDll, 0, MEM_RELEASE);

   if Thread <> 0 then CloseHandle(Thread);

   if Process <> 0 then CloseHandle(Process); 

end;

end;

 

//  Для того чтобы выгрузить библиотеку, необходимо найти ее адрес в удаленном

//  процессе и вызвать там же FreeLibrary

//  Этим у нас будет заниматься вот такая функция

//  Для успешной ее работы необходимо передать 3 параметра.

//  1: Адреса функций GetModuleHandle и FreeLibrary;

//  2: Имя модуля, выгрузку которого мы будем производить

// =============================================================================

function RemoteFreeLibrary(lpParameter: Pointer): DWORD; stdcall;

var

hLibModule: HMODULE;

begin

Result := 0;

if lpParameter = nil then Exit;

// Получаем описатель нашей библиотеки (используем переданные параметры)

hLibModule := TGetModuleHandle(PEjectLibStruct(lpParameter)^.hGetModuleHandle)

   (PEjectLibStruct(lpParameter)^.lpModuleName);

if hLibModule <> 0 then

   // Выгружаем библиотеку

   Result := DWORD(TFreeLibrary(PEjectLibStruct(lpParameter)^.hFreeLibrary)(hLibModule));

end;

 

//  Данная функция запускает в удаленном процессе поток

//  с потоковой функцией RemoteFreeLibrary

//  и подготавливает для ее работы необходимые данные

// =============================================================================

function TfrmMain.EjectLib(const ProcessID: DWORD): Boolean;

var

Process: HWND;

BytesWriten: DWORD;

Thread: DWORD;

ThreadId: DWORD;

ExitCode: DWORD;

EjectLibStruct: TEjectLibStruct;

EjectLibStructAddr: Pointer;

begin

Result := False;

Process := 0;

Thread := 0;

try

   // Открываем процесс

   Process := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or

     PROCESS_VM_WRITE, True, ProcessID);

   if Process = 0 then Exit;

   // Выделяем в нем память под имя модуля

   EjectLibStruct.lpModuleName := VirtualAllocEx(Process, nil, Length(DLLName),

     MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);

   if EjectLibStruct.lpModuleName = nil then Exit;

   // Пишем имя модуля в его адресное пространство

   if not WriteProcessMemory(Process, EjectLibStruct.lpModuleName, PChar(DLLName),

     Length(DLLName), BytesWriten) then Exit;

   if BytesWriten <> DWORD(Length(DLLName)) then Exit;

   // Получаем адрес функции FreeLibrary из Kernel32.dll

   EjectLibStruct.hFreeLibrary :=

     GetProcAddress(GetModuleHandle('Kernel32.dll'), 'FreeLibrary');

   if not Assigned(EjectLibStruct.hFreeLibrary) then Exit;

   // Получаем адрес функции GetModuleHandle из Kernel32.dll

   EjectLibStruct.hGetModuleHandle :=

     GetProcAddress(GetModuleHandle('Kernel32.dll'), 'GetModuleHandleA');

   if not Assigned(EjectLibStruct.hGetModuleHandle) then Exit;

   // Выделяем память под структуру, которая передается нашей функции

   EjectLibStructAddr := VirtualAllocEx(Process, nil, SizeOf(TEjectLibStruct),

     MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);

   if EjectLibStructAddr = nil then Exit;

   // Пишем саму структуру

   if not WriteProcessMemory(Process, EjectLibStructAddr, @EjectLibStruct,

     SizeOf(TEjectLibStruct), BytesWriten) then Exit;

   if BytesWriten <> DWORD(SizeOf(TEjectLibStruct)) then Exit;

 

   // Запускаем удаленный поток

   Thread := CreateRemoteThread(Process, nil, 0, @RemoteFreeLibrary,

     EjectLibStructAddr, 0, ThreadId);

   if Thread = 0 then Exit;

   // Ждем пока удаленный поток отработает...

   if (WaitForSingleObject(Thread, INFINITE) = WAIT_OBJECT_0) then

     if GetExitCodeThread(Thread, ExitCode) then

       Result := BOOL(ExitCode);

finally

   // Удаленный поток свою задачу выполнил и выгрузил нашу библиотеку,

   // можно освобождать занятую память...

   VirtualFreeEx(Process, @EjectLibStruct.lpModuleName, 0, MEM_RELEASE);

   VirtualFreeEx(Process, @EjectLibStructAddr, 0, MEM_RELEASE);

   if Thread <> 0 then CloseHandle(Thread);

   if Process <> 0 then CloseHandle(Process);

end;

end;

 

end.

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить