评论:我们知道应用程序总是不能没有核心服务,如它是使用内存,只要行的操作系统,而不必担心哪里有空闲的内存空间等问题,事实上,这个问题是由操作系统内核做。从黑客的角度来看,如果你能控制的核心,它实际上是控制的核心。






我们知道应用程序总是不能没有核心服务,如它是使用内存,只要行的操作系统,而不必担心哪里有空闲的内存空间等问题,事实上,这个问题是由操作系统内核所做。从黑客的角度来看,如果你能控制的核心,它实际上是各种应用程序控制的核心,本文将向你展示如何建立内核级钩子来控制各种低级别的功能,操作系统提供的内核级的钩子,我们不仅可以控制和监测等程序和过滤数据,而且实现了Rootkit本身和其他程序的隐蔽性。

本文首先回顾了系统调用表和内存保护的相关知识,然后介绍了如何实现内核钩子。最后,我们对一些重要的核函数作了简要的描述。



一、系统调用表



系统调用表,也称为系统服务表或服务描述表,是一个函数指针表的Windows内核需要执行不同的操作系统。也就是说,该表的各种功能,提供系统服务地址。当然,表是指系统本身的一些的功能,但是如果我们做一些事情,我们可以让它指向自己的功能。这是本文的重点。

读者必须明白,修改系统调用表和更换核函数都会对系统的整体情况的影响,和一点不经意的会导致系统崩溃。所以,在我们开始之前,我们应该在我们可以用我们自己的函数替换这些内核函数表中的每一个功能足够知识。你知道的越多,你越让内核挂钩。但是,有太多的系统调用表的表项,一些指向字符串的操作,有点对客户/服务器操作,等等。所以它是不可能在短时间内了解所有的项目,所以只有选择和广义介绍他们在下面。



两。内存保护



现代的Windows操作系统通常设置内存页面,系统调用表设置为只读提供保护。如果你不能解决这个问题,内核钩子技术的实现是痴人说梦,是试图将数据写入只读存储器,即修改只读内存区,蓝色的屏幕将立即进行。为此,让我们先了解内存保护知识。

内存描述符表是内存保护的关键之一。具体的定义是在ntddk详细。微软DDK H头。我们这里有一个简单的介绍:

_mdl { typedef struct

结构_mdl *下;

CSHORT大小;

CSHORT MdlFlags;

结构_eprocess过程;

mappedsystemva PVOID;

startva PVOID;

ULONG ByteCount;

ULONG ByteOffset;

MDL * PMDL };

# mdl_mapped_to_system_va端口定义

#定义mdl_pages_locked 0x0002

#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004

#定义mdl_allocated_fixed_size 0x0008

#定义mdl_partial 0x0010

#定义mdl_partial_has_been_mapped 0x0020

#定义mdl_io_page_read 0x0040

#定义mdl_write_operation 0x0080

#定义mdl_parent_mapped_system_va 0x0100

#定义mdl_free_extra_ptes 0x0200

#定义mdl_io_space 0x0800

#定义mdl_network_header 0x1000

#定义mdl_mapping_can_fail 0x2000

#定义mdl_allocated_must_succeed 0x4000

#定义mdl_mapping_flags(mdl_mapped_to_system_va |

| mdl_pages_locked

| mdl_source_is_nonpaged_pool

| mdl_partial_has_been_mapped

| mdl_parent_mapped_system_va

| mdl_system_va

mdl_io_space)





的内存描述表的功能(MDL)是地图的虚拟内存到物理页。如果对系统调用表的内存调用页面的MDL的mdlflags成员设置mdl_mapped_to_system_va和页锁定,然后内核钩子技术可以使用。下面的代码将用于这目的:

# pragma包(1)

typedef struct servicedescriptorentry

{

unsigned int * ServiceTableBase;

unsigned int * ServiceCounterTableBase;

unsigned int numberofservices;

unsigned char * ParamTableBase;

servicedescriptortableentry_t * pservicedescriptortableentry_t };

