基于taskmgr的应用层进程隐藏技术

 

目前进程隐藏技术网上流程的主要是在驱动层进行挂钩,但是由于win7之后,windows操作系统权限管理之类越来越严格,win7之后加载驱动首先需要管理员权限,另外windows加载驱动同时还需要有微软签发的驱动证书,这对于土八路来说基本是一个无解的难题,基本难以弄到正规公司的签证,同时,逆向windows的签证管理系统工作量太大,目前网上也没有签证伪造技术流传。

 

相对驱动层来说,直接hookssdt表或者直接修改内核函数都较为方便,在应用层的话,其原理也是改写功能实现函数,从思路角度说,可以改写taskmgr.exetxt段,导入表,对dll的函数代码进行hook等手法等三种。

 

无论哪种方法,可能都需要逆向一下Taskmgr.exe,分析一下其显示进程信息的相关原理。就win7而言,251kb大小,同时作为一款窗口进程,如何快速的我们感兴趣的功能尽快找到,并逆向出其工作原理,也算是一个难点。

 

图片1

 

 

Taskmgr.exe的快速逆向方法:这里要介绍一种快速逆向的方法,可以快速得到指定功能的实现原理。

 

1,将taskmgr.exe拖进ida中进行逆向,查看导入表信息

 

图片2

 

寻找所有相关进程查询的api,之后再bdg中下函数断点,下断函数为ZwQuerySystemInformation,很快可以定位到进程查询的相关代码。这是逆向的第二层境界,根据正向思路来逆向,逆向修炼在进一步的就是编写驱动监视cpu执行流程,io,总线活动之类来逆向。

 

图片5

 

 

 

rcx参数为5时,ZwQuerySystemInformation执行的就是对进程链表的查询功能。

 

ida可以看到进程信息查询的汇编代码:

 

图片6

 

Hook的三种方案

 

对于修改windows的进程管理器,肯定是要对taskmgr进行hook,通常hook是对软件的代码执行路径上的必经之路上下hook函数,在应用层上来说一共三个节点是必须要经过的,1taskmgr代码中调用ZwQuerySystemInformation函数进行进程信息查询的函数,2pe导入表的ZwQuerySystemInformation地址所在表项,3ntdllZwQuerySystemInformation所在位置。对应的,有三种下钩子函数的手法。

 

程序中查询进程信息函数——–>PE导入表———->Ntdll.dllZwQuerySystemInformation的实现。

 

taskmgr.exetxt段的代码改写:

 

很容易寻找到相关的进程信息查询部分,这时,根据64fast传参规则,rdx指向的就是进程信息接收指针所在的位置,此时可以直接使用汇编改写进程信息查询函数,在结束ZwQuerySystemInformation函数的调用之后,可以对接收到的进程信息,抹去需要隐藏的进程信息后提交给原程序的处理流程。此方法的问题在于windows各个版本的进程管理器都略有差别,此方法需要大量使用汇编代表,难以实现兼容。

 

taskmgr.exepe导出表的指针改写:

 

在之前的逆向分析中得知,获取到进程信息的函数为ZwQuerySystemInformation,可以根据pe+信息(32pe文件,64pe+文件),寻找到pe+文件的导入表信息,将ZwQuerySystemInformation函数的导入地址修改,改为自己已经编写好的函数地址,再调用ZwQuerySystemInformation函数,将接受到内核层返回数据之后,再做屏蔽相关的进程信息。这种方法可能是最佳的方法,其优点在于可以直接使用c语言编写代码,而不需要使用汇编,汇编是一种十分依赖硬件环境的语言,此例中只需要对文件的导入表修改8字节大小即可,且,pe+文件的导入表是拥有可读可写可执行权限的,动作最小,但由于此种手法为病毒常用手法之一,被杀软重点关注,故并未使用此手法。计算机病毒防范艺术一书中,讲述文件病毒的一种中专门有一节论述此技术以及升级手法,不做太多描述,手法较为常规不太好用其实。

 

ntdll.dll进行hook

 

