Example #1
0
 public IPSession()
 {
     events = new List<TCPEvent>();
     streamIn = new PacketStream();
     streamOut = new PacketStream();
     nodes = new List<TransactionNode>();
 }
Example #2
0
        private TransactionNode ExtractTNSData(PacketStream stream, StreamDirection direction)
        {
            TransactionNode node;
            OracleTransactionType type;
            List<PacketSlice> slices = new List<PacketSlice>();
            Int16 pLen = 0;
            int packetType;
            try {

                pLen = stream.PeekInt16();
                stream.ReadBytes(2, slices);
                stream.ReadBytes(2); //skip checksum
                packetType = stream.ReadByte();
                type = (OracleTransactionType)packetType;
                stream.ReadByte(); //skip the reserved byte
            } catch (Exception e) {
                logger.AddMessage(e.Message);
                return null;
            }
            switch (type) {
                case OracleTransactionType.CONNECT:
                    try {
                        node = new TransactionNode("Connect");
                        node.AddField("Packet Size", pLen, "Packet Size", slices);

                        Int16 headerChecksum = stream.ReadInt16();
                        Int16 version = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Version", version, "Version", slices);
                        Int16 compatVersion = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Version (compatible)", compatVersion, "Compatible Version", slices);
                        Int16 serviceOptions = stream.ReadInt16();
                        Int16 sessionDataUnitSize = stream.ReadInt16();
                        Int16 maxTxDataUnitSize = stream.ReadInt16();
                        Int16 NTProtCharacteristics = stream.ReadInt16();
                        Int16 lineTurnValue = stream.ReadInt16();
                        Int16 valueOfOneInHW = stream.ReadInt16();
                        Int16 ctDataLen = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Data Length", ctDataLen, "The length of the connect datastring.", slices);
                        Int16 ctDataOffset = stream.ReadInt16();
                        Int16 maxRecCtData = stream.ReadInt16();
                        Int16 ctFlagsA = stream.ReadInt16();
                        Int16 ctFlagsB = stream.ReadInt16();
                        Int32 traceItemA = stream.ReadInt32();
                        Int32 traceItemB = stream.ReadInt32();
                        Int64 traceID = stream.ReadInt64();
                        stream.ReadInt64();
                        byte[] ctData = stream.PeekBytes(ctDataLen);
                        string connectData = StaticUtils.DecodeASCII(ctData);

                        stream.ReadBytes(ctDataLen, slices);
                        node.AddField("Connect data", connectData, "Connect data", slices);
                        try {
                            Match match = Regex.Match(connectData, "\\(PROTOCOL=(?<proto>\\w{2,})\\)\\(HOST=(?<host>[.\\w]{7,})\\)\\(PORT=(?<port>\\d{2,})\\)\\).*SERVICE_NAME=(?<sid>[.\\w]{1,})\\)");
                            string proto = match.Groups["proto"].Value;
                            string host = match.Groups["host"].Value;
                            string newPort = match.Groups["port"].Value;
                            string sid = match.Groups["sid"].Value;
                            TransactionNode cInfoNode = new TransactionNode("Connection Info");
                            cInfoNode.AddField("Protocol", proto, "Protocol", slices);
                            cInfoNode.AddField("Host", host, "Server being connected to", slices);
                            cInfoNode.AddField("Port", newPort, "Port", slices);
                            cInfoNode.AddField("Service", sid, "Service", slices);
                            node.AddChild(cInfoNode);
                        } catch (ArgumentException) {
                        }
                        return node;
                    } catch (Exception e) {
                        logger.AddMessage(e.Message);
                        return null;
                    }
                case OracleTransactionType.ACCEPT:
                    node = new TransactionNode("Accept");
                    node.AddField("Packet Size", pLen, "Packet Size", slices);

                    try {
                        Int16 headerChecksum = stream.ReadInt16();
                        Int16 version = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Version", version, "Version", slices);
                        Int16 serviceOptions = stream.ReadInt16();
                        Int16 sessionDataUnitSize = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Session Data Unit Size", sessionDataUnitSize, "Session Data Unit Size", slices);
                        Int16 maxTxDataUnitSize = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Max Tx Unit Size", maxTxDataUnitSize, "Maximum Transmission Data Unit Size", slices);

                        Int16 valueOfOneInHW = stream.ReadInt16();
                        Int16 acceptDataLength = stream.ReadInt16();
                        Int16 dataOffset = stream.ReadInt16();
                        int connectFlagsA = stream.ReadByte();
                        int connectFlagsB = stream.ReadByte();
                        stream.ReadBytes(pLen - 24); //read out empty bytes
                    } catch (Exception e) {
                        logger.AddMessage(e.Message);
                        return null;
                    }
                    return node;
                case OracleTransactionType.REDIRECT:
                    node = new TransactionNode("Redirect");
                    node.AddField("Packet Size", pLen, "Packet Size", slices);

                    try {
                        Int16 headerChecksum = stream.ReadInt16();
                        Int16 redirLen = stream.PeekInt16();
                        stream.ReadBytes(2, slices);
                        node.AddField("Redirection Data Length", redirLen, "Length of the redirection data string", slices);
                        byte[] redirData = stream.PeekBytes(redirLen);
                        string sRedir = StaticUtils.DecodeASCII(redirData);
                        stream.ReadBytes(redirLen, slices);
                        node.AddField("Redirection Data", sRedir, "Redirection data", slices);
                        //get the redirected port
                        string newPort = null;
                        string proto = null;
                        string host = null;
                        try {
                            Match match = Regex.Match(sRedir, "\\(PROTOCOL=(?<proto>\\w{2,})\\)\\(HOST=(?<host>[.\\w]{7,})\\)\\(PORT=(?<port>\\d{2,})\\)\\)");
                            proto = match.Groups["proto"].Value;
                            host = match.Groups["host"].Value;
                            newPort = match.Groups["port"].Value;
                        } catch (ArgumentException) {
                            // Syntax error in the regular expression
                        }
                        if(!newPort.Equals(""))
                            redirPort = Int32.Parse(newPort);
                        TransactionNode redirInfo = new TransactionNode("Redirection Info");
                        redirInfo.AddField("Protocol", proto, "Protocol used", slices);
                        redirInfo.AddField("Host", host, "Host", slices);
                        redirInfo.AddField("Port", newPort, "Port", slices);
                        node.AddChild(redirInfo);
                    } catch (Exception e) {
                        logger.AddMessage(e.Message);
                        return null;
                    }
                    return node;
                case OracleTransactionType.DATA:
                    string label;
                    if (direction == StreamDirection.IN)
                        label = "Response";
                    else
                        label = "Request";
                    node = new TransactionNode("Data - "+label );
                    node.AddField("Packet Size", pLen, "Packet Size", slices);

                    try {
                        Int16 headerChecksum = stream.ReadInt16();
                        Int16 dataFlags = stream.ReadInt16();
                        int payLoadLength = pLen - 10;
                        byte[] payLoad = stream.PeekBytes(payLoadLength);
                        string sPayload = StaticUtils.DecodeASCII(payLoad);
                        stream.ReadBytes(payLoadLength, slices);
                        node.AddField("Data", sPayload, "Data", slices);
                    } catch (Exception e) {
                        logger.AddMessage(e.Message);
                        return null;
                    }
                    return node;
                default:
                    logger.AddMessage(String.Format("Packet dissection not implemented [TransactionType={0}]", type));
                    return null;
            }
        }
