首页 > 编程知识 正文

单片机程序分析,进程控制开发总结

时间:2023-05-06 05:39:48 阅读:118099 作者:1574

很久没写博客了,一个月要尽量保证一篇。 今天谈论Hook技术。

在Window平台上开发一点基础的东西,基本上就是Hook在天上飞。 普通的APP应用就是这样。 安全软件更是如此。 这里简要记录了常见的Hook技术。

基本上,从事Windows开发的人都知道这个API,它提供了拦截系统事件和消息的机会。 此外,还可以将DLL注入其他流程。

但是,随着64位时代的到来和Vista及更高版本的UAC机制的开启,此API在许多情况下不再工作:

首先,32位DLL的地址空间完全不同,因此不能直接注入64位APP应用程序。 当然不能直接注入,但在权限范围内,系统会尽量通过消息接收64位程序的消息事件。

其次,如果UAC打开,则低权限程序无法Hook高权限程序。 实际上,即使以高权限程序窗口为Owner创建窗口,低权限程序也将失败。 低权限程序在高权限程序窗口中模拟鼠标键盘也会失败。

据说我们可以关闭UAC。 在windows7上确实可以做到,但在windows8上微软不支持真正关闭UAC。 从这里也可以看出微软的技术转移方法。 提供一个选项,以便在中途逐渐适应,最后关闭此选项。 UAC和Aero两种模式。

那么如何解决这些问题呢?

针对64位问题,该解决方案可以提供两个DLL,分别将32位和64位程序Hook32。

对于权限问题,解决方法是提高权限,注册系统服务,服务程序创建我们的工作流程。 这里为什么不直接在服务流程中工作而创建其他流程? 在Vista之后,我们有会话隔离机制,所以服务程序在会话0上运行,我们的其他程序在会话1、会话2等上运行。 如果我们直接在服务程序上工作,我们只能在Session 0上工作。 创建进程时,可以通过在DuplicateTokenEx之后将Token的SessionID设置为目标Session,并在CreateProcessAsUser中指定目标WinStation和Desktop来创建系统

很多人可能不知道这个API,这个API其实很重要,看名字就知道那是Hook事件(Event )。 具体哪个事件可以看到这里。

为什么这个API很重要,是因为这个API在大多数情况下都没有SetWindowsHookEx的权限问题。 也就是说,此API可以Hook到同时支持进程(WINEVENT_INCONTEXT )和进程外(WINEVENT_OUTOFCONTEXT )的高权限程序中的事件

为什么这个API没有权限问题,是因为它用于访问权限,也就是自动测试和故障工具,所以必须保证有效。

我见过任何程序(无论权限如何)只要有窗口拖动(拖动标题栏以更改位置、拖动边框以调整大小),程序就可以捕获的程序,但怎么做到

Spy显示窗口消息,WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE表示进入或退出此事件,但也只能获得自己的消息。 其他程序的信息是怎么捕获的? 当时被怀疑使用Hook,但发现没有DLL注入。 检查Windows API时,没有找到API来检查窗口是否处于此拖动状态。 最后,我们发现我们使用了SetWinEventHook中的EVENT_SYSTEM_MOVESIZESTART和EVENT_SYSTEM_MOVESIZEEND。

API Hook

典型的API Hook有两种类型:基于PE文件的导入表(IAT )和用于修改前五个字节的直接JMP的在线hook。

对于基于IAT的方法,原理是在PE文件中有导入表,表示该模块调用了哪个外部API。 当模块加载到内存中时,PE加载器将修改该表,并将地址更改为外部API重新定位后的实际地址。 我们直接把里面的地址更改为我们新函数的地址,就完成了对对应API的Hook。 《Windows核心编程》在第22章有包装很好的CAPIHook类。 我们可以直接拿来用。

我用API Hook实现过自动测试。 请参阅这里的API Hook在TA中的应用

对于基于Jmp方法的inline hook,原理是修改目标函数的前五个字节,然后直接将Jmp传递给新函数。 原理很简单,但是因为使用了平台相关的汇编代码,所以一般人很难写稳定的代码。 真正在项目中使用还是需要稳定,所以我们一般使用微软封装的Detours。 关于Detours的原理,这里有一篇很好的文章

比较一下以下两种方法。

IAT的方式比较安全、简单,但仅适用于Hook引入函数方式的API的情况。

Inline Hook相对复杂,但可以对任何函数(API和内部函数)进行Hook。 但是,多线程重写可能会引起冲突,因此必须知道所需的函数至少为5个字节,以及修改的时间和Freeze的其他线程。

COM Hook

因为Window中以COM方式提供了很多开发包(

DirectX), 所以我们就有了拦截COM调用的COM Hook。

因为COM里面很关键的是它的接口是C++里虚表的形式提供的, 所以COM的Hook很多是时候其实就是虚表(vtable)的Hook。

关于C++ 对象模型和虚表可以看我这篇

对于COMHook,考虑下面2种case:

一种是我们Hook程序先运行,然后启动某个游戏程序(DirectX 9), 我们想Hook游戏的绘画内容。

这种方式下, 我们可以先Hook APIDirect3DCreate9, 然后我们继承于IDirect3D9, 自己实现一个COM对象返回回去, 这样我们就可以拦截到所有对该对象的操作,为所欲为了, 当然我们自己现实的COM对象内部会调用真正的Direct3DCreate9,封装真正的IDirect3D9。

当然有时我们可能不用替代整个COM组件,我们只需要修改其中一个或几个COM函数, 这种情况下我们可以创建真正的IDirect3D9对象后直接修改它的虚表, 把其中某些函数改成我们自己的函数地址就可以了。

其实ATL就是用接口替代的方式来调试和记录COM接口引用计数的次数, 具体可以看我这篇

还有一种case是游戏程序已经在运行了, 然后才启动我们的Hook进程, 我们怎么样才能Hook到里面的内容?

这种情况下我们首先要对程序内存有比较详细的认识, 才能思考创建出来的D3D对象的虚表位置, 从而进行Hook, 关于程序内存布局,可见我这篇。

理论上说COM对象如果是以C++接口的方式实现, 虚表会位于PE文件的只读数据节(.rdata), 并且所有该类型的对象都共享该虚表, 所以我们只要创建一个该类型对象,我们就可以获得其他人创建的该类型对象的虚表位置,我们就可以改写该虚表实现Hook(实际操作时需要通过VirtualProtect修改页面的只读属性才能写入)。

但是实际上COM的虚表只是一块内存, 它并不一定是以C++实现, 所以它可以存在于任何内存的任何地方。另外对象的虚表也不一定是所有同类型的对象共享同一虚表, 我们完全可以每个对象都有自己的一份虚表。比如我发现IDirect3D9是大家共享同一虚表的(存在D3D9.dll的), 但是IDirect3DDevice9就是每个对象都有自己的虚表了(存在于堆heap)。所以如果你要HookIDirect3DDevice9接口,通过修改虚表实际上没法实现。

但是尽管有时每个对象的虚表不一样,同类型对象虚表里的函数地址却都是一样的, 所以这种情况下我们可以通过inline Hook直接修改函数代码。当然有些情况下如果是静态链接库,即使函数代码也是每个模块都有自己的一份, 这种情况下就只能反汇编获取虚表和函数的地址了。

最后,总结一下, 上面主要探讨了Windows上的各种Hook技术,通过将这些Hook技术组起来, 可以实现很多意想不到的功能, 比如我们完全可以通过Hook D3D实现Win7任务栏那种Thumbnail预览的效果(当然该效果可以直接由DWM API实现, 但是如果我们可以通过HOOK已动画的方式实现是不是更有趣 )。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。