在托管应用程序中,我将托管dll注入notepad.exe(所有64位),然后调用dll的导出。但是必须有……。因为我的代码不对:
CreateRemoteThread
进入超时状态。那我在做什么错(请参见下面的源代码)?
class Injector
{
private string _dll = AppDomain.CurrentDomain.BaseDirectory + "MyDLL.dll";
public bool IsModuleInjected(int pid, string moduleName)
{
var process = Process.GetProcessById(pid);
foreach (ProcessModule module in process.Modules)
{
if (!module.FileName.Equals(_dll)) continue;
return true;
}
return false;
}
public bool Inject(int pid)
{
var process = Process.GetProcessById(pid);
if (IsModuleInjected(pid, _dll)) {
return false;
}
var hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id);
if (hProcess == IntPtr.Zero)
{
_log.Error("Opening process failed with '{0}'.",
new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var allocAddress = VirtualAllocEx(hProcess, IntPtr.Zero, (uint)Encoding.Unicode.GetByteCount(_dll.ToCharArray()), AllocationType.Commit, MemoryProtection.ReadWrite);
if (allocAddress == IntPtr.Zero) {
_log.Error("Allocating memory for '{0}' faild with '{1}'.", _dll, new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
if (!WriteProcessMemory(hProcess, allocAddress, Encoding.Unicode.GetBytes(_dll),
Encoding.Unicode.GetByteCount(_dll.ToCharArray()), out _))
{
_log.Error("Writing path to remote process failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var moduleHandle = GetModuleHandle("kernel32.dll");
if (moduleHandle == IntPtr.Zero) {
_log.Error("GetModuleHandle resulted in '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var procAddress = GetProcAddress(moduleHandle, "LoadLibraryW");
if (procAddress == IntPtr.Zero) {
_log.Error("Getting address failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var hRemoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, procAddress, allocAddress, 0, IntPtr.Zero);
if (hRemoteThread == IntPtr.Zero) {
_log.Error("Creating remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var result = WaitForSingleObject(hRemoteThread, int.MaxValue);
switch ((WaitForSingleObjectReturnValues)result)
{
case WaitForSingleObjectReturnValues.WaitFailed:
_log.Error("Waiting for remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
case WaitForSingleObjectReturnValues.Timeout:
_log.Error("Timeout while waiting for remote thread with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
if (!VirtualFreeEx(hProcess, allocAddress, Encoding.Unicode.GetByteCount(_dll), AllocationType.Decommit))
{
_log.Error("Freeing memory for dll path failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
if (!CloseHandle(hProcess))
{
_log.Error("Closing process handle failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
return true;
}
public bool Eject(int pid)
{
var process = Process.GetProcessById(pid);
ProcessModule targetModule = null;
foreach (ProcessModule module in process.Modules)
{
if (module.FileName.Equals(_dll))
{
targetModule = module;
}
}
if (targetModule == null)
{
_log.Warn("Module '{0}' not inside process. Not calling.", _dll);
return false;
}
var hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id);
if (hProcess == IntPtr.Zero)
{
_log.Error("Opening process failed with '{0}'.",
new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var moduleHandle = GetModuleHandle("kernel32.dll");
if (moduleHandle == IntPtr.Zero)
{
_log.Error("GetModuleHandle resulted in '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var procAddress = GetProcAddress(moduleHandle, "FreeLibrary");
if (procAddress == IntPtr.Zero)
{
_log.Error("Getting address failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var hRemoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, procAddress, targetModule.BaseAddress, 0, IntPtr.Zero);
if (hRemoteThread == IntPtr.Zero)
{
_log.Error("Creating remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var result = WaitForSingleObject(hRemoteThread, 10 * 1000);
switch ((WaitForSingleObjectReturnValues)result)
{
case WaitForSingleObjectReturnValues.WaitFailed:
_log.Error("Waiting for remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
case WaitForSingleObjectReturnValues.Timeout:
_log.Error("Timeout while waiting for remote thread with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
return true;
}
public bool Call(int pid)
{
var process = Process.GetProcessById(pid);
ProcessModule targetModule = null;
foreach (ProcessModule module in process.Modules)
{
if (module.FileName.Equals(_dll))
{
targetModule = module;
}
}
if (targetModule == null)
{
_log.Warn("Module '{0}' not inside process. Not calling.", _dll);
return false;
}
var hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id);
if (hProcess == IntPtr.Zero)
{
_log.Error("Opening process failed with '{0}'.",
new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var hLoaded = LoadLibraryEx(_dll, IntPtr.Zero, LoadLibraryFlags.DontResolveDllReferences);
if (hLoaded == IntPtr.Zero) {
_log.Error("Failed loading library with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var procAddress = GetProcAddress(hLoaded, "ShowMessage");
if (procAddress == IntPtr.Zero)
{
_log.Error("Getting address failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var offset = (ulong)procAddress - (ulong)hLoaded;
if (!FreeLibrary(hLoaded))
{
_log.Error("Unloading library failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var hRemoteThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, (IntPtr)((ulong)targetModule.BaseAddress + offset), IntPtr.Zero, 0, IntPtr.Zero);
if (hRemoteThread == IntPtr.Zero)
{
_log.Error("Creating remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
var result = WaitForSingleObject(hRemoteThread, 10 * 1000);
switch ((WaitForSingleObjectReturnValues)result)
{
case WaitForSingleObjectReturnValues.WaitFailed:
_log.Error("Waiting for remote thread failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
case WaitForSingleObjectReturnValues.Timeout:
_log.Error("Timeout while waiting for remote thread with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
if (CloseHandle(hProcess)) return true;
_log.Error("Closing process handle failed with '{0}'.", new Win32Exception(Marshal.GetLastWin32Error()).Message);
return false;
}
}