Example #3
0
        static void Main(string[] args)
        {
            PacketStream stream = new PacketStream();

            IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Parse("169.254.2.2"), 27516);
            IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Parse("169.254.2.1"), 1056);

            int n = 1;

            IPPacket p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                                      NewArrayIncremental(6, 10));
            stream.AppendPacket(p);

            p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                             NewArrayIncremental(3, 35));
            stream.AppendPacket(p);

            p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                             NewArrayIncremental(1, 60));
            stream.AppendPacket(p);

            p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                             NewArrayIncremental(1, 200));
            stream.AppendPacket(p);

            p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                             NewArrayIncremental(3, 210));
            stream.AppendPacket(p);

            p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                             NewArrayIncremental(1, 70));
            stream.AppendPacket(p);

            p = new IPPacket(n++, 1, PacketDirection.PACKET_DIRECTION_OUTGOING, localEndpoint, remoteEndpoint,
                             NewArrayIncremental(1, 80));
            stream.AppendPacket(p);

            Debug.Assert(stream.Position == 0, "Position != 0");
            Debug.Assert(stream.Length == 16, "Length != 16");

            byte[] buf = new byte[stream.Length];
            Debug.Assert(stream.Read(buf, 0, 16) == 16, "Read() != 16");
            byte[] expectedBytes = new byte[] { 10, 11, 12, 13, 14, 15,
                                                35, 36, 37,
                                                60,
                                                200,
                                                210, 211, 212,
                                                70,
                                                80 };

            Debug.Assert(CompareByteArrays(buf, expectedBytes), "Content after first read is not as expected");

            Debug.Assert(stream.Position == 16, "Position != 16");

            Debug.Assert(stream.Read(buf, 0, 10) == 0, "Read at offset 16 doesn't return 0");

            stream.Seek(-1, SeekOrigin.Current);
            Debug.Assert(stream.Read(buf, 2, 100) == 1, "Read at offset 15 doesn't return 1");

            Debug.Assert(buf[2] == 80, "Byte at offset 15 isn't 80");

            stream.Seek(-16, SeekOrigin.Current);
            Debug.Assert(stream.Position == 0, "Position != 0 after reverse seek");

            stream.Position = 9;
            Debug.Assert(stream.Read(buf, 1, 1) == 1, "Read at Position=9 didn't yield 1 byte");
            Debug.Assert(buf[1] == 60, "buf[1] != 60");

            stream.Position = 13;
            Debug.Assert(stream.Read(buf, 5, 4) == 3, "Read at Position=13 didn't yield 3 bytes");
            Debug.Assert(buf[5] == 212, "buf[5] != 212");
            Debug.Assert(buf[6] == 70, "buf[5] != 70");
            Debug.Assert(buf[7] == 80, "buf[5] != 80");

            System.Console.WriteLine("All tests passed");
            System.Console.ReadKey();
        }
