什么是内核级木马?

nanyuan 2020-08-18 15:42 98

摘要:首先,什么是内核级特洛伊木马内核级木马是一个独立的远程控制后门程序,没有进程,没...

首先,什么是内核级特洛伊木马

内核级木马是一个独立的远程控制后门程序,没有进程,没有动态链接库,没有启动项目和多个Rootkit技术特征。它使用线程将动态链接库注入系统进程,删除动态链接库映射,删除自己的文件和启动项目,并在关闭时恢复。它是一个内核级的木马程序,其主要部分工作在Ring0,因此具有很强的隐蔽性和杀伤力。

二,内核级木马的意义

目前,由于一些主动防御软件和免费使用防病毒软件,传统的应用层特洛伊木马对它们的技能了如指掌。特洛伊木马能带来巨大危害的主要原因是它们的隐蔽性。各种反病毒工具的快速发展导致了寻求利益的木马成本大幅增加,其带来的利益和威胁也在逐年下降。由于传统应用层木马的隐蔽性大大降低,黑客们更迫切需要改进木马的隐蔽技术,以提高效益,获得对受控主机更持久的控制。

内核级木马隐藏主要采用内核Rootkit技术,使得远程黑客能够长时间享受对目标机器底层系统的控制,同时很大程度上不被杀毒软件发现,从而对被控主机造成更严重的安全威胁。此外,内核Rootkit不仅存在于Windows系统中,也存在于其他系统中,如LINUX。

对于信息安全工作者来说,找出防范内核级木马的最有效方法自然是深入了解内核木马的工作机制、内核Rootkit攻击技术和内核Rootkit隐藏技术,掌握它们的规律和特点,从而更好地找到应对这类木马的措施,对未来潜在的安全风险做出一些防范。

第三,内核木马隐藏技术与传统应用层木马隐藏技术的比较

内核级木马隐藏主要包括进程隐藏、文件隐藏、自启动隐藏、通信隐藏等。,这主要与特洛伊木马架构有关。对于一些主从内核级的木马,木马涉及的功能模块越多,隐藏的项目自然就越多,有时甚至包括注册表隐藏和服务隐藏。

3.1 .进程隐藏

进程隐藏的最初技术系统是最简单的混淆字符隐藏。例如,系统进程名为svchost.exe,特洛伊木马进程名更改为svch0st.exe隐藏,然后是注册服务隐藏和dll注入隐藏。目前,大多数内核级特洛伊木马通过从进程控制块的活动进程链接中移除自身,或者通过从PspCidTable表中移除自身来隐藏。

3.2 .文件隐藏

文件隐藏最初是通过存储在敏感目录(系统目录)和混淆文件名来实现的。后来,一些人通过在应用层挂钩应用编程接口实现了这个目标,比如查找第一个文件,查找下一个文件。现在,在内核层隐藏文件的方法通常由FSDHook或FSDInlineHook实现。

3.3 .自启动隐藏

自启动隐藏是通过增加注册表运行值、修改系统启动文件、注册为服务、修改定时程序、感染系统文件技术来实现的。现在黑客开始关注硬盘固件、bios等地方来实现自启动隐藏。

3.4通信隐藏

对于通信隐藏,一些研究者已经实现了NDIS端口驱动层的隐藏,但是主流木马仍然在TDI层或NDIS中间层进行通信。

第四,内核级隐藏技术分析

由于应用层隐藏技术位于ring3层,一般很难抵抗一些从内核层获取相应信息的软件的检测。在内核级隐藏技术中,各种方案使用的隐藏技术因其不同的特点和不同的目的而不同。在本节中,我们将重点分析内核级特洛伊木马可能使用的一些隐藏技术。

4.1自启动隐藏

对于应用程序级特洛伊木马,有各种自启动方法,如绑定文件、修改注册表项、添加自启动快捷方式等。但是,安全软件对应用层进行严格的检查,虽然对内核层的自启动方法也有检查,但是相对来说,内核级的自启动一般更有效。常见的内核级木马自启动方法主要包括以下几点:

(1)注册为背景服务

这与分级特洛伊木马自启动时注册为服务的原理相同,只是前者将应用程序注册为系统服务,而在这里将编写的驱动程序注册为系统服务,从而实现自启动。这种方法主要是将驱动注册为系统的一项服务(一般来说,单片机(Service Control Manager)接口用来实现服务的安装、启动和停止等)。,并且以这种方式加载的驱动程序是不可分页的,因此不需要考虑分页问题。另外,BSOD通常不是由驱动程序的加载引起的),并且[HKEY _本地_机器系统当前控制集是在注册表服务名称& rdquo]子键,然后设置一些启动参数,如ImagePath。普通的驱动通常是这样加载的,内核木马的驱动模块也可以使用这种方法。但是,因为它涉及将键值插入注册表,所以在加载过程中可能会被截获。此外,如果加载成功,有必要在后续代码中隐藏注册表项和服务项。

