万剑归宗 发表于 2023-6-1 01:00

在win7 x64下做个简单的内核绘制

本帖最后由 万剑归宗 于 2023-6-1 12:25 编辑

2023/06/01:搬运我自己在某个司马论坛发过的帖子,以后有新帖会在52更新。

2018/11/08:
1.0
       本贴只针对win7 x64系统下的 32位D3D9程序,局限性太大,仅作为抛砖引玉 。

下面进入正题。

基本流程如下:
1:在内核中 hook相关shadowSSDT或SSDT函数
2:在目标进程申请内存,写入用于D3D9绘制的shellcode
3:利用APC的力量回到 用户模式,执行用于D3D9绘制的 shellcode。
1.1
       首先,如果我们要做一个hook D3D9的绘制。
自然是要编写dll,
注入到目标进程,
hook D3D9虚函数,
获取到D3D9设备,
执行绘制代码。

      时至今日,这种技术已经是基本操作了。
经历各大游戏厂商(代{过}{滤}理商)以及外挂作者们之间的斗争,
这种注入以及hook的方式已然不可取。

      那么是否有一种相对隐蔽的方式来完成这项工作呢?
答案是有的。(废话,没有你写这贴干嘛【滑稽】)
      从我们能想到的根本问题入手的话......
在应用层 hook D3D9虚函数以及直接注入dll会拉闸,
既然如此,我们在内核层做hook,代码全都以shellcode的形式
在目标进程里跑起来。
1.2
       在win7 x64下, 通过调试一个网上下载的D3D9示例Demo
仔细跟踪其 D3D9的Present函数,我们发现 Present 最终会调用
USER32.HungWindowFromGhostWindow+20处的代码
反汇编如下:

call fs:其实是call Wow64子系统的调用
经过Wow64子系统的包装,最终进入内核。

mov eax, 000012CF这句汇编代码
其中 000012CF代表的是 shadowSSDT 的索引值
了解过 SSDT&shadowsSSDT的朋友都知道
第一个4k页面指向的是SSDT函数
第二个4k页面指向的是shadowSSDT函数
另外两个页面未使用(这是题外话。)
00000012CF在第二个页面上,所以这个索引指向shadowSSDT函数。
我们减去 0x1000 就是它的真实索引值 0x02CF,十进制就是 719。

我们打开PChunter这款非常有用的软件, 我们可以看到索引719指向的
shadowSSDT函数名 NtUserHwndQueryRedirectionInfo


       接下来我们就hook这个函数并写好过滤
一般来说,这种shadowSSDT函数,只传进来一个参数(rcx), 保险起见我们写四个。
示例过滤函数如下:(自备shadowSSDT hook代码,本贴不会放完整代码,防止伸手)



       But, 光是这样是不够的, 我们还要在这里获取到D3D9的设备。
这就给我们出了一个难题,一般在应用层都是hook取设备的。
经过查资料,我们想到了一个好办法,利用栈回溯,找到最初调用
Present函数的地方, 并把第一个参数(也就是设备)取出来。
好在windows x86下的栈回溯是基于EBP来回溯的,原理相对简单,
我们可以手动编写一下。
1.3

       应用层在通过syscall进入内核之前,会把当前的TrapFrame保存
起来。在内核中当前_KTHREAD成员 TrapFrame 就是应用层保存的
TrapFrame 指针。



在win7 x64下,其结构偏移为 0x1D8。
       至此,我们可以顺利的获取应用层最后保存的RBP了。

接下来写栈回溯,具体原理我就不多做描述,大家可以移步这两个帖子看一下
https://blog.csdn.net/chenlycly/article/details/78144769

https://blog.csdn.net/wu330/article/details/29213201

示例代码如下:

笔者这里偷了个懒,直接判断call 地址是否小于 0x00500000
以此确定 当前帧就是call present的。
       当然,获取到设备的同时,得以确认,当前线程就是从
Present函数一直call 进内核的。下面就可以放心的执行绘制操作了。
2.0
      在内核中给当前进程申请内存,最方便的莫过于ZwAllocateVirtualMemory
申请内存成功之后,写入shell code。
比如直接call D3D9的 Clear函数,画个方块。
示例如下:

要注意的是,不要一直不停的申请内存,我想各位看官应该不会这么做[滑稽]。
3.0
      做完如上工作,接下来就可以想办法回到用户模式,执行shellcode了。
回到用户模式的方法有好几种,比如KeUserModeCallBack, APC。
其中 KeUserModeCallBack 需要在应用层中写好代{过}{滤}理分发,并且如果目标进程是
wow64进程,还需要多写一层代{过}{滤}理函数,着实麻烦。
      所以我们采用相对简单的 APC,利用APC机制回到用户模式。
