|
@@ -14,17 +14,26 @@ import struct
|
|
|
import commands
|
|
|
import argparse
|
|
|
|
|
|
-VERSION = "0.71"
|
|
|
+VERSION = "0.75"
|
|
|
|
|
|
PROC_TCP4 = "/proc/net/tcp"
|
|
|
PROC_UDP4 = "/proc/net/udp"
|
|
|
+PROC_ICMP4 = "/proc/net/icmp"
|
|
|
PROC_TCP6 = "/proc/net/tcp6"
|
|
|
PROC_UDP6 = "/proc/net/udp6"
|
|
|
PROC_PACKET = "/proc/net/packet"
|
|
|
|
|
|
+# Services
|
|
|
TSERV = dict((TCP_SERVICES[k], k) for k in TCP_SERVICES.keys())
|
|
|
USERV = dict((UDP_SERVICES[k], k) for k in UDP_SERVICES.keys())
|
|
|
|
|
|
+# IP Protocol Numbers (dec)
|
|
|
+IPPROTO_ICMP = 1
|
|
|
+IPPROTO_TCP = 6
|
|
|
+IPROTOP_IGP = 9
|
|
|
+IPPROTO_UDP = 17
|
|
|
+
|
|
|
+nostate = set(['04','05','06''07','08','09','0C','0D'])
|
|
|
tcp_payload_hdrs = ['GET|POST|HTTP|HEAD|PUT|PATCH|DELETE|TRACE|OPTIONS|CONNECT']
|
|
|
numeric = False
|
|
|
payloadH = False
|
|
@@ -32,9 +41,10 @@ fillter = ""
|
|
|
|
|
|
def get_conn_info(proto,hosts,ports):
|
|
|
''' returns: pid, exe, uid '''
|
|
|
-
|
|
|
+ uid = 0
|
|
|
+
|
|
|
line_array = _proc4load(proto,hosts,ports)
|
|
|
-
|
|
|
+
|
|
|
if line_array == 0:
|
|
|
return ['?','?','?']
|
|
|
'''
|
|
@@ -43,16 +53,18 @@ def get_conn_info(proto,hosts,ports):
|
|
|
except:
|
|
|
uid = line_array[7]
|
|
|
'''
|
|
|
- uid = 0
|
|
|
+
|
|
|
+ inode = str(line_array[9])
|
|
|
+ if inode == "0":
|
|
|
+ return ['.','.','.']
|
|
|
|
|
|
- inode = line_array[9] # Need the inode to get process pid.
|
|
|
- if inode == 0:
|
|
|
- return ['?','-','?']
|
|
|
+ pid = _get_pid_of_inode(inode) # try get a pid
|
|
|
|
|
|
- pid = _get_pid_of_inode(inode)
|
|
|
- if pid == "NoPid":
|
|
|
- return ["NoPid", "NoExe", uid]
|
|
|
|
|
|
+ if pid == "NoPid":
|
|
|
+ #print ">>>>>>>>>>>NoPID:" + str(hosts) +" "+ str(ports) + "//" + str(line_array)
|
|
|
+ return ['-', '-', uid]
|
|
|
+
|
|
|
try: # try read the process name.
|
|
|
exe = os.readlink('/proc/'+pid+'/exe').split('/')[-1]
|
|
|
except:
|
|
@@ -65,7 +77,7 @@ def get_conn_info(proto,hosts,ports):
|
|
|
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
|
|
|
+ ---- TCP states from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp_states.h?id=HEAD
|
|
|
enum {
|
|
|
TCP_ESTABLISHED = 1,
|
|
|
TCP_SYN_SENT,
|
|
@@ -84,48 +96,74 @@ def _proc4load(proto,hosts,ports):
|
|
|
};
|
|
|
----------
|
|
|
'''
|
|
|
- content = []
|
|
|
- if proto == 6:
|
|
|
+
|
|
|
+ #xhosts = _ip_hexrev(hosts)
|
|
|
+ xports = _dec2hex(ports)
|
|
|
+
|
|
|
+ if proto == IPPROTO_UDP:
|
|
|
+ try:
|
|
|
+ with open(PROC_UDP4,'r') as f:
|
|
|
+ next(f)
|
|
|
+ for line in f:
|
|
|
+ line_arrayu = _remove_empty(line.split(' '))
|
|
|
+ l_xhost,l_xport = line_arrayu[1].split(':')
|
|
|
+ if l_xhost not in xMYADDRS:
|
|
|
+ continue
|
|
|
+ if l_xport == xports:
|
|
|
+ return line_arrayu
|
|
|
+
|
|
|
+ return 0
|
|
|
+ except:
|
|
|
+ print "open proc_udp4 error"
|
|
|
+ return 0
|
|
|
+ elif proto == IPPROTO_TCP:
|
|
|
try:
|
|
|
with open(PROC_TCP4,'r') as f:
|
|
|
- content = f.readlines()
|
|
|
- f.close()
|
|
|
- content.pop(0)
|
|
|
+ next(f)
|
|
|
+ for line in f:
|
|
|
+ line_arrayt = _remove_empty(line.split(' '))
|
|
|
+ if line_arrayt[3] in nostate: # not some TCP state
|
|
|
+ continue
|
|
|
+ l_xhost,l_xport = line_arrayt[1].split(':')
|
|
|
+ if l_xhost not in xMYADDRS:
|
|
|
+ continue
|
|
|
+ if l_xport == xports:
|
|
|
+ return line_arrayt
|
|
|
+
|
|
|
+ return 0
|
|
|
except:
|
|
|
- print "open proc_tcp4 error"
|
|
|
+ print "open proc_tcp error"
|
|
|
return 0
|
|
|
- if proto == 17:
|
|
|
+
|
|
|
+ elif proto == IPPROTO_ICMP:
|
|
|
try:
|
|
|
- with open(PROC_UDP4,'r') as f:
|
|
|
- content = f.readlines()
|
|
|
- f.close()
|
|
|
- content.pop(0)
|
|
|
+ with open(PROC_ICMP4,'r') as f:
|
|
|
+ next(f)
|
|
|
+ for line in f:
|
|
|
+ line_arrayi = _remove_empty(line.split(' '))
|
|
|
+ l_xhost,l_xport = line_arrayi[1].split(':')
|
|
|
+ if l_xhost not in xMYADDRS:
|
|
|
+ continue
|
|
|
+ if l_xport == xports:
|
|
|
+ return line_arrayi
|
|
|
+
|
|
|
+ return 0
|
|
|
except:
|
|
|
- print "open proc_udp4 error"
|
|
|
+ print "open proc_icmp4 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 _dec2hex(p):
|
|
|
+ return hex(int(p)).split('x')[-1].upper()
|
|
|
+
|
|
|
def _ip(s):
|
|
|
ip = [(_hex2dec(s[6:8])),(_hex2dec(s[4:6])),(_hex2dec(s[2:4])),(_hex2dec(s[0:2]))]
|
|
|
return '.'.join(ip)
|
|
@@ -135,13 +173,17 @@ def _ip6(s):
|
|
|
#print '66666:', ':'.join(ip), s
|
|
|
return ':'.join(ip)
|
|
|
|
|
|
+def _ip_hexrev(ip):
|
|
|
+ return ''.join([hex(int(x)+256)[3:] for x in ip.split('.')][::-1]).upper()
|
|
|
+
|
|
|
def _remove_empty(array):
|
|
|
- return [x for x in array if x !='']
|
|
|
+ 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]*'):
|
|
|
+ s_term = r'^socket\:\['+ inode +r'\]$'
|
|
|
+ for item in glob.iglob('/proc/[0-9]*/fd/[0-9]*'):
|
|
|
try:
|
|
|
- if re.search(inode,os.readlink(item)):
|
|
|
+ if re.match(s_term,os.readlink(item)):
|
|
|
return item.split('/')[2]
|
|
|
except:
|
|
|
pass
|
|
@@ -180,36 +222,41 @@ def doPackets(packet):
|
|
|
# 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
|
|
|
+ if packet.haslayer(TCP) or packet.haslayer(UDP) or packet.haslayer(ICMP):
|
|
|
+ try:
|
|
|
+ conn_port = packet[0][2].sport
|
|
|
+ except:
|
|
|
+ conn_port = 99999
|
|
|
o_dir = 1
|
|
|
else:
|
|
|
conn_addr = packet[0][1].dst
|
|
|
- if packet.haslayer(TCP) or packet.haslayer(UDP):
|
|
|
- conn_port = packet[0][2].dport
|
|
|
+ if packet.haslayer(TCP) or packet.haslayer(UDP) or packet.haslayer(ICMP):
|
|
|
+ try:
|
|
|
+ conn_port = packet[0][2].dport
|
|
|
+ except:
|
|
|
+ conn_port = 99999
|
|
|
o_dir = 0
|
|
|
|
|
|
- if packet.haslayer(TCP) or packet.haslayer(UDP):
|
|
|
+ if packet.haslayer(TCP) or packet.haslayer(UDP) or packet.haslayer(ICMP): # grrr, no info in /proc/net/icmp so far. or packet.haslayer(ICMP):
|
|
|
# logemol casch
|
|
|
- c_hash = conn_addr+'.'+str(conn_port)
|
|
|
+ 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:
|
|
|
+ if len(conn_cache) >= cc_maxlen:
|
|
|
conn_cache.pop(0)
|
|
|
conn_cache.append([c_hash,program,pid])
|
|
|
#print conn_cache
|
|
|
else:
|
|
|
- program = "-"
|
|
|
- pid = "-"
|
|
|
- uid = "-"
|
|
|
+ program = sexe
|
|
|
+ pid = spid
|
|
|
+ uid = suid
|
|
|
else:
|
|
|
# me honds fom casch
|
|
|
indx = [x[0] for x in conn_cache].index(c_hash)
|
|
@@ -234,7 +281,7 @@ def doPackets(packet):
|
|
|
o_sport = str(packet[0][2].sport)
|
|
|
flags = ""
|
|
|
#o_payload = packet[0].sprintf('%10s,UDP.payload%')
|
|
|
- if packet.haslayer(TCP):
|
|
|
+ elif packet.haslayer(TCP):
|
|
|
o_proto = "TCP"
|
|
|
try:
|
|
|
o_dport = "\033[1m"+TSERV[packet[0][2].dport]+"\033[0m"
|
|
@@ -252,7 +299,24 @@ def doPackets(packet):
|
|
|
request_line, gaga = tpld.split('\r\n', 1)
|
|
|
o_payload = str(request_line)
|
|
|
#o_payload = tpld[0:20]
|
|
|
-
|
|
|
+ elif packet.haslayer(ICMP):
|
|
|
+ o_proto = "ICMP"
|
|
|
+ if conn_port == 99999:
|
|
|
+ o_dport = "-"
|
|
|
+ o_sport = "-"
|
|
|
+ else:
|
|
|
+ try:
|
|
|
+ o_dport = "\033[1m"+USERV[packet[0][2].sport]+"\033[0m"
|
|
|
+ except:
|
|
|
+ o_dport = str(packet[0][2].sport)
|
|
|
+ try:
|
|
|
+ o_sport = "\033[1m"+USERV[packet[0][2].dport]+"\033[0m"
|
|
|
+ except:
|
|
|
+ o_sport = str(packet[0][2].dport)
|
|
|
+ flags = "["+packet[0].sprintf('%ICMP.type%') + "/" + packet[0].sprintf('%ICMP.code%')+"]"
|
|
|
+ else:
|
|
|
+ o_proto = "UNKNOWN"
|
|
|
+
|
|
|
if o_dir == 1:
|
|
|
if numeric == False:
|
|
|
if res_cache.has_key(packet[0][1].dst):
|
|
@@ -283,8 +347,8 @@ 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()
|
|
|
+ #print conf
|
|
|
+ sys.exit()
|
|
|
|
|
|
# get the interfaces
|
|
|
ifaces = commands.getoutput("ls /sys/class/net")
|
|
@@ -311,6 +375,7 @@ if args.filter:
|
|
|
MYADDRS = _remove_empty(commands.getoutput("hostname -I").split(' '))
|
|
|
MYADDRS.append('0.0.0.0')
|
|
|
MYADDRS.append('127.0.0.1')
|
|
|
+xMYADDRS = [_ip_hexrev(x) for x in MYADDRS]
|
|
|
print "> My IP-Addresses: " + str(MYADDRS)
|
|
|
|
|
|
# confirmed connections cache (ringboffer)
|
|
@@ -320,12 +385,13 @@ cc_maxlen = 20
|
|
|
# resolver cache
|
|
|
res_cache = {}
|
|
|
n_try = 3
|
|
|
-
|
|
|
+print
|
|
|
+print "Prog/PID mavericks: ?/? = No entry in /proc/net/xxx; -/- = No PID for Inode found; ./. = Inode=0;"
|
|
|
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)
|
|
|
+sniff(filter="ip"+fillter,iface=iface,prn=doPackets, store=0)
|
|
|
|
|
|
## -- oond denn isch schloss
|