(2)使用nativeapizwsetsysteminformation()

此方法使用未记录的应用编程接口函数ZwSetSystemInformation(),它可以在不创建注册表项的情况下加载驱动程序。然而,由于驱动程序的分页,如果通过这种方法加载的内核木马驱动程序在驱动程序运行过程中被分页,其访问将导致BSOD[11]。因此,如果我们想使用这个方案,我们需要设计分页问题。例如,migbot通过将所有操作代码复制到非分页内存池来实现这个目标。

4.2文件隐藏

一般来说,应用程序级别的文件隐藏是基于伪装的,而不是真正意义上的隐藏,或者可以说它在视觉上欺骗了用户,例如将文件名更改为类似于系统文件的名称(通过使用一些令人困惑的字符)。在内核中,可以通过在文件操作期间修改内核处理流程来隐藏文件,这样用户就不能通过工具(使用相同或更高级别的方法来枚举文件的工具)查看系统中隐藏的文件。内核层有几种常见的文件隐藏技术:

(1)HookZwQueryDirectoryFile()函数

在Windows环境下,文件的枚举操作是通过调用native eapi(inntdl . dll)函数NtQueryDirectoryFile(),然后中断进入内核,通过查询ssdt(system service descriptable table)表获取相应函数ZwQueryDirectoryFile()的地址,然后调用实函数执行器完成文件的枚举。HookSSDT表中的隐藏文件主要是篡改SSDT表中函数的真实地址,这样在枚举文件信息时,程序首先输入修改后的地址对应的函数来执行,然后过滤出要隐藏的文件信息,这样应用层和通过这种机制获取文件信息的工具方法枚举出隐藏文件。

(2)文件过滤驱动

1)过滤器驱动程序:

对于文件过滤驱动程序,主要是拦截上层的文件操作请求,并根据需要的功能进行处理。

2)文件系统驱动程序(FSD):

它是Windows下的标准核心层驱动程序,主要负责处理用户与磁盘等存储介质之间的存储信息,维护各种文件系统(如FAT32、NTFS等)的磁盘结构。)。

3)设备驱动程序:

主要处理相应的硬件,直接连接到相应的硬件设备上。磁盘等存储驱动主要实现对存储设备的管理和存储。文件隐藏是通过文件过滤驱动程序实现的,主要是通过设置IRP_MJ_DIRECTORY_CONTROL分布函数,并在其中设置回调函数,所以IRP发送到文件系统中的卷设备,当它从文件系统驱动程序返回时,将触发回调函数的执行,待过滤的文件将从回调函数返回的FILE _ BOTH _ DIR _ INFORMATION结构链表中删除,从而实现隐藏指定文件的功能。

4.3过程隐藏

内核级特洛伊木马开发了许多进程隐藏方法,但从根本上说,进程隐藏是通过挂钩内核函数和修改内核返回信息(文件链表或句柄表)来实现的。有内核钩子、DKOM技术、擦除进程句柄等等。

(1)内核钩子

SSDT实现了从用户模式功能到内核模式功能的引导。当SSDT被连接时,对应于进程枚举和查询类函数(通常连接到ZwQuerySystemInformation()函数)的内核服务函数的地址在SSDT表中被修改。这样,当进程枚举的调用被生成时,被修改的函数将被运行,然后在被修改的函数中,

首先,获取完整的流程信息,然后找到要隐藏的流程信息,对其进行过滤,然后将处理后的结果返回给上层,这样最终用户层的用户就看不到隐藏的流程。通过内核钩子实现进程隐藏的另一种方法是挂钩IDT。在视窗系统中,用户层的应用编程接口函数通过软中断进入内核。当发生软中断时,系统将从IDT表中调用相应的中断服务处理程序,与INT2E中断对应的服务处理程序是KiSystemService()。该程序将调用SSDT表中的函数来实现最终调用。因此,通过挂钩IDT和修改中断响应过程,可以监控和修改过程信息,以达到隐藏的目的。

(2)DKOM科技

DKOM(直接内核对象操作)使用另一种机制来实现进程隐藏。与上述内核挂钩相比,它隐藏性更好,一般不容易被检测到。当谈到使用这种机制来隐藏进程时,我们必须提到一个与进程相关的数据结构——视窗下的EPROCESS。

