Внедрение библиотеки через CreateRemoteThread
Falk0ner, вс, 06/07/2008 - 15:34.
Приложение:
Взято из http://forum.sources.ru
Автор: Rouse_Проект также доступен по адресу: http://rouse.front.ru/injectlib.zip
Внедрение библиотеки через CreateRemoteThread
А также исполнение своего кода в удаленном процессе через CreateRemote
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Project : Inject/Eject Library Demo
// * Unit Name : HookDLL
// * Purpose : Демонстрационный пример внедрения библиотеки через CreateRemoteThread
// * Author : Александр (Rouse_) Багель
// * Version : 1.00
// ****************************************************************************
//
Library HookDLL;
{©Drkb v.3(2007): www.drkb.ru}
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.
//
// ****************************************************************************
// * Project : Inject/Eject Library Demo
// * Unit Name : HookDLL
// * Purpose : Демонстрационный пример внедрения библиотеки через CreateRemoteThread
// * Author : Александр (Rouse_) Багель
// * Version : 1.00
// ****************************************************************************
//
Library HookDLL;
{©Drkb v.3(2007): www.drkb.ru}
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.
Приложение:
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * 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.
//
// ****************************************************************************
// * 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.
Взято из http://forum.sources.ru
Автор: Rouse_Проект также доступен по адресу: http://rouse.front.ru/injectlib.zip
Отправить комментарий