Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support + Overlapping Segmentation #14

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ install:
# Copy in the sudoers file
- sudo cp /tmp/sudoers.tmp /etc/sudoers
# Now that sudo is good to go, finish installing dependencies
- sudo python3 -m pip install -r requirements.txt
- sudo python3 -m pip install -r requirements_linux.txt
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we work on a windows test in travis?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts? Can't run travis on windows

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a branch to add testing with Circle CI - I’ll message you

- sudo python3 -m pip install slackclient pytest-cov

script:
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ This code release specifically contains the strategy engine used by Geneva, its

## Setup

Geneva has been developed and tested for Centos or Debian-based systems. Due to limitations of
netfilter and raw sockets, Geneva does not work on OS X or Windows at this time and requires *python3.6* (with more versions coming soon).
Geneva has been developed and tested for Centos or Debian-based systems. Windows support is currently in beta and requires more testing, but is available in this repository. Due to limitations of netfilter and raw sockets, Geneva does not work on OS X at this time and requires *python3.6* on Linux (with more versions coming soon).

Install netfilterqueue dependencies:
Install netfilterqueue dependencies (Linux):
```
# sudo apt-get install build-essential python-dev libnetfilter-queue-dev libffi-dev libssl-dev iptables python3-pip
```

Install Python dependencies:
Install Python dependencies (Linux):
```
# python3 -m pip install -r requirements.txt
# python3 -m pip install -r requirements_linux.txt
```

Install Python dependencies (Windows):
```
# python3 -m pip install -r requirements_windows.txt
```

## Running it
Expand Down
47 changes: 37 additions & 10 deletions actions/fragment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


class FragmentAction(Action):
def __init__(self, environment_id=None, correct_order=None, fragsize=-1, segment=True):
def __init__(self, environment_id=None, correct_order=None, fragsize=-1, segment=True, overlap=0):
Kkevsterrr marked this conversation as resolved.
Show resolved Hide resolved
'''
correct_order specifies if the fragmented packets should come in the correct order
fragsize specifies how
Expand All @@ -17,6 +17,7 @@ def __init__(self, environment_id=None, correct_order=None, fragsize=-1, segment
self.terminal = False
self.fragsize = fragsize
self.segment = segment
self.overlap = overlap

if correct_order == None:
self.correct_order = self.get_rand_order()
Expand Down Expand Up @@ -87,6 +88,9 @@ 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
Expand All @@ -101,7 +105,11 @@ def tcp_segment(self, packet, logger):
fragsize = int(len(payload)/2)

# Craft new packets
pkt1 = IP(packet["IP"])/payload[:fragsize]

# Make sure we don't go out of bounds by choosing the min
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:]

# We cannot rely on scapy's native parsing here - if a previous action has changed the
Expand Down Expand Up @@ -147,10 +155,15 @@ def __str__(self):
Returns a string representation with the fragsize
"""
s = Action.__str__(self)
if self.overlap == 0:
ending = "}"
else:
ending = ":" + str(self.overlap) + "}"

if self.segment:
s += "{" + "tcp" + ":" + str(self.fragsize) + ":" + str(self.correct_order) + "}"
s += "{" + "tcp" + ":" + str(self.fragsize) + ":" + str(self.correct_order) + ending
else:
s += "{" + "ip" + ":"+ str(self.fragsize) + ":" + str(self.correct_order) + "}"
s += "{" + "ip" + ":"+ str(self.fragsize) + ":" + str(self.correct_order) + ending
return s

def parse(self, string, logger):
Expand All @@ -169,22 +182,36 @@ def parse(self, string, logger):
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)
Expand Down
20 changes: 12 additions & 8 deletions actions/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,15 @@ def get_interface():
"""
Chooses an interface on the machine to use for socket testing.
"""
ifaces = netifaces.interfaces()
for iface in ifaces:
if "lo" in iface:
continue
info = netifaces.ifaddresses(iface)
# Filter for IPv4 addresses
if netifaces.AF_INET in info:
return iface
if os.name == 'nt':
# Windows code
return
else:
ecthros marked this conversation as resolved.
Show resolved Hide resolved
ifaces = netifaces.interfaces()
for iface in ifaces:
if "lo" in iface:
continue
info = netifaces.ifaddresses(iface)
# Filter for IPv4 addresses
if netifaces.AF_INET in info:
return iface
Loading