首页
社区
课程
招聘
[旧帖] 驱动中如何在多CPU下进行系统代码执行同步 0.00雪花
发表于: 2014-3-6 11:18 3168

[旧帖] 驱动中如何在多CPU下进行系统代码执行同步 0.00雪花

2014-3-6 11:18
3168
大家好,如果经常玩内核的,想必都碰到过这么一种情况:在驱动下要对系统的某部分打运行时补丁,但不巧补丁字节超过了一个原子操作(一条汇编指令,这几乎是肯定会超的),那么很有可能正当你补丁到一半时,线程切换或其它CPU正巧执行到你的“垃圾代码(不完整的指令,因为你只有一半指令,还不全)”上。

    在单核CPU下,想必比较简单,直接提升 IRQL 到2就可以解决,因为可以防止线程切换。
    在多核CPU下,就比较麻烦了,虽然有提升 IRQL 加 DPC 的方式实现伪自旋锁来解决,但这个方法好像不能保证绝对安全。

     如果大家不知道伪自旋锁怎么同步,可以先找找资料,下面我说一下我碰到的问题场景。

     我在驱动程序中 KeStackAttachProcess 了某个进程,进入了它的地址空间,然后找到某个已知地址的函数入口点,需要修改这个入口点为 JMP 0x00XXXXXX 的形式(这条指令大于4字节),先JMP到我的ShellCode,再JMP回去执行原流程。

    我打算使用伪自旋锁,这是我目前已知最优的同步方法了。但我仔细想了想,好像还是有问题。比如:

     我投递 DPC 到每个CPU上,想让除当前CPU以外的所有CPU空转(空转是在IRQL=2),但如果在投递之前,他们中的一个CPU正在 PASSIVE_LEVEL 执行我将要替换的原指令的一半(原指令几乎有两三条之多,像典型的 push ebp;mov ebp,esp;。这使得我后期修改为JMP后,后面都是 NOP 填充补位),那么我投递 DPC会让这个CPU中断并提升IRQL,发生空转。这时我当前CPU修改了指令,通过释放伪自旋锁,那么那个CPU随后会回到 PASSIVE_LEVEL 上继续执行代码指令。这样一来,它会碰到一个不认识的指令,肯定崩溃。

   不知道我是否描述清楚了,我的最终问题是,有办法安全的打补丁吗?

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 126
活跃值: (651)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
多核inline hook如果要修改的指令长度超过了一个原子操作能完成的话,必然不安全(99%安全,呵呵),没有好办法,只能尽量用较少的几个原子操作完成!
2014-3-6 11:54
0
雪    币: 468
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
同样的问题,我也提出过
http://bbs.pediy.com/showthread.php?t=184183
还有一个问题啊。
假设你还没开始hook的时候,一个线程正好运行到你想要hook的第3个字节,这个时候被切换,那么系统中保存的是下次在调度运行这个线程的时候,从第3个字节开始运行。
然后你进行了hook,很显然第3个字节是不可运行的,是错误的指令。
然后系统又调度原来那个线程从第3字节开始恢复运行,然后就蓝屏了。
所以如何避免呢?
还要检查所有的被挂起的现成,检查这些线程将要被恢复的eip不是指向第3字节。如果真有某个线程eip恰好指向第3字节,那么先不要hook,先让这个线程再运行一段时间,eip已经经过了第3字节到了别的地方了,再挂起这个线程。再查看所有的线程,确保任何一个线程的将要恢复的eip不是指向第3字节。然后才开始hook。
2014-3-7 11:53
0
游客
登录 | 注册 方可回帖
返回
//