/// <summary> /// Decode Slow-Path Update PDU including Slow-Path Graphics Update PDU and Slow-Path Pointer Update PDU. /// </summary> /// <param name="data">data to be parsed</param> /// <param name="decryptedUserData">decrypted user data to be parsed</param> /// <param name="type">security header type</param> /// <returns>decoded Slow-Path Update PDU</returns> public StackPacket DecodeSlowPathInputEventPDU( byte[] data, byte[] decryptedUserData, SecurityHeaderType type) { TS_INPUT_PDU pdu = new TS_INPUT_PDU(); // data index int dataIndex = 0; // SlowPathOutputPDU: commonHeader pdu.commonHeader = ParseMcsCommonHeader(data, ref dataIndex, type); // user data index int userDataIndex = 0; // SlowPathOutputPDU: slowPathUpdates pdu.shareDataHeader = ParseTsShareDataHeader(decryptedUserData, ref userDataIndex); pdu.numberEvents = ParseUInt16(decryptedUserData, ref userDataIndex, false); pdu.pad2Octets = ParseUInt16(decryptedUserData, ref userDataIndex, false); pdu.slowPathInputEvents = new Collection<TS_INPUT_EVENT>(); // ETW Provider Dump Message if (pdu.commonHeader.securityHeader != null) { // RDP Standard Security string messageName = "RDPBCGR:" + pdu.GetType().Name; ExtendedLogger.DumpMessage(messageName, RdpbcgrUtility.DumpLevel_Layer3, pdu.GetType().Name, decryptedUserData); } while (userDataIndex < decryptedUserData.Length) { pdu.slowPathInputEvents.Add(ParseSlowPathInputEvent(decryptedUserData, ref userDataIndex)); } // Check if data length exceeded expectation VerifyDataLength(decryptedUserData.Length, userDataIndex, ConstValue.ERROR_MESSAGE_DATA_LENGTH_EXCEEDED); return pdu; }
/// <summary> /// /// </summary> /// <param name="inputPdu"></param> public void VerifyPdu(TS_INPUT_PDU inputPdu) { int versionLow = inputPdu.shareDataHeader.shareControlHeader.pduType.typeAndVersionLow>>4&0x0F; site.CaptureRequirementIfAreEqual<int>(1, versionLow, 1542, @"In TS_SHARECONTROLHEADER structure, for PduType's subfield, versionLow field MUST be set to TS_PROTOCOL_VERSION (0x1)."); // not capture 1543 //CaptureRequirement(inputPdu.shareDataHeader.shareControlHeader.pduType.versionHigh == 0, 1543); site.CaptureRequirementIfAreEqual<versionHigh_Values>(versionHigh_Values.V1, inputPdu.shareDataHeader.shareControlHeader.pduType.versionHigh, 1544, @"In TS_SHARECONTROLHEADER, for PduType's subfield, the versionHigh field must be 1 byte which is the most " + @"significant byte of pduType field."); site.CaptureRequirementIfIsTrue(inputPdu.shareDataHeader.streamId == streamId_Values.STREAM_UNDEFINED || inputPdu.shareDataHeader.streamId == streamId_Values.STREAM_LOW || inputPdu.shareDataHeader.streamId == streamId_Values.STREAM_MED || inputPdu.shareDataHeader.streamId == streamId_Values.STREAM_HI, 1554, @"In TS_SHAREDATAHEADER structure, the streamId can be the following: STREAM_UNDEFINED 0x00 ,STREAM_LOW" + @" 0x01,STREAM_MED 0x02,STREAM_HI 0x04"); //R1612 cannot be verified if( inputPdu.commonHeader.securityHeader != null && (inputPdu.commonHeader.securityHeader.flags & TS_SECURITY_HEADER_flags_Values.SEC_FLAGSHI_VALID ) == TS_SECURITY_HEADER_flags_Values.SEC_FLAGSHI_VALID ) CaptureRequirement(inputPdu.commonHeader.securityHeader.flagsHi != 0, 1611); if (inputPdu.commonHeader.securityHeader is TS_SECURITY_HEADER2) { TS_SECURITY_HEADER2 header2 = (TS_SECURITY_HEADER2)inputPdu.commonHeader.securityHeader; site.CaptureRequirementIfAreEqual<TS_SECURITY_HEADER2_length_Values>(TS_SECURITY_HEADER2_length_Values.V1, header2.length, 1619, @"The TS_SECURITY_HEADER2 structure,the length field MUST be set to 0x0010 (16 bytes) for legacy reasons."); //have defined ConstValue.TSFIPS_VERSION1 in sdk site.CaptureRequirementIfAreEqual<byte>(1, header2.version, 1621, @"In TS_SECURITY_HEADER2 structure,the version field SHOULD be set to TSFIPS_VERSION1 (0x01)."); } //2.2.8.1.1.3 if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT || serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT || serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT) { site.CaptureRequirementIfIsInstanceOfType(inputPdu.commonHeader.securityHeader, typeof(TS_SECURITY_HEADER1), 1630, @"In Client Input Event PDU (TS_INPUT_PDU), If Standard RDP Security is in effect and the " + @"Encryption Method selected by the server is greater than ENCRYPTION_METHOD_NONE (0)," + @" then this securityHeader field will contain Non-FIPS Security Header (section 2.2.8.1.1.2.2)" + @" if the Encryption Level Method selected by the server (see sections 5.3.2 and 2.2.1.4.3)" + @" is ENCRYPTION_LEVEL_LOW (1METHOD_40BIT (0x00000001), ENCRYPTION_LEVEL_CLIENT_COMPATIBLE" + @" (2METHOD_56BIT (0x00000008), or ENCRYPTION_LEVEL_HIGH (3). METHOD_128BIT (0x00000002)."); } else if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS) { site.CaptureRequirementIfIsInstanceOfType(inputPdu.commonHeader.securityHeader, typeof(TS_SECURITY_HEADER2), 1631, @"In Client Input Event PDU (TS_INPUT_PDU),If Standard RDP Security is in effect and the " + @"Encryption Method selected by the server is greater than ENCRYPTION_METHOD_NONE (0)," + @" then this securityHeader field will contain FIPS Security Header (section 2.2.8.1.1.2.3)" + @" if the Encryption LevelMethod selected by the server (see sections 5.3.2 and 2.2.1.4.3) " + @"is ENCRYPTION_METHOD_FIPS (0x00000010). "); } else if (serverConfig.encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_NONE) { site.CaptureRequirementIfIsNull(inputPdu.commonHeader.securityHeader, 1632, @"In Client Input Event PDU (TS_INPUT_PDU),If Enhanced RDP Security is in effect or the " + @"Encryption Method selected by the server is ENCRYPTION_METHOD_NONE (0), then this " + @"securityHeader field MUST NOT be included in the PDU."); } //2.2.8.1.1.3.1 site.CaptureRequirementIfAreEqual<ShareControlHeaderType>(ShareControlHeaderType.PDUTYPE_DATAPDU, (ShareControlHeaderType)(inputPdu.shareDataHeader.shareControlHeader.pduType.typeAndVersionLow & 0x0F), 1635, @"In Client Input Event PDU (TS_INPUT_PDU),the shareDataHeader field contains information about" + @" the packet. The type subfield of the pduType field of the Share Control Header MUST be set" + @" to PDUTYPE_DATAPDU (7). "); site.CaptureRequirementIfAreEqual<pduType2_Values>(pduType2_Values.PDUTYPE2_INPUT, inputPdu.shareDataHeader.pduType2, 1636, @"In Client Input Event PDU (TS_INPUT_PDU),the pduType2 field of the Share Data Header MUST be " + @"set to PDUTYPE2_INPUT (28)."); //2.2.8.1.1.3.1.1 foreach (TS_INPUT_EVENT e in inputPdu.slowPathInputEvents) { VerifyStructure(e); } }
/// <summary> /// Create an instance of the class that is identical to the current PDU. /// </summary> /// <returns>The new instance.</returns> public override StackPacket Clone() { TS_INPUT_PDU cloneInputPdu = new TS_INPUT_PDU(context); cloneInputPdu.commonHeader = commonHeader.Clone(); cloneInputPdu.numberEvents = numberEvents; cloneInputPdu.pad2Octets = pad2Octets; cloneInputPdu.shareDataHeader = shareDataHeader; if (slowPathInputEvents != null) { cloneInputPdu.slowPathInputEvents = new Collection<TS_INPUT_EVENT>(); for (int count = 0; count < this.slowPathInputEvents.Count; count++) { cloneInputPdu.slowPathInputEvents.Add(slowPathInputEvents[count]); } } return cloneInputPdu; }