在窗口中,使用双链表的典型例子是进程和线程的数据结构。对于进程,每个进程都有自己的EPROCESS数据结构,用于描述进程的地址空、进程名、线程和其他信息。此结构中的“活动进程链接”字段是一个列表条目结构,所有进程的EPROCESS结构都通过列表条目链接到一个双链表中。这样,使用这个结构,我们可以很容易地遍历链表,找到所需的LIST_ENTRY结构。

然而,EPROCESS结构在内存中的位置几乎在每次操作系统发布时都会改变,这给我们在内存中查找进程的EPROCESS带来了一些麻烦。幸运的是,指向当前运行的进程的指针总是可以通过PsGetCurrentProcess()函数找到,然后就可以找到当前进程的EPROCESS结构。然后,以当前进程指针作为终止判断条件,遍历EPROCESS双链表,就可以确定要隐藏的进程的位置。

在找到要隐藏的进程结构后,通过修改其列表条目中的弗林克和眨眼的值,前一个列表条目结构的弗林克指针指向下一个列表条目结构,而下一个结构的眨眼指向前一个结构。此外,为了防止系统由于指针指向无效内存区域而崩溃,要删除的进程的LIST_ENTRY结构中的Flink和Blink是指向它们自己的。这样就完成了脱链,系统不能用这种方法列出隐藏的流程信息,实线代表实际的流程链表,虚线代表删除待隐藏的流程结构后的流程链表),从而实现了流程隐藏。应该指出的是,从进程链表中移除隐藏的进程结构不会影响进程的调度和执行,因为Windows实现了基于线程的任务调度。

(3)擦除过程句柄

擦除进程句柄的两种常用方法是擦除隐藏在CSRSS句柄表中的进程句柄和擦除隐藏在PspCidTable中的进程句柄。

(1)抹去CSRSS

句柄表中的进程信息创建进程时,系统会为其分配一个句柄表。这个句柄表主要由内核对象调用。事实上,它是一个结构数组,数组中的每个元素包含以下三项:指向内核对象的指针、访问掩码、一些与对象句柄继承相关的标志,等等。对于流程对象,其对象指针也放在句柄表中。通过遍历CSRSS句柄表,可以根据需要过滤的特定进程信息隐藏进程。

(2)清除PspCidTable中的过程信息

PspCidTable是一个特殊的句柄表。与普通句柄表相比,主要区别在于句柄表存储了进程对象e process、线程对象ETHREAD等。因此,系统中的所有进程都可以通过句柄表遍历(这是IceSword工具用来枚举进程的方法)。但是,句柄表没有被导出,所以使用这个方法的隐藏进程需要自己定位PspCidTable的地址。通常,搜索和定位是通过PsLookupProcessByProcessId()函数执行的。定位后,您可以过滤掉要隐藏的进程句柄。然而,当使用这种方法时,应该注意的一点是,如果隐藏的进程存在,它需要恢复原始的进程对象(恢复原始的表结构)。否则,如果您调用ExDestroyHandle()来销毁句柄,如果您遇到不存在的句柄(访问内核中未知的内存地址),它将导致BSOD。

4.4通信隐藏

与内核模式网络编程接口相比,用户模式网络编程隐蔽性稍差,但实现简单,可以使用大量内置功能。然而,为了追求更好的隐蔽性,内核级隐蔽技术尤为重要。毕竟,特洛伊木马不能没有通信模块,否则其功能将无法实现。在视窗系统中,现场视察网络模型和视窗系统结构之间的粗略映射。

网络应用程序是用户基于WinsockAPI编写的通信代码。网络APIDLL为上层应用程序提供网络接口,通过进一步调用下层协议驱动程序来完成最终的通信;客户端是网络应用编程接口的核心驱动,它可以根据相应的网络标准格式化相应的数据包,并将其发送给协议驱动。TDI发送器,即ndis(网络驱动接口规范)协议驱动程序,接收上层发送的数据包,然后根据不同的协议(TCP、IPX等)将相应的协议头添加到数据包中。)根据不同的要求,将它们提供给下层进行进一步处理;NDIS库为其上层和下层提供接口,同时隐藏设备的细节,以便协议驱动程序可以通过这些接口透明地通信,而无需在与网卡驱动程序通信时考虑设备依赖性。

通过以上分析,一般来说,在内核层,要实现通信隐藏,要么是一个由钩子网络应用编程接口调用的函数,要么是必须深入内核,对TDI、NDIS协议驱动或NDIS中间层驱动进行过滤操作。常见的通信隐藏方法如下:

(1)hookzwdeviceocontrolfile()

