static Bool
DnDCPMsgV4IsPacketValid(const uint8 *packet,
size_t packetSize)
{
DnDCPMsgHdrV4 *msgHdr = NULL;
ASSERT(packet);
if (packetSize < DND_CP_MSG_HEADERSIZE_V4) {
return FALSE;
}
msgHdr = (DnDCPMsgHdrV4 *)packet;
/* Payload size is not valid. */
if (msgHdr->payloadSize > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
return FALSE;
}
/* Binary size is not valid. */
if (msgHdr->binarySize > DND_CP_MSG_MAX_BINARY_SIZE_V4) {
return FALSE;
}
/* Payload size is more than binary size. */
if (msgHdr->payloadOffset + msgHdr->payloadSize > msgHdr->binarySize) {//[1]
return FALSE;
}
return TRUE;
}
Bool
DnDCPMsgV4_UnserializeMultiple(DnDCPMsgV4 *msg,
const uint8 *packet,
size_t packetSize)
{
DnDCPMsgHdrV4 *msgHdr = NULL;
ASSERT(msg);
ASSERT(packet);
if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
return FALSE;
}
msgHdr = (DnDCPMsgHdrV4 *)packet;
/*
* For each session, there is at most 1 big message. If the received
* sessionId is different with buffered one, the received packet is for
* another another new message. Destroy old buffered message.
*/
if (msg->binary &&
msg->hdr.sessionId != msgHdr->sessionId) {
DnDCPMsgV4_Destroy(msg);
}
/* Offset should be 0 for new message. */
if (NULL == msg->binary && msgHdr->payloadOffset != 0) {
return FALSE;
}
/* For existing buffered message, the payload offset should match. */
if (msg->binary &&
msg->hdr.sessionId == msgHdr->sessionId &&
msg->hdr.payloadOffset != msgHdr->payloadOffset) {
return FALSE;
}
if (NULL == msg->binary) {
memcpy(msg, msgHdr, DND_CP_MSG_HEADERSIZE_V4);
msg->binary = Util_SafeMalloc(msg->hdr.binarySize);
}
/* msg->hdr.payloadOffset is used as received binary size. */
memcpy(msg->binary + msg->hdr.payloadOffset, //[2]
packet + DND_CP_MSG_HEADERSIZE_V4,
msgHdr->payloadSize);
msg->hdr.payloadOffset += msgHdr->payloadSize;
return TRUE;
}
对于Dnd/CP version 4的功能中,当guest发送分片Dnd/CP命令数据包时,会调用DnDCPMsgV4_UnserializeMultiple函数进行分片重组,重组的时候 DnDCPMsgV4IsPacketValid函数中的[1]处代码校验不严格,会导致[2]处堆溢出,可以构造如下的数据包来触发漏洞