CVE-2023-21674 ALPC ITW Vulnerability Analysis

2023年1月,微软发布了一个在野Oday漏洞补丁,位于NT模块的ALPC相关处理中的UAF漏洞,此漏洞可以导致Chrome沙箱穿越,此前曾再Theori的六个漏洞组成的穿越链漏洞演示中,展示了如何从chrome RCE到VMware逃逸,再到HOST机器提权。此漏洞被用于Chrome沙箱穿越。

漏洞原理

此漏洞将在NtAlpcImpersonateClientOfPort->SeCreateClientSecurity调用链条下导致访问异常,本质是由于KThread对象被提前释放导致的UAF。

创建连接端口

NtAlpcCreatePort用于在服务端创建连接端口,实际上在标准的Client-Server模式的ALPC通信中,存在三个端口(2 个在服务器端,1 个在客户端),即一个连接端口,两个通信端口,但实际上内核统一由一个指定的结构_ALPC_PORT结构来处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
0: kd> dt _ALPC_PORT
nt!_ALPC_PORT
+0x000 PortListEntry : _LIST_ENTRY
+0x010 CommunicationInfo : Ptr64 _ALPC_COMMUNICATION_INFO
+0x018 OwnerProcess : Ptr64 _EPROCESS
+0x020 CompletionPort : Ptr64 Void
+0x028 CompletionKey : Ptr64 Void
+0x030 CompletionPacketLookaside : Ptr64 _ALPC_COMPLETION_PACKET_LOOKASIDE
+0x038 PortContext : Ptr64 Void
+0x040 StaticSecurity : _SECURITY_CLIENT_CONTEXT
+0x088 IncomingQueueLock : _EX_PUSH_LOCK
+0x090 MainQueue : _LIST_ENTRY
+0x0a0 LargeMessageQueue : _LIST_ENTRY
+0x0b0 PendingQueueLock : _EX_PUSH_LOCK
+0x0b8 PendingQueue : _LIST_ENTRY
+0x0c8 DirectQueueLock : _EX_PUSH_LOCK
+0x0d0 DirectQueue : _LIST_ENTRY
+0x0e0 WaitQueueLock : _EX_PUSH_LOCK
+0x0e8 WaitQueue : _LIST_ENTRY
+0x0f8 Semaphore : Ptr64 _KSEMAPHORE
+0x0f8 DummyEvent : Ptr64 _KEVENT
+0x100 PortAttributes : _ALPC_PORT_ATTRIBUTES
+0x148 ResourceListLock : _EX_PUSH_LOCK
+0x150 ResourceListHead : _LIST_ENTRY
+0x160 PortObjectLock : _EX_PUSH_LOCK
+0x168 CompletionList : Ptr64 _ALPC_COMPLETION_LIST
+0x170 CallbackObject : Ptr64 _CALLBACK_OBJECT
+0x178 CallbackContext : Ptr64 Void
+0x180 CanceledQueue : _LIST_ENTRY
+0x190 SequenceNo : Int4B
+0x194 ReferenceNo : Int4B
+0x198 ReferenceNoWait : Ptr64 _PALPC_PORT_REFERENCE_WAIT_BLOCK
+0x1a0 u1 : <anonymous-tag>
+0x1a8 TargetQueuePort : Ptr64 _ALPC_PORT
+0x1b0 TargetSequencePort : Ptr64 _ALPC_PORT
+0x1b8 CachedMessage : Ptr64 _KALPC_MESSAGE
+0x1c0 MainQueueLength : Uint4B
+0x1c4 LargeMessageQueueLength : Uint4B
+0x1c8 PendingQueueLength : Uint4B
+0x1cc DirectQueueLength : Uint4B
+0x1d0 CanceledQueueLength : Uint4B
+0x1d4 WaitQueueLength : Uint4B

下面是NtAlpcCreatePort的内核实现,实际上核心代码在AlpcpCreateConnectionPort函数中实现。

58fc5cb9bc46cf2f3b64f5728152bea2.png

首先调用AlpcpCreatePort创建内核对象。

a96bd1d378c3281d7af5af5a85aa0a80.png

实际上调用ObCreateObjectEx创建AlpcPort对象,共0x1D8大小,如前面所示。

接着调用AlpcpInitializePort来初始化AlpcPort对象结构。

4b12872db3bf808f90f2bb157653071f.png

注意开始的初始化都是将ListEntry结构初始化为成员起始地址。例如MainQueue成员就是将其ListEntry结构的Flink和Blink成员都初始化为MainQueue结构地址。

  • Main queue: A message has been sent, and the client is processing it.
  • Pending queue: A message has been sent and the caller is waiting for a reply, but the reply has not yet been sent.
  • Large message queue: A message has been sent, but the caller’s buffer was to small to receive it. The caller gets another chance to allocate a larger buffer and request the message payload again.
  • Canceled queue: A message that was sent to the port but has since then been canceled.
  • Direct queue: A message that was sent with a direct event attached.

接着返回对象句柄。

a534d0ae9f754c7e6e9fd509223b3b89.png

客户端连接

NtAlpcConnectPortEx用于与Server端进行连接,我们需要了解两个内部操作。

首先使用AlpcpCreateClientPort创建ClientCommunicationPort,类型依旧是_ALPC_PORT。

61a1a68b99cfb4d980201122844521f9.png

其次将连接请求消息放入AlpcPort的MainQueue队首。

85ec62526119d0eaea7eccdcca06b7da.png

处理消息链,首先在AlpcpProcessConnectionRequest中将相关结构放入RequestContext结构,此结构尚未公开,我将其定义为如下所示结构。

1
2
3
4
5
6
7
8
9
10
11
typedef struct _REQUEST_CONTEXT
{
_ALPC_PORT *CommPort;
_KALPC_MESSAGE *RequestMessage;
_ALPC_COMMUNICATION_INFO *CommunicationInfo;
PVOID Reserve2;
_ALPC_PORT *ConnectionPort;
PRKEVENT Event;
ULONG flag;
PVOID Reserve5;
} REQUEST_CONTEXT, *PREQUEST_CONTEXT;

8d26b3e797f3c3e311f1c5d9d2971331.png

接着调用AlpcpDispatchConnectionRequest函数,传入RequestContext结构。

e2cb9913b96af0b94c3eb2400241140d.png

继续向后调用AlpcpCompleteDispatchMessage函数。

46199a64a0a9d2bac348ffcec2e0c97f.png

此函数中,将连接请求的Message消息放入MainQueue队首。

服务端接收连接消息

