在已有软件加壳保护 下实现 Inline hook
如写的不好请见谅,本人水平有限。
个人简历及水平:。 http://www.cnblogs.com/hackdragon/p/3662599.html
正常情况:
接到一个项目实现对屏幕输出内容的获取,于是OD载入,发现是XX加壳保护,正常情况写代码采用jmp跳转到自己的代码处 采用前人使用的CHookApi_Jmp类 源码在http://www.cnblogs.com/showna/articles/850279.html。(我自己用的时候把CHookApi_Jmp修改成了CHookApi)当然我是截取目标程序的绘制函数TextOutA,所以代码如下:
// 原函数声明
//__gdi_entry WINGDIAPI BOOL WINAPI TextOutA( __in HDC hdc, __in int x, __in int y, __in_ecount(c) LPCSTR lpString, __in int c);
//全局初始化类
CHookApi m_HookTextOutA;
//自己的函数
BOOL WINAPI FuncJMP_TextOutA(HDC hdc, int x, int y,LPCSTR lpString, int c)
{
m_HookTextOutA.SetHookOff();//关闭HOOK 实现自己调用原来的WINAPI
{
//做你想做的事情
}
int Func_Ret = TextOutA(hdc,x,y,lpString,c);
m_HookTextOutA.SetHookOn();//开启HOOK 实现拦截下一次函数
return Func_Ret;
}
//适当的位置初始化
void Func_Init()//
{
m_HookTextOutA.Initialize(_T("Gdi32.dll"),"TextOutA",(FARPROC)Hook_FuncTextOutA);
m_HookTextOutA.SetHookOn();
}
正常情况下已经完成了Inline hook,但是由于软件加壳保护了TextOutA函数的前5个字节,我们的jmp转移大法不行了,你修改完 他就给你修改回去,造成程序异常。
寻找办法:
于是OD往下跟踪,发现他继续调用的其他DLL也是软件保护下的,只有动态链接才不保护,本人比较懒不爱继续跟踪了,于是想了一下,他是保护前几个字节,他不能全部保护,于是往下看了看汇编代码(win7的GDI32.dll)。

看到这里调用了下一个函数,那么他这里E8(CALL)后面也是4个字节,于是乎马上我想到自己也可以篡改他的这个地址到咱自己的函数中,鬼使神差的我看了下X版本的GDI32的代码

