-
IncomingCallRequest – 客户端用于请求新的传入虚拟呼叫请求。
-
IncomingCallReply – 由服务器发送用于表示自己是否正在接受虚拟呼叫。它还设置用于跟踪呼叫请求的请求 ID(Call ID)。
-
IncomingCallConnected – 客户端使用它来确认虚拟呼叫的连接并让服务器对其进行完全初始化以准备发送网络数据。
StartControlConnectionRequest() Client -> Server
StartControlConnectionReply() Server -> Client
IncomingCallRequest() Client -> Server
IncomingCallReply() Server -> Client
IncomingCallConnected() Client -> Server
IncomingCallConnected() Client -> Server
void __fastcall PptpCmRegSapPassive(__int64 a1)
{
...
v3 = PptpInitialize(CallMgrAfContext); // 创建第一个socket,可能是GRE的socket?
if ( v3
&& WPP_GLOBAL_Control != (PDEVICE_OBJECT)&WPP_GLOBAL_Control
&& (HIDWORD(WPP_GLOBAL_Control->Timer) & 4) != 0
&& BYTE1(WPP_GLOBAL_Control->Timer) )
{
WPP_SF_(WPP_GLOBAL_Control->AttachedDevice, 26i64, &WPP_a989452d2ce136f272e3b9b86b31e890_Traceguids);
}
v4 = CtlListen(CallMgrAfContext);
if ( v4 )
{
if ( WPP_GLOBAL_Control != (PDEVICE_OBJECT)&WPP_GLOBAL_Control
&& (HIDWORD(WPP_GLOBAL_Control->Timer) & 4) != 0
&& BYTE1(WPP_GLOBAL_Control->Timer) )
{
WPP_SF_(WPP_GLOBAL_Control->AttachedDevice, 27i64, &WPP_a989452d2ce136f272e3b9b86b31e890_Traceguids);
}
if ( v4 < 0 )
goto LABEL_38;
}
...
}
__int64 __fastcall CtlListen(__int64 CallMgrAfContext)
{
...
WORD1(v10) = __ROR2__(PptpControlPort, 8); // 看样子是端口号码,固定的
WORD1(v11) = WORD1(v10);
LOWORD(v10) = 2;
v9 = (__int64)&v10;
v7[0] = 1;
v8 = 1i64;
v7[1] = 6;
SockContext = (__int64)WskCreateAndIntializeSockContext();
v5 = SockContext;
if ( SockContext )
{
*(_QWORD *)(SockContext + 8) = CallMgrAfContext;
*(_QWORD *)(SockContext + 32) = CtlConnectQueryCallback;
*(_QWORD *)(SockContext + 24) = CtlDisconnectCallback;
*(_QWORD *)(SockContext + 16) = CtlReceiveCallback;
*(_QWORD *)(SockContext + 64) = CtlpSendMessageComplete;
*(_QWORD *)(SockContext + 72) = CallMgrAfContext + 96;
*(_QWORD *)(SockContext + 48) = CtlLogWskLibActivity;
ServerSocket = WskCreateServerSocket((__int64)v7, v4, SockContext);
if ( (ServerSocket & 0x80000000) == 0 )
*(_QWORD *)(CallMgrAfContext + 56) = v5;
else
WskDestroySockContext(v5);
}
else
{
ServerSocket = 0xC000009A;
if ( WPP_GLOBAL_Control == (PDEVICE_OBJECT)&WPP_GLOBAL_Control )
return ServerSocket;
if ( (HIDWORD(WPP_GLOBAL_Control->Timer) & 8) != 0 && BYTE1(WPP_GLOBAL_Control->Timer) )
WPP_SF_d(
WPP_GLOBAL_Control->AttachedDevice,
88i64,
&WPP_be37cabcf8053ca2192e70b03bf2a59b_Traceguids,
0xC000009Ai64);
}
...
}
... <- (Windows Bug check handling)
NDIS!NdisMCmActivateVc+0x2d
raspptp!CallEventCallInConnect+0x71
raspptp!CtlpEngine+0xe63
raspptp!CtlReceiveCallback+0x4b
... <- (TCP/IP Handling)
case IncomingCallConnected:
// Ensure the client has sent a valid StartControlConnectionRequest message
if ( lpPptpCtlCx->CtlCurrentState == CtlStateWaitStop )
{
// BigEndian To LittleEndian Conversion
CallIdSentInReply = (unsigned __int16)__ROR2__(lpCtlPayloadBuffer->IncomingCallConnected.PeersCallId, 8);
if ( PptpClientSide ) // If we are the client
CallIdSentInReply &= 0x3FFFu; // Maximum ID mask
// Get the context structure for this call ID if it exists
IncomingCallCallCtx = CallGetCall(lpPptpCtlCx->pPptpAdapterCtx, CallIdSentInReply);
// Handle the incoming call connected event
if ( IncomingCallCallCtx )
CallEventCallInConnect(IncomingCallCallCtx, lpCtlPayloadBuffer);
__int64 __fastcall CallEventCallInConnect(CtlCall *IncomingCallCallCtx, CtlMsgStructs *IncomingCallMsg)
{
unsigned int ActiveateVcRetCode;
...
ActiveateVcRetCode = NdisMCmActivateVc(lpCallCtx->NdisVcHandle, (PCO_CALL_PARAMETERS)lpCallCtx->CallParams);
if ( ActiveateVcRetCode != STATUS_PENDING )
{
if...
PptpCmActivateVcComplete(ActiveateVcRetCode, lpCallCtx, (PVOID)lpCallCtx->CallParams);
}
return 0i64;
}
...
NDIS_STATUS __stdcall NdisMCmActivateVc(NDIS_HANDLE NdisVcHandle, PCO_CALL_PARAMETERS CallParameters)
{
__int64 v2; // rbx
PCO_CALL_PARAMETERS lpCallParameters; // rdi
KIRQL OldIRQL; // al
_CO_MEDIA_PARAMETERS *lpMediaParameters; // rcx
__int64 v6; // rcx
v2 = *((_QWORD *)NdisVcHandle + 9);
lpCallParameters = CallParameters;
OldIRQL = KeAcquireSpinLockRaiseToDpc((PKSPIN_LOCK)(v2 + 8));
*(_DWORD *)(v2 + 4) |= 1u;
lpMediaParameters = lpCallParameters->MediaParameters;
if ( lpMediaParameters->MediaSpecific.Length < 8 )
v6 = (unsigned int)v2;
else
v6 = *(_QWORD *)lpMediaParameters->MediaSpecific.Parameters;
*(_QWORD *)(v2 + 136) = v6;
*(_QWORD *)(v2 + 136) = *(_QWORD *)lpCallParameters->MediaParameters->MediaSpecific.Parameters;
KeReleaseSpinLock((PKSPIN_LOCK)(v2 + 8), OldIRQL);
return 0;
}
void __fastcall PptpCmActivateVcComplete(unsigned int OutGoingCallReplyStatusCode, CtlCall *CallContext, PVOID CallParams)
{
CtlCall *lpCallContext; // rdi
...
if ( lpCallContext->UnkownFlag )
{
if ( lpCallParams )
ExFreePoolWithTag((PVOID)lpCallContext->CallParams, 0);
lpCallContext->CallParams = 0i64;
...
https://labs.nettitude.com/blog/cve-2022-23253-windows-vpn-remote-kernel-null-pointer-dereference/
原文始发于微信公众号(山石网科安全技术研究院):Microsoft VPN远程代码执行漏洞分析1-CVE-2022-23252
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论