It took an afternoon to turn MSDN, wrote this example, for safety, I used Delphi to build a program prjzzhost.exe, which used it as an injected host process.
Write a TestDLL.dll, there is only one log function to output information in file test.txt. The most important program Project1.exe is used to inject.
Test Environment: Windows Server 2003 Delphi 7.0
The procedure is very simple, the master doesn't have to look. Nonsense does not say, look at the code!
Test TestDLL.dll source code (it will be injected into Prjzzhost.exe):
code
Library TestDLL;
Uses
SYSUTILS,
SYSTEM,
Windows,
Classes;
Procedure log (s: pchar); stdcall;
VAR
F: TextFile;
Begin
AssignFile (f, 'test.txt');
If FileExists ('Test.txt') THEN APPEND (F)
Else Rewrite (f);
Writeln (f, s);
Closefile (f);
END;
Procedure DllenTryPoint (dwreason: dword);
Begin
Case dwreason
DLL_PROCESS_ATTACH:
Log ('DLL Process Attach');
DLL_PROCESS_DETACH:
Log ('DLL Process Detach');
DLL_THREAD_ATTACH:
LOG ('DLL Thread Attach');
DLL_THREAD_DETACH:
LOG ('DLL Thread Detach');
END;
END;
Exports
Log;
Begin
DllProc: = @dllentrypoint;
DLLLENTRYPOINT (DLL_PROCESS_ATTACH);
End.
The injected host process prjzzhost.exe (it doesn't work, so I don't give a code here, because it is too simple, haha.
Finally, the most important come:
Project1.exe source code:
code
Unit unit1;
Interface
Uses
Windows, Messages, Sysutils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Stdctrls, Tlhelp32;
Type
TLOG = procedure (s: pchar); stdcall;
TSERVICEMAIN = procedure (argc: integer; var argv: pchar); stdcall;
EDLLOADERROR = Class (Exception);
TFORM1 = Class (TFORM)
Button3: tbutton;
Procedure Button3Click (Sender: TOBJECT);
Private
{Private Declarations}
public
{Public declarations}
END;
VAR
FORM1: TFORM1;
IMPLEMentation
{$ R * .dfm}
{Listing process}
Procedure getmyProcessId (const); control; var processid: DWORD);
VAR
LPPE: TPROCESSENTRY32;
SSHANDLE: THANDLE;
Foundaproc, Foundok: Boolean;
Begin
ProcessID: = 0; {Create System Snapshot}
SSHANDLE: = CreateToolHelp32Snapshot (TH32CS_SNAPPROCESS, 0);
{Get the first process of snapshot}
{Must set the size of the structure, otherwise it will return false}
LPPE.DWSIZE: = Sizeof (TProcesSsentry32);
Foundaproc: = Process32First (Sshandle, LPPE);
While Foundaproc DO
Begin
{Match}
IF pathmatch then
Foundok: = ansistricomp (lppe.szexefile, pchar (afilename) = 0
Else
Foundok: = ansistricomp (pchar (extractfilename (lppe.szeexefile), pchar (extraventfileename)) = 0;
IF Foundok Then
Begin
ProcessID: = lppe.th32processid;
Break;
END;
{Not found, continue next process}
FOUNDAPROC: = Process32Next (SSHANDLE, LPPE);
END;
Closehandle (SSHANDLE);
END;
{ Setting permissions }
Function enableddebugprivilege (const enabled: boolean): boolean;
VAR
HTK: THANDLE; {Open token handle}
RTNTemp: DWORD; {Narrows returned when the permissions}
Tokenpri: Token_Privileges;
Const
SE_Debug = 'sedebugprivilege'; {Query value}
Begin
Result: = FALSE;
{Get Process Token Handle, Set Permissions}
IF (GetProcessToken (GetCurrentProcess (), Token_adjust_privileges, htk) THEN
Begin
Tokenpri.Privilegect: = 1;
{Get Luid value}
LookuppprivileValue (nil, se_debug, tokenpri.privileges [0] .luid);
IF enabled then
TokenPri.Privileges [0] .attributes: = SE_PRIVILE_ENENABED
Else
Tokenpri.Privileges [0] .attributes: = 0;
RTNTEMP: = 0;
{Set new permissions}
AdjustTokenPrivileges (HTK, False, Tokenpri, Sizeof (Tokenpri), NIL, RTNTemp);
Result: = getLastError = Error_suCcess;
CloseHandle (HTK);
END;
END;
{Debug function}
Procedure OutputText (VAR CH: PCHAR);
VAR
FileHandle: TextFile;
Begin
Assignfile (FileHandle, 'zztest.txt');
Append (filehandle);
Writeln (FileHandle, CH);
Flush (FileHandle);
Closefile (FileHandle);
END;
{Injection remote process}
Function InjectTo (Const Host, Guest: String; Const PID: DWORD = 0): DWORD; VAR
{Irotive process handle, process ID}
HREMOTEPROCESS: THANDLE;
DWREMOTEPROCESSID: DWORD;
{Write to the content size of the remote process}
Memsize: DWORD;
{Add to the address after the remote process}
Pszlibfileremote: POINTER;
IReturNCode: boolean;
Tempvar: DWORD;
{Point to function loadLibraryw's address}
PfnStartAddr: tfnthreadstartroutine;
{DLL full path, you need to write to the memory of the remote process to go}
Pszlibafilename: pwidechar;
Begin
Result: = 0;
{ Setting permissions }
Enableddebugprivilege (TRUE);
{Assign the memory size for the injected DLL file path, because it is widechar, so take 2}
GetMem (pszlibafilename, length (guest) * 2 1);
StringTowidechar (Guest, Pszlibafilename, Length (Guest) * 2 1);
{Get Process ID}
IF PID> 0 THEN
DWRemoteProcessid: = PID
Else
GetMyProcessId (Host, False, DwremoteProcessid);
{Get a remote process handle, have write authority}
HREMOTEPROCESS: = OpenProcess (Process_create_thread {Allow Remote Creating Threads}
Process_vm_operation {Allow Remote VM Operation}
Process_vm_write, {Allow Remote VM Write}
False, dwremoteprocessid;
{Function VirtualaLalkEx allocates space in remote process, and write DLL path in WriteProcessMemory}
Memsize: = (1 lstrlenw (pszlibafilename) * Sizeof (Wchar);
PszlibfileRemote: = PWIDESTRING (VirtualaLalkEx (HremoteProcess, NIL, Memsize, Mem_Commit, Page_Readwrite);
Tempvar: = 0;
IReturNCode: = WriteProcessMemory (HREMOTEPROCESS, PSZLIBFILEMOTE, PSZLIBAFILENAME, MEMSIZE, TEMPVAR);
IReturNCode Then
Begin
PfnStartaddr: = getProcaddress (GetModuleHandle ('kernel32'), 'loadLibraryw');
Tempvar: = 0;
{Start DLL} in the remote process
Result: = CreateRemoteThread (HremoteProcess, NIL, 0, PfnStartaddr, PszlibfileRemote, 0, Tempvar);
END;
{Release memory space}
FreeMem (pszlibafilename);
END;
{Test}
Procedure TFORM1.BUTTON3CLICK (Sender: TOBJECT);
Begin
INJECTTTO ('prjzhost.exe', extractfilepath (paramstr (0)) 'Testdll.dll';
End.
The code does not consider after the DLL is loaded, please do not use the system process to avoid accidents.