发现一个问题 他们在TextOutA函数头处到E8的位置并不一样。具体来说
WIN7的 089D-0878 = 0x25(偏移)
XP的 BA7C-BA4F = 0x2D (偏移)
2个的偏移量明显不一样了,这怎么办呢,如果在有其他版本的GDI32是不是也不一样呢。于是想到如下解决办法。
解决问题:
我们要实现inline hook 首先要知道我们要修改的内存地址,其次要知道原来的函数地址。下面这个函数来获取我们的地址。
DWORD GetGDI32_TextOutAEx(DWORD &dwHook,DWORD &dwCall)
{
//取得TextOutA函数地址 也可以直接TextOutA
DWORD dwGDI32TextOutA = (DWORD)GetProcAddress(GetModuleHandle(_T("Gdi32.dll")),"TextOutA");
//转换下
BYTE *lpBuf = (BYTE *)dwGDI32TextOutA;
//每字节对比
for(int i=;i<0x30;i++)
{
DWORD dwAddress = (DWORD)(&lpBuf[i]); //字节地址
DWORD dwFind = *(DWORD*)(dwAddress); //转换获取内容
//为什么是0xE80875FF 这个可以在OD上看下内存内容
//由于这个函数的前一部分都是 push dword ptr ss:[ebp+0x8] 紧跟这就是CALL
//那么对应的内存二进制就是 0xE80875FF 了
if(dwFind==0xE80875FF)
{
//当前地址+3那就是E8了
dwHook = dwAddress+;
//由于“CALL到哪里”的计算方式是计算2个地址的差
//所以我们要取CALL 后面的 4个字节的内容
//当前地址+4那就是E8后面的了
DWORD dwNow = dwAddress+;
//读出来这个值
DWORD dwOff = *(DWORD*)(dwNow);
//和当前的地址相加+(这个自己想一下吧为什么是+)
//在+4是因为本身占用4个字节
dwCall = dwNow+dwOff+;
//得出这个CALL实际的内存地址了。
return ;
}
}
return ;
}
给我们的CHookApi增加一个函数。
BOOL CHookApi::InitializeE8(FARPROC lpOldFunc, FARPROC lpNewFunc)
{
m_lpHookFunc = lpOldFunc;
hProc = GetCurrentProcess();
DWORD dwOldFlag;
if(VirtualProtectEx(hProc,m_lpHookFunc,,PAGE_READWRITE,&dwOldFlag))
{
memcpy_s(m_OldFunc,,m_lpHookFunc,);
//if(ReadProcessMemory(hProc,m_lpHookFunc,m_OldFunc,5,0))
{
if(VirtualProtectEx(hProc,m_lpHookFunc,,dwOldFlag,&dwOldFlag))
{
m_NewFunc[]=0xE8;
DWORD *pNewFuncAddress;
pNewFuncAddress=(DWORD*)&m_NewFunc[];
*pNewFuncAddress=(DWORD)lpNewFunc-(DWORD)m_lpHookFunc-;
return TRUE;
}
}
}
return FALSE;
}
他原来是E9(JMP)那么我们要实现自己的CALL 那么我们用E8 其实我只是偷懒而已。因为原来就是E8 我们只要写入自己的函数的偏移就行了。
实现过程:
//全局初始化类
CHookApi m_HookTextOutAEx;
//要挂钩的地址
DWORD dwHook;
//原来的CALL的地址
DWORD dwCall;
//自己的函数
int WINAPI FuncJMP_TextOutEx(HDC hdc, int x, int y,int A,int B,LPCSTR lpString, int c,int C,int D)
{
//处理函数形式
typedef int (__stdcall *MyTextOut )(HDC hdc, int x, int y,int A,int B,LPCSTR lpString, int c,int C,int D);
//函数指针
MyTextOut TextOutStr = (MyTextOut)dwCall;
//调用
int Ret = TextOutStr(hdc,x,y,A,B,lpString,c,C,D);
//取得返回的地址
DWORD *Ptr = (DWORD *)&D;
if(Ptr[]==0x12345678)//这里你可以加入以提升性能,根据返回的地址来判断是不是你要拦截的输出内容
{
//做你想做的事情
}
return Ret;
}
//适当的位置初始化
void Func_Init2()//
{
GetGDI32_TextOutAEx(dwHook,dwCall);
m_HookTextOutAEx.InitializeE8((FARPROC)dwHook,(FARPROC)FuncJMP_TextOutEx);
m_HookTextOutAEx.SetHookOn();
}
函数参数的判断可以根据push情况自己来处理下,我随便处理下了。不知道多的几个参数干什么用的。
最后总结:
对于有保护的软件,如果不脱壳处理,那么可以曲线实现自己的目的。对于其他有内存校验的软件,则可根据它对应的调用其他未保护的API进行代码插入。算是写完了,也算是我cnblog的第二篇技术类文章吧。写的不对的地方欢迎指正啊。本人QQ:78486367
在已有软件加壳保护 下实现 Inline hook的更多相关文章
- ASProtect注册码使用教程|ASProtect SKE(加壳脱壳工具) 2.56 汉化注册版
ASProtect 是功能非常完善的加壳.加密保护工具.能够在对软件加壳的同时进行各种保护.如:反调试跟踪.自校验及用密钥加密保护等:还有多种限制使用措施,如:使用天数限制.次数限制及对应的注册提醒信 ...
- ART模式下基于Xposed Hook开发脱壳工具
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78092365 Dalvik模式下的Android加固技术已经很成熟了,Dalvik ...
- 总结Themida / Winlicense加壳软件的脱壳方法
总结下Themida/ Winlicense (TM / WL) 的脱壳方法. 1, 查看壳版本,这个方法手动也可以,因为这个壳的版本号是写在程序里面的,在解压后下断点即可查看,这里有通用的脚本,我 ...
- 易语言软件加VMProtect壳的正确方法
VMP是一款很强大的加密壳,代码虚拟化技术可以很好的保护程序不被恶意修改破J但是很多人不知道怎么给自己的程序加壳,今天给大家晋级下加壳的正确方法 相信很多新手都以为只要把软件直接拖到VMP里重新编译一 ...
- Themida和Winlicense加壳软件脱壳教程
(一)Themida和不用license的Winlicense加壳软件就不说了,直接上脚本脱壳. (二)先看看不同版本OEP的一些小特征: Temida2.1.X.X版本之后的OEP特征(2.0.8. ...
- 加壳软件-Virbox Protector Standalone
Virbox Protector Standalone 加壳工具 防止代码反编译,更安全,更方便 产品简介 Virbox Protector Standalone提供了强大的代码虚拟化.高级混淆与智能 ...
- .NET DLL 保护措施详解(非混淆加密加壳)
为什么要保护DLL,我就不多说了,各人有各人的理由.总的来说,就是不想核心逻辑泄露及授权验证被破解两大方面的因素.市面上的混淆加密工具对.NET源码保护的效果天差地别,很多网上下到的混淆工具破解版对. ...
- Android中的Apk的加固(加壳)原理解析和实现
一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...
- Android中的Apk的加固(加壳)原理解析和实现(转)
一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...
随机推荐
- drf之序列化器的使用
一.序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经 ...
- server 2012 R2查询端口
1. win+r弹出运行对话框,输入cmd,打开cmd窗口 netstat -ano | findstr "80" (注80是你想要看查看的端口号) 就会输出包含80端口使用的情况 ...
- 剑指offer——面试题7:重建二叉树
// 面试题7:重建二叉树 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 // 入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1, // 2, ...
- Python Excel操作库
xlrd:支持.xls..xlsx读 xlwt:只支持.xls写 xlutils:只支持.xls读写 依赖于xlrd和xlwt xlwings:支持.xls读,.xlsx读写 可以实现Excel和Py ...
- Oracle使用sys登录时报错ORA-28009解决方法
情况一:使用sqlplus登录: 正常输入用户名的口令,就会报错,因为SYS是在数据库之外的超级管理员,所以我们在登录的时候 要在输入口令:口令+as sysdba(比如:123456 as sysd ...
- 05-ognl基本语法
1 基本取值 @Test //1基础语法演示-基本取值 //取出root中的属性值 public void fun2() throws Exception{ //1 准备OGNLcontext Ogn ...
- php 中全局变量global 的使用
简介 即使开发一个新的大型PHP程序,你也不可避免的要使用到全局数据,因为有些数据是需要用到你的代码的不同部分的.一些常见的全局数据有:程序设定类.数 据库连接类.用户资料等等.有很多方法能够使这些数 ...
- jQuery对象和DOM对象使用说明,需要的朋友可以参考下。
jQuery对象和DOM对象使用说明,需要的朋友可以参考下.1.jQuery对象和DOM对象第一次学习jQuery,经常分辨不清哪些是jQuery对象,哪些是 DOM对象,因此需要重点了解jQuery ...
- 省市区json数据
window.LocalList = [ { region:{ name:'北京市', code:'11', state:[ { name:'北京', code:'01', city:[ {name: ...
- 使用网络技术---WebView
混合技术 1.使用WebView 权限声明: 定义WebView 填充网页: webView=findViewById() //启用js WebSetting seter = webView.sett ...