Passei uma tarde passando pelo MSDN e escrevi este exemplo.
Eu escrevi um testdll.dll, que possui apenas uma função de log, que é usada para produzir informações no teste de arquivo.txt.
Ambiente de teste: WindowsServer2003+Delphi7.0
O programa é muito simples, portanto, os especialistas não precisam lê -lo.
Testdll.dll Código fonte para teste (ele será injetado no prjzzhost.exe):
Código do programabibliotecaTestdll;
usos
Sysutils,
Sistema,
Windows,
Classes;
ProcedureLog (S: PChar); StdCall;
var
F: TextFile;
Começar
atribuifile (f, 'test.txt');
iffileExists ('test.txt') thenappend (f)
elserewrite (f);
writeLn (f, s);
CloseFile (F);
fim;
ProcedsUlelLentryPoint (DWROASN: DWORD);
Começar
CASEDWROASNOF
Dll_process_attach:
Log ('dllProcessattach');
Dll_process_detach:
Log ('dllprocessdetach');
Dll_thread_attach:
Log ('dllthreadattach');
Dll_thread_detach:
Log ('dllthreaddetach');
fim;
fim;
exportações
Registro;
Começar
DllProc: =@dllEntryPoint;
DllEntryPoint (dll_process_attach);
fim.
O processo de host injetado Prjzzhost.exe (não faz nada, é tão inocente :), não vou dar o código aqui porque é muito simples, haha.
Finalmente, o mais importante é:
Código fonte do Project1.exe:
Código do programaUnitUnit1;
interface
usos
Janelas, mensagens, sysutils, variantes, classes, gráficos, controles, formulários,
Diálogos, stdctrls, tlhelp32;
tipo
Tlog = procedimento (s: pchar); stdcall;
TServicemain = procedimento (argc: inteiro; varargv: pchar); stdcall;
EdllloadError = classe (exceção);
Tform1 = classe (tform)
Button3: tbutton;
ProcedureButton3Click (remetente: Tobject);
Privado
{PrivateClarations}
público
{PublicDeclarations}
fim;
var
Form1: TForm1;
Implementação
{$ R*.dfm}
{Inscrição de processos}
ProcedureGetMyProcessId (constafilename: string; constpathMatch: boolean; varprocessid: dword);
var
lppe: tprocessentry32;
Sshandle: Thandle;
FoundAproc, Foundok: Boolean;
Começar
ProcessId: = 0;
{Crie um instantâneo do sistema}
Sshandle: = createToolHelp32snapshot (th32cs_snapprocess, 0);
{Obtenha o primeiro processo no instantâneo}
{Certifique -se de definir o tamanho da estrutura, caso contrário, false será retornado}
lppe.dwsize: = sizeof (tprocessEntry32);
FoundAproc: = Process32First (Sshandle, LPPE);
whilefoundeprocdo
Começar
{faça uma correspondência}
IfPathMatchthen
Foundok: = ANSistricomp (lppe.szexefile, PChar (Afilename)) = 0
outro
Foundok: = ANSistricomp (PChar (ExtractFileName (lppe.szexefile)), PChar (ExtractFileName (AfileName))) = 0;
iffoundokthen
Começar
ProcessID: = lppe.th32ProcessId;
quebrar;
fim;
{Não encontrado, continue para o próximo processo}
FoundAproc: = Process32Next (sshandle, lppe);
fim;
CloseHandle (Sshandle);
fim;
{Definir permissões}
FunctionEnabledDebugPrivilege (ConstEnabled: boolean): booleano;
var
htk: THANDLE; {Open Token Handle}
rtntemp: dword; {valor retornado ao ajustar permissões}
TokenPri: token_privileges;
const
SE_DEBUG = 'SedeBugPrivilege'; {Valor da consulta}
Começar
Resultado: = false;
{Obtenha manipulação de token do processo, defina permissões}
if (openProcessToken (getCurrentProcess (), token_adjust_privileges, htk)) então
Começar
Tokenpri.privileGecount: = 1;
{Get Luid Value}
LookupPrivileGeValue (nil, se_debug, tokenpri.privileges [0] .luid);
IfenabledThen
Tokenpri.privileges [0] .Attributes: = SE_PRIVILEGE_ENABLED
outro
Tokenpri.privileges [0] .Attributes: = 0;
rtntemp: = 0;
{Defina novas permissões}
AjustTokenPrivileges (htk, false, tokenpri, sizeof (tokenpri), nil, rtntemp);
Resultado: = getLasterRor = error_success;
CloseHandle (htk);
fim;
fim;
{Função de depuração}
ProcedureOutputText (Varch: PChar);
var
FileHandle: TextFile;
Começar
Atribuifile (fileHandle, 'zztest.txt');
Anexar (FileHandle);
WriteLN (FileHandle, CH);
Flush (FileHandle);
CloseFile (FileHandle);
FIM;
{Injeção de processo remoto}
functionInjectTo (consthost, convidado: string; constpid: dword = 0): dword;
var
{Individação do processo injetado, ID do processo}
Hromoteprocess: Thandle;
dWremoteProcessId: dword;
{Tamanho do conteúdo escrito para processo remoto}
Memsize: DWORD;
{Endereço após escrever para o processo remoto}
pszlibfileRemote: ponteiro;
IreTurnCode: booleano;
Tempvar: dword;
{Aponte para o endereço da função loadlibraryw}
pfNStartAddr: tfnthreadstartroutine;
{DLL Caminho completo, precisa ser escrito na memória do processo remoto}
pszlibafilename: pwidechar;
Começar
Resultados: = 0;
{Definir permissões}
EnabledDebugprivilege (true);
{Aloce o tamanho da memória para o caminho do arquivo DLL injetado, porque é widechar, deve ser multiplicado por 2}
GetMem (pszlibafilename, comprimento (hóspede)*2+1);
Stringtowidechar (convidado, pszlibafilename, comprimento (hóspede)*2+1);
{obtenha ID do processo}
ifpid> 0then
dWremoteProcessId: = pid
outro
GetMyProcessId (host, false, dwremoteprocessId);
{Obtenha o identificador de processo remoto, tenha permissão de gravação}
HroMoteProcess: = OpenProcess (process_create_thread+{permitir criação remota de threads}
Process_vm_operation+{permitir operações remotas da VM}
Process_vm_write, {permitir escrita remota de VM}
Falso, dwremoteprocessid);
{Use a função virtualalleCex para alocar espaço no processo remoto e escreva o caminho da DLL no writeProcessMemory}
Memsize: = (1+lStrlenw (pszlibafilename))*sizeof (wchar);
pszlibfileRemote: = pwideString (virtualalleCex (hremoteprocess, nil, memsize, mem_commit, page_readwrite);
Tempvar: = 0;
IRETURNCODE: = WriteProcessMemory (HremoteProcess, pszlibFileRemote, Pszlibafilename, Memsize, Tempvar);
IfireturnCodethen
Começar
pfNStartAddr: = getProcaddress (getModuleHandle ('kernel32'), 'loadlibraryw');
Tempvar: = 0;
{Iniciar DLL no processo remoto}
Resultado: = CreateremoteThread (Hromoteprocess, nil, 0, pfnsStartaddr, pszlibfileRemote, 0, tempvar);
fim;
{espaço de memória livre}
Freemem (pslibafilename);
fim;
{teste}
ProcedureTForm1.Button3Click (remetente: TOBJECT);
Começar
InjectTo ('prjzzhost.exe', extractFilePath (paramstr (0))+'testdll.dll');
fim;
fim.
O código não considera as consequências da DLL sendo carregada.