The name of this function sounds like three things at once - Send, Wait and Receive - and that’s exactly what it is. Server and client use this single function to wait for messages, send messages and receive messages on their ALPC port. This sounds unnecessary complex and I can’t tell you for sure why it was build this way, but here’s my guess on it: Remember that ALPC was created as a fast and internal-only communication facility and the communication channel was build around a single kernel object (the ALPC port). Using this 3-way function allows to do multiple operations, e.g. sending and receiving a message, in a single call and thus saves time and reduces user-kernel-land switches. Additionally, this function acts as a single gate into the message exchange process and therefore allows for easier code change and optimizations (ALPC communication is used in a lot of different OS components ranging from kernel drivers to user GUI applications developed by different internal teams). Lastly ALPC is intended as an internal-only IPC mechanism so Microsoft does not need to design it primarily user or 3rd party developer friendly.

正如引用所述,NtAlpcSendWaitReceivePort进行发送-等待-接受一条龙操作。此外,当仅仅想只发送或者只等待接收消息时,可以通过参数来控制即可。在当前漏洞中,我们无需了解发送逻辑,仅仅只需要知道接收消息的逻辑即可。

e4d68ec5ea5b9573c497ef56e9fe7733.png

可以看到,当传入的SendMessage参数为空时,将仅仅执行通过调用AlpcpReceiveMessage函数来进行等待-接受操作。

AlpcpReceiveMessage首先调用 AlpcpReceiveMessagePort函数去访问各个消息队列,循环查看各个消息队列有无消息,并进行处理。

25f3bd23532bca95271b1a016a2580b6.png

正常的消息将在MainQueue队列中被处理,因此当正常消息被发送到MainQueue队列时,将被立即处理。

34dfd520dfb7dd29fdca861bf7f4c474.png

从MainQueue队列拿出消息数据后,再将此消息出队,准备处理下一条。

25da5523dcf64b4b4589923f4337d28e.png

返回AlpcpReceiveMessage函数后,再将拿到的Message结构(KALPC_MESSAGE类型)中最后一个成员放入用户态缓冲区(_PORT_MESSAGE结构如下所示)。

4af7a81959d6656e9d51686a548053d8.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2: kd> dt _KALPC_MESSAGE
nt!_KALPC_MESSAGE
+0x000 Entry : _LIST_ENTRY
+0x010 PortQueue : Ptr64 _ALPC_PORT
+0x018 OwnerPort : Ptr64 _ALPC_PORT
+0x020 WaitingThread : Ptr64 _ETHREAD
+0x028 u1 : <anonymous-tag>
+0x02c SequenceNo : Int4B
+0x030 QuotaProcess : Ptr64 _EPROCESS
+0x030 QuotaBlock : Ptr64 Void
+0x038 CancelSequencePort : Ptr64 _ALPC_PORT
+0x040 CancelQueuePort : Ptr64 _ALPC_PORT
+0x048 CancelSequenceNo : Int4B
+0x050 CancelListEntry : _LIST_ENTRY
+0x060 Reserve : Ptr64 _KALPC_RESERVE
+0x068 MessageAttributes : _KALPC_MESSAGE_ATTRIBUTES
+0x0b0 DataUserVa : Ptr64 Void
+0x0b8 CommunicationInfo : Ptr64 _ALPC_COMMUNICATION_INFO
+0x0c0 ConnectionPort : Ptr64 _ALPC_PORT
+0x0c8 ServerThread : Ptr64 _ETHREAD
+0x0d0 WakeReference : Ptr64 Void
+0x0d8 WakeReference2 : Ptr64 Void
+0x0e0 ExtensionBuffer : Ptr64 Void
+0x0e8 ExtensionBufferSize : Uint8B
+0x0f0 PortMessage : _PORT_MESSAGE

typedef struct _PORT_MESSAGE
{
union
{
struct
{
CSHORT DataLength;
CSHORT TotalLength;
} s1;
ULONG Length;
} u1;
union
{
struct
{
CSHORT Type;
CSHORT DataInfoOffset;
} s2;
ULONG ZeroInit;
} u2;
union
{
CLIENT_ID ClientId;
double DoNotUseThisField;
};
ULONG MessageId;
union
{
SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages
ULONG CallbackId; // only valid for LPC_REQUEST messages
};
} PORT_MESSAGE, *PPORT_MESSAGE;

服务端允许连接

NtAlpcAcceptConnectPort在收到连接请求后,服务端调用此API用来决定是否允许此客户端连接。

最后一参数表明是否允许客户端连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
NTSYSCALLAPI
NTSTATUS
NTAPI
NtAlpcAcceptConnectPort(
_Out_ PHANDLE PortHandle,
_In_ HANDLE ConnectionPortHandle,
_In_ ULONG Flags,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
_In_opt_ PVOID PortContext,
_In_reads_bytes_(ConnectionRequest->u1.s1.TotalLength) PPORT_MESSAGE ConnectionRequest,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ConnectionMessageAttributes,
_In_ BOOLEAN AcceptConnection
);

相似的手法,此函数是对AlpcpAcceptConnectPort的包装。

68a805c5092ed4bf156d4062d8b2b0d0.png

AlpcpAcceptConnectPort调用AlpcpLookupMessage函数根据ConnectionPort、MessageId和CallbacId取出Message(KALPC_MESSAGE)。

4d1209dc6c08bcd3160e4e272ebf83b0.png

接着对取出的Message内容与传入的用户态结构进行校验操作。

AlpcpValidateConnectionMessage=>AlpcpValidateMessage

d1fa2cf0bd7c624572f49ce8af86d51d.png

14f1f188939611e8d52c93f408d8d8a6.png

接着若不允许连接,释放资源,返回。

9aa99034c8fb0173211e584e5f4951a6.png

若允许连接则创建ServerComm端口,后续用于与客户端通信。

de8b4ba1398402a7d4ae3ca8dfd6df36.png

线程池工厂

NtWaitForWorkViaWorkerFactory实际上是windows实现线程池工厂操作函数,具体使用方法不做赘述。

1d209a03127f55bc1c10f0cda5b6cd06.png

在此poc中,我们仅需了解到此函数是为了在工作线程中向通信端口发送消息,但是按照我们朴素的想法,内核AlpcpSendMessage函数肯定不知只有这一处调用,为什么必须使用此函数来进行消息请求呢?

这里先卖一个关子,这里也是除了UAF本身漏洞之外精彩之处。

而内部正是通过AlpcpSendMessage向通信端口发送消息请求,后续再次被NtAlpcSendWaitReceivePort函数进行获取。

关闭线程句柄以及服务端模拟执行

