在CodeProject(Link)上,我读到了使用CreateRemoteThread
和WriteProcessMemory
在另一个进程中注入代码。
- 将HANDLE检索到远程进程(OpenProces)。
- 在远程进程的地址空间中为注入数据分配内存(VirtualAllocEx)。
- 将初始化的INJDATA结构的副本写入分配的内存(WriteProcessMemory)。
- 在远程进程的地址空间中为注入的代码分配内存。
- 将ThreadFunc的副本写入分配的内存。
- 通过CreateRemoteThread启动ThreadFunc的远程副本。
- 等到远程线程终止(WaitForSingleObject)。
- 从远程进程(ReadProcessMemory或GetExitCodeThread)中检索结果。
- 释放步骤#2和#4(VirtualFreeEx)中分配的内存。 块引用
- 关闭步骤#6和#1(CloseHandle)中检索到的句柄。
醇>
由于INJDATA是一个结构,我假设任何类型的参数/变量/记录都可以。
它写得非常好但是我很难将其转换为Delphi。
所以我想在notepad.exe中注入我的程序GetNumber
,该程序显示我可以在记录中声明的数字。
type
TInjectData = record
FNumber: Integer;
end;
procedure GetNumber(var pData: TInjectData);
begin
MessageBoxA(0, PChar(IntToStr(pData.FNumber)), '', 0);
end;
我写了一个应该完成工作的函数InjectCode
。
procedure InjectCode;
var
hWindow: THandle;
dwProcId: Cardinal;
hProcess: THandle;
hThread: THandle;
myData: TInjectData;
pDataRemote, pCodeRemote: Pointer;
dwBytesWritten: DWORD;
cbCodeSize: Integer;
dwThreadId: DWORD;
begin
myData.FNumber := 42;
hWindow := FindWindow('Notepad', nil);
ShowMessage(Format('hWindow: %d', [hWindow]));
GetWindowThreadProcessId(hWindow, dwProcId);
ShowMessage(Format('dwProcId: %d', [dwProcId]));
// 1. Retrieve a HANDLE to the remote process (OpenProces)
hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or
PROCESS_VM_OPERATION or PROCESS_VM_WRITE, False, dwProcId);
ShowMessage(Format('hProcess: %d', [hProcess]));
// 2. Allocate memory in the remote process's address space for injected data (VirtualAllocEx)
// pDataRemote = the address (in the remote process) where myData will be copied to
pDataRemote := VirtualAllocEx(hProcess, nil, SizeOf(myData), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ShowMessage(Format('pDataRemote: %d', [Integer(pDataRemote)]));
// 3. Write a copy of the initialised INJDATA structure to the allocated memory (WriteProcessMemory)
WriteProcessMemory(hProcess, pDataRemote, @myData, SizeOf(myData), dwBytesWritten);
ShowMessage(Format('dwBytesWritten pDataRemote: %d', [dwBytesWritten]));
// Calculate the number of bytes that ThreadFunc occupies
// cbCodeSize = LPBYTE(AfterGetNumber) - LPBYTE(GetNumber);
cbCodeSize := 2500; // correct calculation not yet implemented
// 4. Allocate memory in the remote process's address space for injected code
pCodeRemote := VirtualAllocEx(hProcess, nil, cbCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ShowMessage(Format('pCodeRemote: %d', [Integer(pCodeRemote)]));
// 5. Write a copy of GetNumber to the allocated memory
WriteProcessMemory(hProcess, pCodeRemote, @GetNumber, cbCodeSize, dwBytesWritten);
ShowMessage(Format('dwBytesWritten pCodeRemote: %d', [dwBytesWritten]));
// 6. Start the remote copy of GetNumber via CreateRemoteThread
hThread := CreateRemoteThread(hProcess, nil, 0, pCodeRemote, pDataRemote, 0, dwThreadId);
ShowMessage(Format('hThread: %d', [hThread]));
ShowMessage(Format('dwThreadId: %d', [dwThreadId]));
// 7. Wait until the remote thread terminates (WaitForSingleObject)
WaitForSingleObject(hThread, INFINITE);
// 8. Retrieve the result from the remote process (ReadProcessMemory or GetExitCodeThread).
// not needed in this example
// 9. Free the memory allocated in Steps #2 and #4 (VirtualFreeEx)
if Assigned(pDataRemote) then
VirtualFreeEx(hProcess, pDataRemote, 0, MEM_RELEASE );
if Assigned(pCodeRemote) then
VirtualFreeEx(hProcess, pCodeRemote, 0, MEM_RELEASE );
// 10. Close the handles retrieved in Steps #6 and #1 (CloseHandle).
if hProcess <> 0 then
CloseHandle(hProcess);
if hThread <> 0 then
CloseHandle(hThread);
end;
但每当我调用该过程时,都不会出现MessageBox。 我没有代码注入的经验,所以请耐心等待,因为我已经花了几天时间试图解决这个问题。
感谢任何帮助。
答案 0 :(得分:3)
您尚未执行任何错误检查。所以你不知道代码是如何失败的。你需要养成检查错误的习惯。
您还应该知道,在注入远程线程时,调用约定很重要。您必须提供具有此签名的线程函数:
IntToStr
另一个问题是目标进程是记事本,肯定是64位进程。你无法注入。来自32位进程的64位进程。当然不是32位代码!
但是,一旦修复了所有错误,您的代码仍然无法正常工作。那是因为你注入的函数依赖于存在的Delphi RTL。它链接到Windows API函数。它调用PChar()
。它执行public void Print() {
Database db = new Database();
ResultSet rs = null;
rs = db.getData("SELECT * FROM my_table"
+ "INTO OUTFILE 'E:\\kurtcobain.csv'"
+ "FIELDS TERMINATED BY ','"
+ "ENCLOSED BY '"'"
+ "LINES TERMINATED BY '+\n+'")";
演员表演。所有这些都需要Delphi RTL。更重要的是,它们需要RTL驻留在它在注入器中的地址,因为它是静态链接的。
要以这种方式注入代码,代码必须独立存在。如果你想了解注射,你应该首先注入一个更容易的DLL。
答案 1 :(得分:0)
目标进程不需要具有相同的kernel32.MessageBoxA地址,可能就是这样。在使用之前我会在notepad.exe中获取地址。