




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
概述 当今rootkit技术被广泛应用于恶意软件的开发中,恶意软件利用此技术来做一些应用程序做不到的事情,如文件的隐藏,注册表键值的隐藏,对抗防护软件等。于是对于rootkit程序的检测与清除技术(anti-rootkit(以下简称ark)得以发展。作为rootkit技术的天敌,ARK技术具有与其对手一样的特性。但是ark作为一种检测技术有着比起对手更宽裕的时间来占领内核制高点。ARK基础知识概述(1)WDM内核模块开发 WDM(windows driver model)技术为windowsNT系列操作系统的内核扩展模块开发模型,windowsNT系列系统包括windowsNT,windows2000, windowsXP与windows vista, windows7WDM模型主要采用分层的方法,模仿面向对象的技术,按照微软一贯的思路,先进行逻辑上的“分层”,然后将标准的实现和低层细节“封装”起来,形成“基类”,客户程序通过“继承”的方式来扩展“基类”的功能,完成所需要的实现。在微软的技术文献中,称Windows NT和Windows 2000为“基于对象”(object-based)的系统,和操作系统一样,WDM驱动程序模型也是“基于对象”的系统程序。WDM使用了分层的驱动程序结构,而且WDM是基于对象的。为了便于对硬件的管理,WDM里对每一个单一的硬件引入了一些数据结构,部分描述了一个DEVICE_OBJECT数据结构栈。在数据结构栈中最低层的是物理设备对象(Physical Device Object),用于描述我们的设备与物理总线的关系,简称为PDO。在PDO的上面,有功能设备对象(Function device Object),用来描述设备的逻辑功能,简称为FDO。在数据结构栈的其他位置, FDO的上面或下面,有许多的过滤设备对象(Filter Device Objects),简称为FiDO。在数据结构栈中的每一个对象都属于一个特定的驱动程序,如图中间的虚线所指示的,PDO属于总线驱动程序,FDO属于功能驱动程序,FiDO属于过滤驱动程序。WDM式驱动有许多特定的数据结构,限于篇幅,仅介绍其中最重要的三个DriverObject结构:typedef struct PDEVICE_OBJECT DeviceObject; PUNICODE_STRING HardwareDatabase; PFAST_IO_DISPATCH FastIoDispatch; PDRIVER_INITIALIZE DriverInit; PDRIVER_STARTIO DriverStartIo; PDRIVER_UNLOAD DriverUnload; PDRIVER_DISPATCH MajorFunctionIRP_MJ_NUM+1; DRIVER_OBJECT,*PDRIVER_OBJECT;结构体成员:DeviceObject: 指向驱动程序创建的设备对象.这个驱动程序调用IoCreateDevice的时候会自动赋予正确的设备对象指针. HardwareDatabase: 指向一个字符串.这个字符串是一个注册表路径,这个注册表路径位于的HKEY_LOCAL_MACHINEHardware. FastIoDispatch: 指向这个驱动程序的FastIO入口点定义的一个结构.这个成员只能通过FSDs和网络传输驱动来使用. DriverInit 指向DriverEntry函数的,这是通过IO管理器来建立的. DriverStartIo 指向驱动程序的StartIo函数,这是在驱动程序初始化的时候通过DriverEntry来设置的.如果一个驱动程序没有StartIo函数,这个成员将是NULL. DriverUnload 指向驱动程序卸载函数入口点.在驱动程序初始化的时候通过DriverEntry来设置,如果驱动程序没有卸载函数,这个成员将是NULL. MajorFunctionIRP_MJ_NUM+1 指向驱动程序的DispatchXXX函数指针的数组.每个驱动程序至少要设置一个DispatchXXX函数指针在这个数组里来处理这个驱动程序IRP请求包.任何一个驱动程序可以设置和IRP_MJ_XXX代码一样多的DispatchXXX来处理IRP请求包.每个DispatchXXX结构DeviceObject结构:typedef struct _DEVICE_OBJECT CSHORT Type; USHORT Size; LONG ReferenceCount; struct _DRIVER_OBJECT * DriverObject; struct _DEVICE_OBJECT * NextDevice; struct _DEVICE_OBJECT * AttachedDevice; struct _IRP * CurrentIrp; PIO_TIMER Timer; ULONG Flags; ULONG Characteristics; _volatile PVPB Vpb; PVOID DeviceExtension; DEVICE_TYPE DeviceType; CCHAR StackSize; union LIST_ENTRY ListEntry; WAIT_CONTEXT_BLOCK Wcb; Queue; ULONG AlignmentRequirement; KDEVICE_QUEUE DeviceQueue; KDPC Dpc; ULONG ActiveThreadCount; PSECURITY_DESCRIPTOR SecurityDescriptor; KEVENT DeviceLock; USHORT SectorSize; USHORT Spare1; struct _DEVOBJ_EXTENSION * DeviceObjectExtension; PVOID Reserved; DEVICE_OBJECT, *PDEVICE_OBJECT;DriverObject指向驱动对象描述了加载镜像NextDevice指向下一个被相同驱动去创建的对象DeviceExtension 设备扩展指针输入输出请求报文(以下简称IRP)结构:一个用用来描述主要请求的头部IRPHeader。一组用来描述子请求的参数。Windows Driver Model 程序结构WDM程序的入口点为DriverEntry()卸载例程为DriverUnload()响应IRP_MJ_CLOSE DispatchClose()响应IRP_MJ_CREATE DispatchCreate()响应IRP_MJ_DEVICE_CONTROL DispatchDeviceControl()(2)Windows内核概述(1) irp处理流程1. 客人(IRP)来到大厦(驱动程序)外,该大厦有一个按人名造册的接待系统(IO管理器)。 2. 客人(IRP)先到大厅,查花名册,按人名(设备对象DeviceObject,符号连接SymbolicLink)查。同时查安全薄,看这个人是不是恐怖分子、台独分子(STATUS_INVALID_DEVICE_REQUEST, SECURITY_CLIENT_CONTEXT),不是则被允许进入。如是,则不允许则禁入。 3.如果查不到客人名,则拒绝进入。调用多本花名册(文件系统,FSD),直到识别出来客人,才继续。 4. 接待系统(IO管理器)为客人(IRP)分配房间、会议室,餐饮,一应俱全(RtlZeroMemory ,RtlCopyMemory),并打扫一遍(初始化, KeSetEvent, KeWaitForSingleObject, IoMarkIrpPending, InitializeObjectAttributes)。 5. 接待系统(IO管理器)调用管理人员,将客人的信息传递给下面各部门。各部门管理人员根据他们的子系统情况,分配资源队列(本地IO栈),并决定必须进行哪一种操作(IoGetCurrentIrpStackLocation, Irp-AssociatedIrp.SystemBuffer)。客人是否在不同级别的客人清单中。如果没有这个级别,则新建一个级别(DeviceObject-DeviceExtension),并进行登记。比如是国宾级,则一定要准备一个总统套间。6. 不论是对于客人(Irp),还是客人的级别档次要求(IO栈),都使用模块化的规范流程。 7. 向大厦总经理报告人员进入、级别招待的请求是成功还是失败。8. 获取人员、招待的状态,将是不是超过招待能力的信息(过保护状态)返回给新来的客人。如果超出接待能力,则挂牌“客满,恕不接待”。9. 人员离开,则释放客人占有的所有资源(分配房间、会议室等)。IoCompleteRequest, DriverObject-DriverUnload,IoDeleteDevice, ZwClose10. 招待成功,返回OK或返回错误(Irp-IoStatus.Status = STATUS_SUCCESS,return ntStatus)(2) 内核结构 Intel的cpu把程序运行权限分为四级,Windows将内核代码与用户代码分离。内核代码运行在R0级别,用户代码运行在R3级别 。 Windows内核分为以下几个结构 硬件抽象层(hal) 内核执行体 (kernel) 设备驱动程序(Driver) 输入输出管理器(IO manger) 文件系统及内存管理器Windows整体结构如下图所示(3) 直接内核对象操作技术(以下简称dkoM)所有的操作系统都在内存中存储记账信息,他们通常采用结构或对象的形式,由对象管理器管理。当用户空间进程请求操作系统信息例如进程、线程或设备驱动程序列表时,这些对象被报告给用户。这些对象或结构位于内存中,因此可以直接对其进行修改。隐藏进程主要关注的windows关键数据结构是:进程的EPROCESS结构与线程的ETHREAD结构、链表(如进程、线程链表与CPU的调度链表)等等。DKOM通过操作这些数据结构来达到它们的目的。直接操作内核对象在隐藏进程这方面的应用很多。 (4) Hook 技术简介windows系统下的编程,消息message的传递是贯穿其始终的。hook与消息有着非常密切的联系,钩子技术用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过程前,处理某些特定的消息”。这也是hook分为不同种类的原因。 hook的这个本领,使它能够将自身的代码“融入”被hook住的程序的进程中,成为目标进程的一个部分。在windows2000以后的系统中,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是hook的出现给我们开拓了解决此类问题的道路。,编程时会接触到api函数的使用,常用的api函数大概有2000个左右。最初有些人对某些api函数的功能不太满意,就产生了如何篡改api,使之更好的服务于程序的想法,这样API Hook就自然而然的出现了。我们可以通过API Hook,改变一个系统api的原有功能。基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数 通过篡改api可以达到rootkit技术的目的隐藏,同样,也可以达到ark技术的目的过滤数据。我们可以看到ARK技术与RK技术不过是同一技术的两种应用罢了。在内核层次 RK技术常用的钩子技术有Object hookSSDT(系统服务描述符表)hook 及其shdow表的hookInline hookIdt(中断描述符表)hookIRP hookSYSENTER(进入系统调用指令) HOOKIAT(导入地址表) hookEat(导出地址表)hook以下开发的钩子技术完全采用inline hook过程原理描述如下1. 修改原api的前五字节为jmp 监控api的地址。2. 在程序空间中调用原api。3. 程序将跳转到监控api执行。4. 在自己写的监控api中把原来的5字节改回来。5. 执行监控的代码段。6. 在监控api中调用原api。7. 执行原api的一些操作。8. 在监控api中再次修改api函数的前五字节为jmp 监控api9. 结束过程并收摊。这种修改做法比较彻底,其他的做法就像修改指向目的地的路标,这种方式是把目的地改成别的地方,对于恶意的rk来说缺点是太过于暴露,但对于ark来说这种做法就比较彻底。这是因为一般的钩子检测技术很容易检测到这种做法。我觉得这是ark程序专用的一种钩子技术。 调用Mm 众所周知操作控制寄存器可以打破内存保护 _asm CLI MOV eax, CR0 AND eax, NOT 10000H MOV CR0, eax /关闭内存保护 _asm MOV eax, CR0 OR eax, 10000H MOV CR0, eax STI/开启内存保护、 这样我们可以访问到所有的内存。修改就可以达到目的了。Rootkit检测技术(1) 应用层检测应用层检测主要解决的是对进程调用的非信任内核模块进行拦截。主要思路为拦截驱动(内核模块)的加载,拦截系统调用ZwLoadDriver和ZwSetSystemInformation以及NtOpenSession和检测intel的调用门,中断门,陷阱门,任务门进行监控并对要加载的模块进行文件校验。函数原型NTSTATUS ZwLoadDriver( IN PUNICODE_STRING DriverServiceName );函数说明该函数用于在内核模式或驱动程序中动态加载一个已被正确注册的驱动程序参数说明DriverServiceName:一个指向驱动程序注册表键Unicode字串的指针,该注册表键位于RegistryMachineSystemCurrentControlSetServicesDriverName(一般位于HKEY_LOCAL_MACHINE主键下),DriverName是该驱动的注册名Hook函数为过滤其参数,如果要传入的参数为微软的文件则不予显示若不是则显示出来。至于识别别的厂家这个太复杂了,显示出来让用户定夺ZwSetSystemInformation设置影响操作系统的信息,定义如下:NTSYSAPI NTSTATUS NTAPIZwSetSystemInformation(IN SYSTEM_IMFORMATION_CALSS SystemInformationClass, IN OUT PVOID SystemInformation,IN ULONG SystemInformationLength);参数:SystemInformationClass:将被设置的系统信息的类型,值为SYSTEM_IMFORMATION_CALSS枚举的一个子集,SystemLoadAndCallImage就是SystemInformation:typedef struct _SYSTEM_LOAD_AND_CALL_IMAGEUNICODE_STRING ModuleName; SYSTEM_LOAD_AND_CALL_IMAGE,*PSYSTEM_LOAD_AND_CALL_IMAGE;SystemInformationLength:長度sizeof(SYSTEM_LOAD_AND_CALL_IMAGE)成员: ModuleName:要加载模块的NATIVE NT格式的完整路径备注: 这个信息类只能被设置,不是设置任何信息,而是执行把一个模块加载到内核地址空间和调用其入口点的操作。期望入口点例程是一个带两个参数的_stdcall例程(与设备驱动程序的DriverEntry例程一致)。如果入口点例程返回一个失败代码,则卸载模块。SystemInformation:指向含有被设置信息的一个调用者分配的缓冲区或变量SystemInformationLength:以字节为单位的SystemInformaiton的大小,根据给定的SystemInformationClass来设置它通过拦截这个api在内核层过滤参数,得到SystemInformationClass下的SystemLoadAndCallImage的ModelName来知道这个驱动文件要加载,通过校验其文件的MD5来判断其是否为恶意驱动,然后把信息报告用户。(2) 钩子防御、解决对于系统关键API的挂钩防御并恢复其原有的调用。主要思路为对不信任的指定进程拦截MmGetSystemRoutineAddress()让其返回失败。 由于rk要挂钩系统函数必须调用这个函数,首先对其拦截让其返回调用失败,这样即使是危险的恶意驱动也无法获得内核函数的地址。过滤参数就可以知道程序要挂钩那些函数。(3) 内核模块枚举枚举系统内的所有内核模块。static void ListModule ( void ) NTSTATUS status; PSYSTEM_MODULE_INFORMATION module = NULL;ULONG n = 0; ULONG i = 0;void *buf = NULL; ZwQuerySystemInformation( SystemModuleInformation, &n, 0, &n ); if ( NULL = ( buf = calloc( ( size_t )n, 1 ) ) ) fprintf( stderr, calloc() failedn ); goto ListModule_return;status = ZwQuerySystemInformation( SystemModuleInformation, buf, n, NULL ); if ( !NT_SUCCESS( status ) ) PrintZwError( ZwQuerySystemInformation() failed, status ); goto ListModule_return; module = ( PSYSTEM_MODULE_INFORMATION )( ( PULONG )buf + 1 ); n = *( ( PULONG )buf ); for ( i = 0; i n; i+ ) Dbgprint( 0x%08X %sn, module.Base, module.ImageName + module.ModuleNameOffset ); ListModule_return: if ( buf != NULL ) free( buf ); buf = NULL; return; (4) 文件与注册表枚举 枚举系统内的所有文件与注册表 NTSTATUS RegEnumTest() /枚举注册表子项函数 UNICODE_STRING ustrRegString; UNICODE_STRING ustrKeyName; HANDLE hRegister; ULONG ulSize, i = 0; OBJECT_ATTRIBUTES obj_attrib; NTSTATUS status; PKEY_FULL_INFORMATION pfi; PKEY_BASIC_INFORMATION pbi; / 初始化 RtlInitUnicodeString(&ustrRegString,L”RegistryMachineSOFTWARE360Safe“); InitializeObjectAttributes(&obj_attrib, &ustrRegString, OBJ_CASE_INSENSITIVE, NULL, NULL); / 打开注册表 status = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &obj_attrib); if (NT_SUCCESS(status) KdPrint(”Test ZwOpenKey %wZ Success!”, ustrRegString); / 第一次调用是为了获取需要的长度 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize); pfi = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize); / 第二次调用是为了获取数据 ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize); for (i = 0; i SubKeys; i+) / 获取第i个子项的长度 ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize); pbi = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize); / 获取第i个子项的数据 ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize); ustrKeyName.Length = (USHORT)pbi-NameLength; ustrKeyName.Buffer = pbi-Name; KdPrint(”Test The %d SubItem Name : %wZ.n”, i, &ustrKeyName); / 释放内存 ExFreePool(pbi); ExFreePool(pfi); ZwClose(hRegister); return STATUS_SUCCESS; (5) 网络端口枚举枚举所有使用网络的应用程序及其端口号通过向DeviceTcp发送IOCTL Code=IOCTL_TCP_QUERY_INFORMATION_EX的命令,直接获取进程,端口信息PVOID EnumPortInformation(OUT PULONG OutLength, IN USHORT PortType) ULONG BufLen = PAGE_SIZE; PVOID pInputBuff=NULL; PVOID pOutputBuff=NULL; PVOID pOutBuf=NULL; NTSTATUS status = STATUS_SUCCESS; HANDLE FileHandle=NULL; UNICODE_STRING DeviceName; PFILE_OBJECT pFileObject=NULL; PDEVICE_OBJECT pDeviceObject=NULL; KEVENT Event ; IO_STATUS_BLOCK StatusBlock; PIRP pIrp; PIO_STACK_LOCATION StackLocation ; ULONG NumOutputBuffers; ULONG i; TCP_REQUEST_QUERY_INFORMATION_EX TdiId; RtlZeroMemory(&TdiId, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX); if(TCPPORT = PortType) TdiId.ID.toi_entity.tei_entity = CO_TL_ENTITY; else if(UDPPORT = PortType) TdiId.ID.toi_entity.tei_entity = CL_TL_ENTITY; else KdPrint(需要获取的端口类型无效n); return NULL; TdiId.ID.toi_entity.tei_instance = ENTITY_LIST_ID; TdiId.ID.toi_class = INFO_CLASS_PROTOCOL; TdiId.ID.toi_type = INFO_TYPE_PROVIDER; TdiId.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_EX_ID; pInputBuff = (PVOID)&TdiId; _try if(UDPPORT = PortType) BufLen *= 3; pOutputBuff = ExAllocatePool(NonPagedPool, BufLen); if(NULL = pOutputBuff) KdPrint(输出缓冲区内存分配失败!n); *OutLength = 0; _leave; if(TCPPORT = PortType) status = GetObjectByName(&FileHandle, &pFileObject, DD_TCP_DEVICE_NAME); else if(UDPPORT = PortType) status = GetObjectByName(&FileHandle, &pFileObject, DD_UDP_DEVICE_NAME); if (!NT_SUCCESS(status) KdPrint(获取设备名失败!n); *OutLength = 0; _leave; pDeviceObject = IoGetRelatedDeviceObject(pFileObject); if (NULL = pDeviceObject) KdPrint(获取设备对象失败!n); *OutLength = 0; _leave; KdPrint(Tcpip Driver Object:%08lXn, pDeviceObject-DriverObject); KeInitializeEvent(&Event, NotificationEvent, FALSE); pIrp = IoBuildDeviceIoControlRequest(IOCTL_TCP_QUERY_INFORMATION_EX, pDeviceObject, pInputBuff, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), pOutputBuff, BufLen, FALSE, &Event, &StatusBlock); if (NULL = pIrp) KdPrint(IRP生成失败!n); *OutLength = 0; _leave; StackLocation = IoGetNextIrpStackLocation(pIrp); StackLocation-FileObject = pFileObject;/不设置这里会蓝屏 StackLocation-DeviceObject = pDeviceObject; status = IoCallDriver(pDeviceObject, pIrp); KdPrint(STATUS:%08lXn, status); if (STATUS_BUFFER_OVERFLOW = status) KdPrint(缓冲区太小!%dn,StatusBlock.Information); if (STATUS_PENDING = status) KdPrint(STATUS_PENDING); KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); status = StatusBlock.Status; if(STATUS_CANCELLED = status) KdPrint(STATUS_CANCELLED); if(status = STATUS_SUCCESS) *OutLength = StatusBlock.Information; pOutBuf = pOutputBuff; _finally ObDereferenceObject(pFileObject); if(FileHandle) ZwClose(FileHandle); return pOutBuf; (6) 进程线程枚举枚举系统内正在运行的程序,及其调用模块。、NTSTATUS Ring0EnumProcess()ULONG cbBuffer = 0x8000; / 初始化缓冲大小 32kbPVOID pBuffer = NULL;NTSTATUS Status;PSYSTEM_PROCESS_INFORMATION pInfo;dopBuffer = ExAllocatePool (NonPagedPool, cbBuffer); /分配内存缓冲区if (pBuffer = NULL) /如果内存分配失败return 1; /失败了返回1并退出Status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, pBuffer, cbBuffer, NULL);if (Status = STATUS_INFO_LENGTH_MISMATCH) /如果缓冲区太小ExFreePool(pBuffer); /释放缓冲区cbBuffer *= 2; /增加缓冲区到原来的两倍大小 else if (!NT_SUCCESS(Status) /如果执行失败ExFreePool(pBuffer); /释放分配的内存return 1; /失败了返回1并退出while (Status = STATUS_INFO_LENGTH_MISMATCH);pInfo = (PSYSTEM_PROCESS_INFORMATI
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年市场营销人员招聘面试实战指南及预测题
- 2025年财务分析师求职面试指南模拟题及参考答案详解
- 2025年特岗教师招聘音乐科目模拟题
- 2025年中学历史教师资格认证考试模拟题及答案
- 电力人员消防知识培训课件
- 2025年环境工程师招聘笔试模拟题及复习策略
- 2025年小学全科特岗教师面试模拟题集
- 2025年网络安全工程师招聘考试题库与解析
- 1到10的教学课件
- 2025年物资储备仓库运输作业流程与调度员招聘考试要点
- 建筑公司分包合同管理办法
- 2025至2030苏打水行业发展趋势分析与未来投资战略咨询研究报告
- 2025年秋季学期德育工作计划:向下扎根向上开花
- 2025-2030中国家政服务行业信用体系建设与服务质量监管报告
- 2025年浙江省中考英语真题(解析版)
- 2025年安徽省普通高中学业水平选择性考试(物理)科目高考真题+(答案解析版)
- 2025年成都东部集团有限公司及下属企业招聘考试笔试试卷【附答案】
- 各分项工程质量保证措施
- 国税编制管理办法
- 《矛盾论》、《实践论》导读
- 工程罚款通知单模版
评论
0/150
提交评论