通过NtAlpcSendWaitReceivePort读取到工作线程发来的请求消息,当工作线程退出后。强制销毁工作线程句柄,但由于内核的Message消息依旧保留了内核线程指针,因此造成UAF。

7f1d182879370266f835628aa2418f15.png

具体来看,首先调用AlpcpCaptureIdMessage解析参数port_message,此参数是前面通过NtAlpcSendWaitReceivePort接收到的消息数据。主要是拿到MessageId和CallbackId成员;

接着调用AlpcpLookupMessage拿到内核Message结构。

接着调用在服务端模拟客户端身份执行。接着需要进行身份权限检测。

3eb71bd11f9f463a34040a0b1a22301c.png

再调用SeCreateClientSecurity函数进行权限检测,但由于传入的WaitingThread指针已经被释放,因此当后续访问此结构成员时,将造成UAF。

0dc51ccdefab19dd9d8ce2ef711b7e47.png

漏洞调试

NtAlpcCreatePort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
1: kd> g
Breakpoint 0 hit
nt!AlpcpCreateConnectionPort+0xd5:
fffff803`74305b1d e82286fbff call nt!AlpcpCreatePort (fffff803`742be144)
3: kd> !thread -1
THREAD ffff818dae2d6080 Cid 085c.0698 Teb: 00000039bf0d9000 Win32Thread: 0000000000000000 RUNNING on processor 3
Not impersonating
DeviceMap ffffbe8f716594d0
Owning Process ffff818dad44e080 Image: CVE-2023-21674.exe
Attached Process N/A Image: N/A
Wait Start TickCount 49268 Ticks: 1 (0:00:00:00.015)
Context Switch Count 7 IdealProcessor: 3
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address 0x00007ff6fc54d25d
Stack Init ffffe581b15f0c90 Current ffffe581b15f0530
Base ffffe581b15f1000 Limit ffffe581b15eb000 Call 0000000000000000
Priority 9 BasePriority 8 IoPriority 2 PagePriority 5
Child-SP RetAddr : Args to Child : Call Site
ffffe581`b15f09d0 fffff803`74305a28 : 00000000`00000025 00000000`00000000 00000000`00000000 00000000`00000000 : nt!AlpcpCreateConnectionPort+0xd5
ffffe581`b15f0ac0 fffff803`7400caf5 : ffff818d`ae2d6080 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtAlpcCreatePort+0x28
ffffe581`b15f0b00 00007ffe`ee58e014 : 00007ff6`fc553fbe 00007ff6`fc632838 00000000`00000000 00000000`00000008 : nt!KiSystemServiceCopyEnd+0x25 (TrapFrame @ ffffe581`b15f0b00)
00000039`bf2ff8f8 00007ff6`fc553fbe : 00007ff6`fc632838 00000000`00000000 00000000`00000008 00000000`00000000 : 0x00007ffe`ee58e014
00000039`bf2ff900 00007ff6`fc632838 : 00000000`00000000 00000000`00000008 00000000`00000000 cccccccc`cccccccc : 0x00007ff6`fc553fbe
00000039`bf2ff908 00000000`00000000 : 00000000`00000008 00000000`00000000 cccccccc`cccccccc cccccccc`cccccccc : 0x00007ff6`fc632838

3: kd> dq @r8
ffffe581`b15f0a18 00000000`00000000 00000000`00000000
ffffe581`b15f0a28 00000000`00000000 00000000`0000ff00
ffffe581`b15f0a38 00000000`00000000 00000000`00000000
ffffe581`b15f0a48 00000000`00000000 00000000`00000000
ffffe581`b15f0a58 00000000`00000000 00000000`00000000
ffffe581`b15f0a68 00000000`00000000 ffffb727`3d7ea602
ffffe581`b15f0a78 00000039`bf2fd7a8 00000000`00000000
ffffe581`b15f0a88 00000000`00000000 00000000`00000000
3: kd> p
nt!AlpcpCreateConnectionPort+0xda:
fffff803`74305b22 85c0 test eax,eax
3: kd> dq ffffe581`b15f0a18
ffffe581`b15f0a18 ffff818d`ae55fa70 00000000`00000000
ffffe581`b15f0a28 00000000`00000000 00000000`0000ff00
ffffe581`b15f0a38 00000000`00000000 00000000`00000000
ffffe581`b15f0a48 00000000`00000000 00000000`00000000
ffffe581`b15f0a58 00000000`00000000 00000000`00000000
ffffe581`b15f0a68 00000000`00000000 ffffb727`3d7ea602
ffffe581`b15f0a78 00000039`bf2fd7a8 00000000`00000000
ffffe581`b15f0a88 00000000`00000000 00000000`00000000
3: kd> dt _ALPC_PORT ffff818d`ae55fa70
nt!_ALPC_PORT
+0x000 PortListEntry : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
+0x010 CommunicationInfo : (null)
+0x018 OwnerProcess : (null)
+0x020 CompletionPort : (null)
+0x028 CompletionKey : (null)
+0x030 CompletionPacketLookaside : (null)
+0x038 PortContext : (null)
+0x040 StaticSecurity : _SECURITY_CLIENT_CONTEXT
+0x088 IncomingQueueLock : _EX_PUSH_LOCK
+0x090 MainQueue : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
......
3: kd> !alpc /p ffff818d`ae55fa70
Error querying field ConnectionPort of structure nt!_ALPC_COMMUNICATION_INFO at 0000000000000000
Error querying communication info.

根据上述调试信息可以看到,此时仅仅申请了一个0x1d8大小池内存地址为ffff818d`ae55fa70,并被初始化为0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
3: kd> g
Breakpoint 1 hit
nt!AlpcpInitializePort+0x38:
fffff803`742bdff0 488d81b8000000 lea rax,[rcx+0B8h]
3: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b15f09a0 fffff803`74305b65 nt!AlpcpInitializePort+0x38
01 ffffe581`b15f09d0 fffff803`74305a28 nt!AlpcpCreateConnectionPort+0x11d
02 ffffe581`b15f0ac0 fffff803`7400caf5 nt!NtAlpcCreatePort+0x28
03 ffffe581`b15f0b00 00007ffe`ee58e014 nt!KiSystemServiceCopyEnd+0x25
04 00000039`bf2ff8f8 00007ff6`fc553fbe 0x00007ffe`ee58e014
05 00000039`bf2ff900 00007ff6`fc632838 0x00007ff6`fc553fbe
06 00000039`bf2ff908 00000000`00000000 0x00007ff6`fc632838
3: kd> dq ffff818d`ae55fa70+90
ffff818d`ae55fb00 ffff818d`ae55fb00 ffff818d`ae55fb00
ffff818d`ae55fb10 00000000`00000000 00000000`00000000
ffff818d`ae55fb20 00000000`00000000 00000000`00000000
ffff818d`ae55fb30 00000000`00000000 00000000`00000000
ffff818d`ae55fb40 00000000`00000000 00000000`00000000
ffff818d`ae55fb50 00000000`00000000 00000000`00000000
ffff818d`ae55fb60 00000000`00000000 00000000`00000000
ffff818d`ae55fb70 00000000`00000000 00000000`00000000

