设为首页 加入收藏

TOP

4.3 IAT Hook 挂钩技术(三)
2023-09-23 15:44:03 】 浏览:644
Tags:4.3 IAT Hook
Name); DWORD dwAddr = (DWORD)((DWORD *)((DWORD)pNtHdr->OptionalHeader.ImageBase + pTmpImpDes->FirstThunk) + index); printf("导入地址: 0x%08x \r\n", dwAddr); } thunk++; index++; } pTmpImpDes++; } system("pause"); return 0; }

读者可自行编译并运行上方代码片段,当运行后即可输出d://lyshark.exe程序中所有的导入库与该库中的导入函数信息,输出效果如下图所示;

当有了枚举导入表功能,则下一步是寻找特定函数的导入地址,以MessageBoxA函数为例,该函数的导入地址是0x0047d3a0此时我们只需要在此处进行挂钩,并转向即可实现劫持效果,具体来说这个流程如下所示;

  • 首先需要编写DLL文件,在DLL文件中找出MessageBox的原函数地址。
  • 接着通过代码的方式找到DOS/NT/FILE-Optional头偏移地址。
  • 通过DataDirectory[1]数组得到导入表的起始RVA并与ImageBase基址相加得到VA内存地址。
  • 循环遍历导入表中的IAT表,找到与MessageBox地址相同的4字节位置。
  • 找到后通过VirtualProtect设置内存属性可读写,并将自己的函数地址写入到目标IAT表中。
  • 没有找到的话直接pFirstThunk++循环遍历后面的4字节位置,直到找到为止。
  • 最后将自身弹窗回调函数MyMessageBoxA与原函数做替换,则此时即可实现劫持功能。

通过上述开发流程,读者应该可以自行编写出这段劫持代码,如下代码则是完整的劫持实现,我们通过自定义MyMessageBoxA函数,并通过IATHook()实现对内存中导入函数地址的替换,此时当有新的访问时则会自动跳转到自定义函数上执行,执行结束后既跳转回OldMessageBoxA原函数上返回。

#include <iostream>
#include <Windows.h>
#include <Dbghelp.h>

#pragma comment (lib, "Dbghelp")

typedef int(WINAPI *pfMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
pfMessageBoxA OldMessageBoxA = NULL;

// 我们自己的回调函数
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
  return OldMessageBoxA(hWnd, "hello lyshark", lpCaption, uType);
}

// 得到进程NT头部
PIMAGE_NT_HEADERS GetLocalNtHead()
{
  DWORD dwTemp = NULL;
  PIMAGE_DOS_HEADER pDosHead = NULL;
  PIMAGE_NT_HEADERS pNtHead = NULL;

  // 取自身ImageBase
  HMODULE ImageBase = GetModuleHandle(NULL);

  // 取pDosHead地址
  pDosHead = (PIMAGE_DOS_HEADER)(DWORD)ImageBase;
  dwTemp = (DWORD)pDosHead + (DWORD)pDosHead->e_lfanew;

  // 取出NtHead头地址
  pNtHead = (PIMAGE_NT_HEADERS)dwTemp;
  return pNtHead;
}

// 劫持函数
void IATHook()
{
  PVOID pFuncAddress = NULL;

  // 取Hook函数地址
  pFuncAddress = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");

  // 保存原函数指针
  OldMessageBoxA = (pfMessageBoxA)pFuncAddress;

  // 获取到程序自身NtHead
  PIMAGE_NT_HEADERS pNtHead = GetLocalNtHead();
  PIMAGE_FILE_HEADER pFileHead = (PIMAGE_FILE_HEADER)&pNtHead->FileHeader;
  PIMAGE_OPTIONAL_HEADER pOpHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;

  // 找出导入表偏移
  DWORD dwInputTable = pOpHead->DataDirectory[1].VirtualAddress;
  DWORD dwTemp = (DWORD)GetModuleHandle(NULL) + dwInputTable;
  PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)dwTemp;
  PIMAGE_IMPORT_DESCRIPTOR pCurrent = pImport;

  // 导入表子表,IAT存储函数地址表
  DWORD *pFirstThunk;

  // 遍历导入表
  while (pCurrent->Characteristics && pCurrent->FirstThunk != NULL)
  {
    // 找到内存中的导入表
    dwTemp = pCurrent->FirstThunk + (DWORD)GetModuleHandle(NULL);

    // 赋值 pFirstThunk
    pFirstThunk = (DWORD *)dwTemp;

    // 不为NULl说明没有结束
    while (*(DWORD*)pFirstThunk != NULL)
    {

      // 相等则找到了
      if (*(DWORD*)pFirstThunk == (DWORD)OldMessageBoxA)
      {
        DWORD oldProtected;

        // 开启写权限
        VirtualProtect(pFirstThunk, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtected);
        dwTemp = (DWORD)MyMessageBoxA;
        
        // 将MyMessageBox地址拷贝替换
        memcpy(pFirstThunk, (DWORD *)&dwTemp, 4);

        // 关闭写保护
        VirtualProtect(pFirstThunk, 0x1000, oldProtected, &oldProtected);
      }

      // 继续递增循环
      pFirstThunk++;
    }

    // 每次是加1个导入表结构
    pCurrent++;
  }
}

BOOL APIENTRY DllMain(HANDLE
首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇使用Vulkan-Loader将ncnn代码改成.. 下一篇C++ 学习笔记、01 | 开发简单职工..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目