Example #4
0
File: MSN.cs Project: SayHalou/ospy
        protected void ReadNextP2PMessageChunk(PacketStream stream, TransactionNode parentNode)
        {
            TransactionNode p2pNode = new TransactionNode(parentNode, "MSNP2PMessageChunk");

            // Headers
            TransactionNode p2pHeaders = new TransactionNode(p2pNode, "Headers");

            List<PacketSlice> slices = new List<PacketSlice>();

            UInt32 sessionID = stream.ReadU32LE(slices);
            p2pHeaders.AddField("SessionID", sessionID, "Session ID.", slices);

            UInt32 messageID = stream.ReadU32LE(slices);
            p2pHeaders.AddField("MessageID", messageID, "Message ID.", slices);

            UInt64 dataOffset = stream.ReadU64LE(slices);
            p2pHeaders.AddField("DataOffset", dataOffset, "Data offset.", slices);

            UInt64 dataSize = stream.ReadU64LE(slices);
            p2pHeaders.AddField("DataSize", dataSize, "Data size.", slices);

            UInt32 chunkSize = stream.ReadU32LE(slices);
            p2pHeaders.AddField("ChunkSize", chunkSize, "Chunk size.", slices);

            UInt32 flags = stream.ReadU32LE(slices);
            p2pHeaders.AddField("Flags", flags, StaticUtils.FormatFlags(flags), "Flags.", slices);

            UInt32 ackedMsgID = stream.ReadU32LE(slices);
            p2pHeaders.AddField("AckedMsgID", ackedMsgID, "MessageID of the message to be acknowledged.", slices);

            UInt32 prevAckedMsgID = stream.ReadU32LE(slices);
            p2pHeaders.AddField("PrevAckedMsgID", prevAckedMsgID, "AckedMsgID of the last chunk to ack.", slices);

            UInt64 ackedDataSize = stream.ReadU64LE(slices);
            p2pHeaders.AddField("AckedDataSize", ackedDataSize, "Acknowledged data size.", slices);

            // Body
            TransactionNode p2pContent = null;
            if (chunkSize > 0)
            {
                p2pContent = new TransactionNode(p2pNode, "Content");

                byte[] bytes = stream.ReadBytes((int)chunkSize, slices);

                if (sessionID != 0)
                {
                    p2pContent.AddField("Raw", bytes, StaticUtils.FormatByteArray(bytes), "Raw content.", slices);
                }
                else
                {
                    p2pContent.AddTextField("MSNSLP", bytes, StaticUtils.DecodeUTF8(bytes), "MSNSLP data.", slices);
                }
            }
        }
