private void HandleRapiSession() { List<PacketSlice> slices = new List<PacketSlice>(); TransactionNode node, req, resp; string str; UInt32 val, retVal, lastError; while (stream.GetBytesAvailable() > 0) { UInt32 msgLen, msgType; List<PacketSlice> msgLenSlices = new List<PacketSlice>(1); List<PacketSlice> msgTypeSlices = new List<PacketSlice>(1); // Message length msgLen = stream.ReadU32LE(msgLenSlices); if (msgLen == 5) { node = new TransactionNode("RAPINotification"); node.Description = node.Name; node.AddField("MessageType", "RAPI_NOTIFICATION", "Message type.", msgLenSlices); val = stream.ReadU32LE(slices); node.AddField("NotificationType", (val == 4) ? "REQUEST_NEW_CONNECTION" : StaticUtils.FormatFlags(val), "Notification type.", slices); val = stream.ReadU32LE(slices); node.AddField("Argument", val, "Argument.", slices); session.AddNode(node); if (stream.GetBytesAvailable() < 4) break; else continue; } else if (msgLen == 1) { node = new TransactionNode("RAPIKeepalive"); node.Description = node.Name; req = new TransactionNode(node, "Request"); req.AddField("MessageType", "RAPI_PING", "Message type.", msgLenSlices); stream = session.GetNextStreamDirection(); if (stream.GetBytesAvailable() < 4) break; stream.ReadU32LE(slices); resp = new TransactionNode(node, "Response"); resp.AddField("MessageType", "RAPI_PONG", "Message type.", slices); session.AddNode(node); stream = session.GetNextStreamDirection(); if (stream.GetBytesAvailable() < 4) break; else continue; } // Message type msgType = stream.ReadU32LE(msgTypeSlices); if (msgType >= rapiCallNames.Length) { logger.AddMessage("Unknown call name: {0:x8}", msgType); return; } string name = rapiCallNames[msgType]; RAPICallNode call = new RAPICallNode(name); call.Description = call.Name; req = call.Request; resp = call.Response; req.AddField("MessageLength", msgLen, "Length of the RAPI request.", msgLenSlices); req.AddField("MessageType", String.Format("{0} (0x{1:x2})", name, msgType), "Type of the RAPI request.", msgTypeSlices); if (name == "CeRegOpenKeyEx") { val = stream.ReadU32LE(slices); req.AddField("hKey", StaticUtils.FormatRegKey(val), "Handle to a currently open key or one of the following predefined reserved handle values:\n" + "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices); str = stream.ReadRAPIString(slices); req.AddField("szSubKey", str, "A null-terminated string containing the name of the subkey to open.", slices); req.Summary = String.Format("{0}, \"{1}\"", StaticUtils.FormatRegKey(val, true), str); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); val = stream.ReadU32LE(slices); string result = String.Format("0x{0:x8}", val); resp.AddField("hkResult", result, "Handle to the opened key.", slices); if (retVal == Constants.ERROR_SUCCESS) resp.Summary = String.Format("{0}, {1}", StaticUtils.FormatRetVal(retVal, true), result); else resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeRegCreateKeyEx") { val = stream.ReadU32LE(slices); req.AddField("hKey", StaticUtils.FormatRegKey(val), "Handle to a currently open key or one of the following predefined reserved handle values:\n" + "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices); string szSubKey = stream.ReadRAPIString(slices); req.AddField("szSubKey", (szSubKey != null) ? szSubKey : "(null)", "A null-terminated string specifying the name of a subkey that this function opens or creates. " + "The subkey specified must be a subkey of the key identified by the hKey parameter. This subkey " + "must not begin with the backslash character (\\). If the parameter is NULL, then RegCreateKeyEx " + "behaves like RegOpenKey, where it opens the key specified by hKey.", slices); string szClass = stream.ReadRAPIString(slices); req.AddField("szClass", (szClass != null) ? szClass : "(null)", "A null-terminated string that specifies the class (object type) of this key. This parameter is " + "ignored if the key already exists.", slices); req.Summary = String.Format("{0}, {1}, {2}", StaticUtils.FormatRegKey(val, true), StaticUtils.FormatStringArgument(szSubKey), StaticUtils.FormatStringArgument(szClass)); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); string result = String.Format("0x{0:x8}", stream.ReadU32LE(slices)); resp.AddField("hkResult", result, "Handle to the opened key.", slices); UInt32 disposition = stream.ReadU32LE(slices); resp.AddField("dwDisposition", StaticUtils.FormatRegDisposition(disposition), "Receives one of REG_CREATED_NEW_KEY and REG_OPENED_EXISTING_KEY.", slices); if (retVal == Constants.ERROR_SUCCESS) resp.Summary = String.Format("{0}, {1}, {2}", StaticUtils.FormatRetVal(retVal, true), result, StaticUtils.FormatRegDisposition(disposition, true)); else resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeRegCloseKey") { val = stream.ReadU32LE(slices); req.AddField("hKey", StaticUtils.FormatRegKey(val), "Handle to the open key to close.", slices); req.Summary = StaticUtils.FormatRegKey(val, true); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeRegQueryValueEx") { val = stream.ReadU32LE(slices); req.AddField("hKey", StaticUtils.FormatRegKey(val), "Handle to a currently open key or any of the following predefined reserved handle values:\n" + "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices); string szValueName = stream.ReadRAPIString(slices); req.AddField("szValueName", szValueName, "A string containing the name of the value to query.", slices); UInt32 cbData = stream.ReadU32LE(slices); req.AddField("cbData", cbData, "A variable that specifies the maximum number of bytes to return.", slices); req.Summary = String.Format("{0}, {1}, {2}", StaticUtils.FormatRegKey(val, true), StaticUtils.FormatStringArgument(szValueName), cbData); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); UInt32 dwType = stream.ReadU32LE(slices); resp.AddField("dwType", StaticUtils.FormatRegType(dwType), "The type of data associated with the specified value.", slices); cbData = stream.ReadU32LE(slices); resp.AddField("cbData", Convert.ToString(cbData), "The size of the data returned.", slices); str = ReadAndFormatDataForRegType(dwType, cbData, slices); if (str == null) str = "NULL"; resp.AddField("Data", str, "The data returned.", slices); resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeRegSetValueEx") { UInt32 key = stream.ReadU32LE(slices); req.AddField("hKey", StaticUtils.FormatRegKey(key), "Handle to a currently open key or any of the following predefined reserved handle values:\n" + "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices); string szValueName = stream.ReadRAPIString(slices); req.AddField("szValueName", szValueName, "String containing the name of the value to set. If a value with this name is not already " + "present in the key, the function adds it to the key. If this parameter is NULL or an empty " + "string, the function sets the type and data for the key's unnamed value. Registry keys do " + "not have default values, but they can have one unnamed value, which can be of any type.", slices); UInt32 dwType = stream.ReadU32LE(slices); req.AddField("dwType", StaticUtils.FormatRegType(dwType), "Type of information to be stored as the value's data.", slices); UInt32 cbData = stream.ReadU32LE(slices); req.AddField("cbData", Convert.ToString(cbData), "Specifies the size, in bytes, of the information passed in the the Data field.", slices); str = ReadAndFormatDataForRegType(dwType, cbData, slices); if (str == null) str = "NULL"; req.AddField("Data", str, "Buffer containing the data to be stored with the specified value name.", slices); string dataSummary; if (dwType == Constants.REG_DWORD || dwType == Constants.REG_DWORD_BIG_ENDIAN) { dataSummary = str; } else dataSummary = String.Format("[{0} bytes]", cbData); req.Summary = String.Format("{0}, {1}, {2}, {3}", StaticUtils.FormatRegKey(key), StaticUtils.FormatStringArgument(szValueName), StaticUtils.FormatRegType(dwType), dataSummary); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeProcessConfig") { str = stream.ReadRAPIString(slices); req.AddXMLField("szRequest", str, "Config request.", slices); UInt32 flags = stream.ReadU32LE(slices); req.AddField("dwFlags", StaticUtils.FormatFlags(flags), "Flags.", slices); req.Summary = String.Format("[{0} bytes], 0x{1:x8}", str.Length, flags); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); str = stream.ReadRAPIString(slices); resp.AddXMLField("szResponse", str, "Config response.", slices); if (retVal == Constants.ERROR_SUCCESS) resp.Summary = String.Format("{0}, [{1} bytes]", StaticUtils.FormatRetVal(retVal, true), (str != null) ? str.Length : 0); else resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeGetDesktopDeviceCaps") { string caps = FormatDeviceCaps(stream.ReadU32LE(slices)); req.AddField("nIndex", caps, "The item to return.", slices); req.Summary = caps; SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false); resp.Summary = StaticUtils.FormatValue(retVal); } else if (name == "CeSyncStart") { string xml = stream.ReadRAPIString(slices); req.AddXMLField("szXML", (xml != null) ? xml : "(null)", "Optional message.", slices); if (xml != null) req.Summary = String.Format("[{0} bytes]", xml.Length); else req.Summary = "NULL"; SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError); resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeSyncResume" || name == "CeSyncPause") { req.Summary = ""; SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false); resp.Summary = StaticUtils.FormatRetVal(retVal, true); } else if (name == "CeStartReplication") { req.Summary = ""; SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false); resp.Summary = StaticUtils.FormatBool(retVal); } else if (name == "CeGetFileAttributes") { string fileName = stream.ReadRAPIString(slices); req.AddXMLField("szFileName", fileName, "Name of a file or directory.", slices); req.Summary = String.Format("\"{0}\"", fileName); SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false); resp.Summary = StaticUtils.FormatValue(retVal); } else { if (msgLen > 4) { byte[] bytes = stream.ReadBytes((int)msgLen - 4, slices); req.AddField("UnparsedData", StaticUtils.FormatByteArray(bytes), "Unparsed data.", slices); } req.Summary = "[not yet parsed]"; SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false); resp.Summary = "[not yet parsed]"; } session.AddNode(call); stream = session.GetNextStreamDirection(); if (stream.GetBytesAvailable() == 0) break; } }
private void ReadAllP2PDirectMessages(IPSession session, PacketStream stream) { while (stream.GetBytesAvailable() > 0) { try { TransactionNode node = ReadNextP2PDirectMessage(stream, "MSNP2PDirectMessage"); session.AddNode(node); } catch (EndOfStreamException e) { logger.AddMessage(String.Format("MSNP2PDirect: EOS at {0} ({1})", stream.Position, e)); break; } } }
public override bool HandleSession(IPSession session) { if (session.LocalEndpoint == null || session.LocalEndpoint.Port != 990) return false; this.session = session; stream = session.GetNextStreamDirection(); // The device should send the first DWORD of the handshake if (stream.CurPacket.Direction == PacketDirection.PACKET_DIRECTION_INCOMING) { HandleRapiHandshake(); } if (stream.GetBytesAvailable() >= 4) HandleRapiSession(); return true; }