# pragma包()

__declspec(dllimport)servicedescriptortableentry_t keservicedescriptortable;

newsystemcalltable PVOID *;

PMDL pmymdl = mmcreatemdl(null,

KeServiceDescriptorTable.ServiceTableBase,

keservicedescriptortable.numberofservices×4);

那么使用MmBuildMdlForNonPagedPool(pmymdl);

pmymdl -> mdlflags = pmymdl -> mdlflags mdl_mapped_to_system_va |;

NewSystemCallTable = MmMapLockedPages (pMyMDL, KernelMode);

好了,现在我们可以通过newsystemcalltable创建一个新的系统调用表。系统调用表如图所示。





图1系统调用表示意图



当钩子发生时,可以使用以下宏:

#定义hook_index(function2hook)*(巴)(1)function2hook puchar)

#定义钩(函数名,newpointer2function,oldpointer2function)

oldpointer2function =(PVOID)interlockedexchange(很久)

newsystemcalltable { hook_index(函数名)},(长)newpointer2function)

#定义脱钩(函数名,oldpointer2function)

interlockedexchange((很久)newsystemcalltable { hook_index(函数名)}

(长)

oldpointer2function)



在这些宏,钩子技术将变得更简单和更安全。因为interlockedexchange是一个原子的功能,不需要中断,那么交换指针的方法是安全的。此外,它不需要使用宏钩子来卸载另一个宏的钩子,这样就更方便了。





图2系统调用表截取示意图



系统调用表的数据结构keservicedescriptortable不仅包含ntdll.dll中的所有函数指针,而且基地址和系统调用表表的大小。建立自己的内存描述表时,这些信息是必不可少的。mdl_mapped_to_system_va标记的使用,我们可以设置一个页面(不改变不出内存)MDL,所以我们可以锁定它,并返回自己的系统调用表的地址,系统调用表可写这是很重要的。



三。定义钩子函数



内核钩子主要由三部分组成:钩子函数(以下称为目标函数),以取代的功能是读取功能(以下是钩子函数)和系统调用表。上一节介绍了系统调用表的问题,和钩功能介绍如下。一般来说,当你确定你的钩子函数,你可以先在DDK头文件查找所需函数的原型,然后稍作修改,你可以把目标函数转化为一个钩子函数。



例如,zwmapviewofsection是一个内核函数,允许应用程序映射函数的动态链接库出口的记忆。如果我们想这个核函数,我们可以看看在ntddk函数原型。H头文件如下:



ntsysapi

NTSTATUS

ntapi

zwmapviewofsection(

在处理sectionhandle,

在处理ProcessHandle,

在baseaddress PVOID *,

在页zerobits,

在页commitsize,

在plarge_integer sectionoffset可选,

在psize_t viewsize,

在section_inherit inheritdisposition,

在页allocationtype,

在同步保护);



使用函数原型,我们可以确定指向目标函数的指针,如下所示:



Typedef NTSTATUS(* zwmapviewofsection)(

在处理sectionhandle,

在处理ProcessHandle,

在baseaddress PVOID *,

在页zerobits,

在页commitsize,

在plarge_integer sectionoffset可选,

在psize_t viewsize,

在section_inherit inheritdisposition,

在页allocationtype,

在同步保护);

zwmapviewofsection oldzwmapviewofsection;



钩子函数如下所示:



NTSTATUS newzwmapviewofsection(

在处理sectionhandle,

在处理ProcessHandle,

在baseaddress PVOID *,

在页zerobits,

在页commitsize,

在plarge_integer sectionoffset可选,

在psize_t viewsize,

在section_inherit inheritdisposition,

在页allocationtype,

在同步保护)