Example #5
0
File: MSN.cs Project: SayHalou/ospy
        protected void SBParseMSG(PacketStream stream, TransactionNode payloadNode, int payloadLength)
        {
            List<PacketSlice> slices = new List<PacketSlice>(2);

            string content = stream.PeekStringUTF8(payloadLength);

            TransactionNode headersNode = new TransactionNode(payloadNode, "Headers");

            int pos = content.IndexOf("\r\n\r\n");
            string headers = content.Substring(0, pos);
            string[] lines = headers.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in lines)
            {
                stream.ReadBytes(StaticUtils.GetUTF8ByteCount(line), slices);

                string[] tokens = line.Split(new char[] { ':' }, 2);
                tokens[1] = tokens[1].TrimStart(new char[] { ' ' });

                headersNode.AddField(tokens[0], tokens[1], "Message header field.", slices);

                // Skip CRLF
                stream.ReadBytes(2);
            }

            // Skip extra CRLF
            stream.ReadBytes(2);

            int bodyLength = payloadLength - StaticUtils.GetUTF8ByteCount(headers) - 4;

            if (bodyLength > 0)
            {
                TransactionNode bodyNode = new TransactionNode(payloadNode, "Body");

                string contentType = (string)headersNode.Fields["Content-Type"];
                contentType = contentType.Split(new char[] { ';' }, 2)[0];

                if (contentType == "application/x-msnmsgrp2p")
                {
                    ReadNextP2PMessageChunk(stream, bodyNode);

                    UInt32 appID = stream.ReadU32BE(slices);
                    bodyNode.AddField("AppID", appID, "Application ID.", slices);
                }
                else if (contentType == "text/x-msmsgsinvite")
                {
                    string bodyStr = stream.ReadStringUTF8(bodyLength, slices);

                    bodyNode.AddTextField("Body", bodyStr, "Invite body.", slices);
                }
                else
                {
                    string bodyStr = stream.ReadStringUTF8(bodyLength, slices);

                    bodyNode.AddField("Body", bodyStr, "Body.", slices);
                }
            }
        }
Example #6
0
File: MSN.cs Project: SayHalou/ospy
        private TransactionNode ReadNextP2PDirectMessage(PacketStream stream, string name)
        {
            TransactionNode msgNode = new TransactionNode(name);
            msgNode.Description = msgNode.Name;

            List<PacketSlice> slices = new List<PacketSlice>(1);
            uint len = stream.ReadU32LE(slices);
            msgNode.AddField("MSNP2PLength", len, "P2P message chunk length.", slices);

            ReadNextP2PMessageChunk(stream, msgNode);

            return msgNode;
        }
Example #7
0
File: MSN.cs Project: SayHalou/ospy
 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;
         }
     }
 }
Example #8
0
        private void SwitchToResponseAndParseResult(TransactionNode resp, List<PacketSlice> slices,
                                                    out UInt32 retVal, out UInt32 lastError,
                                                    bool formatRetVal)
        {
            stream = session.GetNextStreamDirection();

            UInt32 msgLen = stream.ReadU32LE(slices);
            resp.AddField("MessageLength", Convert.ToString(msgLen),
                "Length of the RAPI response.", slices);

            lastError = stream.ReadU32LE(slices);
            resp.AddField("LastError", String.Format("0x{0:x8}", lastError),
                "Last error on the CE device.", slices);

            retVal = stream.ReadU32LE(slices);
            resp.AddField("ReturnValue", (formatRetVal) ? StaticUtils.FormatRetVal(retVal) : StaticUtils.FormatValue(retVal),
                "Return value.", slices);
        }
Example #9
0
        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;
            }
        }
