I'm using this code to inject my 64bit dll into a 64bit process on windows 7 64 bit,CreateRemoteThread return 200 but still the dll does not injected, I tested my dll with another source and it works fine, Process Explorer shows that my code does not work,What can be wrong with this code, I'm using delphi XE3 and i have compile the code on 64bit target platform.
function InjectDLL(dwPID: DWORD; DLLPath: pwidechar): integer;
var
dwThreadID: Cardinal;
hProc, hThread, hKernel: NativeUInt;
BytesWritten: NativeUInt;
pRemoteBuffer, pLoadLibrary: Pointer;
begin
try
hProc := OpenProcess(PROCESS_ALL_ACCESS, False, dwPID);
if hProc = 0 then
begin
Result := 0;
Exit;
end;
pRemoteBuffer := VirtualAllocEx(hProc, nil, Length(DLLPath) + 1, MEM_COMMIT,
PAGE_READWRITE);
if pRemoteBuffer = nil then
begin
Result := 0;
Exit;
end;
if WriteProcessMemory(hProc, Pointer(pRemoteBuffer), lpvoid(DLLPath),
Length(DLLPath) + 1, BytesWritten) = False then
begin
Result := 0;
Exit;
end;
hKernel := GetModuleHandle(pwidechar('kernel32.dll'));
pLoadLibrary := (GetProcAddress(hKernel, pansichar('LoadLibraryA')));
hThread := CreateRemoteThread(hProc, Pointer(nil), 0, Pointer(pLoadLibrary),
Pointer(pRemoteBuffer), 0, dwThreadID);
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProc, Pointer(pRemoteBuffer), Length(DLLPath) + 1,
MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProc);
// ShowMessage(IntToStr(hThread)+' '+ inttostr(dwThreadID));
Result := 1;
except
on d: exception do
begin
end;
end;
end;
You are calling LoadLibraryA
, but passing it UTF-16 encoded data. Either switch to LoadLibraryW
or convert the module name to ANSI.
I would do the former. As well as switching to LoadLibraryW
, you need to copy the entire buffer. Achieve that by replacing the two instances of Length(DLLPath) + 1
with SizeOf(Char)*(Length(DLLPath) + 1)
.
Some more comments:
- Using
PROCESS_ALL_ACCESS
is excessive. You only need PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ
.
- The
PAnsiChar
cast in GetProcAddress(hKernel, pansichar('LoadLibraryA'))
looks wrong. Because 'LoadLibraryA'
is UTF-16 encoded. Just use GetProcAddress(hKernel, 'LoadLibraryA')
. Or 'LoadLibraryW'
if you go down that route.
- Using
NativeUInt
for handles is wrong. It doesn't actually matter, but you should use THandle
.
- When using
MEM_RELEASE
you must pass 0
for the size parameter.
Put that all together and the code should look like this:
function InjectDLL(dwPID: DWORD; DLLPath: PWideChar): integer;
var
dwThreadID: Cardinal;
hProc, hThread, hKernel: THandle;
BytesToWrite, BytesWritten: SIZE_T;
pRemoteBuffer, pLoadLibrary: Pointer;
begin
hProc := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, False, dwPID);
if hProc = 0 then
exit(0);
try
BytesToWrite := SizeOf(WideChar)*(Length(DLLPath) + 1);
pRemoteBuffer := VirtualAllocEx(hProc, nil, BytesToWrite, MEM_COMMIT, PAGE_READWRITE);
if pRemoteBuffer = nil then
exit(0);
try
if not WriteProcessMemory(hProc, pRemoteBuffer, DLLPath, BytesToWrite, BytesWritten) then
exit(0);
hKernel := GetModuleHandle('kernel32.dll');
pLoadLibrary := GetProcAddress(hKernel, 'LoadLibraryW');
hThread := CreateRemoteThread(hProc, nil, 0, pLoadLibrary, pRemoteBuffer, 0, dwThreadID);
try
WaitForSingleObject(hThread, INFINITE);
finally
CloseHandle(hThread);
end;
finally
VirtualFreeEx(hProc, pRemoteBuffer, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProc);
end;
exit(1);
end;
Personally, I'd probably pass in a string
rather than a PWideChar
, but perhaps you have some other motivation for doing that.