一次开发的意外逆向之旅

在从事windows内核开发时,我最近因功能需求需要遍历pspsetcreateprocessnotifyroutine回调函数数组。在获取pspcreateprocessnotifyroutine的过程中,我发现了一些有趣的现象,决定在此与大家分享。由于这是我第一次撰写文章,难免有不足之处,还请各位读者多多包涵。

01

1

首先,让我们讨论一下获取这个数组的思路,以Windows 7 x64为例,其他版本大同小异。PspCreateProcessNotifyRoutine是一个PVOID类型的指针,它存储通过PsSetCreateProcessNotifyRoutine函数设置的各种回调函数。我们可以通过以下步骤获取这个数组:

使用MmGetSystemRoutineAddress获取PsCreateProcessNotifyRoutine的地址。在这个函数中,可以发现它调用了PspSetCreateProcessNotifyRoutine。

一次开发的意外逆向之旅2. 在PspSetCreateProcessNotifyRoutine函数中,偏移0x33处有一次对PspCreateProcessNotifyRoutine的操作。

一次开发的意外逆向之旅3. 跟入这个函数地址后,可以看到这是一个函数地址表。然而,通过uf这些地址时,发现这些地址是错误的。这是为什么呢?

一次开发的意外逆向之旅4. 实际上,微软对这些函数进行了加密。要获取真实的函数地址,需要先对其进行解密。解密方法非常简单,只需将这些地址取出并进行 &0xfffffffffffffff8 操作即可。

一次开发的意外逆向之旅5. 这样就可以获得真实的地址指针,通过访问这个指针,可以跟到真实的挂钩函数地址。按照这个思路编写的遍历代码是可行的,此处就不再展示。

一次开发的意外逆向之旅6. 我们可以通过跟入这个函数并对比Pchunter的结果来验证我们的方法是正确的。

一次开发的意外逆向之旅7. 在获取这张函数表后,通过对比模块的基地址和模块大小,可以确定函数所属的模块。同样,可以根据模块名在PsSetCreateProcessNotifyRoutine的函数地址传入有目的的地址和True来取消该模块的挂钩。也可以直接对函数头部进行Ret0操作,但由于可能出现问题,不推荐这样做。

02

2

那么我在Win7 x86版本上遇到了什么问题呢?同样使用MmGetSystemRoutineAddress获取PsCreateProcessNotifyRoutine的函数地址时,发现这个地址虽然是一个函数地址,但实际上是错误的。因为在Windbg中uf获取的PsCreateProcessNotifyRoutine与通过MmGetSystemRoutineAddress获取的地址居然不一样!起初我百思不得其解,但冷静下来后,我开始逐步分析这个过程,有趣的旅程就此展开!

首先,Windbg的u命令一定是准确的。微软自家的调试器在有符号表的情况下,如果连函数位置都不知道,那真是让人无语了!而且我确实进入过u到的函数,确认是正确的。因此,我猜想问题一定出在MmGetSystemRoutineAddress这个关键函数上。

那么MmGetSystemRoutineAddress是如何工作的呢?经过查阅现有资料,我解开了我的疑惑。MmGetSystemRoutineAddress内部实际上是解析模块文件的EAT(导出表)来获取函数调用者所需的函数。通过解析EAT和模块基地址的运算结合ImageLoad的对齐方式,返回对应的函数位置。因此我们的思路有了,因为是x86操作系统,在没有KPP保护的情况下,我的内核的EAT很可能被一些第三方软件挂钩,导致我获取的函数不正确。于是我在Windbg中使用.reload命令重新加载所有模块信息,然后使用lm命令查看所有模块的地址,通过对比各个模块的基地址和模块大小,大致确定了是哪个模块。PCHunter的内核挂钩也验证了我的猜想。

03

模块分析

既然确认内核是被EAT挂钩的,我们不妨分析一下这个模块。

通过数字签名,我们不难看出这个模块是一个安全软件的模块,到这里困惑就解开了。我们猜测是因为在x86系统上没有KPP保护,为了保护自身的钩子不被卸载或者为了监控其他软件的钩子,安全软件选择在EAT挂钩以保护自身的钩子不被其他软件取消,这是一个很好的思路。那么到底是不是这样呢,我们接着分析。

