如何解决CreateRemoteThread 运行没有错误但没有任何反应
我正在尝试将 C++ dll 注入到进程中,并且我正在使用 C# 控制台应用程序来运行它。我的问题是程序运行了但似乎没有任何反应,写入成功并且没有引发 win32 错误。
class Program
{
static void Main()
{
var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var bootstrapperSettingsFilePath = Path.Combine(currentFolder,"bootstrapperSettings.json");
var bootstrapperSettings = JsonConvert.DeserializeObject<BootstrapperSettings>(File.ReadAllText(bootstrapperSettingsFilePath));
var startupInfo = new STARTUPINFO();
CreateProcess(
bootstrapperSettings.TargetPath,null,IntPtr.Zero,false,ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,ref startupInfo,out PROCESS_informatION processInfo);
Thread.Sleep(1000);
var processHandle = Process.GetProcessById((int)processInfo.dwProcessId).Handle;
var loaderPath = Path.Combine(currentFolder,"Loader.dll");
var loaderPathPtr = VirtualAllocEx(
processHandle,(IntPtr)0,loaderPath.Length,MemoryAllocationType.MEM_COMMIT,MemoryProtectionType.PAGE_EXECUTE_READWRITE);
Thread.Sleep(500);
int error = Marshal.GetLastWin32Error();
if (error > 0)
throw new InvalidOperationException($"Failed to allocate memory for Loader.dll,error code: {error}");
var bytes = Encoding.Unicode.GetBytes(loaderPath);
var bytesWritten = 0;
WriteProcessMemory(processHandle,loaderPathPtr,bytes,bytes.Length,ref bytesWritten);
Thread.Sleep(1000);
error = Marshal.GetLastWin32Error();
if (error > 0 || bytesWritten == 0)
throw new InvalidOperationException($"Failed to write Loader.dll into the process,error code: {error}");
var loaderDllPointer = GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryW");
Thread.Sleep(1000);
error = Marshal.GetLastWin32Error();
if (error > 0)
throw new InvalidOperationException($"Failed to get memory address to Loader.dll in the process,error code: {error}");
CreateRemoteThread(processHandle,(IntPtr)null,loaderDllPointer,(IntPtr)null);
Thread.Sleep(1000);
error = Marshal.GetLastWin32Error();
if (error > 0)
throw new InvalidOperationException($"Failed to create remote thread to start execution of Loader.dll in the process,error code: {error}");
VirtualFreeEx(processHandle,MemoryFreeType.MEM_RELEASE);
}
}
还有 C++。这负责调用 WPF 应用程序上的方法,并在 CLR 启动并运行后对其进行初始化。我希望至少在此中点击一个消息框调用,但没有显示任何内容。
#define WIN32_LEAN_AND_MEAN
#define FOR_DOTNET_4
#include <Windows.h>
#include <process.h>
#include <string>
#ifdef FOR_DOTNET_4
#include <Metahost.h>
#else
#include <mscoree.h>
#endif
#include "CorError.h"
#pragma comment( lib,"mscoree" )
#define LOAD_DLL_FILE_NAME L"InjectionTest1.exe"
#define NAMESPACE_AND_CLASS L"InjectionTest1.Loader"
#define MAIN_METHOD L"Load"
#define MAIN_METHOD_ARGS L"NONE"
HMODULE g_myDllModule = NULL;
ICLRMetaHostPolicy* g_pMetaHost = NULL;
ICLRRuntimeInfo* g_pRuntimeInfo = NULL;
ICLRRuntimeHost* g_clrHost = NULL;
HANDLE g_hThread = NULL;
wchar_t* dllLocation = NULL;
#define MB(s) MessageBoxW(NULL,s,NULL,MB_OK);
unsigned __stdcall ThreadMain(void* pParam)
{
MB(L"Test");
HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHostPolicy,IID_ICLRMetaHostPolicy,(LPVOID*)&g_pMetaHost);
if (Failed(hr))
{
MB(L"Could not create instance of ICLRMetaHost");
return 1;
}
DWORD pcchVersion = 0;
DWORD dwConfigFlags = 0;
hr = g_pMetaHost->GetRequestedRuntime(MetaHOST_POLICY_HIGHCOMPAT,dllLocation,&pcchVersion,&dwConfigFlags,IID_ICLRRuntimeInfo,(LPVOID*)&g_pRuntimeInfo);
if (Failed(hr))
{
if (hr == E_POINTER)
{
MB(L"Could not get an instance of ICLRRuntimeInfo -- E_POINTER");
}
else if (hr == E_INVALIDARG)
{
MB(L"Could not get an instance of ICLRRuntimeInfo -- E_INVALIDARG");
}
else
{
wchar_t buff[1024];
wsprintf(buff,L"Could not get an instance of ICLRRuntimeInfo -- hr = 0x%lx -- Is DomainManager.dll present?",hr);
MB(buff);
}
return 1;
}
hr = g_pRuntimeInfo->BindAsLegacyV2Runtime();
if (Failed(hr))
{
MB(L"Failed to bind as legacy v2 runtime! (.NET 3.5 Mixed-Mode Support)");
return 1;
}
hr = g_pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,IID_ICLRRuntimeHost,(LPVOID*)&g_clrHost);
if (Failed(hr))
{
MB(L"Could not get an instance of ICLRRuntimeHost!");
return 1;
}
hr = g_clrHost->Start();
if (Failed(hr))
{
MB(L"Failed to start the CLR!");
return 1;
}
DWORD dwRet = 0;
hr = g_clrHost->ExecuteInDefaultAppDomain(dllLocation,NAMESPACE_AND_CLASS,MAIN_METHOD,MAIN_METHOD_ARGS,&dwRet);
if (Failed(hr))
{
MB(L"Failed to execute in the default app domain!");
switch (hr)
{
case HOST_E_CLRNOTAVAILABLE:
MB(L"CLR Not available");
break;
case HOST_E_TIMEOUT:
MB(L"Call timed out");
break;
case HOST_E_NOT_OWNER:
MB(L"Caller does not own lock");
break;
case HOST_E_ABANDONED:
MB(L"An event was canceled while a blocked thread or fiber was waiting on it");
break;
case E_FAIL:
MB(L"Unspecified catastrophic failure");
break;
default:
char buff[128];
sprintf(buff,"Result is: 0x%lx",hr);
MessageBoxA(NULL,buff,"Info",0);
break;
}
return 1;
}
return 0;
}
void LoadClr()
{
wchar_t buffer[255];
if (!GetmodulefileNameW(g_myDllModule,buffer,255))
return;
std::wstring modulePath(buffer);
modulePath = modulePath.substr(0,modulePath.find_last_of('\\') + 1);
modulePath = modulePath.append(LOAD_DLL_FILE_NAME);
dllLocation = new wchar_t[modulePath.length() + 1];
MB((modulePath).c_str());
wcscpy(dllLocation,modulePath.c_str());
dllLocation[modulePath.length()] = '\0';
g_hThread = (HANDLE)_beginthreadex(NULL,ThreadMain,NULL);
}
BOOL WINAPI DllMain(HMODULE hDll,DWORD dwReason,LPVOID lpReserved)
{
g_myDllModule = hDll;
if (dwReason == DLL_PROCESS_ATTACH)
{
MB(L"Loading");
LoadClr();
}
else if (dwReason == DLL_PROCESS_DETACH)
{
if (g_clrHost)
{
g_clrHost->Stop();
g_clrHost->Release();
}
if (g_hThread)
{
TerminateThread(g_hThread,0);
CloseHandle(g_hThread);
}
}
return TRUE;
}
进口:
using System;
using System.Runtime.InteropServices;
namespace Bootstrapper
{
static class WinImports
{
[DllImport("kernel32.dll")]
internal static extern bool CreateProcess(
string lpApplicationName,string lpCommandLine,IntPtr lpProcessAttributes,IntPtr lpThreadAttributes,bool bInheritHandles,ProcessCreationFlag dwCreationFlags,IntPtr lpEnvironment,string lpCurrentDirectory,ref STARTUPINFO lpStartupInfo,out PROCESS_informatION lpProcessinformation);
[DllImport("kernel32.dll")]
internal static extern IntPtr GetProcAddress(IntPtr hModule,string procName);
[DllImport("kernel32.dll")]
internal static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll",SetLastError = true)]
internal static extern UInt32 WaitForSingleObject(IntPtr hHandle,UInt32 dwMilliseconds);
[DllImport("kernel32.dll",SetLastError = true)]
internal static extern bool CloseHandle(IntPtr hHandle);
[DllImport("kernel32.dll")]
internal static extern IntPtr VirtualAllocEx(
IntPtr hProcess,IntPtr dwAddress,int nSize,MemoryAllocationType dwAllocationType,MemoryProtectionType dwProtect);
[DllImport("kernel32.dll")]
internal static extern bool WriteProcessMemory(
IntPtr hProcess,IntPtr lpBaseAddress,byte[] lpBuffer,int dwSize,ref int lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
internal static extern IntPtr CreateRemoteThread(
IntPtr hProcess,IntPtr lpThreadAttribute,IntPtr dwStackSize,IntPtr lpStartAddress,IntPtr lpParameter,uint dwCreationFlags,IntPtr lpThreadId);
[DllImport("kernel32.dll")]
internal static extern bool VirtualFreeEx(
IntPtr hProcess,MemoryFreeType dwFreeType);
internal enum MemoryAllocationType
{
MEM_COMMIT = 0x1000
}
internal enum MemoryProtectionType
{
PAGE_EXECUTE_READWRITE = 0x40
}
internal enum MemoryFreeType
{
MEM_RELEASE = 0x8000
}
internal enum ProcessCreationFlag
{
CREATE_DEFAULT_ERROR_MODE = 0x04000000
}
internal struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
internal struct PROCESS_informatION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
}
}
解决方法
您的注入器代码有很多问题:
-
通过
HANDLE
(您可以使用它代替CreateProcess()
)和Process.GetProcessById()
泄漏CreateRemoteThread()
的输出。 -
没有在远程进程中分配足够的字节来保存
loaderPath
字符串,并且没有将足够的字节复制到远程进程中。分配内存时,您需要将loaderPath.Length
乘以 2(System.Char
的大小)。更好的解决方案是在调用Encoding.Unicode.GetString()
之前调用VirtualAllocEx()
,然后分配bytes.length
个字节。但是,请注意,LoadLibraryW()
需要一个以空字符结尾的字符串,但您并没有将空终止符复制到远程进程中。 -
在释放分配的内存之前不等待
LoadLibraryW()
实际完成运行(即远程线程终止)。 -
错误处理不正确。
-
对
Thread.Sleep()
的调用是不必要的,应该删除。
尝试更像这样的事情:
class Program
{
static void Main()
{
var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var bootstrapperSettingsFilePath = Path.Combine(currentFolder,"bootstrapperSettings.json");
var bootstrapperSettings = JsonConvert.DeserializeObject<BootstrapperSettings>(File.ReadAllText(bootstrapperSettingsFilePath));
var startupInfo = new STARTUPINFO();
if (!CreateProcess(
bootstrapperSettings.TargetPath,null,IntPtr.Zero,false,ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,ref startupInfo,out PROCESS_INFORMATION processInfo))
{
throw new InvalidOperationException($"Failed to start process,error code: {Marshal.GetLastWin32Error()}");
}
CloseHandle(processInfo.hThread);
try
{
var loaderPath = Path.Combine(currentFolder,"Loader.dll") + "\0";
var bytes = Encoding.Unicode.GetBytes(loaderPath);
var loaderPathPtr = VirtualAllocEx(
processInfo.hProcess,bytes.Length,MemoryAllocationType.MEM_COMMIT,MemoryProtectionType.PAGE_EXECUTE_READWRITE);
if (loaderPathPtr == IntPtr.Zero)
throw new InvalidOperationException($"Failed to allocate memory for Loader.dll,error code: {Marshal.GetLastWin32Error()}");
try
{
var bytesWritten = 0;
if (!WriteProcessMemory(processHandle,loaderPathPtr,bytes,ref bytesWritten))
{
throw new InvalidOperationException($"Failed to write Loader.dll path into the process,error code: {Marshal.GetLastWin32Error()}");
}
if (bytesWritten != bytes.Length)
throw new InvalidOperationException("Failed to write all bytes of Loader.dll path into the process");
var loaderDllPointer = GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryW");
if (loaderDllPointer == IntPtr.Zero)
throw new InvalidOperationException($"Failed to get memory address to Loader.dll in the process,error code: {Marshal.GetLastWin32Error()}");
var hRemoteThread = CreateRemoteThread(
processInfo.hProcess,loaderDllPointer,IntPtr.Zero);
if (hRemoteThread == IntPtr.Zero)
{
throw new InvalidOperationException($"Failed to create remote thread to start execution of Loader.dll in the process,error code: {Marshal.GetLastWin32Error()}");
}
WaitForSingleObject(hRemoteThread,INFINITE);
CloseHandle(hRemoteThread);
}
finally
{
VirtualFreeEx(processInfo.hProcess,MemoryFreeType.MEM_RELEASE);
}
}
finally
{
CloseHandle(processInfo.hProcess);
}
}
}
也就是说,您的 C++ DLL 也是 doing things it shouldn't be doing in DllMain()
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。