此时,经过AlpcpInitializePort函数,开始初始化AlpcPort结构,根据前面的静态分析,此时MainQueue成员应该被初始化为此结构地址,即ffff818d`ae55fb00。

NtAlpcConnectPortEx

NtAlpcConnectPortEx通过以下调用,将在AlpcpCompleteDispatchMessage函数中将消息结构放在MainQueue队列头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
3: kd> g
Breakpoint 1 hit
nt!AlpcpInitializePort+0x38:
fffff803`742bdff0 488d81b8000000 lea rax,[rcx+0B8h]
3: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b15f09a0 fffff803`74305b65 nt!AlpcpInitializePort+0x38
01 ffffe581`b15f09d0 fffff803`74305a28 nt!AlpcpCreateConnectionPort+0x11d
02 ffffe581`b15f0ac0 fffff803`7400caf5 nt!NtAlpcCreatePort+0x28
03 ffffe581`b15f0b00 00007ffe`ee58e014 nt!KiSystemServiceCopyEnd+0x25
04 00000039`bf2ff8f8 00007ff6`fc553fbe 0x00007ffe`ee58e014
05 00000039`bf2ff900 00007ff6`fc632838 0x00007ff6`fc553fbe
06 00000039`bf2ff908 00000000`00000000 0x00007ff6`fc632838
3: kd> dq ffff818d`ae55fa70+90
ffff818d`ae55fb00 ffff818d`ae55fb00 ffff818d`ae55fb00
ffff818d`ae55fb10 00000000`00000000 00000000`00000000
ffff818d`ae55fb20 00000000`00000000 00000000`00000000
ffff818d`ae55fb30 00000000`00000000 00000000`00000000
ffff818d`ae55fb40 00000000`00000000 00000000`00000000
ffff818d`ae55fb50 00000000`00000000 00000000`00000000
ffff818d`ae55fb60 00000000`00000000 00000000`00000000
ffff818d`ae55fb70 00000000`00000000 00000000`00000000
3: kd> g
Breakpoint 1 hit
nt!AlpcpCompleteDispatchMessage+0x1b2:
fffff803`7420a0d2 488bc3 mov rax,rbx
2: kd> !alpc /p ffff818d`ae55fa70
Port ffff818dae55fa70
Type : ALPC_CONNECTION_PORT
CommunicationInfo : ffffbe8f7490aa50
ConnectionPort : ffff818dae55fa70 (TestPort), Connections
ClientCommunicationPort : 0000000000000000
ServerCommunicationPort : 0000000000000000
OwnerProcess : ffff818dad44e080 (CVE-2023-21674), Connections
SequenceNo : 0x00000001 (1)
CompletionPort : 0000000000000000
CompletionList : 0000000000000000
ConnectionPending : No
ConnectionRefused : No
Disconnected : No
Closed : No
FlushOnClose : Yes
ReturnExtendedInfo : No
Waitable : No
Security : Static
Wow64CompletionList : No

Main queue has 1 message(s)

ffffbe8f723c9c60 000011d0 000000000000085c:0000000000000698 0000000000000000 0000000000000000 LPC_CONNECTION_REQUEST

Direct message queue is empty.


Large message queue is empty.


Pending queue is empty.


Canceled queue is empty.

2: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b15f0680 fffff803`742b9f57 nt!AlpcpCompleteDispatchMessage+0x1b2
01 ffffe581`b15f0730 fffff803`742b9b36 nt!AlpcpDispatchConnectionRequest+0x13f
02 ffffe581`b15f0780 fffff803`742bb281 nt!AlpcpProcessConnectionRequest+0x1be
03 ffffe581`b15f0890 fffff803`742b9860 nt!AlpcpConnectPort+0x2c5
04 ffffe581`b15f0a10 fffff803`7400caf5 nt!NtAlpcConnectPortEx+0x70
05 ffffe581`b15f0a90 00007ffe`ee58dff4 nt!KiSystemServiceCopyEnd+0x25
06 00000039`bf2ff8f8 00007ff6`fc55408d 0x00007ffe`ee58dff4
07 00000039`bf2ff900 00007ff6`fc632868 0x00007ff6`fc55408d
08 00000039`bf2ff908 00000000`00000000 0x00007ff6`fc632868

通过windbg提供的!alpc命令,我们也可以看到此时AlpcPort对象的队列上确实存在一个LPC_CONNECTION_REQUEST消息。

此外Connect函数还会创建ClientCommPort。我们具体查看此条消息,可以看到OwnerPort是ALPC_CLIENT_COMMUNICATION_PORT类型,也就是新创建的ClientCommPort。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2: kd> !alpc /m ffffbe8f723c9c60

Message ffffbe8f723c9c60
MessageID : 0x11D0 (4560)
CallbackID : 0x18A22 (100898)
SequenceNumber : 0x00000001 (1)
Type : LPC_CONNECTION_REQUEST
DataLength : 0x0000 (0)
TotalLength : 0x0028 (40)
Canceled : No
Release : No
ReplyWaitReply : No
Continuation : Yes
OwnerPort : ffff818dae0ed6f0 [ALPC_CLIENT_COMMUNICATION_PORT]
WaitingThread : 0000000000000000
QueueType : ALPC_MSGQUEUE_MAIN
QueuePort : ffff818dae55fa70 [ALPC_CONNECTION_PORT]
QueuePortOwnerProcess : ffff818dad44e080 (CVE-2023-21674)
ServerThread : 0000000000000000
QuotaCharged : No
CancelQueuePort : 0000000000000000
CancelSequencePort : 0000000000000000
CancelSequenceNumber : 0x00000000 (0)
ClientContext : 0000000000000000
ServerContext : 0000000000000000
PortContext : 0000000000000000
CancelPortContext : 0000000000000000
SecurityData : 0000000000000000
View : 0000000000000000
HandleData : 0000000000000000
2: kd> !alpc /p ffff818dae0ed6f0
Port ffff818dae0ed6f0
Type : ALPC_CLIENT_COMMUNICATION_PORT
CommunicationInfo : ffffbe8f7490b3e0
ConnectionPort : ffff818dae55fa70 (TestPort), Connections
ClientCommunicationPort : ffff818dae0ed6f0
ServerCommunicationPort : 0000000000000000
OwnerProcess : ffff818dad44e080 (CVE-2023-21674), Connections
SequenceNo : 0x00000000 (0)
CompletionPort : 0000000000000000
CompletionList : 0000000000000000
ConnectionPending : Yes
ConnectionRefused : No
Disconnected : No
Closed : No
FlushOnClose : Yes
ReturnExtendedInfo : No
Waitable : No
Security : Dynamic
Wow64CompletionList : No

Main queue is empty.


Direct message queue is empty.


Large message queue is empty.


Pending queue is empty.


Canceled queue is empty.

具体来说,就是ffff818dae0ed6f0,可以看到在CommunicationInfo成员中已经存在了两个Port对象。

NtAlpcSendWaitReceivePort=>NtAlpcAcceptConnectPort

第一次Reveive消息,去MainQueue队列拿消息。

此时我们查看ConnectionPort,发现消息已经被取走。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2: kd> g
Breakpoint 1 hit
nt!AlpcpReceiveMessagePort+0x516:
fffff803`7420dae6 488b0e mov rcx,qword ptr [rsi]
0: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b15f0880 fffff803`7420c9bd nt!AlpcpReceiveMessagePort+0x516
01 ffffe581`b15f08f0 fffff803`7420c4fe nt!AlpcpReceiveMessage+0x33d
02 ffffe581`b15f09d0 fffff803`7400caf5 nt!NtAlpcSendWaitReceivePort+0xfe
03 ffffe581`b15f0a90 00007ffe`ee58e234 nt!KiSystemServiceCopyEnd+0x25
04 00000039`bf2ff8f8 00007ff6`fc5540f2 0x00007ffe`ee58e234
05 00000039`bf2ff900 00007ff6`fc631fe8 0x00007ff6`fc5540f2
06 00000039`bf2ff908 00000000`00000000 0x00007ff6`fc631fe8

