一般来说通讯使用DeviceIoControl就可以,但是有的时候还不够,比如说Ring0捕获到数据,传递给Ring3,Ring3处理后再反馈给Ring0,Ring0再处理(比如说主动防御的进程监控),这样来说,一次DeviceIoControl的调用明显不够,也不可以,而且必须是一次数据交互要完成的事情,就要走别的路子了。 如何共享内存数据: 物理内存是不变的,物理内存地址也是不变的,在这里做手脚咯。 Ring3申请内存,把内存地址传递给Ring0(DeviceIoControl操作),Ring0把此地址转换为内存物理地址再映射为Ring0可用的虚拟地址,即: MmMapIoSpace( MmGetPhysicalAddress( (PVOID)Addr ), SizeOfData, MmNonCached ); Addr就是Ring3传递过来的虚拟地址了,SizeOfData是该地址的数据范围大小 不再使用此地址时记得MmUnmapIoSpace取消映射 可能的一个缺点就是内存的分页与非分页,解决的办法就是在Ring0下申请内存,再传递给Ring3了,没去实践,还没发现这个问题,嘿嘿。 以上做好了之后就是交互问题了,信号怎么传递,用事件解决。 之前找到的一个方法是在Ring0下创建事件,但是这样Ring3下就不能进行SetEvent等操作了(没权限?),只好在Ring3下创建事件传递给Ring0了,即: PKEVENT kEvent = NULL; hEvent就是Ring3传递过来的Event句柄了,转换之后得到的kEvent即为Ring0所用了 这样Ring3和Ring0就都可以操作同一个事件,都可以进行SetEvent(KeSetEvent)等操作了。 下面就是保护进程了,原想HOOK掉NtOpenProcess的,可是太麻烦,判断复杂(调用的目的不一定结束进程),就去找NtTerminateProcess的麻烦了 HOOK很简单,修改SSDT,就不复述了,还是上代码: ProtectNames[100][100];//存放被保护的进程名 NTSTATUS MyNtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,IN NTSTATUS ExitStatus) if ( ProcessHandle != NULL ) 我是根据进程名判断的,虽然不完善,但是这个程序也监视了进程创建,想冒充也不那么容易,嘿嘿。 其他的还有根据进程句柄来判断的,即被保护进程的HANDLE与函数传递过来的ProcessHandle进行对比,貌似更简单,但我的目的不是这样。。。。。。 好了,这几天就做了那么多事情,也学到了不少东西。 {zh1}一点,Ring0下HOOK与Ring3通讯,貌似与多线程有点关系,用个变量,或者自旋锁解决问题即可。 |