一, 论:
接着上一篇来谈谈, 进程都能隐藏, 单独隐藏进程中的某一个线程干啥?
二, 需求:
需求源动力, 就是有需求, 除了正儿八经热爱喜欢专研的朋友, 无利无名, 无食而学日不思, 真的让人很尊敬.
三, 打个比方:
当你想要去实现隐藏线程的时候你有可能在干什么? 做一个工具? 或者说是学习? 通过隐藏线程可以更深入理解 Windows 内部原理? 进程与线程之间的关系? 一个正常进程里面包含恶意线程? 这是一个很棒的学习方式. 也许你会用它来做一些事情, 以前想写过一个类似于 ARK 的工具, 才有了学习的需求及动力. 但是还没有实际的环境去应用隐藏线程, 没有需求, 但还是把代码认真的写出来, 分享一些知识, 知识在于分享.
四, 还是那些结构体:
有时候我在想, 不用 winAPI 我能做什么事? 也许我还能做很多的事情, 因为有足够的结构体我就不慌, 但是, 如果没有了结构体我能做什么事情? 这个还真不好说, 其实相对于 Windows 我更为喜欢 Linux 那种自由.
介绍主人公_ETHREAD 与_KTHREAD:
- ,_EPROCESS.ThreadListHead ---> _ETHREAD
- ,_KPROCESS.ThreadListHead ---> _KTHREAD
线程属于进程, 一个进程由多个线程, 那么同一个进程的多个线程使用的是相同的进程空间, 线程也叫做轻量级进程. 线程挂靠技术, 也可以本线程使用其他进程的空间.
Windows 下线程是最小执行单位, 每个进程至少会有一个主线程去响应执行. 同样_ETHREAD 属于执行体层, 内嵌偏移 0 是_KTHREAD(微内核层), 异曲同工之妙, Windows 的管理不得不说很优秀, 可以用艺术来形容.
_KPROCESS 中会有一个成员叫做 ThreadListHead 字段是进程所有线程的链表. 指向的位置是_KTHREAD.ThreadListEntry, 这个地方当时异或了好久, 为啥? 为啥这个链表指向的就是这个结构体这个位置, 其实我现在也很纠结.
_KPROCESS.ThreadListHead 指向 -----> _KTHREAD.ThreadListEntry
就是这个情况. 内核就是通过这个来遍历属于某一个进程空间的所有线程. 详细资料还是参考: https://bbs.pediy.com/thread-223858.htm 个人感觉翻译过来的文章质量五星好评.
五, 贴上源码
- #include "HideThreadHeader.h"
- VOID UnLoad(PDRIVER_OBJECT pDriverObj)
- {
- UNICODE_STRING DeleteSymbolicLinkName;
- RtlInitUnicodeString(&DeleteSymbolicLinkName, L"\\DosDevices\\SymbolicLinkName");
- IoDeleteSymbolicLink(&DeleteSymbolicLinkName);
- IoDeleteDevice(pDriverObj->DeviceObject);
- KdPrint(("UnLoad Sucess"));
- }
- NTSTATUS DefaultFun(DEVICE_OBJECT* pDeviceObj, IRP* irp)
- {
- UNREFERENCED_PARAMETER(pDeviceObj);
- irp->IoStatus.Information = 0;
- irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- NTSTATUS onCreate(DEVICE_OBJECT* pDeviceObj, IRP* irp)
- {
- UNREFERENCED_PARAMETER(pDeviceObj);
- irp->IoStatus.Information = 0;
- irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- NTSTATUS onClose(DEVICE_OBJECT* pDeviceObj, IRP* irp)
- {
- UNREFERENCED_PARAMETER(pDeviceObj);
- irp->IoStatus.Information = 0;
- irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
- }
- // 遍历属于某个进程所有线程 通过断链实现隐藏线程
- VOID HideThreadListLink()
- {
- CLIENT_ID* ThreadId = NULL;
- PEPROCESS pkProcess = NULL;
- PKTHREAD pkThread = NULL;
- PETHREAD pEthread = NULL;
- LIST_ENTRY* pEthreadNext = NULL;
- LIST_ENTRY* pEthreadCurrent = NULL;
- pkProcess = PsGetCurrentProcess();
- // 获取_KPROCESS->ThreadListHead(_LIST_ENTRY)
- pEthreadCurrent = (LIST_ENTRY *)((ULONG_PTR)pkProcess + 0x02c);
- /* 注:
- 1. _KPROCESS.ThreadListHead->Flink 指向的是一个_KTHREAD.ThreadListEntry
- 2. _KTHREAD.ThreadListEntry - 偏移 ThreadListEntry 获取到 KTHREAD 地址, 其实也就是 ETHREAD 地址.
- */
- KdPrint(("ThreadListHead.Flink = %p\n", pEthreadCurrent->Flink));
- KdPrint(("ThreadListHead.blink = %p\n", pEthreadCurrent->Blink));
- // 这个 (PETHREAD)(PEPROCESS + 0x2c)
- pEthreadNext = pEthreadCurrent->Flink;
- DbgBreakPoint();
- while (pEthreadCurrent != pEthreadNext)
- {
- pkThread = (PKTHREAD)((ULONG_PTR)pEthreadNext - 0x1e0);
- // pKthread->Teb 偏移 0x88
- // KdPrint(("pKThread->Teb = %p , %s \n", (ULONG_PTR)pkThread + 0x88, (((ULONG_PTR)pKThread + 0x88) == NULL || pkThread->Teb> 0x80000000 ? "System Thread" : "Non System Thread")));
- // 转换成 EPROCESS
- pEthread = (PETHREAD)pkThread;
- DbgBreakPoint();
- // pEthread->Cid 偏移 0x22c
- ThreadId = (CLIENT_ID *)((ULONG_PTR)pEthread + 0x22c);
- KdPrint(("ThreadId = %d, ProcessId = %d\n\n", ThreadId->UniqueThread, ThreadId->UniqueProcess));
- // 这个地方也可以使用断链 伪代码
- if (ThreadId->UniqueThread == "隐藏的线程 id")
- {
- // 与进程隐藏断链方式一样
- }
- pEthreadNext = pEthreadNext->Flink;
- }
- }
- // 驱动对象入口点
- NTSTATUS DriverEntry(DRIVER_OBJECT* pDriverObj, IRP* irp)
- {
- UNREFERENCED_PARAMETER(irp);
- DbgBreakPoint();
- for (int i = 0; i <IRP_MJ_MAXIMUM_FUNCTION; ++i) {
- pDriverObj->MajorFunction[i] = DefaultFun;
- }
- pDriverObj->DriverUnload = UnLoad;
- pDriverObj->MajorFunction[IRP_MJ_CREATE] = onCreate;
- pDriverObj->MajorFunction[IRP_MJ_CLOSE] = onClose;
- UNICODE_STRING DeviceName;
- UNICODE_STRING SymbolicLinkName;
- DEVICE_OBJECT* DeviceObj;
- NTSTATUS nStatus = STATUS_SUCCESS;
- RtlInitUnicodeString(&DeviceName, L"\\Device\\DeviceName");
- RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\SymbolicLinkName");
- nStatus = IoCreateDevice(pDriverObj, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, 0, &DeviceObj);
- if (!NT_SUCCESS(nStatus))
- return nStatus;
- nStatus = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
- if (!NT_SUCCESS(nStatus))
- return nStatus;
- DbgBreakPoint();
- // 没有使用控制码等处理 伪代码进行测试
- HideThreadListLink();
- return STATUS_SUCCESS;
- }
来源: http://www.bubuko.com/infodetail-2912629.html