0: kd> !alpc /p ffff818dae55fa70
Port ffff818dae55fa70
Type : ALPC_CONNECTION_PORT
CommunicationInfo : ffffbe8f7490aa50
ConnectionPort : ffff818dae55fa70 (TestPort), Connections
ClientCommunicationPort : 0000000000000000
ServerCommunicationPort : 0000000000000000
OwnerProcess : ffff818dad44e080 (CVE-2023-21674), Connections
SequenceNo : 0x00000001 (1)
CompletionPort : 0000000000000000
CompletionList : 0000000000000000
ConnectionPending : No
ConnectionRefused : No
Disconnected : No
Closed : No
FlushOnClose : Yes
ReturnExtendedInfo : No
Waitable : No
Security : Static
Wow64CompletionList : No

Main queue is empty.


Direct message queue is empty.


Large message queue is empty.


Pending queue is empty.


Canceled queue is empty.

当Accept最后一参数bool值传入True即Allow时,将创建ServerCommPort,如下所示。

c3b4cabe-1674-4d9e-805a-f327a099f798.png

并且,向ClientCommPort发送Reply消息,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Breakpoint 2 hit
nt!AlpcpCompleteDispatchMessage+0x1b2:
fffff803`7420a0d2 488bc3 mov rax,rbx
3: kd> bl
0 e Disable Clear fffff803`74305b1d 0001 (0001) nt!AlpcpCreateConnectionPort+0xd5
1 e Disable Clear ffff818d`ae55fb00 w 1 0001 (0001)
2 e Disable Clear ffff818d`ae0ed780 w 1 0001 (0001)
3 e Disable Clear ffffbe8f`7490b3e8 w 1 0001 (0001)
4 e Disable Clear ffff818d`ae3e6b10 w 1 0001 (0001)

3: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b15f0650 fffff803`742bcc5a nt!AlpcpCompleteDispatchMessage+0x1b2
01 ffffe581`b15f0700 fffff803`742bceae nt!AlpcpDispatchReplyToPort+0x2d6
02 ffffe581`b15f0760 fffff803`742bbe83 nt!AlpcpDispatchMessage+0x26
03 ffffe581`b15f0790 fffff803`742bb436 nt!AlpcpAcceptConnectPort+0xa2b
04 ffffe581`b15f0a20 fffff803`7400caf5 nt!NtAlpcAcceptConnectPort+0x76
05 ffffe581`b15f0a90 00007ffe`ee58df94 nt!KiSystemServiceCopyEnd+0x25
06 00000039`bf2ff8f8 00007ff6`fc554141 0x00007ffe`ee58df94
07 00000039`bf2ff900 00007ff6`fc631f80 0x00007ff6`fc554141
08 00000039`bf2ff908 00000000`00000000 0x00007ff6`fc631f80
3: kd> !alpc /p ffff818dae0ed6f0
Port ffff818dae0ed6f0
Type : ALPC_CLIENT_COMMUNICATION_PORT
CommunicationInfo : ffffbe8f7490b3e0
ConnectionPort : ffff818dae55fa70 (TestPort), Connections
ClientCommunicationPort : ffff818dae0ed6f0
ServerCommunicationPort : ffff818dae3e6a80
OwnerProcess : ffff818dad44e080 (CVE-2023-21674), Connections
SequenceNo : 0x00000001 (1)
CompletionPort : 0000000000000000
CompletionList : 0000000000000000
ConnectionPending : No
ConnectionRefused : No
Disconnected : No
Closed : No
FlushOnClose : Yes
ReturnExtendedInfo : No
Waitable : No
Security : Dynamic
Wow64CompletionList : No

Main queue has 1 message(s)

ffffbe8f723c9c60 000011d0 000000000000085c:0000000000000698 0000000000000000 0000000000000000 LPC_CONNECTION_REPLY

Direct message queue is empty.


Large message queue is empty.


Pending queue is empty.


Canceled queue is empty.

CreateThread=>NtWaitForWorkViaWorkerFactory