Netstat、Fport和其他用于获取端口列表的工具通常通过iphlpapi.dll提供的allocateAndGettcpTableFromStack()函数获取端口相关信息。最后,这些函数都通过调用NtDeviceIoControlFile()进入内核。因此,通过在SSDT挂钩与该函数相对应的函数ZwDeviceIoControlFile()来过滤返回的端口信息,可以隐藏特定的端口。用户不能通过一些常用工具来枚举木马打开的通信端口,进而实现隐蔽通信的端口隐藏。但是,对于像卡巴斯基防火墙这样使用TDI过滤驱动程序获取网络连接并确保通信安全的软件,这种方法一般很难避免被检测到。

(2)TDI滤波器驱动

为了发送或接收数据,应用层中的网络应用程序必须通过较低的驱动程序格式化数据。然后,只要上层的IRP到达,过滤规则就根据自己的需要来设置,以过滤特定的信息,使用相同机制来实现过滤的用户层或防火墙的一些检测工具将不能查看它们已经处理的通信信息。但是,过滤器驱动程序位于TcpIp.sys上,它属于UpperDriver。如果某些检测工具或防火墙通过TcpIp.sys获取通信信息,这种方法无法过滤特定的数据包,难以避免被检测到。

(3)NDIS过滤器驱动

NDIS是微软和3COM共同制定的网络驱动接口规范,包括NDIS协议驱动、NDiSendermediateDriver(NDIS驱动)和NDIS微端口驱动。在这三个层次的驱动程序中,可以在后两个层次上获取系统网络通信的相关信息,如源地址和目的地址,从而方便地获取通信隐藏的依据,然后将信息直接发送到自己的木马功能模块或调用原进程继续传输。由于直接发送到特洛伊木马模块的通信信息不经过系统的常规流程,这些流程中间的某些级别的检测工具或防火墙将无法拦截这些信息。

4.5驱动模块隐藏

驱动模块隐藏主要是隐藏驱动模块,如内核通信模块和木马功能模块,防止用户通过一些软件查看系统中加载的驱动模块,进而发现非法的木马驱动模块。对于驱动模块的隐藏,使用了DKOM技术,与上面分析的DKOM进程隐藏技术相同,只是使用了EPROCESS结构来隐藏进程,而使用了MODULE_ENTRY结构链表来隐藏驱动模块。

在MODULE_ENTRY结构中(以下简称& ldquo结构1 & rdquo),内核中会记录一些关于驱动程序的信息,如驱动程序路径、驱动程序名称等。该结构实际上是_ LDR _数据_表格_条目(以下简称& ldquo结构2 & rdquo),仅选择与模块相关的一些字段来形成结构MODULE_ENTRY,其中变量1对应于结构2中的InInitializationOrderLinks变量2是为确保与_ LDR _数据_表格_条目中字段的偏移量一致而添加的变量;变量3、4、5、6和7分别对应于结构2中的DllBase、EntryPoint、SizeOfImage、FullDllName和BaseDllName。从模块入口的结构可以看出,它的第一个参数是列表入口结构。相应的_列表_条目的结构如下:

typedefstruct_LIST_ENTRY{

struct _ LIST _ ENTRY * Flink

结构列表条目*闪烁;

}LIST_ENTRY,* PLIST _ ENTRY

Flink参数指向下一个链表结构。如果没有后续节点,则指向链表头。如果当前节点是链表头节点,Flink指向链表的第一个节点。如果链表是空,Flink指向头本身。眨眼

参数实现指向以前的链表结构。如果没有前置节点,它将指向链表的头节点。如果当前节点是链表的头,则“闪烁”指向链表的最后一个节点。如果链表是空,闪烁指向头部本身。

这样,只要您遵循MODULE_ENTRY双链表,您就可以找到要隐藏的驱动模块,并且只要您从其中删除该节点,使用该机制获取驱动模块列表的工具就无法找到隐藏的驱动模块。删除前后的MODULE_ENTRY,实线为未修改的链表结构,虚线为修改后的链表结构。类似于删除链表的过程,为了防止系统因为指针指向无效的内存区域而崩溃,在删除操作之后,要删除的模块的LIST_ENTRY结构中的Flink和Blink指向自身。

4.6注册表隐藏

为了在注册表中隐藏一些键值,我们只需要打破常规的调用机制,在一个易于操作的链接中过滤掉键值。对于内核层,这个功能可以通过挂钩或修改SSDT表、ntoskrnl.exe等中的相关函数来实现。

相关推荐

评论列表
  • 这篇文章还没有收到评论,赶紧来抢沙发吧~
关闭

用微信“扫一扫”