【发布时间】:2015-04-26 06:30:59
【问题描述】:
我正在尝试实现 IAT 挂钩。我在 dll 中编写了 IAT 部分,并使用 CreateRemoteThread 在 exe 中编写了注入部分。我发现注入 dll 后,IAT 部分的 VirtualProtect 函数总是抛出 ERROR_INVALID_PRAMETER,即使我使用刚刚从 VirtualQuery 返回的值传递参数。我不知道发生了什么。 VirtualProtect 是否需要一些我没有的权限?
这是错误部分:
if (0 == lstrcmpA(lpApiName, (LPCSTR)pImport->Name)){
MEMORY_BASIC_INFORMATION thunkMemInfo;
DWORD junk;
DWORD oldProtect;
if (!VirtualQuery(thunk, &thunkMemInfo, sizeof(MEMORY_BASIC_INFORMATION))){
return GetLastError();
}
if (!VirtualProtect(thunkMemInfo.BaseAddress, thunkMemInfo.RegionSize, thunkMemInfo.Protect, &oldProtect)){
return GetLastError(); -------Here returns 87 in decimal
}
MessageBoxA(NULL, "aaaa", "Hooked", MB_OK);
thunk->u1.Function = (DWORD)Callback;
MessageBoxA(NULL, "bbbbb", "Hooked", MB_OK);
if (!VirtualProtect(&thunk, thunkMemInfo.RegionSize, oldProtect, &junk)){
return 3;
}
return S_OK;
}
而我在 C# 中的注入部分是这样的:
public static void InjectDLL(IntPtr hProcess, String strDLLName, Process proc)
{
IntPtr bytesout;
// Length of string containing the DLL file name +1 byte padding
Int32 LenWrite = strDLLName.Length + 1;
// Allocate memory within the virtual address space of the target process
IntPtr AllocMem = (IntPtr)VirtualAllocEx(hProcess, (IntPtr)null, (uint)LenWrite, 0x1000, 0x40); //allocation pour WriteProcessMemory
// Write DLL file name to allocated memory in target process
WriteProcessMemory(hProcess, AllocMem, strDLLName, (UIntPtr)LenWrite, out bytesout);
// Function pointer "Injector"
UIntPtr Injector = (UIntPtr)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (Injector == null)
{
Console.WriteLine(" Injector Error! \n ");
// return failed
return;
}
// Create thread in target process, and store handle in hThread
IntPtr hThread = (IntPtr)CreateRemoteThread(hProcess, (IntPtr)null, 0, Injector, AllocMem, 0, out bytesout);
// Make sure thread handle is valid
if (hThread == null)
{
//incorrect thread handle ... return failed
Console.WriteLine(" hThread [ 1 ] Error! \n ");
return;
}
// Time-out is 10 seconds...
int Result = WaitForSingleObject(hThread, 10 * 1000);
// Check whether thread timed out...
if (Result == 0x00000080L || Result == 0x00000102L || Result == 0xFFFFFFFFL)
{
/* Thread timed out... */
Console.WriteLine(" hThread [ 2 ] Error! \n ");
// Make sure thread handle is valid before closing... prevents crashes.
if (hThread != null)
{
//Close thread in target process
CloseHandle(hThread);
}
return;
}
// Sleep thread for 1 second
Thread.Sleep(1000);
// Clear up allocated space ( Allocmem )
VirtualFreeEx(hProcess, AllocMem, (UIntPtr)0, 0x8000);
// Make sure thread handle is valid before closing... prevents crashes.
if (hThread != null)
{
//Close thread in target process
CloseHandle(hThread);
}
// return succeeded
ResumeThread(hThread);
System.Windows.MessageBox.Show("Inject!");
return;
}
Process proc = Process.GetProcessesByName(exeName)[0];
// System.Windows.MessageBox.Show(proc.ProcessName + "Start!");
uint dwAccl = 0x0002 | 0x0400 | 0x0008 | 0x0010 |0x0020;
InjectDLL((IntPtr)tools.OpenProcess(dwAccl, 1, proc.Id), "Loader.dll", proc);
【问题讨论】:
-
您必须始终检查 winapi 函数的返回值。像 OpenProcess()。不这样做只会产生 SO 问题。那个 (IntPtr) 演员从根本上也是错误的,它没有正确声明。而且你使用了错误的winapi函数,弄乱另一个进程需要VirtualQueryEx和VirtualProtectEx,它们取进程句柄。
-
@HansPassant 为什么 (IntPtr) 转换错误?如果我没记错的话,他使用的是
HANDLE,它在C#中的等价物是IntPtr。 -
@HansPassant 抱歉,我忘了提供 OpenProcess()。它是 public static extern IntPtr OpenProcess( UInt32 dwDesiredAccess, Int32 bInheritHandle, Int32 dwProcessId );
-
thunkMemInfo.State在VirtualProtect之前的值是多少? -
@ElderBug 嗨,thunkMeminfo.State 是 0x1000