一次开发的意外逆向之旅2. 既然我们已经知道被替换函数的地址和被EAT挂钩的名称,那么我们接下来从这两点开始进行逆向。首先,我们先寻找字符串信息,根据模块名称。

一次开发的意外逆向之旅3. 我们先根据字符串找到对这个字符串引用的地址,很明显只有这一处。我们跟进去,结合上下文看到了一个关键函数ZwQuerySystemInformation。到这里,有过内核开发经验的小伙伴们肯定已经猜到这个函数是在获取模块基地址。看他对v4这个参数的引用,应该就是需要返回的模块地址。我们将这个函数命名为GetKeyModuleAddress,同时参数返回的就是模块大小。

影像之匠PixPretty 影像之匠PixPretty

商业级AI人像后期软件,专注于人像精修,色彩调节及批量图片编辑,支持Windows、Mac多平台使用。适用于写真、婚纱、旅拍、外景等批量修图场景。

影像之匠PixPretty 206 查看详情 影像之匠PixPretty

一次开发的意外逆向之旅一次开发的意外逆向之旅4. 接着我们对其x进行调用分析,可以看到有两处。我们跟入第一处,很幸运地找到了所需的函数。在这个函数中,我们可以看到大量关键函数的字符串,而我们的PsSetCreateProcessNotifyRoutine也在其中。这时我们的第二条主线就排上用场了。我们可以看到下图中使用PsSetCreateProcessNotifyRoutine这个字符串的函数也引用了sub_4A504这个函数,而这个函数正是我们内核被挂钩EAT后跳转过去的函数。因此我们猜测sub_49F84这个函数应该是GetProcAddressAndSetHook这两个功能,于是我们对其命名GetProcAddressAndSetHook,同时对sub_49F84这个函数命名为Hook_PsSetCreateProcessNotifyRoutine。

一次开发的意外逆向之旅一次开发的意外逆向之旅5. 接着我们对GetProcAddressAndSetHook(sub_4A504)的流程进行分析。首先进入该函数后,根据传入参数我们不难发现有一个函数名称和一个hook的函数地址。根据使用这两项的函数,我们猜测sub_49DDE这个函数的功能是获取函数地址。在他调用的函数sub_49D60中可以明显看到存在PE特征0x5A 0x4D以及0x45 0x50这几个字节码,所以这个函数肯定是根据函数名称获取函数地址无疑,我们将其命名为GetFunAddress(sub_49D60),其首参数为返回需求函数的地址。

一次开发的意外逆向之旅一次开发的意外逆向之旅6. 接着跟入sub_49B6E这个函数进行分析,我们可以看到明显的内存页操作,调用了IoAllocateMdl,MmProbeAndLockPages,MmMapLockedPagesSpecifyCache这几个关键函数。这很明显是申请MDL对内存页进行锁定,防止换页造成缺页异常等问题,这一般是hook的必要操作,所以我们对其命名为LockPage。

一次开发的意外逆向之旅7. 在完成页锁定之后,必然就是进行hook操作。这里采用了一个很好的方法,并没有使用memcpy或者其他内存填充写入的方法,而是采用了原子操作。这种一箭双雕的方法,首先使用_InterlockedExchange这个原子操作交换函数可以很方便地解决了同步问题,其次在_InterlockedExchange调用的时候返回值是上一次的状态,也很方便地保存了上一次的地址,以便于恢复。所以说是一种一箭双雕的方法,InterlockedExchange的第二个参数也使用到了我们的传入地址,以及刚才的LockPage。

一次开发的意外逆向之旅8. 在完成原子交换之后,GetProcAddressAndSetHook的第五个参数被使用。这里可以看到使用结束之后,之前的地址被保存下来,所以可以论证这里是用于恢复使用的。而且结合外面的函数传入值来看,这里是一个全局对象,而且这里这个值在hook的函数之中仍然需要去调用,所以也论证了这一点。

在之后紧接着调用了sub_4B340这个函数,在这个函数中就是一些基本的解除页面锁定的函数,我们将其命名为UnlockPage。

