Я провел день, проливаясь через MSDN и написал этот пример.
Я написал testdll.dll, который имеет только функцию журнала, которая используется для вывода информации в файле test.txt.
Тестовая среда: WindowsServer2003+delphi7.0
Программа очень проста, поэтому экспертам не нужно ее читать.
Исходный код testdll.dll для тестирования (он будет введен в prjzzhost.exe):
Программный кодLibraryTestdll;
Использование
Sysutils,
Система,
Windows,
Классы;
ProcecureLog (s: pchar); stdcall;
вар
F: Textfile;
Начинать
ussyfile (f, 'test.txt');
iffileExists ('test.txt') thenAppend (f)
ElsereWrite (F);
writeeln (f, s);
FlieFile (F);
конец;
ProcusudlyLentryPoint (DWRESESON: DWORD);
Начинать
CaseDwresonof
Dll_process_attach:
Log ('dllprocessattach');
Dll_process_detach:
Log ('dllprocessdetach');
Dll_thread_attach:
Log ('dllthreadattach');
Dll_thread_detach:
Log ('dllthreaddetach');
конец;
конец;
экспорт
Бревно;
Начинать
Dllproc: =@dllentrypoint;
Dllentrypoint (dll_process_attach);
конец.
Внедренный процесс хоста prjzzhost.exe (он ничего не делает, это так невинно :), я не дам код здесь, потому что он слишком просто, ха -ха.
Наконец, самое главное:
Исходный код Project1.exe:
Программный кодUnitUnit1;
интерфейс
Использование
Windows, сообщения, Sysutils, варианты, классы, графика, управления, формы,
Диалоги, stdctrls, tlhelp32;
тип
Tlog = процедура (s: pchar); stdcall;
Tservicemain = процедура (argc: integer; varargv: pchar); stdcall;
Edllloaderror = class (исключение);
Tform1 = class (tform)
Button3: Tbutton;
Процедура button3click (отправитель: tobject);
Частный
{Privatedeclarations}
публичный
{PublicDeclarations}
конец;
вар
Форма1: tform1;
Выполнение
{$ R*.dfm}
{Зачисление процессов}
ProcecturegetMyProcessId (ConstaFilename: String; ConstPathMatch: Boolean; VarprocessId: DWORD);
вар
LPPE: tProcessEntry32;
Sshandle: Thandle;
Foundaproc, Foundok: логический;
Начинать
ProcessId: = 0;
{Создать системный снимок}
Sshandle: = createToolHelp32snapShot (th32cs_snapcess, 0);
{Получите первый процесс в снимке}
{Обязательно установите размер структуры, в противном случае false будет возвращен}
lppe.dwsize: = sizeof (tprocessentry32);
Foundaproc: = process32first (Sshandle, LPPE);
КАКФОНДАПРОКДО
Начинать
{Сделать совпадение}
ifpathmatchthen
Soundok: = ansistricomp (lppe.szexefile, pchar (afilename)) = 0
еще
Soudok: = ansistricomp (pchar (extractfilename (lppe.szexefile)), pchar (extractfilename (afilename)) = 0;
iffoundokthen
Начинать
ProcessId: = lppe.th32pocessId;
перерыв;
конец;
{Не найдено, продолжить следующий процесс}
Foundaproc: = process32next (sshandle, lppe);
конец;
Крупный рукой (Sshandle);
конец;
{Установить разрешения}
functionenableddebugprivilege (contenabled: boolean): boolean;
вар
htk: thandle; {open токен ручка}
rtntemp: dword; {значение возвращается при корректировке разрешений}
Tokenpri: token_privileges;
констант
Se_debug = 'sedebugprivilege'; {Query value}
Начинать
Результат: = false;
{Получить ручку токена процесса, установить разрешения}
if (openprocesstoken (getCurrentProcess (), token_adjust_privileges, htk))
Начинать
Tokenpri.privilegecount: = 1;
{Получить значение Luid}
Lookupprivilegevalue (nil, se_debug, tokenpri.privileges [0] .luid);
ifenabledthen
Tokenpri.privileges [0] .attributes: = se_privilege_enabled
еще
Tokenpri.privileges [0] .atributes: = 0;
rtntemp: = 0;
{Установить новые разрешения}
AdvitationTokenPrivileges (htk, false, tokenpri, sizeof (tokenpri), nil, rtntemp);
Результат: = getLasterRor = error_success;
Крупный рукой (HTK);
конец;
конец;
{Функция отладки}
ProcusureOutputText (Varch: PCHAR);
вар
FileHandle: TextFile;
Начинать
DessageFile (fileHandle, 'zztest.txt');
Append (filehandle);
Writeln (filehandle, ch);
Flush (fileHandle);
FileFile (FileHandle);
КОНЕЦ;
{Инъекция удаленного процесса}
functionInjectTo (Constost, гость: String; ConstPid: DWORD = 0): DWORD;
вар
{HARDENTED PROCESS, идентификатор процесса}
hremoteprocess: Thandle;
DWREMOTEPROCESSID: DWORD;
{Размер контента, записанный на удаленный процесс}
MEMSIZE: DWORD;
{Адрес после написания в удаленном процессе}
pszlibfileremote: указатель;
Ireturncode: логический;
Tempvar: dword;
{Укажите на адрес функции LoadLibraryw}
pfnstartaddr: tfnthreadstartroutine;
{DLL Полный путь, должен быть записан в память удаленного процесса}
PSZLIBAFILENAME: PWIDECHAR;
Начинать
Результаты: = 0;
{Установить разрешения}
EnabledDebugPrivilege (True);
{Выделите размер памяти для пути инъекционного файла DLL, поскольку он является WideChar, она должна быть умножена на 2}
GetMem (pszlibafilename, длина (гость)*2+1);
Stringtowidechar (гость, pszlibafilename, длина (гость)*2+1);
{получить идентификатор процесса}
ifpid> 0then
DWREMOTEPROCESSID: = PID
еще
GetMyProcessId (хост, false, dwremoteprocessid);
{Получите удаленную ручку процесса, иметь разрешение на запись}
HremoteProcess: = OpenProcess (process_create_thread+{разрешить удаленное создание потоков}
Process_vm_operation+{разрешить удаленные операции VM}
Process_vm_write, {разрешить удаленное виртуальное сообщение}
False, dwremoteprocessid);
{Используйте функцию VirtualAlloCex, чтобы выделить пространство в удаленном процессе и написать путь DLL в writeProcessMemory}
memsize: = (1+lstrlenw (pszlibafilename))*sizeof (wchar);
pszlibfileremote: = pwidestring (virtualallocex (hremoteprocess, nil, memsize, mem_commit, page_readwrite));
Tempvar: = 0;
Ireturncode: = writeprocessmemory (hremoteprocess, pszlibfileremote, pszlibafilename, memsize, tempvar);
ifireurncodethen
Начинать
pfnstartaddr: = getProcadDress (getModuleHandle ('kernel32'), 'LoadLibraryW');
Tempvar: = 0;
{Start DLL в удаленном процессе}
Результат: = CreaterEmothread (hRemoteprocess, nil, 0, pfnstartaddr, pszlibfileremote, 0, tempvar);
конец;
{свободное пространство памяти}
Freemem (pszlibafilename);
конец;
{тест}
ProcecuuretForm1.button3click (отправитель: tobject);
Начинать
Injectto ('prjzzhost.exe', ExtractfilePath (paramstr (0))+'testdll.dll');
конец;
конец.
Код не учитывает последствия загрузки DLL.