Defining New Actions¶
It is simple to add a new packet-level action to Geneva.
Let us assume we are adding a new action, called “mytamper”, which simply sets the ipid
field of a packet.
Our action will take 1 packet and return 1 packet, and we’ll start by making it always set the IPID to 1.
We will subclasss the Action
class, and specify an __init__
method and a run
method.
In the __init__
method, we will specify that our action’s name is ‘mytamper’ and can run in both
inbound and outbound.
Then, in the run()
method, we will use Geneva’s packet API to set the ipid
field to 1 and simply return the packet.
from actions.action import Action
class MyTamperAction(Action):
"""
Geneva action to set the IPID to 1.
"""
# Controls frequency with which this action is chosen by the genetic algorithm
# during mutation
frequency = 0
def __init__(self, environment_id=None):
Action.__init__(self, "mytamper", "both")
def run(self, packet, logger):
"""
The mytamper action returns a modified packet as the left child.
"""
logger.debug(" - Changing IPID field to 1")
packet.set("IP", "ipid", 1)
return packet, None
And that’s it! Now, we can specify this action in our normal strategy DNA: Geneva will discover it dynamically on startup, import it, and we can use it.
Adding Parameters¶
Let’s now assume we want to make our action take parameters. We will add two new methods: parse()
and __str__()
.
We’ll start by adding a new instance variable self.ipid_value
.
def __init__(self, environment_id=None, ipid_value=1):
Action.__init__(self, "mytamper", "both")
self.ipid_value = ipid_value
Next, we’ll add the __str__
method so when our action is printed in the strategy DNA, its components are too:
def __str__(self):
"""
Returns a string representation.
"""
s = Action.__str__(self)
s += "{%g}" % self.ipid_value
return s
Finally, we’ll add the parse()
method so we can parse the value from a string strategy DNA to a live action.
def parse(self, string, logger):
"""
Parses a string representation for this object.
"""
try:
if string:
self.ipid_value = float(string)
except ValueError:
logger.exception("Cannot parse ipid_value %s" % string)
return False
return True
Putting it all together:
from actions.action import Action
class MyTamperAction(Action):
"""
Geneva action to set the IPID to 1.
"""
# Controls frequency with which this action is chosen by the genetic algorithm
# during mutation
frequency = 0
def __init__(self, environment_id=None, ipid_value=1):
Action.__init__(self, "mytamper", "both")
self.ipid_value = ipid_value
def run(self, packet, logger):
"""
The mytamper action returns a modified packet as the left child.
"""
logger.debug(" - Changing IPID field to 1")
packet.set("IP", "ipid", 1)
return packet, None
def __str__(self):
"""
Returns a string representation.
"""
s = Action.__str__(self)
s += "{%g}" % self.ipid_value
return s
def parse(self, string, logger):
"""
Parses a string representation for this object.
"""
try:
if string:
self.ipid_value = float(string)
except ValueError:
logger.exception("Cannot parse ipid_value %s" % string)
return False
return True
And we’re done! Now, we can write strategies like: [TCP:flags:PA]-mytamper{10}-|
, and any TCP packet with the flags field set to PA
will have its ipid
field set to 10.