@author: dlive

0X01 IAT Hook的优缺点

优点:工作原理与实现都比较简单

缺点:如果想钩取的API不在目标进程的IAT中,那么就无法使用该技术进行钩取操作。即如果要钩取的API是由程序动态加载DLL文件而的得以使用的,那么我们将无法使用这项技术钩取它。

0x02 IAT Hook的工作原理

程序开始运行时,PE装载器会将user32.SetWindowTextW()的API地址(77D0960E)记录到该地址(01001110 [calc.exe的IAT区域])。

IAT Hook的流程: 首先向calc.exe注入hookiat.dll,然后修改calc.exe内存IAT区域SetWindowTextW对应的地址为hookiat.dll中攻击者自定义的函数地址,这样当calc.exe调用SetWindowTextW时会跳转至hookiat.dll中的Hook函数,Hook函数执行到最后时调用SetWindowTextW API即可在完成该API正常功能的情况下监控API的参数和返回结果。(当然攻击者可以选择不执行SetWindowTextW的功能)

0x03 IAT Hook代码分析

DllMain

  1. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
  2. {
  3. switch( fdwReason )
  4. {
  5. case DLL_PROCESS_ATTACH :
  6. // 获取original API的地址
  7. g_pOrgFunc = GetProcAddress(GetModuleHandle(L"user32.dll"),
  8. "SetWindowTextW");
  9. // # hook
  10. // MySetWindowTextW并未定义成导出函数
  11. hook_iat("user32.dll", g_pOrgFunc, (PROC)MySetWindowTextW);
  12. break;
  13. case DLL_PROCESS_DETACH :
  14. // # unhook
  15. hook_iat("user32.dll", (PROC)MySetWindowTextW, g_pOrgFunc);
  16. break;
  17. }
  18. return TRUE;
  19. }

代码比较简单,在DLL加载的时候获取SetWindowTextW的地址然后存放在全局变量中,因为被注入进程已经加载了user32.dll,所以直接GetModuleHandle获取其句柄即可(但最好先判断dll是否加载,若没有加载使用LoadLibrary加载DLL)

MySetWindowTextW

  1. BOOL WINAPI MySetWindowTextW(HWND hWnd, LPWSTR lpString)
  2. {
  3. wchar_t* pNum = L"零一二三四五六七八九";
  4. wchar_t temp[2] = {0,};
  5. int i = 0, nLen = 0, nIndex = 0;
  6. nLen = wcslen(lpString);
  7. for(i = 0; i < nLen; i++)
  8. {
  9. // 阿拉伯数字转换为中文
  10. if( L'0' <= lpString[i] && lpString[i] <= L'9' )
  11. {
  12. temp[0] = lpString[i];
  13. nIndex = _wtoi(temp);
  14. lpString[i] = pNum[nIndex];
  15. }
  16. }
  17. // 调用user32!SetWindowTextW(),参数为修改后的字符串缓冲区
  18. return ((PFSETWINDOWTEXTW)g_pOrgFunc)(hWnd, lpString);
  19. }

hook_iat

  1. // hook_iat
  2. // 修改IAT中的数据
  3. // 将IAT中 pfnOrg 修改为 pfnNew
  4. BOOL hook_iat(LPCSTR szDllName, PROC pfnOrg, PROC pfnNew)
  5. {
  6. HMODULE hMod;
  7. LPCSTR szLibName;
  8. PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
  9. PIMAGE_THUNK_DATA pThunk;
  10. DWORD dwOldProtect, dwRVA;
  11. PBYTE pAddr;
  12. // hMod, pAddr = ImageBase of calc.exe
  13. // = VA to MZ signature (IMAGE_DOS_HEADER)
  14. hMod = GetModuleHandle(NULL);
  15. pAddr = (PBYTE)hMod;
  16. // pAddr = VA to PE signature (IMAGE_NT_HEADERS)
  17. pAddr += *((DWORD*)&pAddr[0x3C]);
  18. // dwRVA = RVA to IMAGE_IMPORT_DESCRIPTOR Table
  19. dwRVA = *((DWORD*)&pAddr[0x80]);
  20. // pImportDesc = VA to IMAGE_IMPORT_DESCRIPTOR Table
  21. pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hMod+dwRVA);
  22. // IMAGE_IMPORT_DESCRIPTOR[] 以空的IMAGE_IMPORT_DESCRIPTOR为结尾
  23. for( ; pImportDesc->Name; pImportDesc++ )
  24. {
  25. // szLibName = VA to IMAGE_IMPORT_DESCRIPTOR.Name
  26. szLibName = (LPCSTR)((DWORD)hMod + pImportDesc->Name);
  27. if( !_stricmp(szLibName, szDllName) )
  28. {
  29. // pThunk = IMAGE_IMPORT_DESCRIPTOR.FirstThunk
  30. // = VA to IAT(Import Address Table)
  31. pThunk = (PIMAGE_THUNK_DATA)((DWORD)hMod +
  32. pImportDesc->FirstThunk);
  33. // pThunk->u1.Function = VA to API
  34. // IAT Thunk 数组以空IAT Thunk为结尾
  35. for( ; pThunk->u1.Function; pThunk++ )
  36. {
  37. if( pThunk->u1.Function == (DWORD)pfnOrg )
  38. {
  39. // 修改内存属性为 E R W
  40. VirtualProtect((LPVOID)&pThunk->u1.Function,
  41. 4,
  42. PAGE_EXECUTE_READWRITE,
  43. &dwOldProtect);
  44. // 修改IAT值为新的函数地址
  45. pThunk->u1.Function = (DWORD)pfnNew;
  46. // 恢复内存属性为只读
  47. VirtualProtect((LPVOID)&pThunk->u1.Function,
  48. 4,
  49. dwOldProtect,
  50. &dwOldProtect);
  51. return TRUE;
  52. }
  53. }
  54. }
  55. }
  56. return FALSE;
  57. }

