0x01 简介

有人称它为“钩子”,有人称它为“挂钩”技术。谈到钩子,很容易让人联想到在钓东西,比如鱼钩就用于钓鱼。编程技术的钩子也是在等待捕获系统中的某个消息或者动作。钩子的应用范围非常广泛,比如输入监控、API拦截、消息捕获、改变程序执行流程等方面。杀毒软件会用Hook技术钩住一些API函数,比如钩住注册表读写函数,从而防止病毒对注册表进行写入;病毒使用Hook技术有针对性的捕获键盘的输入,从而记录用户的密码等敏感信息;文件加密系统通过Hook技术在不改变用户操作的情况下对用户的文件进行透明加密,这些都属于Hook范畴的知识。

在windows系统下,Hook技术的方法比较多,使用比较灵活,常见的Hook方法有Inline Hook,IAT Hook,Windows钩子。。。Hook技术涉及DLL相关的知识。Hook技术也涉及注入的知识,想要把完成Hook功能的DLL文件加载到目标进程空间中,就要使用注入的知识。

0x02 常见Hook技术介绍

  • Inline Hook

API函数都保存在操作系统提供的DLL文件中,当在程序中调用某个API函数并运行程序后,程序会隐式地将API函数所在的DLL文件加载入内存中,这样,程序就会像调用自己的函数一样调用API。Inline Hook这种方法是在程序流程中直接进行嵌入jmp指令来改变流程的。

Inline Hook流程

  1. 构造跳转指令。
  2. 在内存中找到欲Hook函数地址,并保存欲Hook位置处的前5字节。
  3. 将构造的跳转指令写入需Hook的位置处。
  4. 当被Hook位置被执行时会转到自己的流程执行。
  5. 如果要执行原来的流程,那么取消Hook,也就是还原被修改的字节。
  6. 执行原来的流程。
  7. 继续Hook住原来的位置

这就是Inline Hook的大概流程。

  • 导入地址表钩子-IAT HOOK

导入地址表是PE文件结构中的一个表结构。在可执行文件中使用其他DLL可执行文件的代码或数据,成为导入或者输入。当PE文件需要运行时,将被系统加载至内存中,此时windows加载器会定位所有的导入的函数或者数据将定位到的内容填写至可执行文件的某个位置供其使用。这个地位是需要借助于可执行文件的导入表来完成的。导入表中存放了所使用的DLL的模块名称及导入的函数名称或函数序号。

在加壳和脱壳的研究中,导入表是非常关键的部分。加壳要尽可能地隐藏或破坏原始的导入表。脱壳一定要找到或者还原或者重建原始的导入表,如果无法还原或修过脱壳后的导入表的话,那么可执行文件仍然是无法运行的。

  • windows钩子函数

windows下的窗口应用程序是基于消息驱动的,但是在某种情况下需要捕获或者修改消息,从而完成一些特殊的功能。对于捕获消息而言,无法使用IAT或Inline Hook之类的方式去进行捕获,不过windows提供了专门用于处理消息的钩子函数。

windows系统提供的钩子按照挂钩范围分为局部钩子和全局钩子。局部钩子是针对一个线程的,而全局钩子这是针对这个操作系统内基于消息机制的应用程序的。全局钩子需要使用DLL文件,DLL文件里面存放了钩子函数的代码。

在操作系统中安装全局钩子以后,只要进程接收到可以发出钩子的消息后,全局钩子的DLL文件会被操作系统自动或强行加载到该进程中,由此可见,设置消息钩子也是一种可以进行DLL注入的方法。

windows下的钩子函数,主要用3个,分别是SetWindowsHookEx() 、CallNextHookEx()和UnhookWindowsHookEx()

0x03 实例

Inline Hook实例

首先通过Process Explorer可以查看程序的父进程,可以看出,大部分普通的应用程序都是由explorer.exe进程创建的(像360、QQProtect以及一些驱动程序除外),那么知道把Explorer.exe 进程中CreateProcessW()函数Hook住,就可以针对要完成的工作做很多事情了,比如,可以记录哪个应用程序被启动,也可以对应用程序进行拦截。

关键代码如下:

ILHook.cpp

#include "ILHook.h"

