本次实现是在WIN7 X86系统上进行,实验要达到的目的就是实现进程的隐藏,以让任务管理器查不到要隐藏的进程。这里要隐藏的程序是一个简单的HelloWord弹窗程序,程序名是demo.exe。
用户层的进程隐藏的实现主要是通过HOOK任务管理器的ZwQuerySystemInformation函数。之所以是这个函数,是因为无论是通过EnumProcess函数还是CreateToolhelp32Snapshot函数来查询进程,它们最终都会调用ntdll.dll中的ZwQuerySystemInformation函数来实现功能。
所以只要采用DLL注入技术,将DLL注入到要HOOK的进程中,并在DLL加载的时候执行HOOK ZwQuerySystemInformation函数就可以实现进程隐藏。关于如何实现DLL注入请参考这篇常见的几种DLL注入技术。而对ZwQuerySystemInformation的HOOK采取的是Inline Hook的技术。如何实现Inline Hook请参考这篇内核层的三种HOOK技术。
在IDA中可以看到ZwQuerySystemInformation的实现如下。由于它最开始的五个字节是为eax赋值调用号,所以其实可以根据热补丁的思想,对这五个字节进行HOOK。然后在HOOK完要执行的函数里面对eax进行重新赋值以后在跳转到下一行代码也就是mov edx, 0x7FFE0300进行执行。
由于之前写过热补丁技术,这里的话就用传统的HOOK步骤。
使用GetProcAddress函数获取要HOOK的函数的地址,并将其保存
修改前五字节的页属性为可读可写可执行
将这五个字节读出来备份起来
计算从需要跳转的大小,公式是: 要跳转的目的地址-(HOOK的函数的地址 + 5)
将计算好距离的跳转指令写入函数的这五个字节
还原页属性
UnHook则非常简单
判断函数是否被HOOK
修改函数地址页属性为可读可写可执行
HOOK的时候保存的五个字节写回到函数地址
恢复函数地址页属性
在完成HOOK以后执行的函数内部就需要以下的步骤来让程序正常运行
首先调用UnHook将函数恢复
调用原函数获取返回结果,将要隐藏的进程隐藏掉
再次对程序进行HOOK操作
至于要如何将进程隐藏起来,就需要首先看看ZwQuerySystemInformation在文档中的定义了
而SYSTEM_INFORMATION_CLASS,在文档中的定义如下
当它指定为SystemProcessInformation(0x5)的时候,就表示要检索系统的进程信息。函数将会得到所有的进程信息并把这些得到的进程信息的内容保存到SYSTEM_PROCESS_INFORMATION结构数组,数组中的每一个元素都代表了一个进程信息。而数组的首地址将会保存到第二个参数SystemInformation中。
而SYSTEM_PROCESS_INFORMATION在文档中的定义如下
其中的NextEntryOffset代表的是下一个SYSTEM_PROCESS_INFORMATION元素距离现在这个SYSTEM_PROCESS_INFORMATION元数的偏移。
而UniqueProcessId就是查询到的这个进程的PID。根据它就可以找到要隐藏的进程,并将它从这个结构体数组中断开,也就是要隐藏进程的SYSTEM_PROCESS_INFORMATION的上一个元数的NextEntryOffset加上当前SYSTEM_PROCESS_INFORMATION的NextEntryOffset。具体代码实现如下
在实现注入HOOK函数之前可以看到任务管理器可以查看到打开的demo.exe进程
完成注入,HOOK成功之后就看不到了
在内核中每一个进程都有对应的一个EPROCESS结构体,在Windows7下这个结构体中的部分成员如下,其中0x16C保存了进程名字的指针。通过这个指针可以获得当前EPROCESS表示的是哪一个进程
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-11-30 10:01
被1900编辑
,原因: