古月不傲 发表于 2019-11-17 01:15

Ring3层 HOOK 导入地址表的基本实现

本帖最后由 古月不傲 于 2019-11-28 03:39 编辑

#include <iostream>

using namespace std;

#include <Windows.h>

//PE头
class _PE_HEADERS
{
public:
      _PE_HEADERS() : m_pDosHeader(NULL), m_pNtHeader(NULL), m_pFileHeader(NULL), m_pOptionalHeader(NULL),
                m_pSectionHeader(NULL), m_pDataDirectory(NULL) { }
      ~_PE_HEADERS(){ }
public:
      PIMAGE_DOS_HEADER m_pDosHeader;
      PIMAGE_NT_HEADERS m_pNtHeader;
      PIMAGE_FILE_HEADER m_pFileHeader;
      PIMAGE_OPTIONAL_HEADER m_pOptionalHeader;
      PIMAGE_SECTION_HEADER m_pSectionHeader;
      PIMAGE_DATA_DIRECTORY m_pDataDirectory;
};

typedef int (WINAPI *PORGFUNCTIONADDRESS)
(_In_opt_ HWND    hWnd,
      _In_opt_ LPCTSTR lpText,
      _In_opt_ LPCTSTR lpCaption,
      _In_   UINT    uType
);

DWORD g_dwNewFunctionAddress = 0;
DWORD g_dwOldFunctionAddress = 0;
DWORD g_dwOldProtect = 0;
PORGFUNCTIONADDRESS pOldFunctionAddress = NULL;

int WINAPI HookedMessageBox
( _In_opt_ HWND    hWnd,
      _In_opt_ LPCTSTR lpText,
      _In_opt_ LPCTSTR lpCaption,
      _In_   UINT    uType
)
{
      char szBuffer = { 0 };
      printf("The has been Hooked that was MessageBoxW!\n");
      printf("窗口句柄:%x!\n", (DWORD)hWnd);
      WideCharToMultiByte(CP_OEMCP, NULL, lpText, lstrlen(lpText), szBuffer, MAX_PATH, 0, FALSE);
      printf("文本:%s!\n", szBuffer);
      ZeroMemory(szBuffer, 0);
      WideCharToMultiByte(CP_OEMCP, NULL, lpCaption, lstrlen(lpCaption), szBuffer, MAX_PATH, 0, FALSE);
      printf("标题:%s!\n", szBuffer);
      printf("窗口类型:%x!\n", uType);

      return ((PORGFUNCTIONADDRESS(g_dwOldFunctionAddress))(hWnd, lpText, lpCaption, uType));
}

//获取本进程模块
HMODULE GetOwnModule()
{
      HMODULE hModule = NULL;
      hModule = GetModuleHandle(NULL);
      if (hModule == NULL)
      {
                return NULL;
      }
      return hModule;
}

//获取原来的函数地址
DWORD GetOldFunctionAddress()
{
      HMODULE hModule = NULL;
      DWORD dwOldFunctionAddress = 0;
      hModule = LoadLibrary(TEXT("user32.dll"));
      if (hModule == NULL)
      {
                return -1;
      }
      dwOldFunctionAddress = (DWORD)GetProcAddress(hModule, "MessageBoxW");
      if (dwOldFunctionAddress == 0)
      {
                return -2;
      }
      return dwOldFunctionAddress;
}

//修改IAT表的函数地址
VOID ChangeFunctionAddressOfIAT(HMODULE hModule, DWORD dwNewFunctionAddress, DWORD &dwOldFunctionAddress, BOOL bFlag)
{
      _PE_HEADERS *pe = new _PE_HEADERS;

      //定位导入表
      pe->m_pDosHeader = (PIMAGE_DOS_HEADER)hModule;
      pe->m_pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pe->m_pDosHeader + pe->m_pDosHeader->e_lfanew);
      pe->m_pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pe->m_pNtHeader + 4);
      pe->m_pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pe->m_pFileHeader + sizeof(IMAGE_FILE_HEADER));
      pe->m_pDataDirectory = pe->m_pOptionalHeader->DataDirectory;

      DWORD dwVitualAddress = (DWORD)pe->m_pDataDirectory.VirtualAddress;
      PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hModule + dwVitualAddress);

      //遍历每个模块的IAT表 找到要HOOK的函数
      while (pImportDirectory->FirstThunk != 0)
      {
                PIMAGE_THUNK_DATA pThunkData = (PIMAGE_THUNK_DATA)((DWORD)hModule + pImportDirectory->FirstThunk);
                while (pThunkData->u1.Function)
                {
                        //修改函数地址
                        if (bFlag)
                        {
                              if (dwOldFunctionAddress == pThunkData->u1.Function)
                              {
                                        DWORD dwOldProtect = 0;
                                        if (!VirtualProtect(pThunkData, 4, PAGE_READWRITE, &dwOldProtect))
                                        {
                                                return;
                                        }
                                        *((DWORD *)pThunkData) = dwNewFunctionAddress;
                                        g_dwOldProtect = dwOldProtect;
                                        break;
                              }
                        }
                        //恢复函数地址
                        else
                        {
                              if (dwNewFunctionAddress == pThunkData->u1.Function)
                              {
                                        DWORD dwOldProtect = 0;
                                        *((DWORD *)pThunkData) = dwOldFunctionAddress;
                                        VirtualProtect(pThunkData, 4, g_dwOldProtect, &dwOldProtect);
                                        break;
                              }
                        }
                        pThunkData++;
                }
                pImportDirectory++;
      }
      g_dwNewFunctionAddress = dwNewFunctionAddress;
      g_dwOldFunctionAddress = dwOldFunctionAddress;
      
      delete pe;
      pe = NULL;
}

int main(void)
{
      HMODULE hModule = NULL;
      DWORD dwNewFunctionAddress = 0;
      DWORD dwOldFunctionAddress = 0;
      
      hModule = GetOwnModule();
      dwOldFunctionAddress = GetOldFunctionAddress();
      ChangeFunctionAddressOfIAT(hModule, (DWORD)HookedMessageBox, dwOldFunctionAddress, TRUE);
      MessageBox(NULL, TEXT("测试"), TEXT("IATHOOK"), MB_YESNOCANCEL);
      ChangeFunctionAddressOfIAT(hModule, (DWORD)HookedMessageBox, dwOldFunctionAddress, FALSE);
      MessageBox(NULL, TEXT("测试"), TEXT("IATHOOK"), MB_YESNOCANCEL);
      system("pause");
      return 0;
}

goldli 发表于 2019-11-17 09:30

支持一下。
页: [1]
查看完整版本: Ring3层 HOOK 导入地址表的基本实现