api调用过程之中,大多说功能型api,都是要进入内核层进行执行功能,api经过ntdll进行封装,变成Ntxxxxx/Zwxxxxx类型名字之后,调用同名系统调用表,经过内核的参数验证后执行功能返回,通常而言,是通过syscall指令执行快速系统调用进入内核层,在xp时代使用的是sysentry指令。这里查询进程信息使用的ZwQuerySystemInformation函数,就是使用的nt函数,此函数直接调用系统调用,若在taskmgr进程直接调用nt函数时,将其挂钩时也能做到隐藏进程。需要改下字节最少需要13字节。

 

进程隐藏实现

 

本次使用的是挂钩dll的方法,在windows7之后,许多非常规手段的使用都不再简单,windows系统机制中加入了各种各样的防御手段。这里是指session 0隔离,以及内存权限控制。

 

Session 0隔离 所有的服务以及dll都存在于session 0中,而用户登录,第一个登录位于session 1,后面的用户登录使用的是 seesion 2,依次类推,常规的VirtualAllocExWriteProcessMemory函数调用,将无法写入dll所在的内存空间之中,因为此类API在实现功能之前会对session 进行校验。挂钩时,必须手动操作指针进行写入读取操作。

 

 

 

内存权限保护 起源于xp时代的dep技术,原本计算机另外的一个名字叫做图灵机,在图灵机模型中数据代码没有明确间隔,但在现代操作系统的内存分割机制下,在内存中,内存拥有读写执行权限,对于一块只读内存区间,是不可以进行写入操作,同时也不允许进行执行操作。在进行挂钩时,必须赋予需要改写的地址可读可写权限,同时,如果被挂钩位置需要执行,还需要赋予可执行权限。更改内存权限需要管理员权限,这是最大的一个缺陷。

 

 

 

Native函数的调用 windows编程技巧中有一种技巧是直接调用Ntxxxxx/Zwxxxx函数,此类函数之间调用同名系统,通常不被导出,但可在windowswdk帮助文档中查询到一些,此类函数由于接近底层,常可用作一些底层操作,同时由于使用量少,网上资料也不多,此类技巧大量被应用于病毒以及安全软件,在挂钩中也经常被使用来突破session 0隔离,内存保护等,但由于此类函数相关介绍不多,在使用时常常会有各种问题出现,如函数ZwProtectVirtualMemory会将函数参数值做一个字节修改,这也是编写安全类软件一大挑战,相关资料可以查询Windows NT 2000 Native API Reference 一书

 

 

 

详细步骤为:

 

1.获取taskmgr.exe进程信息,如pid

 

2.获取注入恶意代码

 

3.恶意代码修改需要hook的目标内存地址的权限

 

4.对目标地址进行修改代码执行流程

 

5.新的执行流程将查询信息返回后屏蔽指定进程后返回

 

 

 

此方法难点在于对ZwQuerySystemInformation函数代码的改下,此函数为 Native Api,为直接调用系统调用的api,在不同版本的操作系统中,系统调用号并不相同。存在需要处理的兼容性问题,另外ZwQuerySystemInformation对于windows7来说,总共只有16个字节,而对x64位系统而言,仅仅一个地址就需要8个字节,另外,jmp指令最多只允许跳转跨越4Gb的内存跨度,但在windows7中,ZwQuerySystemInformationMyQuerySystemInformation(新流程函数,屏蔽需隐藏进程信息函数)函数地址间距由于dll的内存布局问题,两个函数直接跨度超越4Gb大小,需要挂钩时整体考虑,另外,在x64位编程中,内嵌汇编代码也不是一件简单的事情。

图片7 图片8

 

 

 

这里两幅图片分别是win10以及win7中的ZwQuerySystemInformation函数代码,可以看出系统调用号不一致,于此同时,在win7ZwQuerySystemInformation函数代码非常之小。

 

windows 10的挂钩过程中,我曾试用常规挂钩手法:E9 off相对偏移,然而在迁移过程中发现,ZwQuerySystemInformationMyQuerySystemInformation之间的内存地址差距远大于4Gb,需要8字节大小描述距离,然而,jmp指令不支持此类超远距离长度的跳转。

 

这里,我选取的挂钩代码为:

 

Mov rax,offset: ZwQuerySystemInformation

 

Push rax

 

Ret

 

效果图为:

 

图片9

 

 

Written by 冷风

天融信阿尔法实验室攻防研究