CILHook::CILHook()
{
// 对成员变量的初始化
m_pfnOrig = NULL;
ZeroMemory(m_bOldBytes, );
ZeroMemory(m_bNewBytes, );
} CILHook::~CILHook()
{
// 取消HOOK
UnHook();
m_pfnOrig = NULL;
ZeroMemory(m_bOldBytes, );
ZeroMemory(m_bNewBytes, );
} /*
函数名称:Hook
函数功能:对指定模块中的函数进行挂钩
参数说明:
pszModuleName:模块名称
pszFuncName: 函数名称
pfnHookFunc: 钩子函数
*/
BOOL CILHook::Hook(LPSTR pszModuleName, LPSTR pszFuncName, PROC pfnHookFunc)
{
BOOL bRet = FALSE; // 获取指定模块中函数的地址
m_pfnOrig = (PROC)GetProcAddress(GetModuleHandle(pszModuleName), pszFuncName); if ( m_pfnOrig != NULL )
{ // 保存该地址处5个字节的内容
DWORD dwNum = ;
ReadProcessMemory(GetCurrentProcess(), m_pfnOrig, m_bOldBytes, , &dwNum); // 构造JMP指令
m_bNewBytes[] = '\xe9'; // jmp Opcode
// pfnHookFunc是我们HOOK后的目标地址
// m_pfnOrig是原来的地址
// 5是指令长度
*(DWORD *)(m_bNewBytes + ) = (DWORD)pfnHookFunc - (DWORD)m_pfnOrig - ; // 将构造好的地址写入该地址处
WriteProcessMemory(GetCurrentProcess(), m_pfnOrig, m_bNewBytes, , &dwNum); bRet = TRUE;
} return bRet;
} /*
函数名称:UnHook
函数功能:取消函数的挂钩
*/
VOID CILHook::UnHook()
{
if ( m_pfnOrig != )
{
DWORD dwNum = ;
WriteProcessMemory(GetCurrentProcess(), m_pfnOrig, m_bOldBytes, , &dwNum);
}
} /*
函数名称:ReHook
函数功能:重新对函数进行挂钩
*/
BOOL CILHook::ReHook()
{
BOOL bRet = FALSE; if ( m_pfnOrig != )
{
DWORD dwNum = ;
WriteProcessMemory(GetCurrentProcess(), m_pfnOrig, m_bNewBytes, , &dwNum); bRet = TRUE;
} return bRet;
}

HookCreateProcess.cpp

#include "ILHook.h"

CILHook CreateProcessHook;

// 我们实现的Hook函数
BOOL
WINAPI
MyCreateProcessW(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
)
{
BOOL bRet = FALSE; if ( MessageBoxW(NULL, lpApplicationName, lpCommandLine, MB_YESNO) == IDYES )
{
CreateProcessHook.UnHook();
bRet = CreateProcessW(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
CreateProcessHook.ReHook();
}
else
{
MessageBox(NULL, "您启动的程序被拦截", "提示", MB_OK);
} // CreateProcessHook.UnHook();
// // 弹出被创建进程的进程名
// MessageBoxW(NULL, lpApplicationName, lpCommandLine, MB_OK);
//
// // 创建进程
// bRet = CreateProcessW(lpApplicationName,
// lpCommandLine,
// lpProcessAttributes,
// lpThreadAttributes,
// bInheritHandles,
// dwCreationFlags,
// lpEnvironment,
// lpCurrentDirectory,
// lpStartupInfo,
// lpProcessInformation);
//
// CreateProcessHook.ReHook(); return bRet;
} BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch ( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
{
// Hook CreateProcessW()函数
CreateProcessHook.Hook("kernel32.dll",
"CreateProcessW",
(PROC)MyCreateProcessW);
break;
}
case DLL_PROCESS_DETACH:
{
CreateProcessHook.UnHook();
break;
}
} return TRUE;
}

钩子实例:

这里实现一个简单的键盘记录工具。

关键代码如下:

KeyBoradHookTest.cpp  主要来生成dll文件,在该dll文件中需要定义两个导出函数和两个全局变量。

// KeyBoradHookTest.cpp : Defines the entry point for the DLL application.
// #include "stdafx.h" extern "C" __declspec(dllexport) VOID SetHookOn();
extern "C" __declspec(dllexport) VOID SetHookOff(); // 钩子句柄
HHOOK g_Hook = NULL;
// DLL模块句柄
HINSTANCE g_Inst = NULL; BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
// 保存DLL的模块句柄
g_Inst = (HINSTANCE)hModule; return TRUE;
} // 钩子函数
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if ( code < )
{
return CallNextHookEx(g_Hook, code, wParam, lParam);
} if ( code == HC_ACTION && lParam > )
{
char szBuf[MAXBYTE] = { };
GetKeyNameText(lParam, szBuf, MAXBYTE);
MessageBox(NULL, szBuf, NULL, MB_OK);
} return CallNextHookEx(g_Hook, code, wParam, lParam);
} VOID SetHookOn()
{
// 安装钩子
g_Hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_Inst, );
} VOID SetHookOff()
{
// 卸载钩子
UnhookWindowsHookEx(g_Hook);
}

0x04Reference

