- 我正在尝试使用 Scapy 在 GRE 和 IP 之间插入 GRErouting 层。我正在阅读的 pcap 包含一个堆叠如下的数据包:Ethernet/IPv4/GRE/IPv4/ICMP。我看到的是 getLayer 返回当前层 + 它的有效载荷,其中可能包括其他层,这对我不利。我只想获取当前图层。当我为每一层执行 getLayer,然后写入整个数组时,我得到一个奇怪的 pcap,因为每一层都有额外的有效负载。
我也无法使用简单的“打印”将任何数据输出到控制台。我知道这是因为 Scapy 添加了日志记录模块,并禁止了系统日志记录,但我想知道如何撤消它并能够使用“打印”语句。
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])))
问问题
2437 次
1 回答
2
我终于能够回答我自己的两个问题了。请参阅下面的修改代码:
# 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]))))
于 2013-07-02T06:51:17.607 回答