我不太明白发生了什么,但我会解释这个问题。我正在尝试编写一个IAT钩子程序,它在IAT中切换MessageBoxA函数的地址,使其指向我的函数,一个恶意的函数。
下面是我的代码,注释:#include <Windows.h>
#include <stdio.h>
typedef int(__stdcall* FunctionLikeMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
FunctionLikeMessageBoxA originalMsgBoxA = MessageBoxA; // the original MessageBoxA function, before IAT hooking.
int print_evil(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
printf("Evil print");
Sleep(1000);
return originalMsgBoxA(hWnd, lpText, lpCaption, uType);
}
int main()
{
// message box before IAT unhooking
MessageBoxA(NULL, "Before Hooking", "Before Hooking", 0);
LPVOID imageBase = GetModuleHandleA(NULL); // image base, start of the loaded code (?)
PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)imageBase; // dos headers
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeaders->e_lfanew); // ntHeaders are in e_lfanew
PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;
IMAGE_DATA_DIRECTORY importsDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; // IAT
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)imageBase); // img descriptor
LPCSTR currentLibraryName = NULL;
HMODULE loadedLibrary = NULL;
PIMAGE_IMPORT_BY_NAME functionName = NULL;
while (importDescriptor->Name != NULL) // run until library name is not null, meaning we have libraries
{
currentLibraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)imageBase; // get name of library
loadedLibrary = LoadLibraryA(currentLibraryName); // loading the dll library
if (loadedLibrary)
{
PIMAGE_THUNK_DATA originalFirstThunk = NULL;
PIMAGE_THUNK_DATA firstThunk = NULL;
// thunk where the functions are located (?)
originalFirstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->OriginalFirstThunk); // the INT (Names)
firstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->FirstThunk); // the IAT (Addresses)
while (originalFirstThunk->u1.AddressOfData != NULL) // run until function name is not null, meaning we have functions
{
functionName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)imageBase + originalFirstThunk->u1.AddressOfData); // name of function
// if name is MessageBoxA, what we need, then switch the Function address of the function in the IAT, to our function.
if (strcmp(functionName->Name, "MessageBoxA") == 0)
{
DWORD oldProtect = 0;
VirtualProtect((LPVOID)(&firstThunk->u1.Function), 8, PAGE_READWRITE, &oldProtect);
firstThunk->u1.Function = (DWORD_PTR)print_evil;
DWORD newProtect = 0;
VirtualProtect((LPVOID)(&firstThunk->u1.Function), 8, oldProtect, &newProtect);
}
// increase to go over the next functions.
originalFirstThunk++;
firstThunk++;
}
}
// increase to go over the next dlls.
importDescriptor++;
}
// after IAT hooking
MessageBoxA(0, "Hello", "Hello msg", 0);
return 0;
}
代码应该输出&;evil print&;一次。但是它只是一遍又一遍地打印它(我添加了睡眠(1000),所以它不会因为太多的打印而缓冲区溢出…)。
我的猜测是,底部的MessageBoxA
实际上调用了print_evil
函数,而print_evil
函数反复调用自己。
我没有任何解决办法。任何帮助将不胜感激!
代码应该输出&;evil print&;一次。但是它只是一遍又一遍地打印它(我添加了睡眠(1000),所以它不会因为太多的打印而缓冲区溢出…)。
您在编译阶段静态地分配前'MessageBox()'的地址。真正的地址是在程序提交到内存时由加载程序分配的。
在执行流程中按如下方式移动赋值:
#include <Windows.h>
#include <stdio.h>
typedef int (__stdcall * FunctionLikeMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
FunctionLikeMessageBoxA originalMsgBoxA = NULL; // the original MessageBoxA function, before IAT hooking.
int print_evil(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
printf("Evil print");
Sleep(1000);
return originalMsgBoxA(hWnd, lpText, lpCaption, uType);
}
int main(int argc, char *argv[])
{
originalMsgBoxA = MessageBoxA; // Assign here the original MessageBoxA function.
// message box before IAT unhooking
MessageBoxA(NULL, "Before Hooking", "Before Hooking", 0);
LPVOID imageBase = GetModuleHandleA(NULL); // image base, start of the loaded code (?)
PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)imageBase; // dos headers
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS) ((DWORD_PTR)imageBase + dosHeaders->e_lfanew); // ntHeaders are in e_lfanew
PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;
IMAGE_DATA_DIRECTORY importsDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; // IAT
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR) (importsDirectory.VirtualAddress + (DWORD_PTR)imageBase); // img descriptor
LPCSTR currentLibraryName = NULL;
HMODULE loadedLibrary = NULL;
PIMAGE_IMPORT_BY_NAME functionName = NULL;
while (importDescriptor->Name != 0) // run until library name is not null, meaning we have libraries
{
currentLibraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)imageBase; // get name of library
loadedLibrary = LoadLibraryA(currentLibraryName); // loading the dll library
if (loadedLibrary)
{
PIMAGE_THUNK_DATA originalFirstThunk = NULL;
PIMAGE_THUNK_DATA firstThunk = NULL;
// thunk where the functions are located (?)
originalFirstThunk = (PIMAGE_THUNK_DATA) ((DWORD_PTR)imageBase + importDescriptor->OriginalFirstThunk); // the INT (Names)
firstThunk = (PIMAGE_THUNK_DATA) ((DWORD_PTR)imageBase + importDescriptor->FirstThunk); // the IAT (Addresses)
while (originalFirstThunk->u1.AddressOfData != 0) // run until function name is not null, meaning we have functions
{
functionName = (PIMAGE_IMPORT_BY_NAME) ((DWORD_PTR)imageBase + originalFirstThunk->u1.AddressOfData); // name of function
// if name is MessageBoxA, what we need, then switch the Function address of the function in the IAT, to our function.
if (strcmp(functionName->Name, "MessageBoxA") == 0)
{
DWORD oldProtect = 0;
VirtualProtect((LPVOID) (&firstThunk->u1.Function), 8, PAGE_READWRITE, &oldProtect);
firstThunk->u1.Function = (DWORD_PTR)print_evil;
DWORD newProtect = 0;
VirtualProtect((LPVOID) (&firstThunk->u1.Function), 8, oldProtect, &newProtect);
}
// increase to go over the next functions.
originalFirstThunk++;
firstThunk++;
}
}
// increase to go over the next dlls.
importDescriptor++;
}
// after IAT hooking
MessageBoxA(0, "Hello", "Hello msg", 0);
return 0;
}