Browse Source

first commit

sigi 4 years ago
commit
ffac3ca21d
3 changed files with 331 additions and 0 deletions
  1. BIN
      400px-Terminal_059.png
  2. BIN
      Terminal_059.png
  3. 331 0
      sisniff.py

BIN
400px-Terminal_059.png


BIN
Terminal_059.png


+ 331 - 0
sisniff.py

@@ -0,0 +1,331 @@
+#!/usr/bin/python2
+
+# (c) 2017 by Siegrist(SystemLoesungen) <PSS@ZweierNet.ch>
+
+from scapy.all import *
+import pwd
+import os
+import re
+import glob
+import sys
+import string
+import fcntl
+import struct
+import commands
+import argparse
+
+VERSION = "0.71"
+
+PROC_TCP4 = "/proc/net/tcp"
+PROC_UDP4 = "/proc/net/udp"
+PROC_TCP6 = "/proc/net/tcp6"
+PROC_UDP6 = "/proc/net/udp6"
+PROC_PACKET = "/proc/net/packet"
+
+TSERV = dict((TCP_SERVICES[k], k) for k in TCP_SERVICES.keys())
+USERV = dict((UDP_SERVICES[k], k) for k in UDP_SERVICES.keys())
+
+tcp_payload_hdrs = ['GET|POST|HTTP|HEAD|PUT|PATCH|DELETE|TRACE|OPTIONS|CONNECT']
+numeric = False
+payloadH = False
+fillter = ""
+
+def get_conn_info(proto,hosts,ports):
+    ''' returns: pid, exe, uid '''
+
+    line_array = _proc4load(proto,hosts,ports)
+     
+    if line_array == 0:
+        return ['?','?','?']
+    '''    
+    try:
+        uid = pwd.getpwuid(int(line_array[7]))[0]       # Get user from UID.
+    except:
+        uid = line_array[7]
+    '''
+    uid = 0
+    
+    inode = line_array[9]                 # Need the inode to get process pid.
+    if inode == 0:
+        return ['?','-','?']
+    
+    pid = _get_pid_of_inode(inode)
+    if pid == "NoPid":
+        return ["NoPid", "NoExe", uid]
+    
+    try:                                            # try read the process name.
+        exe = os.readlink('/proc/'+pid+'/exe').split('/')[-1]
+    except:
+        exe = None
+    
+    #print str(lhost) +" "+ str(lport) +" "+ inode +" "+ pid
+    return [pid, exe, uid]
+
+    
+def _proc4load(proto,hosts,ports):
+    ''' Read the table of tcp/udp connections
+    tcp/udp: "sl,  local_address, rem_address, st, tx_queue rx_queue, tr tm->when, retrnsmt,   uid , timeout, inode ,..."
+    ---- TCP states
+    enum {
+	TCP_ESTABLISHED = 1,
+	TCP_SYN_SENT,
+	TCP_SYN_RECV,
+	TCP_FIN_WAIT1,
+	TCP_FIN_WAIT2,
+	TCP_TIME_WAIT,
+	TCP_CLOSE,
+	TCP_CLOSE_WAIT,
+	TCP_LAST_ACK,
+	TCP_LISTEN,
+	TCP_CLOSING,	/* Now a valid state */
+	TCP_NEW_SYN_RECV,
+
+	TCP_MAX_STATES	/* Leave at the end! */
+    };
+    ----------
+    '''
+    content = []
+    if proto == 6:
+        try:
+            with open(PROC_TCP4,'r') as f:
+                content = f.readlines()
+                f.close()
+                content.pop(0)
+        except:
+            print "open proc_tcp4 error"
+            return 0
+    if proto == 17:
+        try:
+            with open(PROC_UDP4,'r') as f:
+                content = f.readlines()
+                f.close()
+                content.pop(0)
+        except:
+            print "open proc_udp4 error"
+            return 0
+    
+    for line in content:    # src
+        line_array = _remove_empty(line.split(' '))
+        if line_array[3] in ['04','05','06''07','08','09','0C','0D']:        # not some state
+            continue
+        l_host,l_port = _convert_ipv4_port(line_array[1])
+        # alt if l_host == '127.0.0.1' or l_host not in MYADDRS:
+        if l_host not in MYADDRS:
+            continue
+        
+        if str(l_port) == str(ports):
+            #print l_host+" "+str(l_port)+" // "+host+" "+str(port)
+            return line_array
+    #print "no entry in procfile found!"
+    return 0
+
+def _convert_ipv4_port(array):
+    host,port = array.split(':')
+    return _ip(host),_hex2dec(port)
+
+def _hex2dec(s):
+    return str(int(s,16))
+
+def _ip(s):
+    ip = [(_hex2dec(s[6:8])),(_hex2dec(s[4:6])),(_hex2dec(s[2:4])),(_hex2dec(s[0:2]))]
+    return '.'.join(ip)
+
+def _ip6(s):
+    ip = [s[6:8],s[4:6],s[2:4],s[0:2],s[12:14],s[14:16],s[10:12],s[8:10],s[22:24],s[20:22],s[18:20],s[16:18],s[30:32],s[28:30],s[26:28],s[24:26]]
+    #print '66666:', ':'.join(ip), s
+    return ':'.join(ip)
+
+def _remove_empty(array):
+    return [x for x in array if x !='']
+
+def _get_pid_of_inode(inode):
+    for item in glob.glob('/proc/[0-9]*/fd/[0-9]*'):
+        try:
+            if re.search(inode,os.readlink(item)):
+                return item.split('/')[2]
+        except:
+            pass
+    return "NoPid"
+
+def _resolve_ip(host):
+    """
+    resolve ip und update dictionary res_cache {'ip': 'name'}.
+    If resolution for a ip failed, 'name' is n_try ... 0.
+    """
+    try:
+        hname = socket.gethostbyaddr(host)[0]
+        res_cache[host] = str(hname)
+        return str(hname)
+    except:
+        res_cache[host] = str(host)
+        return str(host)
+
+def check_root():
+   if os.getuid() == 0:
+       return True
+   else:
+       return False
+        
+## Define our Custom Action function
+def doPackets(packet):
+    
+    program = "-"
+    pid = "-"    
+    uid = "-"    
+    o_proto = ""
+    o_dport = "none"
+    o_sport = "none"
+    flags = ""
+    
+    # only local addresses
+    if packet[0][1].src in MYADDRS:
+        conn_addr = packet[0][1].src
+        if packet.haslayer(TCP) or packet.haslayer(UDP):
+            conn_port = packet[0][2].sport
+        o_dir = 1
+    else:
+        conn_addr = packet[0][1].dst
+        if packet.haslayer(TCP) or packet.haslayer(UDP):
+            conn_port = packet[0][2].dport
+        o_dir = 0
+    
+    if packet.haslayer(TCP) or packet.haslayer(UDP):
+        # logemol casch 
+        c_hash = conn_addr+'.'+str(conn_port)
+        if not any(x[0] == c_hash for x in conn_cache):
+            # get the connection info from packet
+            spid,sexe,suid = get_conn_info(packet[0][1].proto, conn_addr, conn_port)
+        
+            if re.match("^[0-9]+$", spid):
+                program = sexe
+                pid = spid
+                uid = suid
+                
+                # update cache
+                if len(conn_cache) > cc_maxlen:
+                    conn_cache.pop(0)
+                conn_cache.append([c_hash,program,pid])
+                #print conn_cache
+            else:
+                program = "-"
+                pid = "-"
+                uid = "-"
+        else:
+            # me honds fom casch
+            indx = [x[0] for x in conn_cache].index(c_hash)
+            program = conn_cache[indx][1]
+            pid = conn_cache[indx][2]
+            uid = 0
+            # cache aktualisieren
+            renew = conn_cache.pop(indx)
+            conn_cache.append(renew)
+        
+    
+    o_payload = ""
+    if packet.haslayer(UDP):
+        o_proto = "UDP"
+        try:
+            o_dport = "\033[1m"+USERV[packet[0][2].dport]+"\033[0m"
+        except:
+            o_dport = str(packet[0][2].dport)
+        try:
+            o_sport = "\033[1m"+USERV[packet[0][2].sport]+"\033[0m"
+        except:
+            o_sport = str(packet[0][2].sport)
+        flags = ""
+        #o_payload = packet[0].sprintf('%10s,UDP.payload%')
+    if packet.haslayer(TCP):
+        o_proto = "TCP"
+        try:
+            o_dport = "\033[1m"+TSERV[packet[0][2].dport]+"\033[0m"
+        except:
+            o_dport = str(packet[0][2].dport)
+        try:
+            o_sport = "\033[1m"+TSERV[packet[0][2].sport]+"\033[0m"
+        except:
+            o_sport = str(packet[0][2].sport)
+        flags = packet[0].sprintf('%3s,TCP.flags%')
+        if payloadH == True:
+            if packet.haslayer(Raw):
+                tpld = packet[0].sprintf('%TCP.payload%')
+                if re.match("^GET|POST|HTTP|HEAD|PUT|PATCH|DELETE|TRACE|OPTIONS|CONNECT.*", tpld[0:8]):
+                    request_line, gaga = tpld.split('\r\n', 1)
+                    o_payload = str(request_line)
+                    #o_payload = tpld[0:20]
+    
+    if o_dir == 1:
+        if numeric == False:
+            if res_cache.has_key(packet[0][1].dst):
+                rem_name = res_cache[packet[0][1].dst]
+            else:
+                rem_name = _resolve_ip(packet[0][1].dst)
+        else:
+            rem_name = packet[0][1].dst
+            
+        return "\033[1m"+str(program)+"\033[0m" +"/"+ str(pid) + " - " + o_proto + ": " + packet[0][1].src + ":" + o_sport + "\033[1m\033[31m  ->>>  \033[0m" + rem_name + ":" + o_dport + " " + flags + " Len:" + str(packet[0][1].len) + " : " + o_payload
+    else:
+        if numeric == False:
+            if res_cache.has_key(packet[0][1].src):
+                rem_name = res_cache[packet[0][1].src]
+            else:
+                rem_name = _resolve_ip(packet[0][1].src)
+        else:
+            rem_name = packet[0][1].src
+            
+        return "\033[1m"+str(program)+"\033[0m" +"/"+ str(pid) + " - " + o_proto + ": " + packet[0][1].dst + ":" + o_dport + "\033[1m\033[36m  <<<-  \033[0m" + rem_name + ":" + o_sport + " " + flags + " Len:" + str(packet[0][1].len) + " : " + o_payload
+
+
+
+## -- Ond denn s'Hooptprogramm
+
+# root check
+if not check_root():
+    print("This program needs root privileges !\nThats because of reading the /proc filesystem and using libpcap functions.\nSo I give up\n")
+    conf.sniff_promisc=0
+    conf.sniff_promisc=0
+    print conf
+    #sys.exit()
+
+# get the interfaces
+ifaces = commands.getoutput("ls /sys/class/net")
+iface_list = ifaces.split('\n')
+
+print
+# commandline params
+parser = argparse.ArgumentParser(description='sisniff V'+VERSION)
+parser.add_argument('-i', help="Interface (mandatory)", choices=iface_list, required=True)
+parser.add_argument('-n', help="Do not resolve IP-Addresses", action="store_true")
+parser.add_argument('-pH', help="Show HTTP Payload", action="store_true")
+parser.add_argument('filter', nargs='?', help="Filter (BPF syntax) on top of IP (in dbl-quotes \"...\")", type=str)
+args = parser.parse_args()
+iface = args.i
+if args.n:
+    numeric = True
+if args.pH:
+    payloadH = True
+if args.filter:
+    fillter = " and (" + args.filter + ")"
+    print "> Applying Filter: \"ip" + fillter + "\"" 
+
+# local addresses 
+MYADDRS = _remove_empty(commands.getoutput("hostname -I").split(' '))
+MYADDRS.append('0.0.0.0')
+MYADDRS.append('127.0.0.1')
+print "> My IP-Addresses: " + str(MYADDRS)
+
+# confirmed connections cache (ringboffer)
+conn_cache = []
+cc_maxlen = 20
+
+# resolver cache
+res_cache = {}
+n_try = 3
+
+print
+print "Program/PID: Local addr:port <<->> Remote addr:port [Flags] Len:length : [Payload]"
+print "-------------------------------------------------------------------------------"
+
+# sniff, filtering for IP traffic
+sniff(filter="ip"+fillter,iface=iface,prn=doPackets)
+
+## -- oond denn isch schloss