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

一、论:
接着上一篇来谈谈,进程都能隐藏,单独隐藏进程中的某一个线程干啥?
二、需求:
需求源动力,就是有需求,除了正儿八经热爱喜欢专研的朋友,无利无名、无食而学日不思,真的让人很尊敬。
三、打个比方:
当你想要去实现隐藏线程的时候你有可能在干什么?做一个工具?或者说是学习?通过隐藏线程可以更深入理解windows内部原理?进程与线程之间的关系?一个正常进程里面包含恶意线程?这是一个很棒的学习方式。也许你会用它来做一些事情,以前想写过一个类似于ARK的工具,才有了学习的需求及动力。但是还没有实际的环境去应用隐藏线程,没有需求,但还是把代码认真的写出来,分享一些知识,知识在于分享。
四、还是那些结构体:
有时候我在想,不用winAPI我能做什么事?也许我还能做很多的事情,因为有足够的结构体我就不慌、但是,如果没有了结构体我能做什么事情?这个还真不好说,其实相对于windows我更为喜欢Linux那种自由。
介绍主人公_ETHREAD与_KTHREAD:
 1、_EPROCESS.ThreadListHead ---> _ETHREAD
 2、_KPROCESS.ThreadListHead ---> _KTHREAD
线程属于进程,一个进程由多个线程、那么同一个进程的多个线程使用的是相同的进程空间,线程也叫做轻量级进程。线程挂靠技术,也可以本线程使用其他进程的空间。
windows下线程是最小执行单位,每个进程至少会有一个主线程去响应执行。同样_ETHREAD属于执行体层,内嵌偏移0是_KTHREAD(微内核层),异曲同工之妙,windows的管理不得不说很优秀,可以用艺术来形容。
_KPROCESS中会有一个成员叫做ThreadListHead字段是进程所有线程的链表。指向的位置是_KTHREAD.ThreadListEntry,这个地方当时异或了好久,为啥?为啥这个链表指向的就是这个结构体这个位置,其实我现在也很纠结.
说说windows内核中为什么要隐藏线程?
 _KPROCESS.ThreadListHead指向 -----> _KTHREAD.ThreadListEntry
说说windows内核中为什么要隐藏线程?
就是这个情况.内核就是通过这个来遍历属于某一个进程空间的所有线程。详细资料还是参考:https://bbs.pediy.com/thread-223858.htm 个人感觉翻译过来的文章质量五星好评。
五、贴上源码
注:
用户层与头文件源码与隐藏线层套路一样,代码可复用(改一下控制码的宏定义即可)
以下测试代码没有到三环进行通讯,在0环进行的测试(主代码断链部分与进程断链一样,这里给出伪代码及思路)

成都创新互联是一家专业提供渝北企业网站建设,专注与成都网站建设、做网站、html5、小程序制作等业务。10年已为渝北众多企业、政府机构等服务。创新互联专业的建站公司优惠进行中。

驱动层:

#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,  UNICODE_STRING* RegistryPath)
{

    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;
}

文章名称:说说windows内核中为什么要隐藏线程?
网站链接:http://pwwzsj.com/article/gggphe.html