-
-
[旧帖]
驱动中如何在多CPU下进行系统代码执行同步
0.00雪花
-
发表于:
2014-3-6 11:18
3174
-
[旧帖] 驱动中如何在多CPU下进行系统代码执行同步
0.00雪花
大家好,如果经常玩内核的,想必都碰到过这么一种情况:在驱动下要对系统的某部分打运行时补丁,但不巧补丁字节超过了一个原子操作(一条汇编指令,这几乎是肯定会超的),那么很有可能正当你补丁到一半时,线程切换或其它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期)