X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=origin%2FCAPture.py;fp=origin%2FCAPture.py;h=0000000000000000000000000000000000000000;hb=2e874f57745e5a1ab10d57e18c6687f5546ab1b4;hp=4d6972ad12f083a21753c62f67624fbe418751a9;hpb=2422deddd73a43bbcbda776d6ddddba05318a2d2;p=pingpong.git diff --git a/origin/CAPture.py b/origin/CAPture.py deleted file mode 100644 index 4d6972a..0000000 --- a/origin/CAPture.py +++ /dev/null @@ -1,385 +0,0 @@ -#!/usr/local/bin/python2.7 - -""" ----------------------------------------------------------------------------- - CAPture - a pcap file analyzer and report generator - (c) 2017 - Rahmadi Trimananda - University of California, Irvine - Programming Language and Systems - ----------------------------------------------------------------------------- - Credits to tutorial: https://dpkt.readthedocs.io/en/latest/ - ----------------------------------------------------------------------------- -""" - -import datetime -import dpkt -from dpkt.compat import compat_ord - -import socket -import sys - -""" ----------------------------------------------------------------------------- - Global variable declarations - ----------------------------------------------------------------------------- -""" -# Command line arguments -INPUT = "-i" -OUTPUT = "-o" -POINT_TO_MANY = "-pm" -VERBOSE = "-v" - - -def mac_addr(address): - # Courtesy of: https://dpkt.readthedocs.io/en/latest/ - """ Convert a MAC address to a readable/printable string - Args: - address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') - Returns: - str: Printable/readable MAC address - """ - return ':'.join('%02x' % compat_ord(b) for b in address) - - -def inet_to_str(inet): - # Courtesy of: https://dpkt.readthedocs.io/en/latest/ - """ Convert inet object to a string - Args: - inet (inet struct): inet network address - Returns: - str: Printable/readable IP address - """ - # First try ipv4 and then ipv6 - try: - return socket.inet_ntop(socket.AF_INET, inet) - except ValueError: - return socket.inet_ntop(socket.AF_INET6, inet) - - -def show_usage(): - """ Show usage of this Python script - """ - print "Usage: python CAPture.py [ -i .pcap ] [ -o .pcap ] [ -pm ] [ -v ]" - print - print "[ -o ] = output file" - print "[ -pm ] = point-to-many analysis" - print "[ -v ] = verbose output" - print "By default, this script does simple statistical analysis of IP, TCP, and UDP packets." - print "(c) 2017 - University of California, Irvine - Programming Language and Systems" - - -def show_progress(verbose, counter): - """ Show packet processing progress - Args: - verbose: verbose output (True/False) - counter: counter of all packets - """ - if verbose: - print "Processing packet number: ", counter - else: - if counter % 100000 == 0: - print "Processing %s packets..." % counter - - -def show_summary(counter, ip_counter, tcp_counter, udp_counter): - """ Show summary of statistics of PCAP file - Args: - counter: counter of all packets - ip_counter: counter of all IP packets - tcp_counter: counter of all TCP packets - udp_counter: counter of all UDP packets - """ - print - print "Total number of packets in the pcap file: ", counter - print "Total number of ip packets: ", ip_counter - print "Total number of tcp packets: ", tcp_counter - print "Total number of udp packets: ", udp_counter - print - - -def save_to_file(tbl_header, dictionary, filename_out): - """ Show summary of statistics of PCAP file - Args: - tbl_header: header for the saved table - dictionary: dictionary to be saved - filename_out: file name to save - """ - # Appending, not overwriting! - f = open(filename_out, 'a') - # Write the table header - f.write("\n\n" + str(tbl_header) + "\n"); - # Iterate over dictionary and write (key, value) pairs - for key, value in dictionary.iteritems(): - f.write(str(key) + ", " + str(value) + "\n") - - f.close() - print "Writing output to file: ", filename_out - - -def statistical_analysis(verbose, pcap, counter, ip_counter, tcp_counter, udp_counter): - """ This is the default analysis of packet statistics (generic) - Args: - verbose: verbose output (True/False) - pcap: object that handles PCAP file content - counter: counter of all packets - ip_counter: counter of all IP packets - tcp_counter: counter of all TCP packets - udp_counter: counter of all UDP packets - """ - for time_stamp, packet in pcap: - - counter += 1 - eth = dpkt.ethernet.Ethernet(packet) - - if verbose: - # Print out the timestamp in UTC - print "Timestamp: ", str(datetime.datetime.utcfromtimestamp(time_stamp)) - # Print out the MAC addresses - print "Ethernet frame: ", mac_addr(eth.src), mac_addr(eth.dst), eth.data.__class__.__name__ - - # Process only IP data - if not isinstance(eth.data, dpkt.ip.IP): - - is_ip = False - if verbose: - print "Non IP packet type not analyzed... skipping..." - else: - is_ip = True - - if is_ip: - ip = eth.data - ip_counter += 1 - - # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) - do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) - more_fragments = bool(ip.off & dpkt.ip.IP_MF) - fragment_offset = ip.off & dpkt.ip.IP_OFFMASK - - if verbose: - # Print out the complete IP information - print "IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)\n" % \ - (inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl, do_not_fragment, - more_fragments, fragment_offset) - - # Count TCP packets - if ip.p == dpkt.ip.IP_PROTO_TCP: - tcp_counter += 1 - - # Count UDP packets - if ip.p == dpkt.ip.IP_PROTO_UDP: - udp_counter += 1 - - show_progress(verbose, counter) - - # Print general statistics - show_summary(counter, ip_counter, tcp_counter, udp_counter) - - -def point_to_many_analysis(filename_out, dev_add, verbose, pcap, counter, ip_counter, - tcp_counter, udp_counter): - """ This analysis presents how 1 device (MAC address or IP address) communicates - to every other device in the analyzed PCAP file. - Args: - dev_add: device address (MAC or IP address) - verbose: verbose output (True/False) - pcap: object that handles PCAP file content - counter: counter of all packets - ip_counter: counter of all IP packets - tcp_counter: counter of all TCP packets - udp_counter: counter of all UDP packets - """ - # Dictionary that preserves the mapping between destination address to frequency - mac2freq = dict() - ip2freq = dict() - for time_stamp, packet in pcap: - - counter += 1 - eth = dpkt.ethernet.Ethernet(packet) - - # Save the timestamp and MAC addresses - tstamp = str(datetime.datetime.utcfromtimestamp(time_stamp)) - mac_src = mac_addr(eth.src) - mac_dst = mac_addr(eth.dst) - - # Process only IP data - if not isinstance(eth.data, dpkt.ip.IP): - - is_ip = False - if verbose: - print "Non IP packet type not analyzed... skipping..." - print - else: - is_ip = True - - if is_ip: - ip = eth.data - ip_counter += 1 - - # Pull out fragment information (flags and offset all packed into off field, so use bitmasks) - do_not_fragment = bool(ip.off & dpkt.ip.IP_DF) - more_fragments = bool(ip.off & dpkt.ip.IP_MF) - fragment_offset = ip.off & dpkt.ip.IP_OFFMASK - - # Save IP addresses - ip_src = inet_to_str(ip.src) - ip_dst = inet_to_str(ip.dst) - - if verbose: - # Print out the complete IP information - print "IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)\n" % \ - (ip_src, ip_dst, ip.len, ip.ttl, do_not_fragment, - more_fragments, fragment_offset) - - # Categorize packets based on source device address - # Save the destination device addresses (point-to-many) - if dev_add == ip_src: - if ip_dst in ip2freq: - freq = ip2freq[ip_dst] - ip2freq[ip_dst] = freq + 1 - else: - ip2freq[ip_dst] = 1 - - if dev_add == mac_src: - if mac_dst in ip2freq: - freq = mac2freq[mac_dst] - mac2freq[mac_dst] = freq + 1 - else: - mac2freq[mac_dst] = 1 - - # Count TCP packets - if ip.p == dpkt.ip.IP_PROTO_TCP: - tcp_counter += 1 - - # Count UDP packets - if ip.p == dpkt.ip.IP_PROTO_UDP: - udp_counter += 1 - - show_progress(verbose, counter) - - # Print general statistics - show_summary(counter, ip_counter, tcp_counter, udp_counter) - # Save results into file if filename_out is not empty - if not filename_out == "": - print "Saving results into file: ", filename_out - ip_tbl_header = "Point-to-many Analysis - IP destinations for " + dev_add - mac_tbl_header = "Point-to-many Analysis - MAC destinations for " + dev_add - save_to_file(ip_tbl_header, ip2freq, filename_out) - save_to_file(mac_tbl_header, mac2freq, filename_out) - else: - print "Output file name is not specified... exitting now!" - - -def parse_cli_args(argv): - """ Parse command line arguments and store them in a dictionary - Args: - argv: list of command line arguments and their values - Returns: - str: dictionary that maps arguments to their values - """ - options = dict() - # First argument is "CAPture.py", so skip it - argv = argv[1:] - # Loop and collect arguments and their values - while argv: - print "Examining argument: ", argv[0] - # Check the first character of each argv list - # If it is a '-' then it is a command line argument - if argv[0][0] == '-': - if argv[0] == VERBOSE: - # We don't have value for the argument VERBOSE - options[argv[0]] = argv[0] - # Remove one command line argument and its value - argv = argv[1:] - else: - options[argv[0]] = argv[1] - # Remove one command line argument and its value - argv = argv[2:] - - return options - - -""" ----------------------------------------------------------------------------- - Main Running Methods - ----------------------------------------------------------------------------- -""" -def main(): - # Variable declarations - global CAP_EXTENSION - global PCAP_EXTENSION - global VERBOSE - global POINT_TO_MANY - - # Counters - counter = 0 - ip_counter = 0 - tcp_counter = 0 - udp_counter = 0 - # Booleans as flags - verbose = False - is_ip = True - is_statistical_analysis = True - is_point_to_many_analysis = False - # Names - filename_in = "" - filename_out = "" - dev_add = "" - - # Welcome message - print - print "Welcome to CAPture version 1.0 - A PCAP file instant analyzer!" - - # Get file name from user input - # Show usage if file name is not specified (only accept 1 file name for now) - if len(sys.argv) < 2: - show_usage() - print - return - - # Check and process sys.argv - options = parse_cli_args(sys.argv) - for key, value in options.iteritems(): - # Process "-i" - input PCAP file - if key == INPUT: - filename_in = value - elif key == OUTPUT: - filename_out = value - elif key == VERBOSE: - verbose = True - elif key == POINT_TO_MANY: - is_statistical_analysis = False - is_point_to_many_analysis = True - dev_add = value - - # Show manual again if input is not correct - if filename_in == "": - print "File name is empty!" - print - show_usage() - print - return - - # dev_add is needed for these analyses - if is_point_to_many_analysis and dev_add == "": - print "Device address is empty!" - print - show_usage() - print - return - - # One PCAP file name is specified - now analyze! - print "Analyzing PCAP file: ", filename_in - - # Opening and analyzing PCAP file - f = open(filename_in,'rb') - pcap = dpkt.pcap.Reader(f) - - # Choose from the existing options - if is_statistical_analysis: - statistical_analysis(verbose, pcap, counter, ip_counter, tcp_counter, udp_counter) - elif is_point_to_many_analysis: - point_to_many_analysis(filename_out, dev_add, verbose, pcap, counter, ip_counter, - tcp_counter, udp_counter) - - -if __name__ == "__main__": - # call main function since this is being run as the start - main() - -