- I am attempting to insert GRErouting layer in between GRE and IP using Scapy. The pcap I am reading contains a single packet stacked as follows: Ethernet/IPv4/GRE/IPv4/ICMP. What I see is that getLayer returns the current layer + its payload, which may include other layers, and that's not good for me. I would like to only get the current layer. When I do getLayer for each layer, and then write the entire array I get a strange pcap because of the additional payload that each layer has over it.
I am also not able to use a simple 'print' to output any data to console. I understand this is because Scapy adds the logging module, and suppresses system logging, but I'd like to know how to undo that and be able to use the 'print' statement.
import os import sys import logging logging.basicConfig() logging.getLogger("scapy.runtime").setLevel(logging.ERROR) from scapy.all import PcapReader, PcapWriter, fuzz, Packet from scapy.layers.l2 import GRE, GRErouting from scapy.layers.inet import IP logging.getLogger("scapy.runtime").setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG) def foo(in_filename, out_filename): f = PcapReader(in_filename) o = PcapWriter(out_filename) p = f.read_packet() while p: layers = [] counter = 0 while True: layer = p.getlayer(counter) if (layer != None): layers.append(layer) if (type(layer) is IP): del layer.chksum if (type(layer) is GRE): logging.getLogger().debug("there is a GRE layer") layer.routing_present = 1 gr = GRErouting() fuzz(gr) layers.append(gr) del layer.chksum else: break counter += 1 logging.getLogger().debug("Layers are: %s\t\t",layers) for l in layers: logging.getLogger().debug("%s", l) o.write(layers) p = f.read_packet() f.close() o.close() if __name__ == "__main__": logging.getLogger().debug('Executing main') if (len(sys.argv) == 3): in_filename = str(sys.argv[1]) out_filename = str(sys.argv[2]) if os.path.exists(in_filename) == False: sys.stderr.write("Either {0} does not exist, or you do not have proper permissions\n".format(in_filename)) else: foo(in_filename, out_filename) else: sys.stderr.write("USAGE: {0} <path to input file> <path to output file>\n".format(str(sys.argv[0])))
Asked
Active
Viewed 2,825 times
1

c-is-best
- 146
- 2
- 9
1 Answers
2
I was finally able to answer my own two questions. See modified code below:
# importing the os package (see api at http://docs.python.org/2.6/library/io.html)
import os
# import function 'basename' from module os.path
from os.path import basename
# importing the sys package (see api at http://docs.python.org/2.6/library/sys.html)
import sys
# importing the logging package (see api at http://docs.python.org/2.6/library/logging.html)
import logging
# by default Scapy attempts to find ipv6 routing information,
# and if it does not find any it prints out a warning when running the module.
# the following statement changes log level to ERROR so that this warning will not
# occur
effective_level = logging.getLogger("scapy.runtime").getEffectiveLevel()
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
# importing Scapy
from scapy.all import PcapReader, PcapWriter
from scapy.layers.l2 import GRE, GRErouting, NoPayload
# return the log level o be what it was
logging.getLogger("scapy.runtime").setLevel(effective_level)
# unfortunately, somewhere in Scapy sys.stdout is being reset.
# thus, using the 'print' command will not produce output to the console.
# the following two lines place stdout back into sys.
if sys.stdout != sys.__stdout__:
sys.stdout = sys.__stdout__
# this is a function declaration. there is no need for explicit types.
# python can infer an object type from its usage
def foo(in_filename, out_filename):
# open the input file for reading
f = PcapReader(in_filename)
# open the output file for writing
o = PcapWriter(out_filename)
# read the first packet from the input file
p = f.read_packet()
# while we haven't processed the last packet
while p:
# gets the first layer of the current packet
layer = p.firstlayer()
# loop over the layers
while not isinstance(layer, NoPayload):
if layer.default_fields.has_key('chksum'):
del layer.chksum
if layer.default_fields.has_key('len'):
del layer.len
if (type(layer) is GRE):
layer.routing_present = 1
layer.chksum_present = 1
# make sure to delete the checksum field. hopefully scapy will calculate it correctly one day
del layer.chksum
gr = GRErouting()
gr.address_family = 0x0800
gr.SRE_len = 4
gr.SRE_offset = 0
gr.routing_info = "1111"
# the NULL routing field
empty_gr = GRErouting()
empty_gr.address_family = 0x0000
empty_gr.SRE_len = 0
gr.add_payload(empty_gr)
gr.add_payload(layer.payload)
layer.remove_payload()
layer.add_payload(gr)
layer = empty_gr
# advance to the next layer
layer = layer.payload
# write the packet we just dissected into the output file
o.write(p)
# read the next packet
p = f.read_packet()
# close the input file
f.close()
# close the output file
o.close()
# i believe this is needed only if we are running the this module
# as the main module. i don't know if this will get executed if this module
# is imported into some other main module
if __name__ == "__main__":
# letting the user know we are starting.
# sys.argv[0] includes the path to the module, including the module name.
# convert sys.argv[0] into string, and extract the module name only
# (using basename)
print '===> Running', basename(str(sys.argv[0]))
# making sure that two parameters were entered on the command line
if (len(sys.argv) == 3):
# get the path to the input file
in_filename = str(sys.argv[1])
# get the path to the output file
out_filename = str(sys.argv[2])
# make sure the input file actually exists.
# if it doesn't, we print out an error and exit
if os.path.exists(in_filename) == False:
# note the method for entering conversion specifiers ({<ordinal>})
sys.stderr.write("Either {0} does not exist, or you do not have proper permissions\n".format(in_filename))
else:
# if the input file does exist, execute 'foo'
foo(in_filename, out_filename)
# print an end script notification
print basename(str(sys.argv[0])), '===> completed successfully'
else:
# write a USAGE message to the standard output stream
sys.stderr.write("USAGE: {0} <path to input file> <path to output file>\n".format(basename(str(sys.argv[0]))))

c-is-best
- 146
- 2
- 9