PE文件和COFF文件格式分析——导出表的应用——一种摘掉Inline钩子(Unhook)的方法
在日常应用中,某些程序往往会被第三方程序下钩子(hook)。如果被下钩子的进程是我们的进程,并且第三方钩子严重影响了我们的逻辑和流程,我们就需要把这些钩子摘掉(Unhook)。本件讲述一种在32位系统上,如何摘掉API钩子的思路和方法。(转载请指明来源于breaksoftware的CSDN博客)
Hook的相应介绍已经很多了,如果对这个技术不是很了解的,可以先搜索下了解下。
一般来说,我们比较熟悉的函数的起始指令是:
push ebp
mov ebp,esp
这两条指令是为了保存前一个函数的栈基址,并将本函数的栈顶指针保存到ebp寄存器中。这样的设计是非常有意义的,在windows平台上,栈的扩展方向是从大端到小端,即由高地址向低地址扩展以申请更大的栈空间。esp则指向栈顶,然而栈顶会根据栈申请和释放而变化,所以如果以esp作为基址来计算变量的位置,将导致一会儿[esp-10]代表变量A,一会儿[esp-20]代表变量A。
虽然这样的结构有种种好处,但是这个肯定不是必须的。所以函数的起始地址指令是不确定的。这儿之所以说这么一大堆,是想说明,Hook库对不同的API进行Hook的方式是不同的。有的是修改函数入口地址的代码,比如上面的入口地址指令可以被Hook库以jmp xxxx来代替。这样就实现了API Hook。本文所讨论和实验的方法也是针对jmp型Hook。
我们以CreateProcessInternalW函数为例,我们看下其汇编代码:
_CreateProcessInternalW@48:
77023BBB push 654h
77023BC0 push 77024968h
77023BC5 call __SEH_prolog4_GS (7701415Ch)
我们使用Hook库下钩子,可以发现其代码变成: _CreateProcessInternalW@48:
77023BBB jmp HookApiByDectours::Mine_CreateProcessInternalW (0A927E0h)
77023BC0 push 77024968h
77023BC5 call __SEH_prolog4_GS (7701415Ch)
我们的思路很简单,就是——以其人之道还治其人之身。
我将从被Hook函数的PE文件中,读取原来的代码,然后和现在内存中的代码做对比。如果不同,则被hook,并将不同的地方改成PE文件中的函数代码。其中涉及的PE知识可以参考《PE文件和COFF文件格式分析》。其中最需要关注的是《PE文件和COFF文件格式分析——导出表》,该文讲述了如何从PE文件中获取代码地址的方法。
具体的替换代码是:
BOOL CUnHookDllFunc::UnHook()
{BOOL bSuc = FALSE;do {LPBYTE lpFunStart = m_lpStart + m_dwRA;HMODULE hModule = GetModuleHandleA(m_strDllPath.c_str());if ( NULL == hModule ) {break;}LPBYTE lpOriFuncAddr = (LPBYTE)hModule + m_dwRVA;DWORD dwModifyCount = 0;for ( int n = 0; n < MAXCOMPCOUNT; n++ ) {if ( *(lpOriFuncAddr + n) != *(lpFunStart + n) ) {dwModifyCount++;}}if ( dwModifyCount == 0 ) {bSuc = TRUE;}else if ( dwModifyCount == MAXCOMPCOUNT ) {// 超过则认为不支持break;}else {DWORD dwOldPro = 0;if ( FALSE == VirtualProtect(lpOriFuncAddr, dwModifyCount, PAGE_EXECUTE_READWRITE, &dwOldPro )) {DWORD dwLastErr = GetLastError();break;}for ( DWORD dwIndex = 0; dwIndex < dwModifyCount; dwIndex++ ) {*(lpOriFuncAddr + dwIndex) = *(lpFunStart + dwIndex);}VirtualProtect(lpOriFuncAddr, dwModifyCount, dwOldPro, &dwOldPro);bSuc = TRUE;}} while (0);return bSuc;
}
最后附上测试工程。其Hook了和UnHook的状态如下图。相关文章:

设置列表字段为主键
转贴:Sample event handler to set a field as a pr imary key (enforce no duplicates) Got this as a request from a reader- how to prevent users from adding items with same titles as ones that already exist in the list. Codeusing System;using System.Collectio…

谁登录了你的linux
最近有一台数据库服务器自动重启。查了一下相关登录信息:查看linux下的用户登录日志,包括用户登录时所用的主机的ip:more /var/log/secure who /var/log/wtmp干了些什么? root账户下输入su - username 切换到username下输入 histo…
一种使用GDI+对图片尺寸和质量的压缩方法
今天同事向我询问图片压缩的算法,我想起大概两三年前做过的一个项目。其中包含了尺寸和质量两种压缩算法,并且支持JPEG、bmp、PNG等格式。今天把这段逻辑贴出来,供大家参考。(转载请指明来源于breaksoftware的CSDN博客)…

.NET企业级应用架构设计系列之应用服务器
本文属spanzhang(张友邦)原创,发布地址为:http://blog.csdn.net/spanzhang。转载或引用请注明原文之出处,谢谢! .NET企业级应用架构设计系列之开场白 .NET企业级应用架构设计系列之技术选型 这里要说到的…
编程语言发展70年,用50种不同语言输出「Hello World」
「免费学习 60 节公开课,投票页面,点击讲师头像」作者 | Sylvain Saurel译者 | 风车云马责编 | 屠敏【导读】历经 70 年,不断出现的编程语言为开发者解决了哪些难题?其存在又有怎样的特性?本文将以「Hello World」为例…

函数循环的理解
2019独角兽企业重金招聘Python工程师标准>>> var ulObjdocument.getElementById("box"); var lisObjulObj.getElementsTagname("li"); for(var i0;i<lisObj.length;i) { lisObj[i].οnclickfunction()//循环时对应节点绑定事件,事…
从LeNet到GoogLeNet:逐层详解,看卷积神经网络的进化
「免费学习 60 节公开课:投票页面,点击讲师头像」作者 | MrCharles来源 | CSDN原力计划获奖作品(*点击阅读原文,查看作者更多文章)前言深度学习的兴起使卷积神经网络在计算机视觉方面大放异彩,本文将按时间…

Windows客户端C/C++编程规范“建议”——前言
前言 工作中接触了很多编程规范。其中最有意思的是,公司最近发布了一版C/C编程规范,然后我看到该规范的最后一段时,有这么一句:“该规范不适用于Windows平台开发”。看来这份规范是由做其他平台开发的同学制定的。那么做Windows开…

storm入门教程 第一章 前言[转]
1.1 实时流计算 互联网从诞生的第一时间起,对世界的最大的改变就是让信息能够实时交互,从而大大加速了各个环节的效率。正因为大家对信息实时响应、实时交互的需求,软件行业除了个人操作系统之外,数据库(更精确的说是…

Windows客户端C/C++编程规范“建议”——函数
1 函数 1.1 代码行数控制在80行及以内 等级:【要求】 说明:每个函数的代码行数控制应该控制在80行以内。如果超过这个限制函数内部逻辑一般可以拆分。如果试图超过这个标准,请列出理由。但理由不包含如下: 无法拆分。流程内部…
把自己朝九晚五的工作自动化了,有错吗?
作者 | Brian Merchant译者 | 谭开朗编辑 | 屠敏来源 | CSDN(ID:CSDNnews)【导读】用代码让自己工作开启自动化之际,是否意味着自己将面临被解雇的风险?2016年,Reddit上出现了一个匿名的帖子,内…

COM组件转换成.NET组件[转]
利用类型库导入器(Type Library Importer)可以将其包装成一个.NET组件,然后就可以像使用.NET组件一样使用它了。 .NET框架只是提供了一个包装,并没有真正改变原有的对象 1.找到要转换的.dll文件 2.在命令提示符窗口中输入.dll文件的文件路径,…
干货:Android 源码使用心得分享
我相信很多初学者会和我一样经常在网上去找Android开发源码,但是往往因为运行不起来非常的懊恼!在做爱开发网站的时候,收集App代码时就遇到了这种困难,我相信网络上面的源码大部分在发布前都会人工测试,能够正常运行才…
60分钟入门深度学习工具PyTorch
「免费学习 60 节公开课:投票页面,点击讲师头像」作者 | Soumith Chintala中文翻译、注释制作 | 黄海广配置环境:PyTorch 1.3,python 3.7,主机:显卡:一块1080ti;内存:32g…

Windows客户端C/C++编程规范“建议”——指针
2 指针 2.1 尽量使用智能指针 等级: 【推荐】说明:正确使用智能指针可以省去指针管理的工作。2.2 类成员变量指针释放后一定要置空 等级: 【必须】说明:如果类成员变量指针在释放后没有置空,将出现如下问题࿱…

Bug tracker .net 部署经验(完善中)
Bug tracker .net 部署经验1. 软件要求windows 2003 serverSP1IISSQL sever 2005Net framework2. 安装和配置Bug tracker .net 提供了一个readme 文件。解压安装文件至某一个目录。在SQL SERVER 2005中新建一个数据库。确保IIS工作正常。定义一个虚拟目录,将其指向安…

Windows客户端C/C++编程规范“建议”——函数调用
3 函数调用 3.1 谨慎使用递归方法 等级: 【推荐】说明:递归方式控制不当,可能会导致栈空间不够而崩溃。一般的递归都可以使用循环代替。3.2 不要使用using namespace 等级: 【必须】说明:这是曾经教科书上的一种写法&a…
“一百万行Python代码对任何人都足够了”
作者 | Jake Edge译者 | Kolen出品 | AI科技大本营(ID: rgznai100)编程语言通常对其操作过程的各个方面都有或明或暗的限制。诸如标识符的最大长度或变量可以存储的值的范围之类的事情,这些是相当明显的例子,但是还有其他一些例子…

网吧电影客户端Realplayer的装配问题
网吧电影客户端Realplayer的装配问题 作者: 出处:网吧联盟 ( 20 ) 砖 ( 22 ) 好 评论 ( 1 ) 条 进入论坛 更新时间:2005-11-24 16:54关 键 词:网吧阅读提示:一般有过开网吧经验的朋友,应当知道如何让自己的realplayer播放器支…

基于Servlet+JDBC+Bootstrap+MySQL+AJAX权限管理系统项目实战教程
项目简介 权限系统一直以来是我们应用系统不可缺少的一个部分,若每个应用系统都重新对系统的权限进行设计,以满足不同系统用户的需求,将会浪费我们不少宝贵时间,所以花时间来设计一个相对通用的权限系统是很有意义的。 本系…

Windows客户端C/C++编程规范“建议”——表达式和运算
4 表达式和运算 4.1 比较操作中将常量设置为左值 等级: 【推荐】说明:编写代码时,如果将常量设置为右值。可能因马虎将“”写成“”导致逻辑错误。这种场景下,编译器是不会报错的,代码检查也比较容易被忽视。例子&…
GitHub标星1.5w+,从此我只用这款全能高速下载工具
「免费学习 60 节公开课:投票页面,点击讲师头像」作者 | Rocky0429来源 | Python空间(ID:Devtogether )大家好,我是 Rocky0429,一个喜欢在网上收集各种资源的蒟蒻...网上资源眼花缭乱,下载的方…

CSS text-transform 属性
定义 text-transform 对元素中的字母进行控制。 继承性:Yes 说明 这个属性会改变元素中的字母大小写,而不论源文档中文本的大小写。如果值为 capitalize,则要对某些字母大写,但是并没有明确定义如何确定哪些字母要大写,…

SeaJS基本开发原则
SeaJS基本开发原则 在讨论SeaJS的具体使用前,先介绍一下SeaJS的模块化理念和开发原则。使用SeaJS开发JavaScript的基本原则就是:一切皆为模块。引入SeaJS后,编写JavaScript代码就变成了编写一个又一个模块,SeaJS中模块的概念有点类…

SMS主站点配置详细图解:Sms2003系列之二
SMS主站点配置在上一篇文章中,我们介绍了如何进行SMS2003+SP2的部署。本文中,我们将介绍如何进行SMS主站点的配置。在SMS中,站点(site)定义并包含了所有SMS管理的对象。当我们第一次安装SMS时,实际安装的是一个SMS站点…
2019,不可错过的NLP“高光时刻”
作者 | Elvis译者 | 凯隐、夕颜出品 | AI科技大本营(ID: rgznai100)【导读】对自然语音处理(NLP)领域而言,2019年是令人印象深刻的一年,本文将回顾2019年NLP和机器学习领域的重要事件。内容 主要集中于 NLP…

Windows客户端C/C++编程规范“建议”——结构
5 结构 5.1 不要使用goto 等级: 【必须】说明:在大型项目中,goto的滥用会导致灾难性后果。因为我们程序中一般不存在从一个函数体内部跳转到另一个函数体内部的场景,所以我们可以将跳转控制在函数内部,从而避免灾难。…

WinForm容器内控件批量效验是否允许为空?设置是否只读?设置是否可用等方法分享...
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chinahuyong/article/details/47395633 WinForm容器内控件批量效验是否允许为空?设置是否只读?设置是否可用等方法分享 在WinForm程序中,我…
“不会Linux,怎么当程序员?”骨灰级程序员:干啥都不行。
说起优秀程序员的必备技能,我想大家都可以说很多,比如:数据结构、算法、数学、编程语言等等。但是,你可能会忽略了每一个程序员都应该掌握的技能:Linux。想一想,我们日常学习、求职、工作场景的中ÿ…