{

NTSTATUS状态;

DbgPrint(comint32:newzwmapviewofsection叫。);

输入我们可以做任何他们想做的事情,可以立即返回,也可以继续执行原来的功能。

状态= oldzwmapviewofsection(sectionhandle,

ProcessHandle,

baseaddress,

zerobits,

commitsize,

sectionoffset可选,

viewsize,

inheritdisposition,

AllocationType,

保护);

基于输出我们可以做他们想做的任何事情,你想要返回什么,返回什么

返回状态;

}



嗯,钩子技术的三大块已经准备好了。现在,我们可以使用它们如下:

钩(zwmapviewofsection,newzwmapviewofsection,oldzwmapviewofsection);



如果你要使用的驱动卸载(),别忘了卸载钩子。



四,核函数序列



通过以上介绍,我们了解了系统调用表的相关知识,也了解了如何截获系统调用表中的函数。现在让我们看看功能我们要钩:目标函数。在这方面,如果我们不仅知道什么功能在系统调用表,我们也知道这些函数的工作机制是最好的。但事实上,有数百名在ntdll.dll导出功能。更不用说一个了,就是把它们都列出来,看看大脑袋。幸运的是,我们不必知道每一个功能,只要了解它的系列,为什么这么说呢因为微软已经根据函数的函数的导出函数ntdll.dll分组,和前面带一个明确的意义,所以我们可以理解他们的一般功能,根据功能系列的前缀。以下是功能系列简介:



1.kietw系列:这个系列的内核函数用于系统内核。这些功能只能从内核内部调用,常用的有kiusercallbackdispatcher,kiraiseuserexceptiondispatcher、KiUserApcDispatcher、KiUserExceptionDispatcher等。



2 CSR系列:此系列函数用于客户机和服务器运行时。如果你想截取客户端/服务器的运行,你需要进一步了解CSR系列的核心功能。常见的:csrclientcallserver,CsrCaptureMessageBuffer,csrconnectclienttoserver,crsnewthread等等。



3。LDR系列:这个系列的核心功能是用于加载程序经理,如果你打算拦截机,然后请这组LDR前缀功能进一步调查,常用的有:LdrInitializeThunk,ldrlockloaderlock,ldrunlockloaderlock、LdrGetDllHandle、LdrGetProcedureAddress等。



4。DBG系列:本系列内核函数用于调试管理。如果你想拦截的调试运行,请进一步检查这套,前缀和DBG功能,以及常用的功能,包括:dbgbreakpoint,dbguserbreakpoint,DbgPrint和dbguiconnecttodbg。



5。ETW系列:本系列内核函数用于跟踪窗口事件。如果你要截获和跟踪行动,请进一步检查这套,前缀与ETW功能。常用的功能包括:etwtraceevent,EtwEnableTrace,etwgettraceenablelevel,和etwgettraceenableflags。



6。RTL系列:该系列内核函数的运行库,RTL前缀函数可以完成各种动作,如初始化和使用字符串、线程、资源、临界区、保障对象、处理、存储和处理异常数据类型,也可以用来完成堆,IPv4和IPv6运行计时器,,以及压缩和解压缩。



7。PFX系列:本系列内核函数用于ANSI字符串操作。如果你想拦截ASNI字符串表的操作,你需要进一步了解这些功能。常用的有:PfxRemovePrefix,PfxInsertPrefix,pfxinitialize、PfxFindPrefix等。



8。ZW系列:这个系列的内核函数用于文件和注册表方面,如文件操作、注册表操作、访问方法、事件操作,标记操作,工艺操作和端口操作。



这里介绍的只是内核函数的一部分,只限于空间的其余部分。



六、结束语



介绍了系统调用表和内存保护的相关知识,并介绍了实现钩子函数的方法。最后,简要介绍了一些重要的内核的功能,内核级的钩子,我们不仅可以控制和监视其他程序和过滤数据,而且达到隐藏Rootkit本身和其他程序的目的。需要说明的是,虽然rootkit的一些功能可以通过内核HOOK技术实现,rootkit在现实中通常结合其他技术,如进程注入,分层过滤驱动等技术,将在以后的文字。