181004(隐藏进程)

一、隐藏进程:

隐藏进程:隐藏特定进程的技术(stealth process),专业术语叫Rootkit,指通过修改(Hooking)系统内核来隐藏进程、文件、注册表的一种技术。
IAT钩取通过操作进程的特定IAT值来实现API钩取,而API代码修改技术则将API代码的前五个字节修改为JMP XXXXXXXX来钩取API。
(1)正常调用API时
调用API时,首先使用CALL 指令调用API,在相应API执行完毕后,返回到调用代码的下一条指令的地址处。
(2)钩取之后:

首先把dll注入目标进程,API起始地址5个字节代码被修改为JMP XXXXXXXX(仅修改五个字节),在我们的XXXXXXXX的位置,首先把APi修改回原样然后调用一次,之后钩取。
注:当API的前五个字节是我们修改过后的时,也即API被钩取。
使用API代码修改技术可以钩取进程中使用的任意API。要钩取的API代码长度要大于五个字节但是所有API代码长度都大于5个字节。

进程隐藏,用户模式下最常用的是ntdll.ZwQuery-SystemInformation()API钩取技术。

为了隐藏某个特定进程,要潜入其他所有进程内存,钩取相关API。

用户模式下检测进程的API分为2类
1、 CreateToolhelp32Snapshot()&EnumProcess()

2、 ZwQuerySystemInformation()
该API可以获取运行中的所有进程信息(结构体),形成一个链表。操作该链表即可隐藏相关进程。
因此我们需要“全局”(global)钩取来实现钩取系统中运行的所有进程的ZwQuerySystemInformation()API。

练习实例

1、练习#1
在虚拟机中按照书上的格式使用书中提供的程序。但是注入失败。经检测发现dll注入正常,经过分析可能是虚拟机自带的procexp是魔改版本,可以保护自身不被dll注入。所以“notepad.exe”并未消失.

使用CreateToolhelp32Snapshot()获取系统中运行的所有进程的列表,然后使用Process32First()与Process32Next()将获取的进程信息存放到PROCESSENTRY32结构体变量pe中进而获取进程的PID.

在代码的注入中,分析源代码发现进程PID小于100的程序我们就没有操作。(系统进程)

这段代码中,我们先创建名为”.SHARE”的共享内存节区,然后创建g_szProcName缓冲区,最后再由导出函数SetProcName()将要隐藏的进程名称保存到g_szProcName中。

JMP加地址 E9 XXXXXXXX 其中XXXXXXXX=要跳转的地址-当前指令地址-当前指令长度

###二、全局API钩取
全局API钩取针对的进程为:(1)当前运行的所有进程(2)将来要运行的所有进程
Kernel32.CreateProcess()被用来创建新进程。因此如果钩取了Kernel32.CreateProcess()那么之后父进程使用它创建的所有子进程都会被注入。
但是要注意(1)还要钩取CreateProcessA()、CreateProcessW()2个API(ASCII和Unicode版本) (2)微软部分软件会调用CreateProcessInternalA/W这两个上述API内部的函数。(若可能,尽量钩取低级API) 。
ntdll.ZwResumeThread()API ,比CreateProcess()更低级,钩取效果更好。
ZwResumeThread()函数在进程创建后,主线程运行前被调用执行(在CreateProcess()API内部调用执行)。但该API尚未被公开,可能会被更改,因此可能在未来的时间钩取操作无法运行。

练习实例

按照书中所说我们把”stealth2.dll”导入系统目录的system32文件夹,并运行了程序

这次和书中的预期结果相同,procExp进程和任务管理器中的“notepad.exe”进程隐藏了。
与实验1的不同是在本次的stealth2.dll中,添加了钩取CreateProcessA()和CreateProcessW()API的代码.
值得注意的是钩取尚未公开的API时,一定要检查它在当前的OS版本中能否正常运行。

###三、 利用“热补丁”技术钩取API
API代码修改技术修改过后的API每次被在程序内部调用时,我们的钩取函数就会被调用执行,不断的“脱钩”/挂钩。造成整体性能地下,更严重的是在多线程环境下还会产生运行时错误。当一个线程尝试运行某段代码时,若另一线程正在对该段代码进行“写”操作,这时就会出现冲突,最后引发运行时错误。
因此,我们需要“热补丁”(Hot Patch/Hot Fix)技术比修改5个字节代码的方法更稳定。热补丁将会修改7个字节代码。
常用API的起始代码部分会以”MOV EDI,EDI”开始(IA-32:0x8BFF),API代码上方有5个NOP指令(IA-32:0x90)。
MOV EDI,EDI 2个字节,NOP 1个字节。 这七个字节的指令没有任何意义。
我们将API起始代码之前的5个字节修改为FAR JMP指令,跳转到用户钩取函数处,然后将API其实代码的2个字节修改为SHORT JMP指令。通过这种我们称为“二次跳转”的技术就完成了对指定API的钩取操作。通过热补丁技术钩取的API并未对原API进行修改,可以用”原API地址+2”开始执行原API。

练习实例

按照书中的实验原理很容易理解,我们来看源码。

在这里的pBuf【5】申明为{0xE9,0},之后使用两次memcpy函数先把 “JMP XXXXXXXX”的XXXXXXX写进去,然后把整个“JMP XXXXXXXX”写到API前的那五个字节。然后用memcpy把MOV EDI,EDI替换为JMP YY指令。
值得注意的是热补丁API钩取技术使用时必须满足它的使用条件。如果不满足使用条件那么就只能使用五字节代码修改技术。
Ntdll.dll中提供的API代码都较短,钩取这些API的时候有一种非常好的方法,将原API备份到用户内存区域,然后使用5字节代码修改技术修改原API的起始部分。 由于API代码较短且代码内部地址无依赖性,因此非常适合使用这一技术钩取。但这一技术需要处理重定位的问题。