至此,Hook的全套流程就已经分析完毕了。接下来我们来看一看hook掉的代理函数做了一些什么。

04

代理函数分析

一次开发的意外逆向之旅1. 首先,第一个函数sub_4A3F2的操作非常奇怪,该函数作为替换函数应该是一个两参函数,但很不幸IDA分析失败了。最开始因为经验欠缺我没有明白这个函数的意义,但随着之后的分析我茅塞顿开。这个函数是通过栈寄存器来获取调用地址的,因为在栈上有函数的调用地址,所以在之后的LogAboutInformation中会有使用。

一次开发的意外逆向之旅2. 根据Hook_PsSetCreateProcessNotifyRoutine的第二个参数True或False来确定具体流程,无论是在取消设置还是在设置函数中都会调用sub_49CE0这个函数,这个函数的唯一作用就是调用之前保存下来给全局变量的原始的PsSetCreateProcessNotifyRoutine,我们将其命名为CallRightOldPsSetCreaetProcess。

一次开发的意外逆向之旅3. 接着会根据对于PsSetCreateProcessNotifyRoutine调用和失败会进入到LogAboutInformation(sub_4A2C8)这个函数中,跟入该函数结合传入参数分析该函数的唯一意义就是获取设置的函数地址模块名称以及调用者的模块名称,对其进行格式化之后结合特定标志位上传到r3上。

一次开发的意外逆向之旅4. 有意思的是在设置回调的代理函数Hook_PsSetCreateProcessNotifyRoutine中在设置行为下是存在拦截操作的,拦截操作的行为依据来源于LogAboutInformation的返回值并且返回0xC0000022,但是在LogAboutInformation的第三个参数为0的情况下LogAboutInformation直接返回0,所以也就是说在该版本下拦截其实并不生效。

一次开发的意外逆向之旅05

恢复与绕过思路

通用思路,首先同样获取系统内核模块的相关函数地址,模拟MmGetSystemRoutineAddtess的流程,但是我们这里需要解析文件并且解些EAT载入内存,如果采用读文件的方式的话需要注意内存对齐问题。

拿到真正的函数地址时,如果需要恢复的话可以直接学习刚才那一套mdl锁+原子交换的理念,这样就可以解决了。

但这里其实并不提倡这种方法,因为在一些软件中会对于代码有crc校验等功能,如果强行解除hook的话很有可能导致crc校验失败导致不可预料的结果,所以直接可以将获取到的函数进行指针强转直接调用即可。

以上就是一次开发的意外逆向之旅的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/594053.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
消息称明年小米 REDMI、一加、iQOO 等品牌将推出 7000mAh 新机
上一篇 2025年11月10日 17:19:12
如何恢复删除分区文件?详细数据恢复攻略
下一篇 2025年11月10日 17:19:17

