Ejemplo n.º 1
0
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out IEEE802_11 packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        var frameControlVersionTypeAndSubtype = new BitVector32(br.ReadByte());
                        var frameControlFlags = new BitVector32(br.ReadByte());
                        var durationID        = br.ReadUInt16();

                        var toDS   = frameControlFlags[1];
                        var fromDS = frameControlFlags[2];

                        byte[] destination;
                        byte[] source;
                        byte[] bssid;
                        byte[] receiver    = null;
                        byte[] transmitter = null;
                        UInt16 sequenceControl;

                        if (!toDS)
                        {
                            destination = br.ReadBytes(6);

                            if (!fromDS)
                            {
                                source = br.ReadBytes(6);
                                bssid  = br.ReadBytes(6);
                            }
                            else
                            {
                                bssid  = br.ReadBytes(6);
                                source = br.ReadBytes(6);
                            }
                            sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees
                        }
                        else
                        {
                            if (!fromDS)
                            {
                                bssid           = br.ReadBytes(6);
                                source          = br.ReadBytes(6);
                                destination     = br.ReadBytes(6);
                                sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees
                            }
                            else
                            {
                                receiver        = br.ReadBytes(6);
                                transmitter     = br.ReadBytes(6);
                                bssid           = transmitter;     //Per airdecap-ng
                                destination     = br.ReadBytes(6);
                                sequenceControl = br.ReadUInt16(); //Was NTHO, wireshark disagrees
                                source          = br.ReadBytes(6);
                            }
                        }

                        var frameType =
                            frameControlVersionTypeAndSubtype[BitVector32.CreateSection(3, BitVector32.CreateSection(3))
                            ];
                        var subType =
                            frameControlVersionTypeAndSubtype[
                                BitVector32.CreateSection(15, BitVector32.CreateSection(15))];

                        byte[] qosControl = null;
                        if (frameType == (int)FrameTypes.Data && subType == (int)DataSubTypes.QoS)
                        {
                            qosControl = br.ReadBytes(2);
                        }

                        var    isProtected   = frameControlFlags[64];
                        byte[] ccmp_WEP_Data = null;

                        if (isProtected)
                        {
                            if (count - br.BaseStream.Position < 4)
                            {
                                packet = null;
                                return(false);
                            }
                            var firstFour = br.ReadBytes(4);
                            if (firstFour[3] == 0)
                            {
                                ccmp_WEP_Data = firstFour;
                            }
                            else
                            {
                                if (count - br.BaseStream.Position < 4)
                                {
                                    packet = null;
                                    return(false);
                                }
                                ccmp_WEP_Data = new byte[8];
                                firstFour.CopyTo(ccmp_WEP_Data, 0);
                                br.ReadBytes(4).CopyTo(ccmp_WEP_Data, 4);
                            }
                        }

                        var isWep = isProtected && ccmp_WEP_Data?.Length == 4;

                        if (count - br.BaseStream.Position - (isWep ? 4 : 0) < 0)
                        {
                            packet = null;
                            return(false);
                        }

                        var unsafePayloadLen = count - (int)br.BaseStream.Position - (isWep ? 4 : 0);
                        var safePayloadLen   = Math.Max(0, unsafePayloadLen);

                        packet = null;

                        if (frameType == (int)FrameTypes.Data && ((subType & 4) != 1) && !isProtected)
                        {
                            LLC payload;
                            if (LLC.TryParse(buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload))
                            {
                                packet = new IEEE802_11 <LLC> {
                                    Payload = payload
                                };
                            }
                        }
                        else if (frameType == (int)FrameTypes.Management && subType == (int)ManagementSubTypes.Beacon)
                        {
                            Beacon802_11 payload;
                            if (Beacon802_11.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position,
                                    safePayloadLen,
                                    out payload))
                            {
                                packet = new IEEE802_11 <Beacon802_11> {
                                    Payload = payload
                                };
                            }
                        }

                        if (packet == null)
                        {
                            Generic payload;
                            Generic.TryParse(buffer, index + (int)br.BaseStream.Position, safePayloadLen, out payload);

                            // This can never fail, so I'm not checking the output
                            packet = new IEEE802_11 <Generic> {
                                Payload = payload
                            };
                        }

                        br.BaseStream.Seek(packet.Payload.Length(), SeekOrigin.Current);

                        UInt32 wep_ICV = 0;
                        if (isWep)
                        {
                            wep_ICV = ByteOrder.NetworkToHostOrder(br.ReadUInt32());
                        }

                        packet.FrameControlVersionTypeAndSubtype = frameControlVersionTypeAndSubtype;
                        packet.FrameControlFlags = frameControlFlags;
                        packet.DurationID        = durationID;
                        packet.Destination       = destination;
                        packet.Source            = source;
                        packet.BSSID             = bssid;
                        packet.SequenceControl   = sequenceControl;
                        packet.Receiver          = receiver;
                        packet.Transmitter       = transmitter;
                        packet.QosControl        = qosControl;
                        packet.CCMP_WEP_Data     = ccmp_WEP_Data;
                        packet.WEP_ICV           = wep_ICV;

                        if (br.BaseStream.Position == count - 4)
                        {
                            packet.FrameCheckSequence = br.ReadUInt32();
                        }

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out Beacon802_11 packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return(false);
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        packet = new Beacon802_11();

                        packet.Timestamp      = br.ReadUInt64();
                        packet.BeaconInterval = br.ReadBytes(2);
                        packet.Capabilities   = br.ReadUInt16();

                        while (br.BaseStream.Position <= count - 2)
                        {
                            IManagementTag newTag     = null;
                            var            tagType    = br.ReadByte();
                            var            tagLength  = br.ReadByte();
                            var            safeLength = Math.Min(tagLength, count - (int)br.BaseStream.Position);
                            switch (tagType)
                            {
                            case (byte)ManagementTagTypes.SSID:
                            {
                                SSIDTag tag;
                                if (SSIDTag.TryParse(
                                        buffer,
                                        index + (int)br.BaseStream.Position - 2,
                                        2 + safeLength,
                                        out tag))
                                {
                                    newTag = tag;
                                }
                            }
                            break;

                            case (byte)ManagementTagTypes.VendorSpecific:
                            {
                                /* We'll ask each vendor to parse. Not the most efficient solution.
                                 * MSTag msTag;
                                 * if (MSTag.TryParse(
                                 *  buffer,
                                 *  index + (int)br.BaseStream.Position - 2,
                                 *  2 + safeLength,
                                 *  out msTag))
                                 * {
                                 *  newTag = msTag;
                                 * }
                                 * else
                                 * {*/
                                VendorTag tag;
                                if (VendorTag.TryParse(
                                        buffer,
                                        index + (int)br.BaseStream.Position - 2,
                                        2 + safeLength,
                                        out tag))
                                {
                                    newTag = tag;
                                }
                                /*}*/
                            }
                            break;
                            }

                            if (newTag == null)
                            {
                                UnsupportedTag tag;
                                UnsupportedTag.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position - 2,
                                    2 + safeLength,
                                    out tag);
                                newTag = tag;
                            }
                            br.BaseStream.Seek(safeLength, SeekOrigin.Current);
                            packet.Tags.Add(newTag);
                        }

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return(false);
            }
        }
        /// <summary>
        ///     Attempts to parse raw data into a structured packet
        /// </summary>
        /// <param name="buffer">Raw data to parse</param>
        /// <param name="packet">Parsed packet</param>
        /// <param name="count">The length of the packet in bytes</param>
        /// <param name="index">The index into the buffer at which the packet begins</param>
        /// <returns>True if parsing was successful, false if it is not.</returns>
        internal static bool TryParse(byte[] buffer, int index, int count, out Beacon802_11 packet)
        {
            try
            {
                if (count < MinimumParseableBytes)
                {
                    packet = null;
                    return false;
                }

                using (var ms = new MemoryStream(buffer, index, count, false))
                {
                    using (var br = new BinaryReader(ms))
                    {
                        packet = new Beacon802_11();

                        packet.Timestamp = br.ReadUInt64();
                        packet.BeaconInterval = br.ReadBytes(2);
                        packet.Capabilities = br.ReadUInt16();

                        while (br.BaseStream.Position <= count - 2)
                        {
                            IManagementTag newTag = null;
                            var tagType = br.ReadByte();
                            var tagLength = br.ReadByte();
                            var safeLength = Math.Min(tagLength, count - (int)br.BaseStream.Position);
                            switch (tagType)
                            {
                                case (byte)ManagementTagTypes.SSID:
                                    {
                                        SSIDTag tag;
                                        if (SSIDTag.TryParse(
                                            buffer,
                                            index + (int)br.BaseStream.Position - 2,
                                            2 + safeLength,
                                            out tag))
                                        {
                                            newTag = tag;
                                        }
                                    }
                                    break;
                                case (byte)ManagementTagTypes.VendorSpecific:
                                    {
                                        // We'll ask each vendor to parse. Not the most efficient solution.
                                        MSTag msTag;
                                        if (MSTag.TryParse(
                                            buffer,
                                            index + (int)br.BaseStream.Position - 2,
                                            2 + safeLength,
                                            out msTag))
                                        {
                                            newTag = msTag;
                                        }
                                        else
                                        {
                                            VendorTag tag;
                                            if (VendorTag.TryParse(
                                                buffer,
                                                index + (int)br.BaseStream.Position - 2,
                                                2 + safeLength,
                                                out tag))
                                            {
                                                newTag = tag;
                                            }
                                        }
                                    }
                                    break;
                            }

                            if (newTag == null)
                            {
                                UnsupportedTag tag;
                                UnsupportedTag.TryParse(
                                    buffer,
                                    index + (int)br.BaseStream.Position - 2,
                                    2 + safeLength,
                                    out tag);
                                newTag = tag;
                            }
                            br.BaseStream.Seek(safeLength, SeekOrigin.Current);
                            packet.Tags.Add(newTag);
                        }

                        return true;
                    }
                }
            }
            catch (Exception)
            {
                packet = null;
                return false;
            }
        }