diff --git a/actions/fragment.py b/actions/fragment.py index a0701c8..d47f37b 100644 --- a/actions/fragment.py +++ b/actions/fragment.py @@ -107,7 +107,7 @@ class FragmentAction(Action): # Craft new packets # Make sure we don't go out of bounds by choosing the min - overlapBytes = min(payload[fragsize:], overlap) + overlapBytes = min(len(payload[fragsize:]), self.overlap) # Attach these bytes to the first packet pkt1 = IP(packet["IP"])/payload[:fragsize + overlapBytes] pkt2 = IP(packet["IP"])/payload[fragsize:] @@ -155,10 +155,15 @@ class FragmentAction(Action): Returns a string representation with the fragsize """ s = Action.__str__(self) - if self.segment: - s += "{" + "tcp" + ":" + str(self.fragsize) + ":" + str(self.correct_order) + "}" + if self.overlap == 0: + ending = "}" else: - s += "{" + "ip" + ":"+ str(self.fragsize) + ":" + str(self.correct_order) + "}" + ending = ":" + str(self.overlap) + "}" + + if self.segment: + s += "{" + "tcp" + ":" + str(self.fragsize) + ":" + str(self.correct_order) + ending + else: + s += "{" + "ip" + ":"+ str(self.fragsize) + ":" + str(self.correct_order) + ending return s def parse(self, string, logger): @@ -177,22 +182,36 @@ class FragmentAction(Action): num_parameters = string.count(":") # If num_parameters is greater than 2, it's not a valid fragment action - if num_parameters != 2: - msg = "Cannot parse fragment action %s" % string - logger.error(msg) - raise Exception(msg) - else: + if num_parameters == 2: params = string.split(":") seg, fragsize, correct_order = params + overlap = 0 if "tcp" in seg: self.segment = True else: self.segment = False + elif num_parameters == 3: + params = string.split(":") + seg, fragsize, correct_order, overlap = params + if overlap.endswith("}"): + overlap = overlap[:-1] # Chop off trailing } + if "tcp" in seg: + self.segment = True + else: + self.segment = False + + else: + msg = "Cannot parse fragment action %s" % string + logger.error(msg) + raise Exception(msg) + try: # Try to convert to int self.fragsize = int(fragsize) - except ValueError: + self.overlap = int(overlap) + except ValueError as e: + print(e) msg = "Cannot parse fragment action %s" % string logger.error(msg) raise Exception(msg) diff --git a/tests/test_fragment.py b/tests/test_fragment.py index 3e7bcee..5beaec3 100644 --- a/tests/test_fragment.py +++ b/tests/test_fragment.py @@ -217,4 +217,78 @@ def test_ip_only_fragment(): assert packet1["Raw"].load == b'datadata', "Left packet incorrectly fragmented" assert packet2["Raw"].load == b"11datadata", "Right packet incorrectly fragmented" +def test_overlapping_segment(): + """ + Basic test for overlapping segments. + """ + fragment = actions.fragment.FragmentAction(correct_order=True) + fragment.parse("fragment{tcp:-1:True:4}", logger) + packet = actions.packet.Packet(IP(src="127.0.0.1", dst="127.0.0.1")/TCP(seq=100)/("datadata11datadata")) + packet1, packet2 = fragment.run(packet, logger) + + assert id(packet1) != id(packet2), "Duplicate aliased packet objects" + + assert packet1["Raw"].load != packet2["Raw"].load, "Packets were not different" + assert packet1["Raw"].load == b'datadata11dat', "Left packet incorrectly segmented" + assert packet2["Raw"].load == b"1datadata", "Right packet incorrectly fragmented" + + assert packet1["TCP"].seq == 100, "First packet sequence number incorrect" + assert packet2["TCP"].seq == 109, "Second packet sequence number incorrect" + +def test_overlapping_segment_no_overlap(): + """ + Basic test for overlapping segments with no overlap. (shouldn't ever actually happen) + """ + fragment = actions.fragment.FragmentAction(correct_order=True) + fragment.parse("fragment{tcp:-1:True:0}", logger) + + packet = actions.packet.Packet(IP(src="127.0.0.1", dst="127.0.0.1")/TCP(seq=100)/("datadata11datadata")) + packet1, packet2 = fragment.run(packet, logger) + + assert id(packet1) != id(packet2), "Duplicate aliased packet objects" + + assert packet1["Raw"].load != packet2["Raw"].load, "Packets were not different" + assert packet1["Raw"].load == b'datadata1', "Left packet incorrectly segmented" + assert packet2["Raw"].load == b"1datadata", "Right packet incorrectly fragmented" + + assert packet1["TCP"].seq == 100, "First packet sequence number incorrect" + assert packet2["TCP"].seq == 109, "Second packet sequence number incorrect" + +def test_overlapping_segment_entire_packet(): + """ + Basic test for overlapping segments overlapping entire packet. + """ + fragment = actions.fragment.FragmentAction(correct_order=True) + fragment.parse("fragment{tcp:-1:True:9}", logger) + + packet = actions.packet.Packet(IP(src="127.0.0.1", dst="127.0.0.1")/TCP(seq=100)/("datadata11datadata")) + packet1, packet2 = fragment.run(packet, logger) + + assert id(packet1) != id(packet2), "Duplicate aliased packet objects" + + assert packet1["Raw"].load != packet2["Raw"].load, "Packets were not different" + assert packet1["Raw"].load == b'datadata11datadata', "Left packet incorrectly segmented" + assert packet2["Raw"].load == b"1datadata", "Right packet incorrectly fragmented" + + assert packet1["TCP"].seq == 100, "First packet sequence number incorrect" + assert packet2["TCP"].seq == 109, "Second packet sequence number incorrect" + +def test_overlapping_segment_out_of_bounds(): + """ + Basic test for overlapping segments overlapping beyond the edge of the packet. + """ + fragment = actions.fragment.FragmentAction(correct_order=True) + fragment.parse("fragment{tcp:-1:True:20}", logger) + + packet = actions.packet.Packet(IP(src="127.0.0.1", dst="127.0.0.1")/TCP(seq=100)/("datadata11datadata")) + packet1, packet2 = fragment.run(packet, logger) + + assert id(packet1) != id(packet2), "Duplicate aliased packet objects" + + assert packet1["Raw"].load != packet2["Raw"].load, "Packets were not different" + assert packet1["Raw"].load == b'datadata11datadata', "Left packet incorrectly segmented" + assert packet2["Raw"].load == b"1datadata", "Right packet incorrectly fragmented" + + assert packet1["TCP"].seq == 100, "First packet sequence number incorrect" + assert packet2["TCP"].seq == 109, "Second packet sequence number incorrect" \ No newline at end of file