相关推荐

  • edge浏览器看视频卡顿怎么办_edge浏览器视频播放卡顿优化技巧

    关闭硬件加速、清除缓存、更新显卡驱动、调整媒体设置及禁用冲突扩展可解决Edge浏览器视频卡顿问题。 如果您在使用Edge浏览器观看在线视频时遇到画面不流畅、频繁缓冲或播放中断的情况,这可能是由于硬件加速冲突、缓存堆积或浏览器设置不当导致的。以下是针对此问题的多种优化方法。 本文运行环境:Dell X…

    2026年9月21日
    000
  • 如何设计统一的API响应格式?

    统一的api响应格式可以通过以下步骤设计:1. 使用包含状态码、消息和数据的基本结构;2. 定义标准的错误码和消息;3. 加入版本字段以支持版本控制和扩展性。这样可以提高api的可读性、简化错误处理和增强可扩展性,提升整体开发效率和用户体验。 统一的API响应格式是构建可靠和用户友好的API的关键。…

    2026年9月21日
    000
  • win11怎么校准笔记本电脑电池_Win11笔记本电池校准方法

    若Windows 11电池显示不准,可通过BIOS校准、手动充放电或第三方软件恢复精度。首先尝试BIOS中“Battery Calibration”功能,执行自动充放循环;若不支持,则手动充满后使用至自动关机再充满;最后可用BatteryInfoView等工具验证校准效果。 如果您发现Windows…

    2026年9月21日
    000
  • 如何在服务器上优化mysql安装

    优化MySQL需从系统环境、配置参数、存储引擎到日常维护多层面入手,首先确保内存合理分配、选用XFS等高性能文件系统、关闭非必要服务并调整内核参数;其次在MySQL配置中优先使用InnoDB引擎,科学设置innodb_buffer_pool_size、innodb_log_file_size、max…

    2026年9月21日
    000
  • 为什么VSCode的语法高亮有时会失效?

    语法高亮失效通常由语言模式识别错误、扩展冲突或配置问题导致。1. 检查右下角语言模式并手动切换为正确类型,确保文件有正确扩展名;2. 禁用近期安装的扩展或以 code –disable-extensions 启动排查冲突;3. 切换至默认主题并检查 settings.json 是否覆盖颜…

    2026年9月21日
    500
  • mysql如何启用binlog日志

    MySQL启用binlog需修改配置文件添加log-bin和server-id,重启服务后执行SHOW VARIABLES LIKE ‘log_bin’验证是否为ON,确认启用。 MySQL启用binlog日志需要修改配置文件并重启服务,同时可进行简单验证确保生效。以下是具体…

    2026年9月21日
    000
  • Linux命令行如何查看登录用户

    Linux命令行如何查看登录用户Linux命令行如何查看登录用户Linux命令行如何查看登录用户Linux命令行如何查看登录用户

    答案是 who、w 和 users 命令用于查看Linux系统登录用户,其中 who 显示登录用户及终端信息,w 还显示用户正在执行的命令和系统负载,users 仅输出用户名列表。 在Linux命令行下,要查看当前系统上有哪些用户登录,最直接、最常用的命令包括 who 、 w 和 users 。它们…

    2026年9月21日 用户投稿
    100
  • Windows系统下的兼容性问题

    windows兼容性问题严重是因为系统演进快、硬件和软件环境多样。处理此问题需:1.了解目标系统版本和配置;2.使用低版本api或兼容性模式;3.检测操作系统版本并调整程序行为;4.避免依赖特定版本的库,提供多版本安装包;5.考虑硬件依赖性,提供备选方案;6.进行跨版本性能测试和优化。 在Windo…

    2026年9月21日
    000
  • Linux如何限制用户执行特定命令

    Linux如何限制用户执行特定命令Linux如何限制用户执行特定命令Linux如何限制用户执行特定命令Linux如何限制用户执行特定命令

    首选sudo进行命令限制,因其灵活且可审计;通过visudo配置精确的用户权限,结合白名单、命令别名和!语法实现允许或拒绝特定命令;同时防范绕过手段如全路径执行、间接调用、脚本执行等,需多层防御并辅以日志监控。 在Linux环境中,限制用户执行特定命令,最直接有效且灵活的方法通常是利用 sudo 权…

    2026年9月21日 用户投稿
    100
  • win11怎么设置默认终端为cmd或powershell_Win11默认终端设置方法

    通过系统设置可更改Windows 11默认终端:1. 进入“设置→隐私与安全性→开发者选项”,在“终端”中选择默认应用;2. 或通过命令提示符属性的“终端”选项卡设定;3. 若使用Windows Terminal,可在其设置中将CMD或PowerShell设为默认配置文件;4. 高级用户可通过修改注…

    2026年9月21日
    100
  • mysql如何理解索引选择性

    索引选择性是衡量索引效率的关键指标,定义为索引列不同值数量与总行数的比值,范围在0到1之间。越接近1,数据唯一性越高,索引过滤能力越强,查询性能越好。例如主键列选择性为1,而性别列因重复值多选择性极低。MySQL优化器会优先选择高选择性索引以缩小搜索范围,提高执行效率。可通过SELECT COUNT…

    2026年9月21日
    000
  • Linux如何查看sudo执行的历史记录

    Linux如何查看sudo执行的历史记录Linux如何查看sudo执行的历史记录Linux如何查看sudo执行的历史记录Linux如何查看sudo执行的历史记录

    要追溯sudo执行的命令,需查看系统日志或配置sudo日志;在Ubuntu/Debian中查/var/log/auth.log,CentOS/RHEL中查/var/log/secure,或使用journalctl _COMM=sudo筛选;通过配置/etc/sudoers中的Defaults log…

    2026年9月21日 用户投稿
    300
  • 如何为VSCode安装新的字体?

    先在操作系统安装字体文件,再在VSCode设置中指定字体名称。1. Windows右键安装.ttf/.otf文件,macOS用字体册安装,Linux复制到~/.fonts并运行fc-cache -fv;2. VSCode中通过设置界面或编辑settings.json修改”editor.f…

    2026年9月21日
    000
  • 如何模拟用户登录状态进行测试?

    模拟用户登录状态是为了测试系统功能和安全性。1.在开发初期帮助发现和修复问题。2.测试不同用户权限下的功能访问。方法包括:1.直接操作session或cookie。2.使用测试框架如junit或testng。3.模拟api请求。 模拟用户登录状态进行测试是确保软件系统用户体验和安全性的关键步骤。无论…

    2026年9月21日
    300
  • Windows11提示“此电脑无法运行Windows 11”但已经安装了怎么办_Windows11提示无法运行系统修复方法

    首先检查并启用TPM 2.0与安全启动,进入UEFI设置开启相关选项;若硬件接近要求,可通过注册表新建AllowUpgradesWithUnsupportedTPMOrCPU并设值为1跳过检查;运行sfc /scannow修复系统文件;专业版用户还可通过组策略启用“移除此电脑不符合Windows 1…

    2026年9月21日
    200
  • 如何在Java中配置系统环境变量以运行程序

    正确配置Java环境变量是运行Java程序的前提。1. 安装JDK并记住安装路径,如Windows下为C:Program FilesJavajdk-17,macOS/Linux下为/usr/lib/jvm/jdk-17。2. 设置JAVA_HOME环境变量:Windows在系统变量中新建JAVA_H…

    2026年9月21日
    100
  • edge浏览器启动速度特别慢怎么办_edge浏览器启动缓慢优化与提速方法

    首先启用Edge的启动增强功能,然后禁用不必要的扩展程序并清除缓存数据,接着重置浏览器设置,关闭硬件加速与后台运行,最后通过干净启动排查第三方程序干扰。 如果您尝试启动Edge浏览器,但发现加载时间异常漫长,则可能是由于后台进程、扩展程序或系统资源占用导致。以下是解决此问题的多种方法。 本文运行环境…

    2026年9月21日
    100
  • 大白菜Win2003PE压缩教程

    大白菜Win2003PE压缩教程大白菜Win2003PE压缩教程大白菜Win2003PE压缩教程大白菜Win2003PE压缩教程

    压缩文件能显著节省存储空间,让用户在有限容量中存放更多数据。最近不少用户对如何在大白菜win2003 pe系统中进行压缩操作存在疑问。本文将全面讲解如何在该环境下使用winrar完成文件的压缩与解压,帮助用户快速上手,提高文件处理效率,轻松满足日常使用需求。 1、 将已制作好的大白菜U盘插入电脑的U…

    2026年9月21日 用户投稿
    200
  • 如何让VSCode记住打开的文件?

    VSCode默认会记住上次打开的文件和布局,只需确保设置正确并正常关闭。1. 启用“window.restoreWindows”为all;2. 通过菜单或关闭按钮退出;3. “files.hotExit”设为onExitAndWindowClose;4. 避免删除用户数据目录中的Backups和Wo…

    2026年9月21日
    600
  • Windows11提示“应用程序无法正常启动(0xc000007b)”怎么解决_Windows11应用程序启动0xc000007b修复方法

    首先使用SFC工具修复系统文件,再重新安装Visual C++运行库,接着更新DirectX组件,最后可借助专用DLL修复工具解决0xc000007b错误。 如果您尝试在Windows 11上启动某个应用程序,但弹出“应用程序无法正常启动(0xc000007b)”的错误提示,则可能是由于系统文件损坏…

    2026年9月20日
    100

发表回复

登录后才能评论
关注微信