J'ai passé un après-midi à parcourir MSDN et à avoir écrit cet exemple.
J'ai écrit un testdll.dll, qui n'a qu'une fonction de journal, qui est utilisée pour produire des informations dans le fichier test.txt.
Environnement de test: WindowsServer2003 + Delphi7.0
Le programme est très simple, donc les experts n'ont pas besoin de le lire.
Testdll.dll Code source pour le test (il sera injecté dans prjzzhost.exe):
Code de programmeLibraryTestDll;
usages
Sysutils,
Système,
fenêtres,
Classes
ProcédureLog (S: PCHA); stdcall;
var
F: TextFile;
Commencer
AssignFile (f, 'test.txt');
iffileExists ('test.txt') alors purge (f)
Elserewrite (F);
Writeeln (f, s);
Fermer File (F);
fin;
ProcédureLlELTRYPOINT (DWRREON: DWORD);
Commencer
CasedWeasonof
Dll_process_attach:
Log («dllprocessattach»);
Dll_process_detach:
Log («dllprocessdetach»);
Dll_thread_attach:
Log ('dllThreadattach');
Dll_thread_detach:
Log ('dllThreadDetach');
fin;
fin;
exportations
Enregistrer;
Commencer
DllProc: = @ dllentrypoint;
DllEntryPoint (dll_process_attach);
fin.
Le processus hôte injecté Prjzzhost.exe (il ne fait rien, c'est tellement innocent :), je ne donnerai pas le code ici parce que c'est trop simple, haha.
Enfin, la chose la plus importante est:
Code source de Project1.exe:
Code de programmeUnitUnit1;
interface
usages
Windows, messages, systèmes, variantes, classes, graphiques, contrôles, formulaires,
Dialogues, stdctrls, tlhelp32;
taper
Tlog = procédure (s: phar); stdcall;
TServiceMain = procédure (argc: entier; varargv: phar); stdcall;
EdllloadError = class (exception);
Tform1 = classe (tform)
Button3: Tbutton;
ProcédureButton3Click (expéditeur: tobject);
Privé
{Privedeclarations}
publique
{PublicDarations}
fin;
var
FORM1: TFORM1;
Mise en œuvre
{$ R * .dfm}
{Inscription des processus}
ProcédureGetMyProcessId (ConstaFileName: String; constpathmatch: boolean; varProcessId: dword);
var
LPPE: TProcessentry32;
SShandle: Thandle;
Foundaproc, Foundok: Boolean;
Commencer
ProcessId: = 0;
{Créer un instantané système}
Sshandle: = createToolHelp32Snapshot (th32cs_snapprocess, 0);
{Obtenez le premier processus dans l'instantané}
{Assurez-vous de définir la taille de la structure, sinon faux sera retourné}
lppe.dwsize: = sizeof (tprocessentry32);
FoundAproc: = process32First (sshandle, LPPE);
tandis que Foundaprocodo
Commencer
{faire un match}
ifpathmatchthen
FoundOK: = ANSistRIComp (lppe.szexeFile, pChar (afileName)) = 0
autre
FoundOK: = ANSistRIComp (pChar (ExtractFileName (lppe.szexefile)), pChar (extractFileName (afileName))) = 0;
iffoundokthen
Commencer
ProcessId: = lppe.th32ProcessId;
casser;
fin;
{Non trouvé, continuez au processus suivant}
FoundAproc: = process32Next (sshandle, LPPE);
fin;
Closehandle (sshandle);
fin;
{Définir les autorisations}
FunctionEnabledDebugPrivilege (constenable: booléen): booléen;
var
htk: thandle; {poignée de jeton ouvert}
rtntemp: dword; {valeur renvoyée lors de l'ajustement des autorisations}
Tokenpri: token_privileges;
const
Se_debug = 'sedebugPrivilege'; {valeur de requête}
Commencer
Résultat: = false;
{Obtenir la poignée de jeton de processus, définir les autorisations}
if (openProcessToken (getCurrentProcess (), token_adjust_privileges, htk)) alors
Commencer
Tokenpri.privilegeCount: = 1;
{obtenir la valeur luid}
LookupprivilegeValue (nil, se_debug, tokenpri.privileges [0] .luid);
ifenabledthhen
Tokenpri.privileges [0] .Attributes: = se_privilege_enabled
autre
Tokenpri.privileges [0] .Attributes: = 0;
rtntemp: = 0;
{Définir de nouvelles autorisations}
ADGLOTKINGPRIVILEGES (HTK, FAUX, TOKENPRI, SIZEOF (TOKENPRI), NIL, RTNEMP);
Résultat: = getLasterRor = error_success;
CloseHandle (HTK);
fin;
fin;
{Fonction de débogage}
ProcédureOutputText (varch: phar);
var
FileHandle: textfile;
Commencer
AssignFile (filehandle, 'zztest.txt');
Ajouter (filehandle);
Writeln (filehandle, ch);
Flush (filehandle);
CloseFile (filehandle);
FIN;
{Injecter le processus distant}
functionInjectTo (Consthost, invité: chaîne; constpid: dword = 0): dword;
var
{Gandage du processus injecté, ID de processus}
Hremoteprocess: Thandle;
dwremoteprocessId: dword;
{Taille du contenu écrit au processus distant}
memSize: dword;
{Adresse après avoir écrit au processus distant}
pszlibfileleMote: pointeur;
ireturncode: booléen;
Tempvar: dword;
{Pointez à l'adresse de la fonction LoadLibraryW}
pfnstartAddr: tfNThreadStartTroutine;
{DLL PATH complet, doit être écrit dans la mémoire du processus distant}
pszlibafilename: pwidechar;
Commencer
Résultats: = 0;
{Définir les autorisations}
ActivéDebugPrivilege (true);
{Allouer la taille de la mémoire pour le chemin du fichier DLL injecté, car il est widEchar, il doit être multiplié par 2}
GetMem (pszlibafilename, longueur (invité) * 2 + 1);
StringTowideChar (invité, pszlibafiléname, longueur (invité) * 2 + 1);
{obtenir un ID de processus}
ifpid> 0ment
dwremoteprocesssid: = pid
autre
GetMyProcessId (hôte, false, dwremoteprocessId);
{Obtenez la poignée du processus distant, ayez une autorisation d'écriture}
hremoteprocess: = openProcess (process_create_thread + {permettre la création à distance de threads}
Process_vm_Operation + {Autoriser les opérations VM distantes}
Process_vm_write, {Autoriser l'écriture VM à distance}
False, dwremoteprocessId);
{Utilisez la fonction VirtualAllocex pour allouer l'espace dans le processus distant et écrivez le chemin de DLL dans WriteProcessMemory}
memSize: = (1 + lstrlenw (pszlibafilename)) * sizeof (wChar);
pszlibfileleMote: = pwidestring (virtualallocex (hremoteprocess, nil, memSize, mem_commit, page_readwrite));
Tempvar: = 0;
ireTurnCode: = writeProcessMemory (hremoteprocess, pszlibfileleMote, pszlibafilename, memsize, tempvar);
ifireurncodethen
Commencer
pfnstartAddr: = getProcaddress (getModuleHandle ('Kernel32'), 'LoadLibraryw');
Tempvar: = 0;
{Démarrer la DLL dans le processus distant}
Résultat: = CreateRemoteThread (hremoteprocess, nil, 0, pfnstartaddr, pszlibfileremote, 0, tempvar);
fin;
{Espace mémoire libre}
Freemem (pszlibafilename);
fin;
{test}
procéduretform1.button3click (expéditeur: tobject);
Commencer
InjectTo ('PrjzzHost.exe', ExtractFilePath (paramstr (0)) + 'TestDll.dll');
fin;
fin.
Le code ne considère pas les conséquences de la DLL en cours de charge.