Example #10
0
        private void HandleRapiHandshake()
        {
            RAPIConnectionState state = RAPIConnectionState.HANDSHAKE;

            List<PacketSlice> slices = new List<PacketSlice>();
            TransactionNode parentNode, node;
            string str;
            UInt32 val;

            // Read and verify the initial request
            UInt32 initialRequest = stream.ReadU32LE(slices);
            if (initialRequest != NOTIFY_INITIAL_HANDSHAKE && initialRequest != NOTIFY_CONNECTION_READY)
            {
                logger.AddMessage("RAPI protocol error, unknown initial request {0}", initialRequest);
                return;
            }

            node = new TransactionNode((initialRequest == 0) ? "RAPIInitialHandshake" : "RAPIConnectionStart");
            node.Description = node.Name;

            node.AddField("InitialRequest", (initialRequest == NOTIFY_INITIAL_HANDSHAKE) ? "NOTIFY_INITIAL_HANDSHAKE" : "NOTIFY_CONNECTION_READY", "Initial request.", slices);

            // Now it's our turn
            stream = session.GetNextStreamDirection();

            if (initialRequest == NOTIFY_INITIAL_HANDSHAKE)
            {
                UInt32 firstPing = stream.ReadU32LE(slices);
                node.AddField("FirstPing", firstPing, "First ping, should be 3.", slices);

                // And the first pong
                stream = session.GetNextStreamDirection();

                UInt32 firstPong = stream.ReadU32LE(slices);
                node.AddField("FirstPong", firstPong, "First pong, should be 4 for older WM5, 6 for newer versions.", slices);

                if (firstPong == 6)
                {
                    // Now we're supposed to send 4 DWORDs
                    stream = session.GetNextStreamDirection();

                    UInt32 secondPing = stream.ReadU32LE(slices);
                    node.AddField("SecondPingValue1", secondPing, "Second ping value #1, should be 7.", slices);

                    secondPing = stream.ReadU32LE(slices);
                    node.AddField("SecondPingValue2", secondPing, "Second ping value #2, should be 8.", slices);

                    secondPing = stream.ReadU32LE(slices);
                    node.AddField("SecondPingValue3", secondPing, "Second ping value #3, should be 4.", slices);

                    secondPing = stream.ReadU32LE(slices);
                    node.AddField("SecondPingValue4", secondPing, "Second ping value #4, should be 1.", slices);

                    // And the device should reply
                    stream = session.GetNextStreamDirection();

                    UInt32 secondPong = stream.ReadU32LE(slices);
                    node.AddField("SecondPong", secondPong, "Second pong, should be 4.", slices);
                }

                // Got it
                session.AddNode(node);

                parentNode = new TransactionNode("RAPIDeviceInfo");
                parentNode.Description = parentNode.Name;

                UInt32 deviceInfoLen = stream.ReadU32LE(slices);
                UInt32 remainingDevInfoLen = deviceInfoLen;
                parentNode.AddField("Length", deviceInfoLen, "Device info length.", slices);

                if (deviceInfoLen > MAX_DEVICE_INFO_LENGTH)
                {
                    logger.AddMessage("RAPI protocol error, length of the device info package should be below {0}, was {1}", MAX_DEVICE_INFO_LENGTH, deviceInfoLen);
                    return;
                }

                node = new TransactionNode(parentNode, "DeviceInfo");

                Guid guid = new Guid(stream.ReadBytes(16, slices));
                str = String.Format("{{0}}", guid.ToString());
                node.AddField("DeviceGUID", str, "Device GUID.", slices);
                remainingDevInfoLen -= 16;

                val = stream.ReadU32LE(slices);
                node.AddField("OsVersionMajor", val, "OS version, major.", slices);
                remainingDevInfoLen -= 4;

                val = stream.ReadU32LE(slices);
                node.AddField("OsVersionMinor", val, "OS version, minor.", slices);
                remainingDevInfoLen -= 4;

                val = stream.ReadU32LE(slices);
                node.AddField("DeviceNameLength", val, "Device name length (in characters, not bytes).", slices);
                remainingDevInfoLen -= 4;

                // calculate the string size in unicode, with terminating NUL word
                val = (val + 1) * 2;
                str = stream.ReadCStringUnicode((int)val, slices);
                node.AddField("DeviceName", str, "Device name.", slices);
                remainingDevInfoLen -= val;

                val = stream.ReadU32LE(slices);
                node.AddField("DeviceVersion", StaticUtils.FormatFlags(val), "Device version.", slices);
                remainingDevInfoLen -= 4;

                val = stream.ReadU32LE(slices);
                node.AddField("DeviceProcessorType", StaticUtils.FormatFlags(val), "Device processor type.", slices);
                remainingDevInfoLen -= 4;

                val = stream.ReadU32LE(slices);
                node.AddField("Unknown1", StaticUtils.FormatFlags(val), "Counter or a flag? ANDed with 0xFFFFFFFE in the code (should take a closer look at this).", slices);
                remainingDevInfoLen -= 4;

                val = stream.ReadU32LE(slices);
                node.AddField("CurrentPartnerId", StaticUtils.FormatFlags(val), "Current partner id.", slices);
                remainingDevInfoLen -= 4;

                val = stream.ReadU32LE(slices);
                node.AddField("DeviceId", StaticUtils.FormatFlags(val), "Current device id. Lives in HKCU\\Software\\Microsoft\\Windows CE Services\\Partners\\<DeviceIdentifier>.", slices);
                remainingDevInfoLen -= 4;

                /*
                dw = stream.ReadU32LE(slices);
                node.AddField("PlatformNameLength", dw, "Platform name length.", slices);
                remainingDevInfoLen -= 4;*/

                // Don't swallow the 4 last
                remainingDevInfoLen -= 4;

                byte[] bytes = stream.ReadBytes((int)remainingDevInfoLen, slices);
                node.AddField("UnknownData1", StaticUtils.FormatByteArray(bytes), "Unknown device info data.", slices);

                val = stream.ReadU32LE(slices);
                node.AddField("PasswordMask", StaticUtils.FormatFlags(val), "Password mask. Non-zero if a password is set.", slices);
                remainingDevInfoLen -= 4;

                state = (val != 0) ? RAPIConnectionState.AUTH : RAPIConnectionState.SESSION;

                // Now it's our turn
                stream = session.GetNextStreamDirection();

                node = parentNode;
            }
            else
            {
                state = RAPIConnectionState.SESSION;
            }

            // Add the last node for each case
            session.AddNode(node);

            while (state == RAPIConnectionState.AUTH)
            {
                parentNode = new TransactionNode("RAPIAuthAttempt");
                parentNode.Description = parentNode.Name;

                node = new TransactionNode(parentNode, "Request");

                val = stream.ReadU16LE(slices);
                node.AddField("Length", val, "Authentication data length.", slices);

                byte[] bytes = stream.ReadBytes((int)val, slices);
                node.AddField("Data", StaticUtils.FormatByteArray(bytes), "Authentication data.", slices);

                stream = session.GetNextStreamDirection();

                node = new TransactionNode(parentNode, "Response");

                val = stream.ReadU16LE(slices);
                node.AddField("Success", (val != 0) ? "TRUE" : "FALSE", "Whether the authentication attempt was successful.", slices);

                session.AddNode(parentNode);

                stream = session.GetNextStreamDirection();

                if (val != 0)
                    state = RAPIConnectionState.SESSION;
            }
        }