代码如下:


注意这里的细节,如果目标进程是 wow64进程,起始地址需要 / -4。
然后就是常规的初始化APC,插入队列。
      由于我们是回到当前进程的应用层,所以初始化APC时,
KeInitializeApc第二个参数填 PsGetCurrentThread()。

最后利用KeTestAlertThread直接触发队列里的APC Routine。
3.1
放上效果图如下:

3.2
But
出现了新的问题
经过笔者测试,有些系统并不走 NtUserHwndQueryRedirectionInfo
而是另外的ShadowSSDT函数,不过我们依然有办法解决这种小问题。

在出问题的机器上,一通调试分析后,找到如下代码


图片可能有点模糊
命中断点位置的代码是cmp ,ebx   
其中 esi+760 = 0xC2D4118
然而地址 0xC2D4118的值为0,
所以代码会 je D3D9.DLL+7C47
抛开这里往下看
如果没有 je D3D9.DLL+7C47
代码会走进这里


一路跟进去

再跟

最终看到了熟悉的代码, 是NtUserHwndQueryRedirectionInfo


3.3
然而直接走到 D3D9.DLL+7C47 肯定不会经过NtUserHwndQueryRedirectionInfo
最简单的解决方式肯定是直接把 je D3D9.DLL+7C47 nop
测试结果如下


很明显
改了之后加载驱动可以直接绘制上这个 基佬色 的方块
然而还原之后

绘制效果消失了
而且在 USER32.HungWindowFromGhostWindow+20处
下断点是不会命中的(这不是废话吗)

4.0
梳理流程


判断函数主要判断 是否为0
如果为0,直接走 D3D9.DLL+7C47,否则走 NtUserHwndQueryRedirectionInfo
这里我有必要提一下,不要想着锁定 的值,这样做会导致D3D无限初始化Surface
虽然进了 NtUserHwndQueryRedirectionInfo,但是会一直在这里死循环,不再进行任何绘制。
而且修改代码段的内存来强行让他走 NtUserHwndQueryRedirectionInfo 恐怕也不是各位看官想要的结果.


4.1

摆在面前的有两条路
1: 在创建窗口->创建D3D设备 这个流程中仔细分析创建需要的参数,找出其原因.
2: 在这个绘制流程中,进入判断函数前 改掉 的值,进入NtUserHwndQueryRedirectionInfo 之后再改回来

由于时间有限,我姑且只讲一下第二种方式。
笔者重新理了一下执行流程

如图所示,我们只需要在 D3DKMTPresent 这个函数进入内核之后
改变其 的值为1
在进入判断代码时,就会顺理成章的进入 NtUserHwndQueryRedirectionInfo
然后我们在NtUserHwndQueryRedirectionInfo里把 的值改成 0
这样走到后面的检测代码中,就不会无限获取D3D9主Surface导致死循环。

还有个很重要的问题 esp+760 如何获取,这个比较简单了,经过笔者指针扫描+瞎猜
这个值可以通过如下方式获得。

最后一级偏移为760,所得地址便是 esp+760 ,所得值便是 。


结语:
来自未来的时间(2023/06/01):
以后有空再对这类型内容做研究,届时依然在52更新

万剑归宗 发表于 2023-6-1 12:37

本帖最后由 万剑归宗 于 2023-6-4 21:25 编辑

早期Demo


2023/06/04
1111111111

tonyfeng 发表于 2024-2-1 17:25

大哥,你好,CAD2005注册机是32位程序,能在WIN7X64运行,也能在运行,但是不能在WIN10 11运行,你有办法让它直接在WIN10X64运行吗

tzblue 发表于 2023-6-5 08:22

离开3环进入0环,还好是Win7,从Win8开始就有云代码,修改内核行不通,除非搞到驱动签名,当然大牛会有更直接的方法。

陨落星辰 发表于 2023-6-1 12:29

Good.從某雪過來支持你

blindcat 发表于 2023-6-1 12:36

太高深了,一点都看不懂

Sm0key 发表于 2023-6-1 12:48

大牛,看不懂,膜拜就完了

内阁首辅 发表于 2023-6-1 14:48

字我都认识

apull 发表于 2023-6-1 16:23

这个厉害了,涨姿势了。

aonima 发表于 2023-6-1 17:41

感谢分享

lafa21 发表于 2023-6-1 20:32

字都认识,下一步做什么才好

moruye 发表于 2023-6-1 22:27

页: [1] 2 3 4 5 6 7
查看完整版本: 在win7 x64下做个简单的内核绘制