黑客爱用的HOOK技术大揭秘 github黑客工具
yuyutoo 2024-10-22 18:36 3 浏览 0 评论
什么是HOOK技术?
病毒木马为何惨遭杀软拦截?
商业软件为何频遭免费破解?
系统漏洞为何能被补丁修复?
这一切的背后到底是人性的扭曲,还是道德的沦丧,尽请收看今天的专题文章:《什么是HOOK技术?》
上面是开个玩笑,言归正传,今天来聊的话题就是安全领域一个非常重要的技术:HOOK技术。
HOOK,英文意思是“钩子”
在计算机编程中,HOOK是一种「劫持」程序原有执行流程,添加额外处理逻辑的一种技术。
按照这个定义,其实我们Python中的装饰器和Java中的注解,这种面向切面编程的手法在某种程度上来说,也算是HOOK。
不同的是,本文要探讨的HOOK并非属于程序原有的逻辑,而是在程序已经编译成可执行文件甚至已经在运行中的时候,如何劫持和修改程序的流程。
按照劫持的目标不同,常见的HOOK有以下这些类型:
Inline HOOKIAT HOOKC++ virtable HOOKSEH HOOKIDT HOOKSSDT HOOKIRP HOOKTDI HOOK && NDIS HOOKWindows Message HOOK
接下来,咱们挨个来看一下。
Inline HOOK
程序和代码是给程序员们看的,计算机要运行,最终是要编译成CPU的机器指令才能执行。
Inline HOOK的目标就是直接修改程序编译后的指令,属于最基础也最常见的HOOK技术。
下面我们以一个实例来感受一下Inline HOOK的效果:
void functionA() {
cout << "this is function A" << endl;
}
void hookFunction() {
cout << "this is hookFunction" << endl;
}
int main() {
cout << "before hook" << endl;
functionA();
// prepare hook
unsigned char code[5] = { 0xe9, 0x00, 0x00, 0x00, 0x00 };
unsigned int offset = (unsigned int)hookFunction - ((unsigned int)functionA + 5);
*(unsigned int*)&code[1] = offset;
// install hook
unsigned long old = 0;
VirtualProtect(functionA, 0x1000, PAGE_EXECUTE_READWRITE, &old);
memcpy(functionA, code, 5);
cout << "after hook" << endl;
functionA();
return 0;
}
输出:
代码中定义了目标函数functionA和hook函数hookFunction。
第一次调用,输出显示调用了原函数。
然后安装一个HOOK,准备了一条jmp指令,覆盖函数入口处的指令。此时观察覆盖前后的函数指令变化对比:
再次调用该函数,则一进入就发生跳转,我们安装的HOOK函数得到了执行。
所以第二次输出显示HOOK函数得到了调用。
大部分情况下,我们习惯于在函数入口处执行HOOK,但这并不是绝对的,还需要具体问题具体分析。比如如果我们需要等待函数执行完毕时拿到返回值才能介入处理,这个时候就需要在函数return的地方进行HOOK。甚至有可能需要在函数中途某个地方介入,这个时候就需要更进一步的对函数的反编译指令进行分析,确定HOOK的点位和处理逻辑。
执行Inline HOOK非常关键的几点:
- 指令所在的内存页是否允许写入操作,若只读,须先添加写入权限
- 需要动态解析目标位置处的指令,不能像上面那样暴力覆盖,否则会影响原来函数的执行逻辑
- 如果在HOOK处理函数中需要调用原函数,注意别陷入死循环
- 如果有参数,需要处理好堆栈平衡
Inline HOOK由于是直接在CPU机器指令层面上的操作,所以首先是无法做到跨平台。同时,还需要对CPU的指令集有一定程序的了解,具备一定的汇编语言功底。
好在,IT行业从来不缺造轮子的人,已经有不少优秀的开源项目将Inline HOOK封装成库,比如:Detours。
除了直接修改函数的机器指令,还有一类HOOK,它们修改的是某些重要的函数指针,从而达到劫持执行的目的。
形形色色的函数指针,就衍生出各式各样的HOOK技术。
IAT HOOK
一个程序的所有代码一般不会全部都编译到一个模块中,分拆到不同的模块既有利于合作开发,也有利于代码管理,降低耦合。
动态链接库就提供了这样的能力,将不同的模块编译成一个个的动态库文件,在使用时引入调用。
在Windows平台上,动态链接库一般以DLL文件的形式存在,主程序模块一般是EXE文件形式存在。无论是EXE还是DLL,都是属于PE文件。
一个模块引用了哪些模块的哪些函数,是被记录在PE文件的导入表IAT中。这个表格位于PE文件的头部,里面记录了模块的名字,函数的名字。
在模块加载时,模块加载器将解析对应函数的实际地址,填入到导入表中。
通过修改导入表IAT中函数的地址,这种HOOK叫IAT HOOK。
SEH HOOK
SEH是Windows操作系统上结构化异常处理的缩写,在代码中通过try/except来捕获异常时,操作系统将会在线程的栈空间里安置一个异常处理器(其实就是一个数据结构),里面定义了发生异常时该去执行哪里的代码处理异常。
异常处理可以多级嵌套,那多个异常处理就构成了一个链表,存在于栈空间之上。
当发生异常时,操作系统系统就从最近的异常处理器进行寻求处理,如果能处理则罢了,不能处理就继续寻求更上一级的异常处理器,直到找到能处理的异常处理器。如果都没法处理,那对不起,只好弹出那个经典的报错对话框,进程崩溃。
SEH HOOK针对的目标就是修改这些异常处理器中记录的函数指针,当异常发生时就能获得执行,从而劫持到执行流!因为这些异常处理器都位于线程的栈空间,修改起来并非难事。
C++ virtable HOOK
C++是一门面向对象的编程语言,支持面向对象的三大特性:封装性、继承性、多态性。
其中的多态性,各个C++编译器基本上都是通过一种叫虚函数表的机制来实现。
下面通过一个实际的例子来感受一下虚函数表在C++多态性上发挥的作用。
#include <iostream>
using namespace std;
class Animal {
public:
virtual void breathe() {
cout << "Animal breathe" << endl;
}
virtual void eat() {
cout << "Animal eat" << endl;
}
};
class Fish : public Animal {
public:
virtual void breathe() {
cout << "Fish breathe" << endl;
}
virtual void eat() {
cout << "Fish eat" << endl;
}
};
class Cat : public Animal {
public:
virtual void breathe() {
cout << "Cat breathe" << endl;
}
virtual void eat() {
cout << "Cat eat" << endl;
}
};
int main() {
Animal* animal = nullptr;
Fish* fish = new Fish();
Cat* cat = new Cat();
animal = fish;
animal->breathe();
animal->eat();
cout << "--------------" << endl;
cout << "sizeof(fish) = " << sizeof(fish) << endl;
cout << "sizeof(cat) = " << sizeof(cat) << endl;
cout << "--------------" << endl;
animal = cat;
animal->breathe();
animal->eat();
delete fish;
delete cat;
return 0;
}
输出:
通过上面的输出,可以看到,fish和cat对象都只占据4个字节。因为这两个类都没有成员变量,唯一需要存储的就是一个虚函数表指针。
以cat对象为例,看一下它的地址,是0x005cfc30:
看一下这个地址起始的4个字节,是什么:
虚表指针是0x000d9b90(这里需要注意字节顺序)。
通过这个地址,找到虚函数表,里面有两个函数地址:
查看这两个地址,都是指向了一个jmp指令,分别跳到了Cat类的两个虚函数。
通过上面的实例,总结一下对象、虚函数表和虚函数代码之间的关系如下图所示:
每个包含虚函数的类对象,在内存中都有一个指针,位于对象头部,指向的是一个虚函数表,表中的每一项都是虚函数地址。
类继承后,如果重写了父类的虚函数,子类对象指向的表格中对应函数的地址将会更新为子类的函数。
这样,使用父类指针指向子类对象,通过指针调用虚函数时,就能调用到子类重写的虚函数,从而实现多态性。
既然是记录函数地址的表格,那就有存在被篡改的可能,这就是C++ virtable HOOK。
通过篡改对应虚函数的地址,实现对相应函数调用的拦截。
实施这种HOOK,需要逆向分析目标C++对象的结构,掌握虚函数表中各个函数的位置,才能精准打击。
上面几种HOOK,修改的都是应用层的函数指针,而操作系统内核中还有一些非常重要的表格,它们的表项中记录了一些更加关键的函数,HOOK这些表格中的函数是非常高危的操作,操作不当将导致操作系统崩溃。当然,高风险高回报,HOOK这些函数,能实现一些非常强大的功能,是病毒、木马、安全软件非常爱干的事情。
SSDT HOOK
系统调用是操作系统提供给应用程序的编程接口API,应用程序通过这些API得以操作计算机的资源(如进程、网络、文件等)。
执行系统调用的时候,CPU将从用户模式切换到内核模式,进入内核后,将会根据系统调用的API编号,去找到对应的系统服务函数,实现对应API的功能。
操作系统将所有的系统服务函数地址,存放在了一个表格中,这个表格就是系统服务描述符表。在Linux上,这个表格的名字叫sys_call_table,在Windows上,它叫KeServiceDescriptorTable,简称SSDT。
Windows上的SSDT向来是兵家必争之地,安全软件为了监控应用程序的行为,通常都会替换SSDT表格中的系统服务函数地址为它们的函数。当系统调用触发时,安全软件将会及时知晓,并通过应用程序的参数来判定是否“放行”这次调用。
IDT HOOK
内核中除了记录系统服务的SSDT,还有一个非常重要的表格:中断描述符表IDT。
IDT用于记录CPU执行过程中遇到中断、异常等情况时,该转向哪里去处理这些情况的函数地址。
HOOK IDT有一个注意事项,不同于SSDT是全局唯一的,IDT是与CPU核心紧密相关的,对于多核处理器,会对应多个IDT表。如果想通过HOOK IDT中的函数来搞事情的话,可能需要同时处理多个表。
除了直接修改函数指令和修改函数指针之外,还有一类特殊的HOOK,它们通过系统提供的机制拦截某些消息、通知,从而有机会介入监听、拦截。
IRP HOOK
在Windows系统上,用户程序和内核驱动之间的交互是通过一种称为IRP的数据结构实现的,你可以简单将其理解为应用程序发送了一个消息下去,这个消息就是一个IRP。
而接收消息的目标,是驱动程序创建的设备Device。注意,这个设备不一定是物理设备,也可能完全不存在的虚拟设备,驱动程序可以任意创建一个不存在的设备。
Windows内核中提供了驱动设备的挂载操作,允许别的驱动程序对指定设备进行挂载,从而可以截获发送给该设备的“消息”,这种HOOK方式被称为IRP HOOK。
国内一些安全软件为了互相攻击,经常用这种方式拦截对方驱动程序的消息,从而可以“保护”自己不被对方干掉。
TDI HOOK && NDIS HOOK
这两种HOOK方式与Windows内核中的网络子系统密切相关。
Windows内核中的网络结构是分层式设计。从最上层的API socket层、到TCP/IP协议栈层、再到底层的网卡驱动程序,分了很多个层次。
而层与层之间的交互,是通过一系列标准接口来实现的,其中最重要的两个接口标准就是TDI和NDIS。TDI封装了不同协议栈的差异(Windows不止支持TCP/IP协议栈)提供给上层统一的调用接口。NDIS则封装了底层不同网卡的驱动程序接口差异,提供给上层统一的收发数据包接口。
Windows为了扩展性支持,允许类似防火墙之类的软件通过这些接口接入,从而能够截获到网络通信流量,进行安全审计。
既然开了这些接口,一些流氓软件和木马病毒也就盯上了它们,通过这些接口就能轻松监听、篡改网络数据,达到邪恶的目的。
Windows Message HOOK
Windows操作系统的UI交互是以消息来驱动的,用户的键盘输入、鼠标操作都会被操作系统以消息的形式发送到各个应用程序处理。
Windows提供了API接口,可以被程序用于捕获这些消息,从而实现一些特定的功能。
HHOOK SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
HINSTANCE hmod,
DWORD dwThreadId
);
这种机制叫做Windows消息钩子,最常见的就要数键盘钩子了,在十多年前流氓软件和木马病毒大行其道的时候,这些恶意软件经常喜欢通过这种方式来监听用户的键盘输入,从而来盗取QQ密码(当然,现在肯定是不行的了)。
总结
以上就是要介绍的全部HOOK技术了。当然有HOOK,就有反HOOK,很多安全软件都会检查关键的位置是否被篡改。不仅如此,因为流氓软件随意修改系统,Windows从Win7 x64开始加入了PatchGuard机制,针对操作系统核心数据结构都加入了定时检测机制,一旦发现被篡改,立刻蓝屏给你看,而且在随着系统升级换代,这个检查的粒度和强度变得越来越强。
最后来回到文章开头的几个问题:
病毒木马为何惨遭杀软拦截?
因为安全软件在内核中HOOK了大量的关键位置,病毒木马的进程、文件、网络行为都将受到监控,一举一动都难逃杀软的眼睛,想要拦截易如反掌。
商业软件为何频遭免费破解?
通过逆向分析加上Inline HOOK,破解者可以篡改掉商业软件的注册校验机制,让校验函数返回成功,绕开软件的限制。
系统漏洞为何能被补丁修复?
统一通过Inline HOOK,操作系统能够修改原来有bug的代码,转而执行修复后的新版本,解决系统漏洞。
需要HOOK技术文档的同学可以 点赞+关注后 私信【技术文档】即可免费领取
【HOOK技术文档】
** 你看,技术就是一柄双刃剑,善或恶,一念之间。
相关推荐
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
-
Mysql和Oracle实现序列自增/*ORACLE设置自增序列oracle本身不支持如mysql的AUTO_INCREMENT自增方式,我们可以用序列加触发器的形式实现,假如有一个表T_WORKM...
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
-
概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...
- MySQL CREATE TABLE 简单设计模板交流
-
推荐用MySQL8.0(2018/4/19发布,开发者说同比5.7快2倍)或同类型以上版本....
- mysql学习9:创建数据库(mysql5.5创建数据库)
-
前言:我也是在学习过程中,不对的地方请谅解showdatabases;#查看数据库表createdatabasename...
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
-
执行"CREATETABLE新表ASSELECT*FROM原表;"后,新表与原表的字段一致,但主键、索引不会复制到新表,会把原表的表记录复制到新表。...
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
-
在街上看到的PandaDunk的超载可能让一些球鞋迷们望而却步,但Dunk的浪潮仍然强劲,看不到尽头。我们看到的很多版本都是为女性和儿童制作的,这种新配色为后者引入了一种令人耳目一新的新选择,而...
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
-
多功能雷达AN/SPY-1的特性和技术能力,该雷达已经在美国海军服役了30多年,其修改-AN/SPY-1A、AN/SPY-1B(V)、AN/SPY-1D、AN/SPY-1D(V),以及雷神...
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
-
全面分析汽车音响使用或安装技术常识一:主机是大多数人最熟习的音响器材,有关主机的各种性能及规格,也是耳熟能详的事,以下是一些在使用或安装时,比较需要注意的事项:LOUDNESS:几年前的主机,此按...
- 【推荐】ProAc Response系列扬声器逐个看
-
有考牌(公认好声音)扬声器之称ProAcTablette小音箱,相信不少音响发烧友都曾经,或者现在依然持有,正当大家逐渐掌握Tablette的摆位设定与器材配搭之后,下一步就会考虑升级至表现更全...
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
-
作者:初吻给了烟sco混迹张大妈时日不短了,手没少剁。家里有了汪星人,吸尘器使用频率相当高,偶尔零星打扫用卧式的实在麻烦(汪星人:你这分明是找借口,我掉毛是满屋子都有,铲屎君都是用卧式满屋子吸的,你...
- 专题|一个品牌一件产品(英国篇)之Quested(罗杰之声)
-
Quested(罗杰之声)代表产品:Q212FS品牌介绍Quested(罗杰之声)是录音监听领域的传奇品牌,由英国录音师RogerQuested于1985年创立。在成立Quested之前,Roger...
- 常用半导体中英对照表(建议收藏)(半导体英文术语)
-
作为一个源自国外的技术,半导体产业涉及许多英文术语。加之从业者很多都有海外经历或习惯于用英文表达相关技术和工艺节点,这就导致许多英文术语翻译成中文后,仍有不少人照应不上或不知如何翻译。为此,我们整理了...
- Fyne Audio F502SP 2.5音路低音反射式落地音箱评测
-
FyneAudio的F500系列,有新成员了!不过,新成员不是新的款式,却是根据原有款式提出特别版。特别版产品在原有型号后标注了SP字样,意思是SpecialProduction。Fyne一共推出...
- 有哪些免费的内存数据库(In-Memory Database)
-
以下是一些常见的免费的内存数据库:1.Redis:Redis是一个开源的内存数据库,它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis提供了快速的读写操作,并且支持持久化数据到磁...
- RazorSQL Mac版(SQL数据库查询工具)
-
RazorSQLMac特别版是一款看似简单实则功能非常出色的SQL数据库查询、编辑、浏览和管理工具。RazorSQLformac特别版可以帮你管理多个数据库,支持主流的30多种数据库,包括Ca...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
- MySQL CREATE TABLE 简单设计模板交流
- mysql学习9:创建数据库(mysql5.5创建数据库)
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
- 【推荐】ProAc Response系列扬声器逐个看
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)