全局句柄表以及解析句柄表并遍历进程
概念:Windows中有两种句柄表分别是:全局句柄表私有句柄表全局句柄表与私有句柄表使用一个结构体在三环调用API需要调用ID打开句柄的有:进程(OpenProcess)线程(Ope 2020-12-16 00:49:03 Author: www.f4ckweb.top(查看原文) 阅读量:411 收藏

概念:

Windows中有两种句柄表分别是:

  1. 全局句柄表
  2. 私有句柄表

全局句柄表与私有句柄表使用一个结构体

在三环调用API需要调用ID打开句柄的有:

  1. 进程(OpenProcess)
  2. 线程(OpenThread)

句柄表中存放的是指针,32位就是32位指针

x64 算法:
进程ID / 4 = 表索引
表索引 * 16 = 全局句柄表条目

x86算法:

进程ID / 4 = 表索引
表索引 * 8 = 全局句柄表条目

为什么 * 8 因为每一项占8字节,前4字节为头,后4字节为地址

实验:

选择某目标进程获取到PID2220:

clipboard.png

可以使用PspCidTable来寻找句柄表指针:

kd> dq PspCidTable
fffff800`0403dbc8  fffff8a0`00004970 00000000`00000000
fffff800`0403dbd8  ffffffff`8000001c 00000000`00000101
fffff800`0403dbe8  ffffffff`800002bc ffffffff`80000024
fffff800`0403dbf8  00000000`00000000 00000000`00000113
fffff800`0403dc08  00000000`00000000 00000000`00000000
fffff800`0403dc18  fffff800`03f98b40 00000000`00000000
fffff800`0403dc28  00000000`00000000 00000000`00000000
fffff800`0403dc38  00000000`00000000 00000000`00000008

查看_handle_table结构相关信息:

kd> dt _handle_table fffff8a0`00004970
nt!_HANDLE_TABLE
   +0x000 TableCode        : 0xfffff8a0`01738001
   +0x008 QuotaProcess     : (null) 
   +0x010 UniqueProcessId  : (null) 
   +0x018 HandleLock       : _EX_PUSH_LOCK
   +0x020 HandleTableList  : _LIST_ENTRY [ 0xfffff8a0`00004990 - 0xfffff8a0`00004990 ]
   +0x030 HandleContentionEvent : _EX_PUSH_LOCK
   +0x038 DebugInfo        : (null) 
   +0x040 ExtraInfoPages   : 0n0
   +0x044 Flags            : 1
   +0x044 StrictFIFO       : 0y1
   +0x048 FirstFreeHandle  : 0x8a8
   +0x050 LastFreeHandleEntry : 0xfffff8a0`01739980 _HANDLE_TABLE_ENTRY
   +0x058 HandleCount      : 0x20f
   +0x05c NextHandleNeedingPool : 0xc00
   +0x060 HandleCountHighWatermark : 0x264

其中tableCode记录了表级与表地址,HandleCount记录了当前句柄表中有多少个句柄,在tableCode最后一位说明了句柄表中有几层:

0xfffff8a0`01738001 代表句柄表中有两层

当最后一位为0时,代表直接指向句柄表,当最后一位为1时代表指向一个数组,数组中的值才指向的是句柄,这个数组可以存放句柄表的指针,为2时就变成了一个三维数组

clipboard (1).png

代码表示为:

X86下_HANDLE_TABLE_ENTRY结构大小为8,x64下结构大小为16,每张表4k大小4k/16=256,所以一张表可以存256个handle。二级三级表存放指针,x64下一个指针地址占用8字节,x86下占用4字节。4k/8=512


/*为0时*/

Handle Handle_table[256] = {};

/*为1时*/

Handle_table Handle_table[512][0] = Handle_table;

查看数组发现了三个handle表:

kd> dq 0xfffff8a0`01738000
fffff8a0`01738000  fffff8a0`00005000 fffff8a0`01739000
fffff8a0`01738010  fffff8a0`01bdc000 00000000`00000000
fffff8a0`01738020  00000000`00000000 00000000`00000000
fffff8a0`01738030  00000000`00000000 00000000`00000000
fffff8a0`01738040  00000000`00000000 00000000`00000000
fffff8a0`01738050  00000000`00000000 00000000`00000000
fffff8a0`01738060  00000000`00000000 00000000`00000000
fffff8a0`01738070  00000000`00000000 00000000`00000000

以刚刚的进程为例子,PID=2220:

2220 / 4 = 555 

得到结果555,每张表存放256个句柄,555-256 = 299,299>256,那么此进程在第三张表中,299-256=0x2B:

fffff8a0`01bdc000+0x2b*F

最终此进程句柄为fffff8a0`01bdc000+0x2B,句柄实例结构体为:_HANDLE_TABLE_ENTRY

kd> dt _HANDLE_TABLE_ENTRY fffff8a0`01bdc000+0x2b*10
nt!_HANDLE_TABLE_ENTRY
   +0x000 Object           : 0xfffffa80`02a5d061 Void
   +0x000 ObAttributes     : 0x2a5d061
   +0x000 InfoTable        : 0xfffffa80`02a5d061 _HANDLE_TABLE_ENTRY_INFO
   +0x000 Value            : 0xfffffa80`02a5d061
   +0x008 GrantedAccess    : 0
   +0x008 GrantedAccessIndex : 0
   +0x00a CreatorBackTraceIndex : 0
   +0x008 NextFreeTableEntry : 0

然后使用_EPROCESS结构体就可以查看到进程信息了得到的对象最后一位要-1,因为最后一位为权限位

kd> dt _EPROCESS 0xfffffa80`02a5d060
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x160 ProcessLock      : _EX_PUSH_LOCK
   +0x168 CreateTime       : _LARGE_INTEGER 0x0001d6d2`8cc51d24
   +0x170 ExitTime         : _LARGE_INTEGER 0x0
   +0x178 RundownProtect   : _EX_RUNDOWN_REF
   +0x180 UniqueProcessId  : 0x48000000`00000008 Void
   +0x188 ActiveProcessLinks : _LIST_ENTRY [ 0xb8fffffa`80020483 - 0xf0fffffa`8001977c ]
   +0x198 ProcessQuotaUsage : [2] 0xb0000000`00000059
   +0x1a8 ProcessQuotaPeak : [2] 0xc0000000`0000005e
   +0x1b8 CommitCharge     : 0x80000000`00000003
   +0x1c0 QuotaBlock       : 0x00fffffa`800367bd _EPROCESS_QUOTA_BLOCK
   +0x1c8 CpuQuotaBlock    : (null) 
   +0x1d0 PeakVirtualSize  : 0x78260
   +0x1d8 VirtualSize      : 0xa0000000`00076800
   +0x1e0 SessionProcessLinks : _LIST_ENTRY [ 0x10fffffa`80020483 - 0x00fffffa`8001977d ]
   +0x1f0 DebugPort        : 0x40000000`00000000 Void
   +0x1f8 ExceptionPortData : 0x90fffffa`8003611c Void
   +0x1f8 ExceptionPortValue : 0x90fffffa`8003611c
   +0x1f8 ExceptionPortState : 0y100
   +0x200 ObjectTable      : 0x93fffff8`a0093bcb _HANDLE_TABLE
   +0x208 Token            : _EX_FAST_REF
   +0x210 WorkingSetPage   : 0x20e
   +0x218 AddressCreationLock : _EX_PUSH_LOCK
   +0x220 RotateInProgress : (null) 
   +0x228 ForkInProgress   : (null) 
   +0x230 HardwareTrigger  : 0
   +0x238 PhysicalVadRoot  : (null) 
   +0x240 CloneRoot        : 0x8d000000`00000000 Void
   +0x248 NumberOfPrivatePages : 2
   +0x250 NumberOfLockedPages : 0x10000000`00000000
   +0x258 Win32Process     : 0x00fffff9`00c011c0 Void
   +0x260 Job              : 0xf0000000`00000000 _EJOB
   +0x268 SectionObject    : 0x00fffff8`a0084a1a Void
   +0x270 SectionBaseAddress : 0x0f000000`00003100 Void
   +0x278 Cookie           : 0x559554
   +0x27c UmsScheduledThreads : 0
   +0x280 WorkingSetWatch  : 0x58000000`00000000 _PAGEFAULT_HISTORY
   +0x288 Win32WindowStation : 0x78000000`00000000 Void
   +0x290 InheritedFromUniqueProcessId : 0x00000000`00000007 Void
   +0x298 LdtInformation   : (null) 
   +0x2a0 Spare            : (null) 
   +0x2a8 ConsoleHostProcess : 0x40000000`00000000
   +0x2b0 DeviceMap        : 0x00fffff8`a0015b97 Void
   +0x2b8 EtwDataSource    : (null) 
   +0x2c0 FreeTebHint      : 0x00000000`007efd50 Void
   +0x2c8 FreeUmsTebHint   : 0x00000000`01000000 Void
   +0x2d0 PageDirectoryPte : _HARDWARE_PTE
   +0x2d0 Filler           : 0
   +0x2d8 Session          : 0x73fffff8`80042630 Void
   +0x2e0 ImageFileName    : [15]  "etup_wm.exe"
   +0x2ef PriorityClass    : 0 ''
   +0x2f0 JobLinks         : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
   +0x300 LockedPagesList  : 0x80000000`00000000 Void
   +0x308 ThreadListHead   : _LIST_ENTRY [ 0x10fffffa`8001fa2f - 0x00fffffa`8002d978 ]
   +0x318 SecurityPort     : (null) 
   +0x320 Wow64Process     : 0x08000000`007efde0 Void
   +0x328 ActiveThreads    : 0xc8000000
   +0x32c ImagePathHash    : 0x10e4cb6
   +0x330 DefaultHardErrorProcessing : 0
   +0x334 LastThreadExitStatus : 0n0
   +0x338 Peb              : 0x00000000`007efdf0 _PEB
   +0x340 PrefetchTrace    : _EX_FAST_REF
   +0x348 ReadOperationCount : _LARGE_INTEGER 0x0
   +0x350 WriteOperationCount : _LARGE_INTEGER 0xb6000000`00000000
   +0x358 OtherOperationCount : _LARGE_INTEGER 0x40000000`00000000
   +0x360 ReadTransferCount : _LARGE_INTEGER 0x0
   +0x368 WriteTransferCount : _LARGE_INTEGER 0xfc000000`00000000
   +0x370 OtherTransferCount : _LARGE_INTEGER 0xc
   +0x378 CommitChargeLimit : 0xdf000000`00000000
   +0x380 CommitChargePeak : 3
   +0x388 AweInfo          : 0x90000000`00000000 Void
   +0x390 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x398 Vm               : _MMSUPPORT
   +0x420 MmProcessLinks   : _LIST_ENTRY [ 0x50fffffa`80020485 - 0x00fffffa`8001977f ]
   +0x430 HighestUserAddress : 0x07000000`007fff00 Void
   +0x438 ModifiedPageCount : 1
   +0x43c Flags2           : 0x10000d0
   +0x43c JobNotReallyActive : 0y0
   +0x43c AccountingFolded : 0y0
   +0x43c NewProcessReported : 0y0
   +0x43c ExitProcessReported : 0y0
   +0x43c ReportCommitChanges : 0y1
   +0x43c LastReportMemory : 0y0
   +0x43c ReportPhysicalPageChanges : 0y1
   +0x43c HandleTableRundown : 0y1
   +0x43c NeedsHandleRundown : 0y0
   +0x43c RefTraceEnabled  : 0y0
   +0x43c NumaAware        : 0y0
   +0x43c ProtectedProcess : 0y0
   +0x43c DefaultPagePriority : 0y000
   +0x43c PrimaryTokenFrozen : 0y0
   +0x43c ProcessVerifierTarget : 0y0
   +0x43c StackRandomizationDisabled : 0y0
   +0x43c AffinityPermanent : 0y0
   +0x43c AffinityUpdateEnable : 0y0
   +0x43c PropagateNode    : 0y0
   +0x43c ExplicitAffinity : 0y0
   +0x440 Flags            : 0x3144d08
   +0x440 CreateReported   : 0y0
   +0x440 NoDebugInherit   : 0y0
   +0x440 ProcessExiting   : 0y0
   +0x440 ProcessDelete    : 0y1
   +0x440 Wow64SplitPages  : 0y0
   +0x440 VmDeleted        : 0y0
   +0x440 OutswapEnabled   : 0y0
   +0x440 Outswapped       : 0y0
   +0x440 ForkFailed       : 0y1
   +0x440 Wow64VaSpace4Gb  : 0y0
   +0x440 AddressSpaceInitialized : 0y11
   +0x440 SetTimerResolution : 0y0
   +0x440 BreakOnTermination : 0y0
   +0x440 DeprioritizeViews : 0y1
   +0x440 WriteWatch       : 0y0
   +0x440 ProcessInSession : 0y0
   +0x440 OverrideAddressSpace : 0y0
   +0x440 HasAddressSpace  : 0y1
   +0x440 LaunchPrefetched : 0y0
   +0x440 InjectInpageErrors : 0y1
   +0x440 VmTopDown        : 0y0
   +0x440 ImageNotifyDone  : 0y0
   +0x440 PdeUpdateNeeded  : 0y0
   +0x440 VdmAllowed       : 0y1
   +0x440 CrossSessionCreate : 0y1
   +0x440 ProcessInserted  : 0y0
   +0x440 DefaultIoPriority : 0y000
   +0x440 ProcessSelfDelete : 0y0
   +0x440 SetTimerResolutionLink : 0y0
   +0x444 ExitStatus       : 0n-1426063359
   +0x448 VadRoot          : _MM_AVL_TABLE
   +0x488 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x4a8 TimerResolutionLink : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
   +0x4b8 RequestedTimerResolution : 0xb000000
   +0x4bc ActiveThreadsHighWatermark : 0
   +0x4c0 SmallestTimerResolution : 0
   +0x4c8 TimerResolutionStackRecord : 0x53000000`00000000 _PO_DIAG_STACK_RECORD

如何知道对方是进程还是线程?

在内核中每个对象都有一个结构体_OBJECT_HEADER,在x64下,目标结构体为:

kd>  dt _OBJECT_HEADER -v
nt!_OBJECT_HEADER
struct _OBJECT_HEADER, 12 elements, 0x38 bytes
   +0x000 PointerCount     : Int8B
   +0x008 HandleCount      : Int8B
   +0x008 NextToFree       : Ptr64 to Void
   +0x010 Lock             : struct _EX_PUSH_LOCK, 7 elements, 0x8 bytes
   +0x018 TypeIndex        : UChar
   +0x019 TraceFlags       : UChar
   +0x01a InfoMask         : UChar
   +0x01b Flags            : UChar
   +0x020 ObjectCreateInfo : Ptr64 to struct _OBJECT_CREATE_INFORMATION, 9 elements, 0x40 bytes
   +0x020 QuotaBlockCharged : Ptr64 to Void
   +0x028 SecurityDescriptor : Ptr64 to Void
   +0x030 Body             : struct _QUAD, 2 elements, 0x8 bytes

目标大小为38,第30个字节为他的身体,所以我们需要-30:

kd> dt _OBJECT_HEADER 0xfffffa80`02a5d060-30
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n143
   +0x008 HandleCount      : 0n4
   +0x008 NextToFree       : 0x00000000`00000004 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0x7 ''
   +0x019 TraceFlags       : 0 ''
   +0x01a InfoMask         : 0x8 ''
   +0x01b Flags            : 0 ''
   +0x020 ObjectCreateInfo : 0xfffffa80`0367bd80 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0xfffffa80`0367bd80 Void
   +0x028 SecurityDescriptor : 0xfffff8a0`0177df5d Void
   +0x030 Body             : _QUAD

其中的TypeIndex就在说明内核对象的类型,说明放在了ObTypeIndexTable中:

kd> dd ObTypeIndexTable
fffff800`04040340  00000000 00000000 bad0b0b0 00000000
fffff800`04040350  0184cca0 fffffa80 0184cb50 fffffa80
fffff800`04040360  0184ca00 fffffa80 018eef10 fffffa80
fffff800`04040370  018eecf0 fffffa80 018eeba0 fffffa80
fffff800`04040380  018eea50 fffffa80 018ee900 fffffa80
fffff800`04040390  018ee7b0 fffffa80 018eff30 fffffa80
fffff800`040403a0  019b4570 fffffa80 01998a30 fffffa80
fffff800`040403b0  019988e0 fffffa80 0196ea50 fffffa80

将ObTypeIndexTable首地址:fffff800`04040340,取出来然后+7*8(x86为7*4):

kd> dq fffff800`04040340+7*8
fffff800`04040378  fffffa80`018eeba0 fffffa80`018eea50
fffff800`04040388  fffffa80`018ee900 fffffa80`018ee7b0
fffff800`04040398  fffffa80`018eff30 fffffa80`019b4570
fffff800`040403a8  fffffa80`01998a30 fffffa80`019988e0
fffff800`040403b8  fffffa80`0196ea50 fffffa80`0196e900
fffff800`040403c8  fffffa80`01983a50 fffffa80`01983900
fffff800`040403d8  fffffa80`01944a50 fffffa80`01944900
fffff800`040403e8  fffffa80`01936a50 fffffa80`01936900

然后使用_OBJECT_TYPE查看是什么类型:

kd> dt _OBJECT_TYPE fffffa80`018eeba0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`018eeba0 - 0xfffffa80`018eeba0 ]
   +0x010 Name             : _UNICODE_STRING "Process"
   +0x020 DefaultObject    : (null) 
   +0x028 Index            : 0x7 ''
   +0x02c TotalNumberOfObjects : 0x25
   +0x030 TotalNumberOfHandles : 0xd4
   +0x034 HighWaterNumberOfObjects : 0x2f
   +0x038 HighWaterNumberOfHandles : 0x102
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x636f7250
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`018eec60 - 0xfffffa80`018eec60 ]

解析全局句柄表并遍历进程:

#include <ntddk.h>




VOID DriverUnload(PDRIVER_OBJECT driver)
{

    if (driver != NULL)
    {
        DbgPrint("Driver Uninstall");
    }
}



DWORD32 GetPspCidTable()
{
    UNICODE_STRING uStrName;
    DWORD32* pPsLookupProcessByProcessId;
    int i = 0;
    DWORD32 PspCidTable = 0;

    RtlInitUnicodeString(&uStrName, L"PsLookupProcessByProcessId");
    pPsLookupProcessByProcessId = (DWORD32*)MmGetSystemRoutineAddress(&uStrName);
    if (!pPsLookupProcessByProcessId)
    {
        return 0;
    }

    /*
   8406f590 ff7508          push    dword ptr [ebp+8]
   8406f593 8b3d345ff583    mov     edi,dword ptr [nt!PspCidTable (83f55f34)]
    */

    while (i < 258)
    {
        if (*((UCHAR*)pPsLookupProcessByProcessId + i) == 0xFF && *((UCHAR*)pPsLookupProcessByProcessId + i + 1) == 0x75 && *((UCHAR*)pPsLookupProcessByProcessId + i + 2) == 0x08)
        {
            DbgPrint("找到了!找到了!");
            PspCidTable = *(DWORD32*)((UCHAR*)pPsLookupProcessByProcessId + i + 5);
            DbgPrint("%x", PspCidTable);
            break;
        }

        i++;

    }


    return PspCidTable;
}


NTSTATUS DriverEntry(PDRIVER_OBJECT driverT, PUNICODE_STRING string_path)
{
    DbgPrint("Hello Word My Driver");

    if (string_path != NULL)
    {
        DbgPrint("[%s]Driver RegisterPath : %wZ\n", __FUNCTION__, string_path);
    }


    if (driverT != NULL)
    {
        DbgPrint("[%s]Driver Object Address : %p\n", __FUNCTION__, driverT);
        driverT->DriverUnload = DriverUnload;
    }

    DWORD32* PspCidTable = (DWORD32*)GetPspCidTable();
    DbgPrint("PspCidTable:%x\n", *PspCidTable);
    DWORD32 tablecode = *(DWORD32*)(*PspCidTable);
    DbgPrint("TableCode:%x\n", tablecode);

    UINT8 low = tablecode & 3;
    DbgPrint("Level:%x\n", low);


    switch (low)
    {
    case 0x0:

        break;
    case 0x1:
        //DbgPrint("%x", *((DWORD32 *)((tablecode - low)+(sizeof(DWORD32)*1))));
        //DbgPrint("%x", (*(DWORD32*)(tablecode - low)));
        for (DWORD32 i = 0; i < 1024; i++)
        {
            if (*((DWORD32*)((tablecode - low) + (sizeof(DWORD32) * i))) == 0)
            {
                break;
            }
            DWORD32 Handle_table = *((DWORD32*)((tablecode - low) + (sizeof(DWORD32) * i)));
            DbgPrint("句柄表:%x", Handle_table);
            for (DWORD32 x = 0x0; x < 0x200; x++) {
                DWORD32 ProcessObj = *(DWORD32*)(Handle_table + (x * 0x8));
                if (ProcessObj == 0) {
                    continue;
                }
                //DbgPrint("%d", *(USHORT*)((DWORD32*)((ProcessObj - 0x1) - 0x18 + 0xC)));

                USHORT IndexType = (*(USHORT*)((DWORD32*)((ProcessObj - 0x1) - 0x18 + 0xC)));
                //DbgPrint("%d",IndexType);
                if (IndexType == 7) {
                    //DbgPrint("%s",  (PCHAR)((DWORD32*)((ProcessObj - 0x1) + 0x16c)));
                    DbgPrint("ProcessOBJ:%x,对象类型:%x,进程ID:%d,进程名称:%s\n", ProcessObj - 0x1, *(USHORT*)((DWORD32*)((ProcessObj - 0x1) - 0x18 + 0xC)), *(DWORD32*)((ProcessObj - 0x1)+ 0x0b4), (PCHAR)((ProcessObj - 0x1) + 0x16c));
                }

            }
        }
        break;
    case 0x2:
        break;
    }

    return STATUS_SUCCESS;

}


文章来源: http://www.f4ckweb.top/index.php/archives/159/
如有侵权请联系:admin#unsafe.sh