1.http://blog.csdn.net/u013761036/article/details/52268500 DLL劫持(HiJack)原理以及实现细节

Windows Hook技术的更多相关文章

  1. 逆向实用干货分享,Hook技术第一讲,之Hook Windows API

    逆向实用干货分享,Hook技术第一讲,之Hook Windows API 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) ...

  2. HOOK技术的一些简单总结

    好久没写博客了, 一个月一篇还是要尽量保证,今天谈下Hook技术. 在Window平台上开发任何稍微底层一点的东西,基本上都是Hook满天飞, 普通应用程序如此,安全软件更是如此, 这里简单记录一些常 ...

  3. API HOOK技术

    API HOOK技术是一种用于改变API执行结果的技术,Microsoft 自身也在Windows操作系统里面使用了这个技术,如Windows兼容模式等. API HOOK 技术并不是计算机病毒专有技 ...

  4. windows hook (转)

    http://blog.csdn.net/friendan/article/details/12226201 原文地址:http://blog.sina.com.cn/s/blog_628821950 ...

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

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

  6. 逆向实用干货分享,Hook技术第二讲,之虚表HOOK

    逆向实用干货分享,Hook技术第二讲,之虚表HOOK 正好昨天讲到认识C++中虚表指针,以及虚表位置在反汇编中的表达方式,这里就说一下我们的新技术,虚表HOOK 昨天的博客链接: http://www ...

  7. x64内核HOOK技术之拦截进程.拦截线程.拦截模块

    x64内核HOOK技术之拦截进程.拦截线程.拦截模块 一丶为什么讲解HOOK技术. 在32系统下, 例如我们要HOOK SSDT表,那么直接讲CR0的内存保护属性去掉. 直接讲表的地址修改即可. 但是 ...

  8. 什么是HOOK技术

    https://zhidao.baidu.com/question/50557962.html HOOK技术是Windows消息处理机制的一个平台,应用程序可以在上面设置子程序以监视指定窗口的某种消息 ...

  9. Hook技术

    hook钩子: 使用技术手段在运行时动态的将额外代码依附现进程,从而实现替换现有处理逻辑或插入额外功能的目的. 它的技术实现要点有两个: 1)如何注入代码(如何将额外代码依附于现有代码中). 2)如何 ...

随机推荐

  1. 所有eclipse版本,主题黑化,代码黑化的简单两步

    一.下载两个文件 二.打开eclipse,Import   .epf文件 三.把.jar 复制到 eclipse的plugins目录下,重启eclipse 效果如下: 注 以上方法:来自互联网

  2. [十二省联考2019]D1T2字符串问题

    嘟嘟嘟 省选Day1真是重大失误,T2连暴力都没时间写. 上周五重新答了遍Day1,竟然搞了187分吼吼吼吼. T2按40分写的暴力,结果竟然得了60分. 稍微说一下暴力吧:预处理哈希,对于一组支配关 ...

  3. 手写token解析器、语法解析器、LLVM IR生成器(GO语言)

    最近开始尝试用go写点东西,正好在看LLVM的资料,就写了点相关的内容 - 前端解析器+中间代码生成(本地代码的汇编.执行则靠LLVM工具链完成) https://github.com/daibinh ...

  4. PyQt5中的信号与槽,js 与 Qt 对象之间互相调用

    一.PyQt中的信号与槽 信号(Signal)和槽(Slot)是Qt中的核心机制,用在对象之间互相通信.在Qt中每个QObject对象和PyQt中所有继承自QWidget的控件(这些都是QObject ...

  5. JAVA基础知识回顾(面试资料)

    关于数据库知识和面试:https://www.cnblogs.com/yanqb/p/9894943.html 关于数据库知识和面试:https://www.cnblogs.com/yanqb/p/1 ...

  6. Http和Https有什么区别

    以前去面试的时候,好几家公司都会问到这个问题:http和https有什么区别? 最近突然想恶补一些基础,再夯实一下自己实力,毕竟强大的能力才是工资的保证嘛,今天就来简单记录一下htttp和https的 ...

  7. 个人jQuery的使用总结

    一.使用方法 参考内容有: http://www.w3school.com.cn/jquery/jquery_ref_events.asp http://www.cnblogs.com/zhangzi ...

  8. 详解volatile 关键字与内存可见性

    先来看一个例子: public class VolatileTest {            public static void main(String[] args) {           T ...

  9. vue scoped >>> & git conflict <<<<<<< HEAD

    vue scoped >>> & git conflict <<<<<<< HEAD Q: ???还有这操作 A: > > ...

  10. VBS 备份文件

    http://www.cnblogs.com/top5/archive/2009/11/17/1604767.html 参考上面的博客 ' =============== 局域网文件自动备份 VBS ...