在实际对抗中,攻击者往往第一件事就是一个OpenProcess,然后执行注入、内存读写等操作。OpenProcess会返回一个叫做句柄的东西。而防守方通常对某些进程的句柄非常敏感,通过各种手段使OpenProcess失败或对返回的句柄进行处理,从而将恶意行为扼杀在摇篮里。本章通过学习句柄的一系列知识来体会下句柄防护在实际攻防对抗中的重要性。
当调用OpenProcess时,会传入进程ID、权限等参数。此时系统会通过进程ID去全局句柄表
中搜索进程对象,然后把找到的进程对象插入到调用OpenProcess的进程
的私有句柄表中
,再将插入后的索引返回给调用者,这个索引就是句柄
。
线程的句柄获取方式与进程相同。
全局句柄表中存储着当前系统所有进程及线程的对象信息。且全局句柄表中仅存储进程、线程信息。
进程ID、线程ID,每一个ID对应全局句柄表中一个成员,每个ID都是4的整数倍。但全局句柄表每个成员占8字节。宏观体现如下:(假设全局句柄表地址为0x12345670)
当进程、线程数量过多时,一张表的512项显然不够,这时全局句柄表地址最后一位会变成1,代表额外增加一层,宏观体现如下:(全局句柄表地址0x12345671,实际地址为0x12345670,最后一位仅代表层级)
当双层结构也不够存储时,又会增加一层。结构如下:
在虚拟机中随便打开个进程,查看该进程的PID,如dbgview:540(十进制)
全局句柄表存在名为PspCidTable
的全局变量中,windbg中查看该变量。
句柄表实质是个名为_HANDLE_TABLE
的结构,windbg中查看该结构。
第一个成员TableCode值为0x9a8d6001,最后一位为1,说明有两层结构。第一层表中每个成员占4字节,每个成员都指向一张表。windbg查看第一层。
上文dbgview进程ID为540,每个进程、线程ID都是4的倍数,因此540除以4等于135,索引从0开始,也就是第136个。每个表存储521个进程、线程信息,因此dbgview存在第一张表中。使用windbg命令查看第一张表索引为135的成员:
找到的成员为0000000087fd0571,最后3个二进制位需要清空,就变成了0000000087fd0570,这个地址就是dbgview进程结构的地址:
索引为135的8字节成员同时也是一个名为 _HANDLE_TABLE_ENTRY 的结构,使用dt _HANDLE_TABLE_ENTRY 8d405000+8*0x87 也能得到进程结构体地址。这里直接看低4字节数据是因为全局句柄表中没有权限划分,因此高4字节必然为0。
上文通过指定进程PID查询到了进程结构体,但全局句柄表中既有进程也有线程,反向查询时单凭一个结构体首地址无法得知这个结构体是进程的还是线程的。
每个内核对象地址前面都有一个对象头结构,描述了这个对象的类型。对象头结构占0x18字节。
在windbg中查看全局句柄表中索引为1的对象头信息:
其中TypeIndex成员指明了这个内核对象的类型,这个成员是内核对象类型表
的索引值,内核对象类型表存储在全局变量ObTypeIndexTable
中,每个成员占4个字节,每个成员都是一个名为_OBJECT_TYPE
的结构体。使用windbg查看该内核对象具体类型信息:
思路:
效果:
无法打开目标进程。
全局句柄表中仅存储所有进程和线程。类似互斥体、事件、信号量这些东西的句柄都存储在调用者进程自身的私有句柄表中。私有句柄表中还存储OpenProcess、OpenThread返回的句柄和从父进程继承的句柄。
使用windbg随便查看一个进程的EPROCESS结构,在偏移0xF4处有一个成员名为ObjectTable,其类型为 _HANDLE_TABLE 。与全局句柄表类型结构一致,查找方式也一致。这个句柄表就是该进程的私有句柄表。
该句柄表结构
该句柄表结构成员信息:
查看句柄表内每个句柄:
第一个句柄为-2,代表当前线程。在3环调用GetCurrentProcess会返回-1代表当前进程,GetCurrentThread返回-2代表当前线程。
继续查看第二个句柄结构:
一些公司为了防止自身进程被操作,会遍历系统中所有进程的私有句柄表。如果发现某个进程的私有句柄表有自己的进程(判断进程名、进程ID、CR3、进程结构体地址等手段),就清空该私有句柄表的自身句柄的权限位(_HANDLE_TABLE_ENTRY->GrantedAccess)。这样导致该句柄不再具有读写等权限,从而保护自身进程。
由于我们的进程打开目标进程后,私有句柄表内的句柄权限被循环清空,导致无法读写目标进程的内存或只能查看很短的时间。因此我们需要进行句柄的替换。
需注意句柄结构中Object成员包含0x18大小的对象头部数据,在复制时要将目标进程的对象头结构一同复制。
kd> dd PspCidTable
83f7bf34
8d404008
00000000
80000020
00000101
83f7bf44
80000320
80000024
00000000
00000000
83f7bf54
00000000
00000000
00000000
00000113
83f7bf64
00000000
00000000
83f2c35a
00000000
83f7bf74
00000000
00000000
00000000
00000008
83f7bf84
00000000
83f7bf88
83f7bf88
00000000
83f7bf94
00000000
00000000
00000000
00000000
83f7bfa4
00000000
807c8c38
807c4c38
00000000
kd> dd PspCidTable
83f7bf34
8d404008
00000000
80000020
00000101
83f7bf44
80000320
80000024
00000000
00000000
83f7bf54
00000000
00000000
00000000
00000113
83f7bf64
00000000
00000000
83f2c35a
00000000
83f7bf74
00000000
00000000
00000000
00000008
83f7bf84
00000000
83f7bf88
83f7bf88
00000000
83f7bf94
00000000
00000000
00000000
00000000
83f7bfa4
00000000
807c8c38
807c4c38
00000000
kd> dt _HANDLE_TABLE
8d404008
ntdll!_HANDLE_TABLE
+
0x000
TableCode :
0x9a8d6001
+
0x004
QuotaProcess : (null)
+
0x008
UniqueProcessId : (null)
+
0x00c
HandleLock : _EX_PUSH_LOCK
+
0x010
HandleTableList : _LIST_ENTRY [
0x8d404018
-
0x8d404018
]
+
0x018
HandleContentionEvent : _EX_PUSH_LOCK
+
0x01c
DebugInfo : (null)
+
0x020
ExtraInfoPages :
0n0
+
0x024
Flags :
1
+
0x024
StrictFIFO :
0y1
+
0x028
FirstFreeHandle :
0xf98
+
0x02c
LastFreeHandleEntry :
0x9a8d7808
_HANDLE_TABLE_ENTRY
+
0x030
HandleCount :
0x255
+
0x034
NextHandleNeedingPool :
0x1000
+
0x038
HandleCountHighWatermark :
0x304
kd> dt _HANDLE_TABLE
8d404008
ntdll!_HANDLE_TABLE
+
0x000
TableCode :
0x9a8d6001
+
0x004
QuotaProcess : (null)
+
0x008
UniqueProcessId : (null)
+
0x00c
HandleLock : _EX_PUSH_LOCK
+
0x010
HandleTableList : _LIST_ENTRY [
0x8d404018
-
0x8d404018
]
+
0x018
HandleContentionEvent : _EX_PUSH_LOCK
+
0x01c
DebugInfo : (null)
+
0x020
ExtraInfoPages :
0n0
+
0x024
Flags :
1
+
0x024
StrictFIFO :
0y1
+
0x028
FirstFreeHandle :
0xf98
+
0x02c
LastFreeHandleEntry :
0x9a8d7808
_HANDLE_TABLE_ENTRY
+
0x030
HandleCount :
0x255
+
0x034
NextHandleNeedingPool :
0x1000
+
0x038
HandleCountHighWatermark :
0x304
kd> dd
0x9a8d6000
ReadVirtual:
9a8d6000
not
properly sign extended
9a8d6000
8d405000
9a8d7000
00000000
00000000
9a8d6010
00000000
00000000
00000000
00000000
9a8d6020
00000000
00000000
00000000
00000000
9a8d6030
00000000
00000000
00000000
00000000
9a8d6040
00000000
00000000
00000000
00000000
9a8d6050
00000000
00000000
00000000
00000000
9a8d6060
00000000
00000000
00000000
00000000
9a8d6070
00000000
00000000
00000000
00000000
kd> dd
0x9a8d6000
ReadVirtual:
9a8d6000
not
properly sign extended
9a8d6000
8d405000
9a8d7000
00000000
00000000
9a8d6010
00000000
00000000
00000000
00000000
9a8d6020
00000000
00000000
00000000
00000000
9a8d6030
00000000
00000000
00000000
00000000
9a8d6040
00000000
00000000
00000000
00000000
9a8d6050
00000000
00000000
00000000
00000000
9a8d6060
00000000
00000000
00000000
00000000
9a8d6070
00000000
00000000
00000000
00000000
kd> dq
8d405000
+
8
*
0x87
ReadVirtual:
8d405438
not
properly sign extended
8d405438
00000000
`
87fd0571
00000000
`
87ac9b31
8d405448
00000000
`
87ac9609
00000000
`
87ac7cc1
8d405458
00000000
`
87ad1971
00000000
`
87ad21c1
8d405468
00000000
`
87ad8bf9
00000000
`
87ad8281
8d405478
00000000
`
87ad98b1
00000000
`
87ad5031
8d405488
0000090c
`
00000000
00000000
`
877a7b01
8d405498
000003bc
`
00000000
000003f4
`
00000000
8d4054a8
00000af4
`
00000000
00000000
`
87b51031
kd> dq
8d405000
+
8
*
0x87
ReadVirtual:
8d405438
not
properly sign extended
8d405438
00000000
`
87fd0571
00000000
`
87ac9b31
8d405448
00000000
`
87ac9609
00000000
`
87ac7cc1
8d405458
00000000
`
87ad1971
00000000
`
87ad21c1
8d405468
00000000
`
87ad8bf9
00000000
`
87ad8281
8d405478
00000000
`
87ad98b1
00000000
`
87ad5031
8d405488
0000090c
`
00000000
00000000
`
877a7b01
8d405498
000003bc
`
00000000
000003f4
`
00000000
8d4054a8
00000af4
`
00000000
00000000
`
87b51031
kd> dq
8d405000
/
/
0
~
511
句柄表
ReadVirtual:
8d405000
not
properly sign extended
8d405000
fffffffe`
00000000
00000000
`
865e8739
8d405010
00000000
`
865e8461
00000000
`
86617021
8d405020
00000000
`
8661f021
00000000
`
865e9a49
8d405030
00000000
`
86637d49
00000000
`
86637a71
8d405040
00000000
`
86633d49
00000000
`
86633a71
8d405050
00000000
`
8662fd49
00000000
`
8662fa71
8d405060
00000000
`
8661fd49
00000000
`
8661fa71
8d405070
00000000
`
8661bd49
00000000
`
8661ba71
kd> dt _OBJECT_HEADER
865e8738
-
0x18
/
/
记得清空后三个二进制位
nt!_OBJECT_HEADER
+
0x000
PointerCount :
0n149
+
0x004
HandleCount :
0n3
+
0x004
NextToFree :
0x00000003
Void
+
0x008
Lock : _EX_PUSH_LOCK
+
0x00c
TypeIndex :
0x7
''
+
0x00d
TraceFlags :
0
''
+
0x00e
InfoMask :
0
''
+
0x00f
Flags :
0x2
''
+
0x010
ObjectCreateInfo :
0x83f6fcc0
_OBJECT_CREATE_INFORMATION
+
0x010
QuotaBlockCharged :
0x83f6fcc0
Void
+
0x014
SecurityDescriptor :
0x8d404d96
Void
+
0x018
Body : _QUAD
kd> dq
8d405000
/
/
0
~
511
句柄表
ReadVirtual:
8d405000
not
properly sign extended
8d405000
fffffffe`
00000000
00000000
`
865e8739
8d405010
00000000
`
865e8461
00000000
`
86617021
8d405020
00000000
`
8661f021
00000000
`
865e9a49
8d405030
00000000
`
86637d49
00000000
`
86637a71
8d405040
00000000
`
86633d49
00000000
`
86633a71
8d405050
00000000
`
8662fd49
00000000
`
8662fa71
8d405060
00000000
`
8661fd49
00000000
`
8661fa71
8d405070
00000000
`
8661bd49
00000000
`
8661ba71
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!