Code:
(*
- C++ DLL Injector Example (By Information Systems and Internet Security (ISIS) Laboratory)
- Delphi DLL Injector Example
Ported to delphi by: Sn!per X ^ AT4RE
Release date: 02-02-2016.
C++ Source: http://forum.exetools.com/showthread.php?t=17186
*)
program DLLInjector;
uses
Windows, SysUtils, TlHelp32, ShellAPI;
function GetProcessID(appname: string): DWORD;
{ Take only the application filename, not full path! }
var
snapshot: THandle;
processEntry: TProcessEntry32;
begin
Result := 0;
appName := UpperCase(appname);
snapshot := CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS,
0);
if snapshot <> 0 then
try
processEntry.dwSize := Sizeof(processEntry);
if Process32First(snapshot, processEntry) then
repeat
if Pos(appname,
UpperCase(ExtractFilename(
StrPas(processEntry.szExeFile)))) > 0 then
begin
Result := processEntry.th32ProcessID;
Break;
end; { If }
until not Process32Next(snapshot, processEntry);
finally
CloseHandle(snapshot);
end; { try }
end;
procedure InjectDLL(ExeName, DLLPath: pAnsichar);
// DLLPath : this will be the full filename of our attacking dll
var
ProcHandle: THANDLE; //a handle to the process we want to inject our dll into
ThreadHandle: THANDLE; //this will be a handle to the remote thread we will create
DllHandle: HMODULE; //a module handle to the dll we want to inject into a running process
ProcID: Integer; //this will be the process id of the process we want to inject our dll into
LoadLibraryAddr: Pointer; //the address of the load library function
BaseAddr : Pointer; // the base address of our arguments to loadlibrary function
BytesWritten: DWORD;
lpThreadId : DWORD;
begin
ProcID := GetProcessID(ExeName);
(*
Begin the dll injection process
1) get a handle to the process we want to inject our dll into
2) Get the address of the windows function LoadLibraryA function
3) Create the arguments structure to pass into our create thread function
4) Call CreateRemoteThread
*)
// 1. Get a handle to our process
ProcHandle := OpenProcess(PROCESS_ALL_ACCESS, //desired access
FALSE, //inherit handle, is this handle inheritable
ProcID //procid of the process
);
if (ProcHandle = 0) then
begin
MessageBox(0, 'Error, could not get a handle to the process', 'Error', MB_OK
or MB_ICONERROR);
Exit;
end;
try
//2. Get the address to LoadLibraryA
//2a. First get a handle to the Kernel32 dll, since this is where LoadLibraryA
DllHandle := GetModuleHandle('Kernel32.dll');
if (dllhandle = 0) then
begin
MessageBox(0, 'Error, could not get a handle to Kernel32.dll', 'Error', MB_OK
or MB_ICONERROR);
Exit;
end;
//2b. Now that we have the handle to kernel32 we just need to get
//the base address of the LoadLibraryA function
LoadLibraryAddr := GetProcAddress
(
dllhandle, //hmodule
'LoadLibraryA' //process name
);
if (LoadLibraryAddr = nil) then
begin
MessageBox(0, 'Error, unable to obtain the address to LoadLibraryA',
'Error', MB_OK or MB_ICONERROR);
Exit;
end;
//3. Allocate and fill in the memory we will use for our arguments to
// the remote thread
BaseAddr := VirtualAllocEx
(
ProcHandle, //handle to our process, which address space the mem is allocated in
nil, //address
256, //size of allocated memory
MEM_COMMIT or MEM_RESERVE, // allocation type
PAGE_READWRITE // protections
);
if (BaseAddr = nil) then
begin
MessageBox(0, 'Error, unable to allocate memory', 'Error', MB_OK or
MB_ICONERROR);
Exit;
end;
Try
//4. Fill in the memory allocated for our arguments
if WriteProcessMemory
(
ProcHandle, //handle to the process containing our allocated memory
BaseAddr, //the address of the memory location
DLLPath, //the actual argument characters
SizeOf(WideChar) * Length(DLLPath) + 1, //the size of the argument plus a null byte
BytesWritten //number of bytes written
) = false then
// this would be the condition that we weren't able to write to memory
begin
MessageBox(0, 'Error, could not write the arguments into memory', 'Error',
MB_OK or MB_ICONERROR);
exit;
end;
//5. Create a thread inside of our remote process we use this to get
// into the address space of a remote process
ThreadHandle := CreateRemoteThread
(
ProcHandle, //the handle to our remote process
nil, //thread attributes
0, //stack size
LoadLibraryAddr, //start address //(LPTHREAD_START_ROUTINE)
BaseAddr, //the address of our arg stack
0, //creation flags
lpThreadId //thread id
);
try
WaitForSingleObject(ThreadHandle, INFINITE);
finally
CloseHandle(ThreadHandle);
end;
finally
VirtualFreeEx(ProcHandle, BaseAddr, 0, MEM_RELEASE);
end;
finally
CloseHandle(ProcHandle);
end;
end;
begin
if ShellExecute(0, 'open', 'TestApp.exe', nil, nil, SW_SHOWNORMAL) <> 0 then
begin
Sleep(100); // Sleep so we make sure the TestApp.exe is fully executed
// You can avoid using Sleep by using WaitForSingleObject ...
InjectDLL('TestApp.exe', pChar(ExtractFilePath(ParamStr(0))+'\TestDLL.dll'));
end;
end.