Example #11
0
        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;
        }
Example #12
0
        protected void AddBodyNode(PacketStream stream,
                                   TransactionNode transactionNode,
                                   string contentType,
                                   string contentEncoding,
                                   int bodyLen)
        {
            List<PacketSlice> slices = new List<PacketSlice>(1);

            TransactionNode bodyNode = new TransactionNode("Body");
            byte[] body = stream.ReadBytes(bodyLen, slices);

            if (contentType == "text/html" || contentType == "text/xml")
            {
                int realBodyLen = body.Length;
                if (body[realBodyLen - 1] == '\0')
                    realBodyLen--;

                Decoder dec;
                if (contentEncoding == "utf-8")
                {
                    dec = Encoding.UTF8.GetDecoder();
                }
                else
                {
                    dec = Encoding.ASCII.GetDecoder();
                }

                char[] bodyChars = new char[dec.GetCharCount(body, 0, realBodyLen)];
                dec.GetChars(body, 0, realBodyLen, bodyChars, 0);
                string bodyStr = new string(bodyChars);

                if (contentType == "text/xml")
                    bodyNode.AddXMLField("XML", bodyStr, "Body XML data.", slices);
                else
                    bodyNode.AddTextField("HTML", bodyStr, "Body HTML data.", slices);
            }
            else if (contentType == "application/vnd.ms-sync.wbxml")
            {
                string xml = WBXML.ConvertToXML(body);
                bodyNode.AddXMLField("WBXML", xml, "Body WBXML data.", slices);
            }
            else
            {
                bodyNode.AddField("Raw", body, StaticUtils.FormatByteArray(body),
                    "Raw body data.", slices);
            }

            transactionNode.AddChild(bodyNode);
        }
