CreateRemoteThread 运行没有错误,但没有任何反应
CreateRemoteThread runs with no error but nothing happens
我正在尝试将 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,
IntPtr.Zero,
false,
ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,
IntPtr.Zero,
null,
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, (IntPtr)0, loaderDllPointer, loaderPathPtr, 0, (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, loaderPathPtr, 0, MemoryFreeType.MEM_RELEASE);
}
}
还有 C++。这负责在 WPF 应用程序上调用方法并在 CLR 启动和 运行ning 后初始化它。我希望至少点击其中一个消息框调用,但没有显示任何内容。
#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, NULL,
NULL, &pcchVersion,
NULL, NULL,
&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()] = '[=11=]';
g_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadMain, NULL, 0, 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,
IntPtr dwAddress,
int nSize,
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;
}
}
}
你的注入器代码有很多问题:
通过CreateProcess()
(您可以使用它代替Process.GetProcessById()
)和CreateRemoteThread()
.
泄漏HANDLE
s输出
没有在远程进程中分配足够的字节来保存 loaderPath
字符串,也没有将足够的字节复制到远程进程中。分配内存时需要将loaderPath.Length
乘以2(aSystem.Char
的大小)。更好的解决方案是在调用 VirtualAllocEx()
之前调用 Encoding.Unicode.GetString()
,然后分配 bytes.length
个字节。但是,请注意 LoadLibraryW()
需要一个以 null 结尾的字符串,但您并未将 null 终止符复制到远程进程中。
在释放分配的内存之前不等待 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,
IntPtr.Zero,
false,
ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,
IntPtr.Zero,
null,
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") + "[=10=]";
var bytes = Encoding.Unicode.GetBytes(loaderPath);
var loaderPathPtr = VirtualAllocEx(
processInfo.hProcess,
IntPtr.Zero,
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, bytes.Length, 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,
IntPtr.Zero,
0,
loaderDllPointer,
loaderPathPtr,
0,
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, loaderPathPtr, 0, MemoryFreeType.MEM_RELEASE);
}
}
finally
{
CloseHandle(processInfo.hProcess);
}
}
}
也就是说,你的 C++ DLL 也是 doing things it shouldn't be doing in DllMain()
。
我正在尝试将 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,
IntPtr.Zero,
false,
ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,
IntPtr.Zero,
null,
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, (IntPtr)0, loaderDllPointer, loaderPathPtr, 0, (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, loaderPathPtr, 0, MemoryFreeType.MEM_RELEASE);
}
}
还有 C++。这负责在 WPF 应用程序上调用方法并在 CLR 启动和 运行ning 后初始化它。我希望至少点击其中一个消息框调用,但没有显示任何内容。
#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, NULL,
NULL, &pcchVersion,
NULL, NULL,
&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()] = '[=11=]';
g_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadMain, NULL, 0, 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,
IntPtr dwAddress,
int nSize,
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;
}
}
}
你的注入器代码有很多问题:
通过
泄漏CreateProcess()
(您可以使用它代替Process.GetProcessById()
)和CreateRemoteThread()
.HANDLE
s输出没有在远程进程中分配足够的字节来保存
loaderPath
字符串,也没有将足够的字节复制到远程进程中。分配内存时需要将loaderPath.Length
乘以2(aSystem.Char
的大小)。更好的解决方案是在调用VirtualAllocEx()
之前调用Encoding.Unicode.GetString()
,然后分配bytes.length
个字节。但是,请注意LoadLibraryW()
需要一个以 null 结尾的字符串,但您并未将 null 终止符复制到远程进程中。在释放分配的内存之前不等待
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,
IntPtr.Zero,
false,
ProcessCreationFlag.CREATE_DEFAULT_ERROR_MODE,
IntPtr.Zero,
null,
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") + "[=10=]";
var bytes = Encoding.Unicode.GetBytes(loaderPath);
var loaderPathPtr = VirtualAllocEx(
processInfo.hProcess,
IntPtr.Zero,
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, bytes.Length, 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,
IntPtr.Zero,
0,
loaderDllPointer,
loaderPathPtr,
0,
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, loaderPathPtr, 0, MemoryFreeType.MEM_RELEASE);
}
}
finally
{
CloseHandle(processInfo.hProcess);
}
}
}
也就是说,你的 C++ DLL 也是 doing things it shouldn't be doing in DllMain()
。