Exemplo n.º 1
0
    def ip_fragment(self, packet, logger):
        """
        Perform IP fragmentation.
        """
        if not packet.haslayer("IP") or not hasattr(packet["IP"], "load"):
            return packet, packet.copy(
            )  # duplicate if no TCP or no payload to segment
        load = ""
        if packet.haslayer("TCP"):
            load = bytes(packet["TCP"])
        elif packet.haslayer("UDP"):
            load = bytes(packet["UDP"])
        else:
            load = bytes(packet["IP"].load)

        # If there is no load, duplicate the packet
        if not load:
            return packet, packet.copy()

        if self.fragsize == -1 or (self.fragsize *
                                   8) > len(load) or len(load) <= 8:
            fragsize = int(int(((int(len(load) / 2)) / 8)) * 8)
            frags = self.fragment(packet.copy().packet, fragsize=fragsize)
        else:
            # packet can be fragmented as requested
            frags = self.fragment(packet.copy().packet,
                                  fragsize=self.fragsize * 8)
        packet1 = layers.packet.Packet(frags[0])
        packet2 = layers.packet.Packet(frags[1])
        if self.correct_order:
            return packet1, packet2
        else:
            return packet2, packet1
Exemplo n.º 2
0
    def __packet_callback(self, scapy_packet):
        """
        This callback is called whenever a packet is applied.
        Returns true if it should finish, otherwise, returns false.
        """
        packet = layers.packet.Packet(scapy_packet)
        for proto in ["TCP", "UDP"]:
            if(packet.haslayer(proto) and ((packet[proto].sport == self.port) or (packet[proto].dport == self.port))):
                break
        else:
            return self.stop_sniffing_flag

        self.logger.debug(str(packet))
        self.packet_dumper.write(scapy_packet)
        return self.stop_sniffing_flag
Exemplo n.º 3
0
    def in_callback(self, nfpacket):
        """
        Callback bound to the incoming nfqueue rule. Since we can't
        manually send packets to ourself, process the given packet here.
        """
        if not self.running_nfqueue:
            return
        packet = layers.packet.Packet(IP(nfpacket.get_payload()))

        if self.save_seen_packets:
            self.seen_packets.append(packet)

        self.logger.debug("Received packet: %s", str(packet))

        # Run the given strategy
        packets = self.strategy.act_on_packet(packet,
                                              self.logger,
                                              direction="in")

        # GFW will send RA packets to disrupt a TCP stream
        if packet.haslayer("TCP") and packet.get("TCP", "flags") == "RA":
            self.censorship_detected = True

        # Branching is disabled for the in direction, so we can only ever get
        # back 1 or 0 packets. If zero, drop the packet.
        if not packets:
            nfpacket.drop()
            return

        if self.forwarder:
            nfpacket.drop()
            self.handle_packet(packet)
            return

        # Otherwise, overwrite this packet with the packet the action trees gave back
        nfpacket.set_payload(bytes(packets[0]))

        # If the strategy requested us to sleep before accepting on this packet, do so here
        if packets[0].sleep:
            time.sleep(packets[0].sleep)

        # Accept the modified packet
        nfpacket.accept()
Exemplo n.º 4
0
    def is_applicable(self, packet, logger):
        """
        Checks if this trigger is applicable to a given packet.
        """
        will_run = False
        self.num_seen += 1
        if not packet.haslayer(self.trigger_proto):
            return False

        packet_value = packet.get(self.trigger_proto, self.trigger_field)
        if self.has_wildcard:
            will_run = (self.trigger_value in packet_value)
        else:
            will_run = (self.trigger_value == packet_value)

        # Track if this action is used
        if (not GAS_ENABLED or self.gas_remaining is None) and will_run:
            self.ran = True
        # If this is a normal trigger and we are out of gas, do not run
        elif not self.bomb_trigger and will_run and self.gas_remaining == 0:
            will_run = False
        # If this is a bomb trigger, run once gas hits zero
        elif self.bomb_trigger and will_run and self.gas_remaining == 0:
            self.ran = True
        # If this is a normal trigger and we still have gas remaining, run and
        # decrement the gas
        elif will_run and self.gas_remaining > 0:
            # Gas is enabled and we haven't run out yet, subtract one from our gas
            self.gas_remaining -= 1
            self.ran = True
        # A bomb trigger has negative gas - it does not allow the action to run until the trigger
        # matches x times
        elif will_run and self.gas_remaining < 0:
            self.gas_remaining += 1
            will_run = False

        return will_run
Exemplo n.º 5
0
    def tcp_segment(self, packet, logger):
        """
        Segments a packet into two, given the size of the first packet (0:fragsize)
        Always returns two packets, since fragment is a branching action, so if we
        are unable to segment, it will duplicate the packet.

        If overlap is specified, it will select n bytes from the second packet
        and append them to the first, and increment the sequence number accordingly
        """
        if not packet.haslayer("TCP") or not hasattr(
                packet["TCP"], "load") or not packet["TCP"].load:
            return packet, packet.copy(
            )  # duplicate if no TCP or no payload to segment

        # Get the original payload and delete it from the packet so it
        # doesn't come along when copying the TCP layer
        payload = packet["TCP"].load
        del (packet["TCP"].load)

        fragsize = self.fragsize
        if self.fragsize == -1 or self.fragsize > len(payload) - 1:
            fragsize = int(len(payload) / 2)

        # Craft new packets

        # Make sure we don't go out of bounds by choosing the min
        overlap_bytes = min(len(payload[fragsize:]), self.overlap)
        # Attach these bytes to the first packet
        pkt1 = IP(packet["IP"]) / payload[:fragsize + overlap_bytes]
        pkt2 = IP(packet["IP"]) / payload[fragsize:]

        # We cannot rely on scapy's native parsing here - if a previous action has changed the
        # fragment offset, scapy will not identify this as TCP, so we must do it for scapy
        if not pkt1.haslayer("TCP"):
            pkt1 = IP(packet["IP"]) / TCP(bytes(pkt1["IP"].load))

        if not pkt2.haslayer("TCP"):
            pkt2 = IP(packet["IP"]) / TCP(bytes(pkt2["IP"].load))

        packet1 = layers.packet.Packet(pkt1)
        packet2 = layers.packet.Packet(pkt2)

        # Reset packet2's SYN number
        if packet2["TCP"].seq + fragsize > MAX_UINT:
            # Wrap sequence numbers around if greater than MAX_UINT
            packet2["TCP"].seq = packet2["TCP"].seq + fragsize - MAX_UINT - 1
        else:
            packet2["TCP"].seq += fragsize

        del packet1["IP"].chksum
        del packet2["IP"].chksum
        del packet1["IP"].len
        del packet2["IP"].len
        del packet1["TCP"].chksum
        del packet2["TCP"].chksum
        del packet1["TCP"].dataofs
        del packet2["TCP"].dataofs

        if self.correct_order:
            return [packet1, packet2]
        else:
            return [packet2, packet1]