Example #13
0
        private TransactionNode ExtractHttpData(PacketStream stream, HTTPTransactionType type, string nodeName)
        {
            if (nodeName == null)
            {
                nodeName = (type == HTTPTransactionType.REQUEST) ? "Request" : "Response";
            }

            TransactionNode node = new TransactionNode(nodeName);
            List<PacketSlice> slices = new List<PacketSlice>();

            string line = stream.PeekLineUTF8();

            int fieldCount = (type == HTTPTransactionType.REQUEST) ? 3 : 2;

            string[] tokens = line.Split(new char[] { ' ' }, fieldCount);
            if (tokens.Length < fieldCount)
                throw new ProtocolError();

            if (type == HTTPTransactionType.REQUEST)
            {
                stream.ReadBytes(StaticUtils.GetUTF8ByteCount(tokens[0]), slices);
                node.AddField("Verb", tokens[0], "Request verb.", slices);

                stream.ReadByte();

                stream.ReadBytes(StaticUtils.GetUTF8ByteCount(tokens[1]), slices);
                node.AddField("Argument", tokens[1], "Request argument.", slices);

                stream.ReadByte();

                stream.ReadBytes(StaticUtils.GetUTF8ByteCount(tokens[2]), slices);
                node.AddField("Protocol", tokens[2], "Protocol identifier.", slices);

                // Set a description
                node.Description = String.Format("{0} {1}", tokens[0], tokens[1]);
                if (node.Description.Length > MAX_DESCRIPTION_LENGTH)
                {
                    node.Description = node.Description.Substring(0, MAX_DESCRIPTION_LENGTH - ellipsis.Length);
                    node.Description += ellipsis;
                }
            }
            else
            {
                stream.ReadBytes(StaticUtils.GetUTF8ByteCount(tokens[0]), slices);
                node.AddField("Protocol", tokens[0], "Protocol identifier.", slices);

                if (tokens.Length > 1)
                {
                    stream.ReadByte();

                    stream.ReadBytes(StaticUtils.GetUTF8ByteCount(tokens[1]), slices);
                    node.AddField("Result", tokens[1], "Result.", slices);
                }

                // Set a description
                string result = tokens[1];
                if (result.Length > MAX_DESCRIPTION_LENGTH)
                {
                    result = result.Substring(0, MAX_DESCRIPTION_LENGTH - ellipsis.Length) + ellipsis;
                }

                node.Description = result;
            }

            stream.ReadBytes(2);

            TransactionNode headersNode = new TransactionNode("Headers");
            Dictionary<string, string> headerFields = new Dictionary<string, string>();

            do
            {
                line = stream.PeekLineUTF8();
                if (line.Length > 0)
                {
                    tokens = line.Split(new char[] { ':' }, 2);
                    if (tokens.Length < 2)
                        throw new ProtocolError();

                    string key = tokens[0];
                    string value = tokens[1].TrimStart();

                    stream.ReadBytes(StaticUtils.GetUTF8ByteCount(line), slices);
                    headersNode.AddField(key, value, "Header field.", slices);

                    headerFields[key.ToLower()] = value;
                }

                stream.ReadBytes(2);
            } while (line != "");

            if (headersNode.Fields.Count > 0)
            {
                node.AddChild(headersNode);
            }

            int contentLen = -1;

            if (headerFields.ContainsKey("content-length"))
                contentLen = Convert.ToInt32(headerFields["content-length"]);
            else if (headerFields.ContainsKey("contentlength"))
                contentLen = Convert.ToInt32(headerFields["contentlength"]);

            if (contentLen != -1)
            {
                string contentType = null, contentEncoding = null;

                if (headerFields.ContainsKey("content-type"))
                    contentType = headerFields["content-type"];
                else if (headerFields.ContainsKey("contenttype"))
                    contentType = headerFields["contenttype"];
 
                if (contentType != null)
                {
                    contentType = contentType.ToLower();

                    tokens = contentType.Split(new char[] { ';' });
                    contentType = tokens[0].Trim();
                    if (tokens.Length > 1)
                    {
                        string[] encTokens = tokens[1].Split(new char[] { '=' }, 2);
                        if (encTokens[0].Trim() == "charset" && encTokens.Length > 1)
                        {
                            contentEncoding = encTokens[1];
                        }
                    }
                }

                string str = stream.PeekStringASCII(5);
                if (str == "<?xml")
                {
                    contentType = "text/xml";
                    contentEncoding = "utf-8"; // FIXME
                }

                if (contentLen > 0)
                {
                    AddBodyNode(stream, node, contentType, contentEncoding, contentLen);
                }
            }
            
            return node;
        }
Example #14
0
 private TransactionNode ExtractHttpData(PacketStream stream, HTTPTransactionType type)
 {
     return ExtractHttpData(stream, type, null);
 }