接下来在线程工厂中,工作现场调用NtWaitForWorkViaWorkerFactory函数,实际上向ConnectionPort发送消息,立即返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
3: kd> g
Breakpoint 1 hit
nt!AlpcpCompleteDispatchMessage+0x1b2:
fffff803`7420a0d2 488bc3 mov rax,rbx
1: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b1b33610 fffff803`74209e94 nt!AlpcpCompleteDispatchMessage+0x1b2
01 ffffe581`b1b336c0 fffff803`74209b6f nt!AlpcpDispatchNewMessage+0x2d4
02 ffffe581`b1b33720 fffff803`73e16d91 nt!AlpcpSendMessage+0x9ff
03 ffffe581`b1b33860 fffff803`7400caf5 nt!NtWaitForWorkViaWorkerFactory+0x6e1
04 ffffe581`b1b33a90 00007ffe`ee590b14 nt!KiSystemServiceCopyEnd+0x25
05 00000039`bf3ffc88 00007ff6`fc553a40 0x00007ffe`ee590b14
06 00000039`bf3ffc90 00007ff6`fc675034 0x00007ff6`fc553a40
07 00000039`bf3ffc98 cccccccc`cccccccc 0x00007ff6`fc675034
08 00000039`bf3ffca0 cccccccc`cccccccc 0xcccccccc`cccccccc
09 00000039`bf3ffca8 cccccccc`cccccccc 0xcccccccc`cccccccc
0a 00000039`bf3ffcb0 00000039`bf3ffd08 0xcccccccc`cccccccc
0b 00000039`bf3ffcb8 cccccccc`cccccccc 0x00000039`bf3ffd08
0c 00000039`bf3ffcc0 cccccccc`cccccccc 0xcccccccc`cccccccc
0d 00000039`bf3ffcc8 00000000`00000000 0xcccccccc`cccccccc
1: kd> !alpc /p ffff818dae55fa70
Port ffff818dae55fa70
Type : ALPC_CONNECTION_PORT
CommunicationInfo : ffffbe8f7490aa50
ConnectionPort : ffff818dae55fa70 (TestPort), Connections
ClientCommunicationPort : 0000000000000000
ServerCommunicationPort : 0000000000000000
OwnerProcess : ffff818dad44e080 (CVE-2023-21674), Connections
SequenceNo : 0x00000001 (1)
CompletionPort : 0000000000000000
CompletionList : 0000000000000000
ConnectionPending : No
ConnectionRefused : No
Disconnected : No
Closed : No
FlushOnClose : Yes
ReturnExtendedInfo : No
Waitable : No
Security : Static
Wow64CompletionList : No

Main queue has 1 message(s)

ffffbe8f7200bc90 00001494 000000000000085c:0000000000000f24 ffff818dae171080 0000000000000000 LPC_REQUEST

Direct message queue is empty.


Large message queue is empty.


Pending queue is empty.


Canceled queue is empty.

当我们具体查看此消息时,发现已经绑定了当前工作线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1: kd> !alpc /m ffffbe8f7200bc90

Message ffffbe8f7200bc90
MessageID : 0x1494 (5268)
CallbackID : 0x18A27 (100903)
SequenceNumber : 0x00000001 (1)
Type : LPC_REQUEST
DataLength : 0x0000 (0)
TotalLength : 0x0028 (40)
Canceled : No
Release : No
ReplyWaitReply : No
Continuation : Yes
OwnerPort : ffff818dae0ed6f0 [ALPC_CLIENT_COMMUNICATION_PORT]
WaitingThread : ffff818dae171080
QueueType : ALPC_MSGQUEUE_MAIN
QueuePort : ffff818dae55fa70 [ALPC_CONNECTION_PORT]
QueuePortOwnerProcess : ffff818dad44e080 (CVE-2023-21674)
ServerThread : 0000000000000000
QuotaCharged : No
CancelQueuePort : 0000000000000000
CancelSequencePort : 0000000000000000
CancelSequenceNumber : 0x00000000 (0)
ClientContext : 0000000000000000
ServerContext : 0000000000000000
PortContext : 00000000000000ac
CancelPortContext : 0000000000000000
SecurityData : 0000000000000000
View : 0000000000000000
HandleData : 0000000000000000

此时,我们查看线程内存属性,此时线程句柄尚未关闭。

1
2
3
4
5
6
7
1: kd> !pool ffff818dae171080
unable to get nt!PspSessionIdBitmap
Pool page ffff818dae171080 region is Nonpaged pool
*ffff818dae171000 size: a00 previous size: 0 (Allocated) *Thre
Pooltag Thre : Thread objects, Binary : nt!ps
ffff818dae171a10 size: 480 previous size: 0 (Allocated) Via5
ffff818dae171e90 size: 150 previous size: 0 (Free) ..FB

NtAlpcSendWaitReceivePort=>NtClose

接着接受前面的消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
1: kd> g
Breakpoint 1 hit
nt!AlpcpReceiveMessagePort+0x516:
fffff803`7420dae6 488b0e mov rcx,qword ptr [rsi]
3: kd> k
# Child-SP RetAddr Call Site
00 ffffe581`b15f0880 fffff803`7420c9bd nt!AlpcpReceiveMessagePort+0x516
01 ffffe581`b15f08f0 fffff803`7420c4fe nt!AlpcpReceiveMessage+0x33d
02 ffffe581`b15f09d0 fffff803`7400caf5 nt!NtAlpcSendWaitReceivePort+0xfe
03 ffffe581`b15f0a90 00007ffe`ee58e234 nt!KiSystemServiceCopyEnd+0x25
04 00000039`bf2ff8f8 00007ff6`fc554282 0x00007ffe`ee58e234
05 00000039`bf2ff900 00007ff6`fc632010 0x00007ff6`fc554282
06 00000039`bf2ff908 00000000`00000000 0x00007ff6`fc632010
3: kd> !alpc /p ffff818dae3e6a80
Port ffff818dae3e6a80
Type : ALPC_SERVER_COMMUNICATION_PORT
CommunicationInfo : ffffbe8f7490b3e0
ConnectionPort : ffff818dae55fa70 (TestPort), Connections
ClientCommunicationPort : ffff818dae0ed6f0
ServerCommunicationPort : ffff818dae3e6a80
OwnerProcess : ffff818dad44e080 (CVE-2023-21674), Connections
SequenceNo : 0x00000001 (1)
CompletionPort : 0000000000000000
CompletionList : 0000000000000000
ConnectionPending : No
ConnectionRefused : No
Disconnected : No
Closed : No
FlushOnClose : Yes
ReturnExtendedInfo : No
Waitable : No
Security : Static
Wow64CompletionList : No

Main queue is empty.


Direct message queue is empty.


Large message queue is empty.


Pending queue is empty.


Canceled queue is empty.

3: kd> !alpc /m ffffbe8f7200bc90

Message ffffbe8f7200bc90
MessageID : 0x1494 (5268)
CallbackID : 0x18A27 (100903)
SequenceNumber : 0x00000001 (1)
Type : LPC_REQUEST
DataLength : 0x0000 (0)
TotalLength : 0x0028 (40)
Canceled : No
Release : No
ReplyWaitReply : No
Continuation : Yes
OwnerPort : ffff818dae0ed6f0 [ALPC_CLIENT_COMMUNICATION_PORT]
WaitingThread : ffff818dae171080
QueueType : ALPC_MSGQUEUE_NONE
QueuePort : 0000000000000000 []
QueuePortOwnerProcess : 0000000000000000 ()
ServerThread : 0000000000000000
QuotaCharged : No
CancelQueuePort : 0000000000000000
CancelSequencePort : 0000000000000000
CancelSequenceNumber : 0x00000000 (0)
ClientContext : 0000000000000000
ServerContext : 0000000000000000
PortContext : 00000000000000ac
CancelPortContext : 0000000000000000
SecurityData : 0000000000000000
View : 0000000000000000
HandleData : 0000000000000000

返回用户态,关闭工作线程句柄。

1
2
3
4
3: kd> !pool ffff818dae171080
Pool page ffff818dae171080 region is Nonpaged pool
ffff818dae171a10 size: 480 previous size: 0 (Allocated) Via5
ffff818dae171e90 size: 150 previous size: 0 (Free) ..FB

原先内存将被释放或者重新使用,如上所示。

触发UAF=>NtAlpcImpersonateClientOfPort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
3: kd> g
Breakpoint 6 hit
nt!NtAlpcImpersonateClientOfPort:
fffff803`7420e420 4c8bdc mov r11,rsp
3: kd> !thread -1
THREAD ffff818dae2d6080 Cid 085c.0698 Teb: 00000039bf0d9000 Win32Thread: 0000000000000000 RUNNING on processor 3
Not impersonating
DeviceMap ffffbe8f716594d0
Owning Process ffff818dad44e080 Image: CVE-2023-21674.exe
Attached Process N/A Image: N/A
Wait Start TickCount 49270 Ticks: 32 (0:00:00:00.500)
Context Switch Count 16 IdealProcessor: 3
UserTime 00:00:00.000
KernelTime 00:00:00.015
Win32 Start Address 0x00007ff6fc54d25d
Stack Init ffffe581b15f0c90 Current ffffe581b15f0770
Base ffffe581b15f1000 Limit ffffe581b15eb000 Call 0000000000000000
Priority 8 BasePriority 8 IoPriority 2 PagePriority 5
Child-SP RetAddr : Args to Child : Call Site
ffffe581`b15f0af8 fffff803`7400caf5 : 00000000`00000000 00000000`00000000 ffffffff`ffb3b4c0 00000000`00000000 : nt!NtAlpcImpersonateClientOfPort
ffffe581`b15f0b00 00007ffe`ee58e174 : 00007ff6`fc5542c5 00007ff6`fc632060 00000000`00000000 00000039`00000000 : nt!KiSystemServiceCopyEnd+0x25 (TrapFrame @ ffffe581`b15f0b00)
00000039`bf2ff8f8 00007ff6`fc5542c5 : 00007ff6`fc632060 00000000`00000000 00000039`00000000 00000000`00000000 : 0x00007ffe`ee58e174
00000039`bf2ff900 00007ff6`fc632060 : 00000000`00000000 00000039`00000000 00000000`00000000 00000039`bf2ffac8 : 0x00007ff6`fc5542c5
00000039`bf2ff908 00000000`00000000 : 00000039`00000000 00000000`00000000 00000039`bf2ffac8 00000000`00000000 : 0x00007ff6`fc632060

3: kd> !pool ffff818dae171080
Pool page ffff818dae171080 region is Nonpaged pool
ffff818dae171a10 size: 480 previous size: 0 (Allocated) Via5
ffff818dae171e90 size: 150 previous size: 0 (Free) ..FB
3: kd> bp 0xfffff8037420e558
3: kd> g
Breakpoint 5 hit
nt!NtAlpcImpersonateClientOfPort+0x138:
fffff803`7420e558 e883ccffff call nt!AlpcpLookupMessage (fffff803`7420b1e0)
3: kd> dq @rax
ffffe581`b15f0a70 00000000`00000000 00000000`00000000
ffffe581`b15f0a80 00000001`cb29f648 fffff803`7400caf5
ffffe581`b15f0a90 00000000`00000000 00000000`00000000
ffffe581`b15f0aa0 00000000`00000000 00000000`00000000
ffffe581`b15f0ab0 00000000`00000000 ffffe581`b15f0b80
ffffe581`b15f0ac0 ffff818d`ae2d6080 fffff803`7420e423
ffffe581`b15f0ad0 00000000`00000000 00000000`00000000
ffffe581`b15f0ae0 00000000`00000000 00000000`00000000
3: kd> p
nt!NtAlpcImpersonateClientOfPort+0x13d:
fffff803`7420e55d 448bf0 mov r14d,eax
3: kd> dq ffffe581`b15f0a70
ffffe581`b15f0a70 ffffbe8f`7200bc90 00000000`00000000
ffffe581`b15f0a80 00000001`cb29f648 fffff803`7400caf5
ffffe581`b15f0a90 00000000`00000000 00000000`00000000
ffffe581`b15f0aa0 00000000`00000000 00000000`00000000
ffffe581`b15f0ab0 00000000`00000000 ffffe581`b15f0b80
ffffe581`b15f0ac0 ffff818d`ae2d6080 fffff803`7420e423
ffffe581`b15f0ad0 00000000`00000000 00000000`00000000
ffffe581`b15f0ae0 00000000`00000000 00000000`00000000
3: kd> !alpc /m ffffbe8f`7200bc90

Message ffffbe8f7200bc90
MessageID : 0x1494 (5268)
CallbackID : 0x18A27 (100903)
SequenceNumber : 0x00000001 (1)
Type : LPC_REQUEST
DataLength : 0x0000 (0)
TotalLength : 0x0028 (40)
Canceled : No
Release : No
ReplyWaitReply : No
Continuation : Yes
OwnerPort : ffff818dae0ed6f0 [ALPC_CLIENT_COMMUNICATION_PORT]
WaitingThread : ffff818dae171080
QueueType : ALPC_MSGQUEUE_PENDING
QueuePort : ffff818dae55fa70 [ALPC_CONNECTION_PORT]
QueuePortOwnerProcess : ffff818dad44e080 (CVE-2023-21674)
ServerThread : ffff818dae2d6080
QuotaCharged : No
CancelQueuePort : 0000000000000000
CancelSequencePort : 0000000000000000
CancelSequenceNumber : 0x00000000 (0)
ClientContext : 0000000000000000
ServerContext : 0000000000000000
PortContext : 00000000000000ac
CancelPortContext : 0000000000000000
SecurityData : 0000000000000000
View : 0000000000000000
HandleData : 0000000000000000
3: kd> bp 0xfffff8037420e6d6
3: kd> g
Breakpoint 7 hit
nt!AlpcpImpersonateMessage+0xe6:
fffff803`7420e6d6 488b4f20 mov rcx,qword ptr [rdi+20h]
3: kd> u
nt!AlpcpImpersonateMessage+0xe6:
fffff803`7420e6d6 488b4f20 mov rcx,qword ptr [rdi+20h]
fffff803`7420e6da 4885c9 test rcx,rcx
fffff803`7420e6dd 0f8455010000 je nt!AlpcpImpersonateMessage+0x248 (fffff803`7420e838)
fffff803`7420e6e3 4585e4 test r12d,r12d
fffff803`7420e6e6 0f856bce1d00 jne nt!AlpcpImpersonateMessage+0x1dcf67 (fffff803`743eb557)
fffff803`7420e6ec 4533c0 xor r8d,r8d
fffff803`7420e6ef 488d9004010000 lea rdx,[rax+104h]
fffff803`7420e6f6 4c8d8c2490000000 lea r9,[rsp+90h]
3: kd>
nt!AlpcpImpersonateMessage+0x10e:
fffff803`7420e6fe 395c2430 cmp dword ptr [rsp+30h],ebx
fffff803`7420e702 0f851b010000 jne nt!AlpcpImpersonateMessage+0x233 (fffff803`7420e823)
fffff803`7420e708 e803760100 call nt!SeCreateClientSecurity (fffff803`74225d10)
fffff803`7420e70d 8bf8 mov edi,eax
fffff803`7420e70f 85c0 test eax,eax
fffff803`7420e711 785c js nt!AlpcpImpersonateMessage+0x17f (fffff803`7420e76f)
fffff803`7420e713 488d9c2490000000 lea rbx,[rsp+90h]
fffff803`7420e71b 41bf01000000 mov r15d,1
3: kd> dq @rdi
ffffbe8f`7200bc90 ffff818d`ae55fb28 ffff818d`ae55fb28
ffffbe8f`7200bca0 ffff818d`ae55fa70 ffff818d`ae0ed6f0
ffffbe8f`7200bcb0 ffff818d`ae171080 00000001`0000100b
ffffbe8f`7200bcc0 00000000`00000000 00000000`00000000
ffffbe8f`7200bcd0 00000000`00000000 00000000`00000000
ffffbe8f`7200bce0 00000000`00000000 00000000`00000000
ffffbe8f`7200bcf0 00000000`00000000 00000000`00000000
ffffbe8f`7200bd00 00000000`00000000 00000000`000000ac

此时,正如静态分析所述,将拿出Message–>WaitingThread成员,将在SeCreateClientSecurity访问,导致UAF。

只有一种触发方式?Yes!

现在需要解开前面卖的关子。前面的静态分析和调试,其实一直没有注意到内核消息构造的过程中,KThread指针和Message结构是如何关联的。

1
2
3
4
5
__int64 __fastcall AlpcpSendMessage(
REQUEST_CONTEXT *RequestContext,
__m256i *UniqueThread,
int *a3,
__int64 AccessMode)

注意AlpcpSendMessage的第一参数,实际上是我们前面提到的REQUEST_CONTEXT结构,后续继续调用 AlpcpDispatchNewMessage函数时,同样使用REQUEST_CONTEXT结构。

d6df13df114d05146d190428d556722c.png

而在内部调用AlpcpCompleteDispatchMessage完成最终的消息投递之前,会判断Flag & 0x20000是否为真,为真才将当前内核线程结构放入Message结构。

因此对于其他的交叉引用,大部分函数的调用是直接制定了Flag,即就是不为0x20000标志。

例如①LpcRequest函数。

cf702ab32ebb605dec2d75b6fe03a879.png

②NtRequest函数。

f3103e5110753b7599e7110b2c870638.png③NtReplyWaitReceivePortEx函数

49e645292a87702856011b3898ee3ccd.png

以及④NtReplyPort函数。

2a29fc6d875c1419b3928f799fb81b64.png

如前所述,均指定了flag的值,因此无法后续造成UAF。

而对于未指定flag值的调用,例如 NtAlpcSendWaitReceivePort函数,我一开始觉得依旧可以造成UAF。

5ed538a487ff095c9419c0a41a5963b5.png

但是更进一步的静态分析以及经过测试代码测试,是无法完成的。原因在于NtAlpcSendWaitReceivePort如下所示的代码中,是不存在只进行Send操作的逻辑的,即只能发送完等待或者返回错误,如下所示。

65afa02cd84ab186955c3d263028ae23.png

而有没有这样一种思路,即手动停止线程结束Recv等待,因为我们Send消息并且绑定线程指针的目的已经达到了。

实际上这个思路也是行不通的,根据测试以及静态分析来看,当线程停止等待时,会手动将WaitingThread成员置为空。

a277da1720dcb7b5aa774d894a239c69.png

因此,到现在谜底解开,这也是为什么avast原始POC使用线程工厂的原因,因为只有这一种方法可以保证只发送消息后立即返回。

演示

在对NT模块开启Verifier校验后,运行poc将造成BSOD。

22.gif

补丁

2023年1月微软的补丁中,做出了如下修正。

cfde2daf399650b8139e0d526e2d4ca6.png

可以看到是对两处函数做出了修正。

NtWaitForWorkViaWorkerFactory

24674bc80efc7921c4ce2c4a9c545d2b.png

对flag = 0x20000时作出严格判断。

 AlpcpCreateClientPort

8ddec775b6eccc9847d56bf3e7771d46.png

传参做了改变,通过查看前后逻辑,此处修改似乎是因为以前传入的参数实际并未在内部使用,因此此次更新进行了修正,实际与此漏洞的修补无关。

参考链接

[1]https://msrc.microsoft.com/update-guide/vulnerability/CVE-2023-21674

[2]https://twitter.com/theori_io/status/1764544922005430576

[3]https://ti.dbappsecurity.com.cn/vul/DAS-T104708

[4]https://csandker.io/2022/05/24/Offensive-Windows-IPC-3-ALPC.html

[5]https://i.blackhat.com/Asia-22/Friday-Materials/AS-22-Xu-The-Next-Generation-of-Windows-Exploitation-Attacking-the-Common-Log-File-System.pdf

[6]https://github.com/hd3s5aa/CVE-2023-21674

[7]Windows Internals, Part 2, 7th Edition (Andrea Allievi, Alex Ionescu, Mark Russinovich etc.)