Pasé una tarde lanzando MSDN y escribí este ejemplo.
Escribí un testdll.dll, que solo tiene una función de registro, que se utiliza para generar información en el archivo test.txt.
Entorno de prueba: WindowsServer2003+Delphi7.0
El programa es muy simple, por lo que los expertos no necesitan leerlo.
Testdll.dll Código fuente para la prueba (se inyectará en prjzzhost.exe):
Código de programaLibraryTestdll;
usos
Sysutils,
Sistema,
Windows,
Clases;
procedimientoLog (s: pchar); stdcall;
varilla
F: TEXTFILE;
Comenzar
asignarfile (f, 'test.txt');
iffileExists ('test.txt') entonces apoderada (f)
ElsereWrite (f);
WriteLn (F, S);
CloseFile (f);
fin;
procedidollEntryPoint (DWREasion: DWORD);
Comenzar
Casedwrasteof
Dll_process_attach:
Log ('dllprocessattach');
Dll_process_detach:
Log ('dllprocessDetach');
Dll_thread_attach:
Log ('dllthreadattach');
Dll_thread_detach:
Log ('dllthreadDetach');
fin;
fin;
exportaciones
Registro;
Comenzar
Dllproc: =@dllentrypoint;
Dllentrypoint (dll_process_attach);
fin.
El proceso de host inyectado prjzzhost.exe (no hace nada, es tan inocente :), no daré el código aquí porque es demasiado simple, jaja.
Finalmente, lo más importante es:
Código fuente de Project1.exe:
Código de programaUnitunit1;
interfaz
usos
Windows, mensajes, sysutils, variantes, clases, gráficos, controles, formularios,
Diálogo, stdctrls, tlhelp32;
tipo
Tlog = procedimiento (s: pchar); stdcall;
TserviceMain = procedimiento (argc: entero; varargv: pchar); stdcall;
EdllloadError = class (excepción);
TForm1 = class (tForm)
Button3: tbutton;
procedimientoButton3Click (remitente: tobject);
Privado
{Privatedeclarations}
público
{PublicDeclarations}
fin;
varilla
Form1: tform1;
Implementación
{$ R*.dfm}
{Inscripción de procesos}
procedimientogetMyProcessID (constafileName: string; constpathMatch: boolean; varprocessid: dword);
varilla
LPPE: TProcessEntry32;
Sshandle: Thandle;
Foundaproc, Fundado: booleano;
Comenzar
ProcessID: = 0;
{Crear una instantánea del sistema}
Sshandle: = createToolHelp32SnapShot (th32cs_snapprocess, 0);
{Obtenga el primer proceso en la instantánea}
{Asegúrese de establecer el tamaño de la estructura, de lo contrario se devolverá falso}
lppe.dwsize: = sizeof (tprocessentry32);
FOUNDAPROC: = Process32First (sshandle, lppe);
whayfoundaprocdo
Comenzar
{Haz un partido}
ifpathmatchthen
FUNDOK: = AnsistRicomp (LPPE.SZEXEFILE, PCHAR (AFILENAME)) = 0
demás
FUNDOK: = AnsIsMiComp (pChar (ExtractFileName (LPPE.SZEXEFILE)), PCHAR (ExtractFileName (AfileName)) = 0;
iffoundokthen
Comenzar
ProcessID: = lppe.th32processid;
romper;
fin;
{No se encuentra, continúe al siguiente proceso}
FoundAPROC: = Process32Next (sshandle, lppe);
fin;
CloseHandle (sshandle);
fin;
{Establecer permisos}
FuncionEnableDeBUgPrivilege (Constenable: boolean): boolean;
varilla
htk: thandle; {mango de token abierto}
rtntemp: dword; {valor devuelto al ajustar los permisos}
Tokenpri: token_privileges;
estúpido
SE_DEBUG = 'SEDEBUGPRIVILEA'; {valor de consulta}
Comenzar
Resultado: = falso;
{Obtenga el mango de token de proceso, configure permisos}
if (OpenProcesStoken (getCurrentProcess (), token_adjust_privileges, htk)) luego
Comenzar
Tokenpri.privilegecount: = 1;
{Get Luid Value}
LookupPrivilegeValue (nil, se_debug, tokenpri.privileges [0] .luid);
ifenableThen
Tokenpri.privileges [0] .Attributes: = SE_Privilege_Enabled
demás
Tokenpri.privileges [0] .Attributes: = 0;
rtntemp: = 0;
{Establecer nuevos permisos}
AjustarTokenPrivileges (htk, falso, tokenpri, sizeOf (tokenpri), nil, rtntemp);
Resultado: = getLasterRor = ERROR_SUCCESS;
CloseHandle (htk);
fin;
fin;
{Función de depuración}
ProcedureOutputText (Varch: PCHAR);
varilla
FileHandle: TextFile;
Comenzar
Asignación (fileHandle, 'zztest.txt');
Append (FileHandle);
WriteLn (FileHandle, CH);
FLUSH (FileHandle);
CloseFile (FileHandle);
FIN;
{Inyectar proceso remoto}
functionInjectTO (conshost, invitado: string; constpid: dword = 0): dword;
varilla
{Mango de proceso inyectado, ID de proceso}
Hremoteprocess: Thandle;
DWREMOTEPROCESSID: DWORD;
{Tamaño del contenido escrito al proceso remoto}
memsize: dword;
{Dirección después de escribir en el proceso remoto}
pszlibFileremote: puntero;
Ireturncode: booleano;
Tempvar: dword;
{Punto a la dirección de la función LoadLibraryW}
pfnstartaddr: tfnthreadstartroutine;
{Ruta completa de dll, debe escribirse en la memoria del proceso remoto}
Pszlibafilename: Pwidechar;
Comenzar
Resultados: = 0;
{Establecer permisos}
HabilitéDeBugPrivilege (verdadero);
{Asignar el tamaño de la memoria para la ruta del archivo DLL inyectado, porque es Widechar, debe multiplicarse por 2}
GetMem (pszlibafilename, longitud (invitado)*2+1);
Stringtowidechar (invitado, pszlibafilename, longitud (invitado)*2+1);
{Obtener ID de proceso}
ifpid> 0then
dwremoteprocessid: = pid
demás
GetMyProcessid (host, falso, dwremoteprocessid);
{Obtenga el mango de proceso remoto, tenga permiso de escritura}
hremoteprocess: = OpenProcess (process_create_thread+{Permitir la creación remota de hilos}
Process_vm_operation+{permitir operaciones de VM remotas}
Process_vm_write, {permitir la escritura de VM remota}
Falso, dwremoteprocessid);
{Use la función virtualLoCex para asignar espacio en el proceso remoto y escriba la ruta DLL en 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);
ifireturncodethen
Comenzar
pfnstartaddr: = getProcAddress (getModuleHandle ('kernel32'), 'loadLibraryW');
Tempvar: = 0;
{Iniciar DLL en proceso remoto}
Resultado: = CreaterMotethread (HREMOTEPROCESS, NIL, 0, PfnStartaddr, PSZLIBFILEREMOTE, 0, TEMPVAR);
fin;
{espacio de memoria libre}
Freemem (pszlibafilename);
fin;
{prueba}
ProceduretForm1.Button3Click (remitente: tobject);
Comenzar
InyectTO ('prjzzhost.exe', extractFilePath (paramstr (0))+'testdll.dll');
fin;
fin.
El código no considera las secuelas de la DLL que se está cargando.