很久没有写博客了,最近抽时间把这些杂碎零散的知识梳理下来,分享给更多朋友去找乐子,在草稿箱里面仍了好几天忘发了。
接下来谈谈本篇主题,隐藏两字。
1、隐藏意味着什么?
不想被人发现呗,人性如此,亦是如此。
2、为何要隐藏?
其实我的觉着这是根本,好好写个程序你为何要隐藏本身的进程、线程?为啥?无非你不想让别人知道,或者不应让别人知道。windwos下有不少未公开的东西,这是隐藏。面对对象程序设计封装性,这也是隐藏。有些病毒,其实叫恶意代码更为亲切一些,更喜欢隐藏或者依附正常的进程来达到欺骗电脑,欺骗杀毒软件,这都是隐藏。对有些不可告人的秘密。
3、对于进程隐藏能欺骗杀毒软件?或者系统监控工具?
至少目前我没有见过靠隐藏进程就能够瞒天过海,不表明没有,格局有限.....,隐藏进程后,windows系统自带的任务管理器已经看不到进程的身影,可是随便找一个ARK就能够看到隐藏的进程,还可使用procexp或者火绒剑等工具去查看,为何隐藏了进程这些工具仍然能够找到?
4、浅谈隐藏进程
由于windows用户层,就是任务管理器是依赖于链表结构(_LIST_ENTRY)遍历操做系统下有哪些进程,其实早些时候不懂widnows下链表重要性(当时本身学数据结构都说windows下双向链表、树很重要),后来才知道,嗯其实不依赖winAPI来作本身想作的事情,真的很重要。双向链表请看之前的博客双向链表:http://www.javashuo.com/article/p-aecaroqa-hc.html
建立进程的时候会填充结构体_EPROCESS(看雪论坛搜索一下有详细的建立过程),这样咱们_EPROCESS里面就有数据与内容了,关于这个结构体不一样操做系统数据有可能会不同,windbg里面输入: dt _EPROCESS 便可查看结构体内容与偏移。
windows内核分为、执行体、微内核、HAL(最底层),_EPROCESS是属于执行体层,包含进程建立信息、I/O、安全、句柄表、虚拟内存等等,有意思的是里面内嵌了一个(偏移0)_KPROCESS,他属于微内核层,用来线程配额、调用还有优先级等信息。
咱们重点来讲一下_EPROCESS中的ActiveProcessLink,光看名字就知道活动进程链,以下图所示。
这个就是隐藏进程的关键,他是一个双向循环链表,咱们能够经过链表去遍历整个系统进程,对就是呢么简单,以下图所示:
更多结构体信息请看(我很是喜欢的一位笔者,他翻译国外一些文章很严谨且详细),贴下地址:https://bbs.pediy.com/thread-223858.htm 里面有对EPROCESS等经常使用的结构体详细介绍,强烈推荐,也许你有些疑惑,若是你认真看完上面连接知识,你的疑惑将在他的文章里找到答案。
5、实现?为何要实现?
其实我之前也这思考、这些东西你为何要去学?为何要去作?我无从答案。好奇心?专研?热爱?可是不能否认当你认真的作了这些事情以后,你有所收获,有所进步。也许当你再一次看到procexp或者火绒剑能够把那些隐藏的进程遍历出来的时候,你内心知道能够暴力枚举或者检测恢复断链本身也能够实现,原来这些都是可能的,这样作都是能够的。
若是你会双向链表,删除一个节点对你来讲不值一提,若是不会我但愿大家去好好学习一下,学而用,这才是知识。若是你想恢复隐藏的进程(原来的节点位置),记得保存“邻居的指针地址”。
最后2019年,祝你们新的一年新生活,19年愿世人都能喝上一碗热粥。编程
源代码展现以下:
用户层与驱动层头文件都须要包含:windows
#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环),这里使用直接IO pDriverObj->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; // 处理irp IoCompleteRequest(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 // 其实调用的IoGetCurrentProcess pEprocess = PsGetCurrentProcess(); // 获取ActiveProcessLinks ListCurrProc = (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 - 0xb8 if (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; }
用户层:数据结构
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"); } else printf("驱动成功加载\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; }