IAT Hook的步骤如下:

calc.exe的ImageBase的地址 -> Image_Nt_Headers地址 -> Image_Import_Descriptor结构体组成的数组的起始地址(其中存储着DLL名称,IAT数组的起始地址)-> 通过DLL名称找到user32.dll对应的Image_Import_Descriptor -> 找到对应的IAT数组起始地址 -> 遍历IAT找到SetWindowTextW对应的条目,修改其值为MySetWindowTextW

IAT Hook的更多相关文章

  1. EAT/IAT Hook

    标 题: EAT/IAT Hook 作 者: Y4ng 时 间: 2013-08-21 链 接: http://www.cnblogs.com/Y4ng/p/EAT_IAT_HOOK.html #in ...

  2. ring3下的IAT HOOK

    标 题: [原创]ring3下的IAT HOOK作 者: hostzhen时 间: 2013-03-28,11:30:53链 接: http://bbs.pediy.com/showthread.ph ...

  3. IAT Hook 原理分析与代码编写

    Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...

  4. C++浅析——虚表和虚表Hook

    为了探究虚表的今生前世,先来一段测试代码 虚函数类: class CTest { public: int m_nData; virtual void PrintData() { printf(&quo ...

  5. hook研究结果备忘

    hook研究结果: 最近一周时间仔细研究了一下hook,也许不能称之为研究吧.顶多是让别人的思想拿过来抄袭一遍而已,写点结果也算对得起自己的这几天的苦心了. 1,首先从同事旁边听到了hook,然后看的 ...

  6. hook技术分类

    1.HOOK SERVICE TABLE:HOOK SSDT 这种方法对于拦截 NATIVE API 来说用的比较多. SSDT hook,一句话——Windows把需要调用的内核API地址全都存在了 ...

  7. XP下的进程静音技术(遍历进程,遍历输入模块,遍历输入函数,找到函数并HOOK) good

    很多浏览器有这种功能,实现原理都是一样.发声源基本都来自Flash,比如Flash游戏啦,视频播放器啦等等 而Flash的发声都是通过winmm.dll::waveOutWrite函数来完成,所以,我 ...

  8. 64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 )

    64位下Hook NtOpenProcess的实现进程保护 + 源码 (升级篇 ) [PS: 如果在64位系统下,出现调用测试demo,返回false的情况下,请修改Hook Dll的代码] glhH ...

  9. 【Hook技术】实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展

    [Hook技术]实现从"任务管理器"中保护进程不被关闭 + 附带源码 + 进程保护知识扩展 公司有个监控程序涉及到进程的保护问题,需要避免用户通过任务管理器结束掉监控进程,这里使用 ...

随机推荐

  1. 財務会計関連(FI&CO)

    [財務会計伝票]FB01: 登録FB02: 伝票変更FB09: 明細変更FB03: 照会FB04: 変更履歴照会FB08: 反対仕訳FB05: 消込転記FB50: G/L勘定伝票一般転記FB1S: 勘 ...

  2. git回滚到指定commit

    一次性commit好多文件,push上去之后,发现工程不可用,只能回滚,上网搜索回滚办法,下边这个是自己亲试的,特别好使: 操作步骤: 1.git checkout the_branch 2.git ...

  3. 2,Python常用库之二:Pandas

    Pandas是用于数据操纵和分析,建立在Numpy之上的.Pandas为Python带来了两种新的数据结构:Pandas Series和Pandas DataFrame,借助这两种数据结构,我们能够轻 ...

  4. 编译ffmpeg

    1.下载ffmpeg-0.9.2.tar.gz  http://ffmpeg.org/releases/ 下载需要的版本 2.编译linux (centos5.5) 64位版本 ./configure ...

  5. php中utf-8转unicode

    public function utf8_unicode($str) { $unicode = array(); $values = array(); $lookingFor = 1; for ($i ...

  6. SQL Server 分组取 Top 笔记(row_number + over 实现)

    先看SQL语句(注意:这是在SQL Server 2005+ [包括2005] 的版本才支持的哦,o(∩_∩)o 哈哈~) SELECT col1,col2,col3 FROM table1 AS a ...

  7. cannot bind to 127.0.0.1:5037 报错

    使用appium连接真机时,提示这个错误,找了很久,发现是端口被占用 打开cmd,netstat -nao查看当前的TCP连接,找到使用127.0.0.1:5037的代码,然后到任务管理器查看详细进程 ...

  8. 常用模块(random)

    import randomimport string# dt = random.randint(1,2) # 从1-2间取随机数,包括1.2# dt = random.randrange(1,3) # ...

  9. 九 DIP 依赖倒置原则

    首先看定义: 1.高层模块不依赖于低层模块,两者都应该依赖于抽象层 2.抽象不能依赖于细节,细节必须依赖于抽象 首先,模块是个抽象的概念,可以大到一个系统中的子系统作为一个模块,也可以是某个子系统中的 ...

  10. 重复造轮子系列--字符串处理(C语言)

    这些字符代码是以前写的,源于很久很久以前的一个VC++项目,在当时的部门编程比赛里因为用了项目代码的xsplit函数,万万没想到,那个做了几年的项目里面居然有坑..xsplit函数居然不能split连 ...