├── Files List ├── Linux │ ├── File_list.pdp │ └── File_list.py ├── README.md └── Windows │ ├── File_list.pdp │ └── File_list.py ├── GeoIP ├── Linux │ ├── GeoIP.pdp │ └── GeoIP.py ├── README.md ├── Windows │ ├── GeoIP.bat │ └── GeoIP.pdp └── pyinstaller │ └── GeoIP.spec ├── PCAP_tools ├── Linux │ └── 1.2 │ │ ├── pcap_tools.py │ │ ├── pcap_tools_Wireshark.pdp │ │ ├── pcap_tools_files.pdp │ │ ├── pcap_tools_stream_file.pdp │ │ └── pcap_tools_streams.pdp ├── README.md └── Windows │ └── 1.2 │ ├── pcap_tools.bat │ ├── pcap_tools_Wireshark.pdp │ ├── pcap_tools_files.pdp │ ├── pcap_tools_stream_file.pdp │ └── pcap_tools_streams.pdp ├── README.md └── license.txt /Files List/Linux/File_list.pdp: -------------------------------------------------------------------------------- 1 | Name = Files List 2 | Author = Beercow 3 | Version = 1.0 4 | Type = MainMenuItem 5 | Architecture = LinuxShellScript 6 | File = File_list.py 7 | Priority = 9 8 | RunHidden = 0 9 | RunExclusively = 1 10 | CanOverrideOtherPlugins = 0 11 | CanOverrideProcDot = 0 12 | -------------------------------------------------------------------------------- /Files List/Linux/File_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | def main(): 6 | 7 | data = os.getenv('PROCDOTPLUGIN_GraphFileDot') 8 | out = os.getenv('PROCDOTPLUGIN_ResultCSV') 9 | outfile = open(out, 'w') 10 | outfile.write ('"File Path","Exists"\n') 11 | outfile.write ('"*","*"\n') 12 | with open(data) as f: 13 | for line in f: 14 | if line.startswith(' "FILE:'): 15 | if 'fontcolor = magenta' in line: 16 | line = line.strip().split('"') 17 | f1 = (','.join(line[1:2])) 18 | f2 = (','.join(line[3:4])) 19 | outfile.write('{{color:purple}}' + '"' + f1[5:] + ' -> ' + f2[5:] + '","rename"\n') 20 | elif 'fontcolor = red' in line: 21 | line = line.strip().split('"') 22 | line = (','.join(line[1:2])) 23 | outfile.write('{{color:red}}' + '"' + line[5:] + '","No"\n') 24 | else: 25 | line = line.strip().split('"') 26 | line = (','.join(line[1:2])) 27 | outfile.write('"' + line[5:] + '","Yes"\n') 28 | 29 | if __name__ == '__main__': 30 | main() 31 | -------------------------------------------------------------------------------- /Files List/README.md: -------------------------------------------------------------------------------- 1 | # Files List 2 | 3 | ## Project source can be downloaded from 4 | 5 | ## Author & Contributor List 6 | Brian Maloney 7 | 8 | ## Overview 9 | Sometimes there can be a lot going on in a graph. By using this plugin, you can get a list of files. It will tell you if they exist on the system and if they have been renamed. This plugin adds an entry to the plugins menu called **Files List**. 10 | 11 | ![ProcDOT graph](https://cloud.githubusercontent.com/assets/10360919/15474300/e758d324-20c9-11e6-8fc5-179d70fbc108.png) ![Files List](https://cloud.githubusercontent.com/assets/10360919/15474306/ea96ae9e-20c9-11e6-8102-9e4c2fccd744.png) 12 | -------------------------------------------------------------------------------- /Files List/Windows/File_list.pdp: -------------------------------------------------------------------------------- 1 | Name = Files List 2 | Author = Beercow 3 | Version = 1.0 4 | Type = MainMenuItem 5 | Architecture = WindowsBatchScript 6 | File = File_list.py 7 | Priority = 9 8 | RunHidden = 0 9 | RunExclusively = 1 10 | CanOverrideOtherPlugins = 0 11 | CanOverrideProcDot = 0 12 | -------------------------------------------------------------------------------- /Files List/Windows/File_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | def main(): 6 | 7 | data = os.getenv('PROCDOTPLUGIN_GraphFileDot') 8 | out = os.getenv('PROCDOTPLUGIN_ResultCSV') 9 | outfile = open(out, 'w') 10 | outfile.write ('"File Path","Exists"\n') 11 | outfile.write ('"*","*"\n') 12 | with open(data) as f: 13 | for line in f: 14 | if line.startswith(' "FILE:'): 15 | if 'fontcolor = magenta' in line: 16 | line = line.strip().split('"') 17 | f1 = (','.join(line[1:2])) 18 | f2 = (','.join(line[3:4])) 19 | outfile.write('{{color:purple}}' + '"' + f1[5:] + ' -> ' + f2[5:] + '","rename"\n') 20 | elif 'fontcolor = red' in line: 21 | line = line.strip().split('"') 22 | line = (','.join(line[1:2])) 23 | outfile.write('{{color:red}}' + '"' + line[5:] + '","No"\n') 24 | else: 25 | line = line.strip().split('"') 26 | line = (','.join(line[1:2])) 27 | outfile.write('"' + line[5:] + '","Yes"\n') 28 | 29 | if __name__ == '__main__': 30 | main() 31 | -------------------------------------------------------------------------------- /GeoIP/Linux/GeoIP.pdp: -------------------------------------------------------------------------------- 1 | Name = GeoIP 2 | Author = Beercow 3 | Description = Adds geoip data to details 4 | Version = 0.1 5 | Type = EventHandler 6 | Architecture = LinuxShellScript 7 | File = GeoIP.py 8 | Priority = 9 9 | RunHidden = 0 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | Event = AfterRefresh 14 | -------------------------------------------------------------------------------- /GeoIP/Linux/GeoIP.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import pygeoip 5 | import sys 6 | import urllib 7 | import gzip 8 | 9 | reload(sys) 10 | sys.setdefaultencoding('utf8') 11 | out = os.getenv('PROCDOTPLUGIN_ResultTXT') 12 | 13 | def database(url,dbgz,db): 14 | geo = urllib.URLopener() 15 | try: 16 | geo.retrieve(url, dbgz) 17 | with gzip.open(dbgz, 'rb') as infile: 18 | with open(db, 'wb') as outfile: 19 | for line in infile: 20 | outfile.write(line) 21 | os.remove(dbgz) 22 | except Exception as e: 23 | open(out, 'wb').write(str(e)) 24 | sys.exit(0) 25 | 26 | if os.path.isfile('GeoLiteCity.dat'): 27 | pass 28 | else: 29 | database('http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz', 'GeoLiteCity.dat.gz', 'GeoLiteCity.dat') 30 | 31 | if os.path.isfile('GeoIPASNum.dat'): 32 | pass 33 | else: 34 | database('http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz', 'GeoIPASNum.dat.gz', 'GeoIPASNum.dat') 35 | 36 | tfolder = os.listdir(os.getenv('PROCDOTPLUGIN_TempFolder')) 37 | details = open(os.getenv('PROCDOTPLUGIN_GraphFileDetails'),'rb').readlines() 38 | n = open(os.getenv('PROCDOTPLUGIN_GraphFileDetails'),'w') 39 | 40 | for num, line in enumerate(details,1): 41 | if 'IP-Address' in line: 42 | query = pygeoip.GeoIP('GeoLiteCity.dat') 43 | asn = pygeoip.GeoIP('GeoIPASNum.dat') 44 | x = [x.strip() for x in line.split(' ')][2] 45 | try: 46 | results = query.record_by_addr(x) 47 | asn_info = asn.asn_by_addr(x) 48 | for key, val in results.items(): 49 | details.insert(num,str(key) + ' = ' + str(val) + '\n') 50 | 51 | try: 52 | details.insert(num,'asn = '+asn_info+'\n') 53 | except: 54 | pass 55 | except: 56 | pass 57 | details = "".join(details) 58 | n.write(details) 59 | n.close() 60 | sys.exit(0) -------------------------------------------------------------------------------- /GeoIP/README.md: -------------------------------------------------------------------------------- 1 | # GeoIP 2 | 3 | ## Project source can be downloaded from 4 | 5 | ## Author & Contributor List 6 | Brian Maloney 7 | 8 | ## Overview 9 | This plugin adds geographical information to server nodes. GeoIP is an event hadler plugin so you will not see anything added to the graph or plugin menus. It is designed to run after the refresh button is clicked. You should now see the extra information when you click the details on a server node. The first run of GeoIP, you might have a slight delay because teh plugin needs to download the Maxmind database. 10 | 11 | -------------------------------------------------------------------------------- /GeoIP/Windows/GeoIP.bat: -------------------------------------------------------------------------------- 1 | @setlocal enabledelayedexpansion && C:\Python27\python.exe -x "%~f0" %* & exit /b !ERRORLEVEL! 2 | #!/usr/bin/env python 3 | 4 | import os 5 | import pygeoip 6 | import sys 7 | import urllib 8 | import gzip 9 | 10 | reload(sys) 11 | sys.setdefaultencoding('utf8') 12 | out = os.getenv('PROCDOTPLUGIN_ResultTXT') 13 | 14 | def database(url,dbgz,db): 15 | geo = urllib.URLopener() 16 | try: 17 | geo.retrieve(url, dbgz) 18 | with gzip.open(dbgz, 'rb') as infile: 19 | with open(db, 'wb') as outfile: 20 | for line in infile: 21 | outfile.write(line) 22 | os.remove(dbgz) 23 | except Exception as e: 24 | open(out, 'wb').write(str(e)) 25 | sys.exit(0) 26 | 27 | if os.path.isfile('GeoLiteCity.dat'): 28 | pass 29 | else: 30 | database('http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz', 'GeoLiteCity.dat.gz', 'GeoLiteCity.dat') 31 | 32 | if os.path.isfile('GeoIPASNum.dat'): 33 | pass 34 | else: 35 | database('http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz', 'GeoIPASNum.dat.gz', 'GeoIPASNum.dat') 36 | 37 | tfolder = os.listdir(os.getenv('PROCDOTPLUGIN_TempFolder')) 38 | details = open(os.getenv('PROCDOTPLUGIN_GraphFileDetails'),'rb').readlines() 39 | n = open(os.getenv('PROCDOTPLUGIN_GraphFileDetails'),'w') 40 | 41 | for num, line in enumerate(details,1): 42 | if 'IP-Address' in line: 43 | query = pygeoip.GeoIP('GeoLiteCity.dat') 44 | asn = pygeoip.GeoIP('GeoIPASNum.dat') 45 | x = [x.strip() for x in line.split(' ')][2] 46 | try: 47 | results = query.record_by_addr(x) 48 | asn_info = asn.asn_by_addr(x) 49 | for key, val in results.items(): 50 | details.insert(num,str(key) + ' = ' + str(val) + '\n') 51 | 52 | try: 53 | details.insert(num,'asn = '+asn_info+'\n') 54 | except: 55 | pass 56 | except: 57 | pass 58 | details = "".join(details) 59 | n.write(details) 60 | n.close() 61 | sys.exit(0) -------------------------------------------------------------------------------- /GeoIP/Windows/GeoIP.pdp: -------------------------------------------------------------------------------- 1 | Name = GeoIP 2 | Author = Beercow 3 | Description = Adds geoip data to details 4 | Version = 0.1 5 | Type = EventHandler 6 | Architecture = WindowsBatchScript 7 | File = GeoIP.bat 8 | Priority = 9 9 | RunHidden = 0 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | Event = AfterRefresh 14 | -------------------------------------------------------------------------------- /GeoIP/pyinstaller/GeoIP.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['GeoIP.py'], 7 | pathex=['/home/remnux/Desktop/procdot/lin64/plugins'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=[], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | pyz = PYZ(a.pure, a.zipped_data, 18 | cipher=block_cipher) 19 | exe = EXE(pyz, 20 | a.scripts, 21 | a.binaries, 22 | a.zipfiles, 23 | a.datas, 24 | name='GeoIP', 25 | debug=False, 26 | strip=False, 27 | upx=True, 28 | runtime_tmpdir=None, 29 | console=False ) 30 | -------------------------------------------------------------------------------- /PCAP_tools/Linux/1.2/pcap_tools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | #works with tcpdump verion 4.9.0 4 | 5 | import os 6 | import sys 7 | 8 | if os.getenv('PROCDOTPLUGIN_VerificationRun') == '0' or os.getenv('PROCDOTPLUGIN_Name') == 'Extract Files From PCAP': 9 | pass 10 | else: 11 | if os.getenv('PROCDOTPLUGIN_CurrentNode_name')[:6] == 'SERVER': 12 | sys.exit(1) 13 | else: 14 | sys.exit(0) 15 | 16 | import csv 17 | import hashlib 18 | import shutil 19 | import subprocess as sub 20 | from httplib import HTTPMessage 21 | import StringIO 22 | import zlib 23 | from Tkinter import * 24 | import tkFileDialog 25 | import base64 26 | import re 27 | from datetime import datetime 28 | from datetime import timedelta 29 | import time 30 | import itertools 31 | import string 32 | from random import * 33 | 34 | out = os.getenv('PROCDOTPLUGIN_ResultTXT') 35 | temp = os.getenv('PROCDOTPLUGIN_TempFolder')+'\\tcpflow_out\\' 36 | 37 | #check for executable files 38 | def ext(header): 39 | if 'MZ' in header: 40 | return '.mz' 41 | else: 42 | return '.bin' 43 | 44 | #tcpflow file endings 45 | def extn(): 46 | ending = (('.ez', '.aw', '.atom', '.atomcat', '.atomsvc', '.ccxml', '.cdmia', '.cdmic', '.cdmid', '.cdmio', '.cdmiq', '.cu', '.davmount', '.dssc', '.xdssc', '.ecma', '.emma', '.epub', '.exi', '.pfr', '.stk', '.ipfix', '.jar', '.ser', '.class', '.js', '.json', '.lostxml', '.hqx', '.cpt', '.mads', '.mrc', '.mrcx', '.mb', '.mathml', '.mbox', '.mscml', '.meta4', '.mets', '.mods', '.mp21', '.mp4s', '.doc', '.mxf', '.oda', '.opf', '.ogx', '.onetoc', '.xer', '.pdf', '.pgp', '.asc', '.prf', '.p10', '.p7m', '.p7s', '.p8', '.ac', '.cer', '.crl', '.pkipath', '.pki', '.pls', '.ps', '.cww', '.pskcxml', '.rdf', '.rif', '.rnc', '.rl', '.rld', '.rs', '.rsd', '.rss', '.rtf', '.sbml', '.scq', '.scs', '.spq', '.spp', '.sdp', '.setpay', '.setreg', '.shf', '.smil', '.rq', '.srx', '.gram', '.grxml', '.sru', '.ssml', '.teicorpus', '.tfi', '.tsd', '.plb', '.psb', '.pvb', '.tcap', '.pwn', '.aso', '.imp', '.acu', '.atc', '.air', '.fxp', '.xdp', '.xfdf', '.ahead', '.azf', '.azs', '.azw', '.acc', '.ami', '.apk', '.cii', '.fti', '.atx', '.mpkg', '.m3u8', '.swi', '.aep', '.mpm', '.bmi', '.rep', '.cdxml', '.mmd', '.cdy', '.cla', '.rp9', '.c4g', '.c11amc', '.c11amz', '.csp', '.cdbcmsg', '.cmc', '.clkx', '.clkk', '.clkp', '.clkt', '.clkw', '.wbs', '.pml', '.ppd', '.car', '.pcurl', '.rdz', '.fe_launch', '.dna', '.mlp', '.dpg', '.dfac', '.ait', '.svc', '.geo', '.mag', '.nml', '.esf', '.msf', '.qam', '.slt', '.ssf', '.es3', '.ez2', '.ez3', '.fdf', '.mseed', '.seed', '.gph', '.ftc', '.fm', '.fnc', '.ltf', '.fsc', '.oas', '.oa2', '.oa3', '.fg5', '.bh2', '.ddd', '.xdw', '.xbd', '.fzs', '.txd', '.ggb', '.ggt', '.gex', '.gxt', '.g2w', '.g3w', '.gmx', '.kml', '.kmz', '.gqf', '.gac', '.ghf', '.gim', '.grv', '.gtm', '.tpl', '.vcg', '.hal', '.zmm', '.hbci', '.les', '.hpgl', '.hpid', '.hps', '.jlt', '.pcl', '.pclxl', '.sfd-hdstx', '.x3d', '.mpy', '.afp', '.irm', '.sc', '.icc', '.igl', '.ivp', '.ivu', '.igm', '.xpw', '.i2g', '.qbo', '.qfx', '.rcprofile', '.irp', '.xpr', '.fcs', '.jam', '.rms', '.jisp', '.joda', '.ktz', '.karbon', '.chrt', '.kfo', '.flw', '.kon', '.kpr', '.ksp', '.kwd', '.htke', '.kia', '.knp', '.skp', '.sse', '.lasxml', '.lbd', '.lbe', '.123', '.apr', '.pre', '.nsf', '.org', '.scm', '.lwp', '.portpkg', '.mcd', '.mc1', '.cdkey', '.mwf', '.mfm', '.flo', '.igx', '.mif', '.daf', '.dis', '.mbk', '.mqy', '.msl', '.plc', '.txf', '.mpn', '.mpc', '.xul', '.cil', '.cab', '.xls', '.xlam', '.xlsb', '.xlsm', '.xltm', '.eot', '.chm', '.ims', '.lrm', '.thmx', '.cat', '.stl', '.ppt', '.ppam', '.pptm', '.sldm', '.ppsm', '.potm', '.mpp', '.docm', '.dotm', '.wps', '.wpl', '.xps', '.mseq', '.mus', '.msty', '.nlu', '.nnd', '.nns', '.nnw', '.ngdat', '.n-gage', '.rpst', '.rpss', '.edm', '.edx', '.ext', '.odc', '.otc', '.odb', '.odf', '.odft', '.odg', '.otg', '.odi', '.oti', '.odp', '.otp', '.ods', '.ots', '.odt', '.odm', '.ott', '.oth', '.xo', '.dd2', '.oxt', '.pptx', '.sldx', '.ppsx', '.potx', '.xlsx', '.xltx', '.docx', '.dotx', '.mgp', '.dp', '.pdb', '.paw', '.str', '.ei6', '.efif', '.wg', '.plf', '.pbd', '.box', '.mgz', '.qps', '.ptid', '.qxd', '.bed', '.mxl', '.musicxml', '.cryptonote', '.cod', '.rm', '.link66', '.st', '.see', '.sema', '.semd', '.semf', '.ifm', '.itp', '.iif', '.ipk', '.twd', '.mmf', '.teacher', '.sdkm', '.dxp', '.sfs', '.sdc', '.sda', '.sdd', '.smf', '.sdw', '.sgl', '.sm', '.sxc', '.stc', '.sxd', '.std', '.sxi', '.sti', '.sxm', '.sxw', '.sxg', '.stw', '.sus', '.svd', '.sis', '.xsm', '.bdm', '.xdm', '.tao', '.tmo', '.tpt', '.mxs', '.tra', '.ufdl', '.utz', '.umj', '.unityweb', '.uoml', '.vcx', '.vsd', '.vis', '.vsf', '.wbxml', '.wmlc', '.wmlsc', '.wtb', '.nbp', '.wpd', '.wqd', '.stf', '.xar', '.xfdl', '.hvd', '.hvs', '.hvp', '.osf', '.osfpvg', '.saf', '.spf', '.cmp', '.zir', '.zaz', '.vxml', '.wgt', '.hlp', '.wsdl', '.wspolicy', '.7z', '.abw', '.ace', '.aam', '.aas', '.bcpio', '.torrent', '.bz', '.bz2', '.vcd', '.chat', '.pgn', '.cpio', '.csh', '.deb', '.dir', '.wad', '.ncx', '.dtb', '.res', '.dvi', '.bdf', '.gsf', '.psf', '.otf', '.pcf', '.snf', '.ttf', '.afm', '.woff', '.spl', '.gnumeric', '.gtar', '.hdf', '.jnlp', '.latex', '.mobi', '.m3u8', '.application', '.wmd', '.wmz', '.xbap', '.mdb', '.obd', '.crd', '.clp', '.mvb', '.wmf', '.mny', '.pub', '.scd', '.trm', '.wri', '.nc', '.p12', '.p7b', '.p7r', '.rar', '.sh', '.shar', '.swf', '.xap', '.sit', '.sitx', '.sv4cpio', '.sv4crc', '.tar', '.tcl', '.tex', '.tfm', '.texi', '.ustar', '.src', '.crt', '.fig', '.xpi', '.xdf', '.xenc', '.xhtml', '.xml', '.dtd', '.xop', '.xslt', '.xspf', '.xvml', '.yang', '.yin', '.zip', '.adp', '.au', '.mid', '.mp4a', '.m4a', '.mpga', '.ogg', '.uvva', '.eol', '.dra', '.dts', '.dtshd', '.lvp', '.pya', '.ecelp4800', '.ecelp7470', '.ecelp9600', '.rip', '.weba', '.aac', '.aiff', '.m3u', '.wax', '.wma', '.ram', '.rmp', '.wav', '.cdx', '.cif', '.cmdf', '.cml', '.csml', '.xyz', '.bmp', '.cgm', '.g3', '.gif', '.ief', '.jp2', '.jpg', '.ktx', '.pict', '.png', '.btif', '.svg', '.tiff', '.psd', '.uvi', '.djvu', '.sub', '.dwg', '.dxf', '.fbs', '.fpx', '.fst', '.mmr', '.rlc', '.mdi', '.npx', '.wbmp', '.xif', '.webp', '.ras', '.cmx', '.fh', '.ico', '.pntg', '.pcx', '.pict', '.pnm', '.pbm', '.pgm', '.ppm', '.qtif', '.rgb', '.xbm', '.xpm', '.xwd', '.eml', '.iges', '.mesh', '.dae', '.dwf', '.gdl', '.gtw', '.mts', '.vtu', '.vrml', '.manifest', '.ics', '.css', '.csv', '.html', '.n3', '.txt', '.dsc', '.rtx', '.sgml', '.tsv', '.roff', '.ttl', '.urls', '.curl', '.dcurl', '.mcurl', '.scurl', '.fly', '.flx', '.gv', '.3dml', '.spot', '.jad', '.wml', '.wmls', '.asm', '.c', '.f', '.java', '.pas', '.etx', '.uu', '.vcs', '.vcf', '.3gp', '.3g2', '.h261', '.h263', '.h264', '.jpgv', '.jpm', '.mj2', '.ts', '.m4v', '.mpg', '.ogv', '.mov', '.uvvh', '.uvvm', '.uvvp', '.uvvs', '.uvvv', '.fvt', '.m4u', '.pyv', '.uvvu', '.viv', '.webm', '.dv', '.f4v', '.fli', '.flv', '.m4v', '.asf', '.wm', '.wmv', '.wmx', '.wvx', '.avi', '.movie', '.ice')) 47 | return ending 48 | 49 | def parse_files(temp,path,IP,reply): 50 | #parse all files from pcap 51 | if reply == 'MD5': 52 | h = hashlib.md5() 53 | elif reply == 'SHA1': 54 | h = hashlib.sha1() 55 | elif reply == 'SHA256': 56 | h = hashlib.sha256() 57 | if IP == None: 58 | for infile in os.listdir(temp): 59 | if 'HTTPBODY' in infile: 60 | if infile.endswith(extn()): 61 | with open (temp+infile, 'rb') as afile: 62 | buf = afile.read() 63 | h.update(buf) 64 | output = h.hexdigest() 65 | afile.close() 66 | filename, fileExtention = os.path.splitext(infile) 67 | os.chdir(path) 68 | shutil.move((temp+infile),(output+fileExtention)) 69 | else: 70 | try: 71 | with open(temp+infile, 'rb') as afile: 72 | end = ext(afile.read(20)) 73 | buf = afile.read() 74 | h.update(buf) 75 | output = h.hexdigest() 76 | afile.close() 77 | filename, fileExtention = os.path.splitext(infile) 78 | os.chdir(path) 79 | shutil.move((temp+infile),(output+end)) 80 | except: 81 | pass 82 | #parse files for tcp flow 83 | else: 84 | folder = str(os.listdir(temp)) 85 | if IP in folder: 86 | for infile in os.listdir(temp): 87 | if 'HTTPBODY' in infile: 88 | if IP in infile: 89 | if infile.endswith(extn()): 90 | with open (temp+infile, 'rb') as afile: 91 | buf = afile.read() 92 | h.update(buf) 93 | output = h.hexdigest() 94 | afile.close() 95 | filename, fileExtention = os.path.splitext(infile) 96 | os.chdir(path) 97 | shutil.move((temp+infile),(output+fileExtention)) 98 | else: 99 | try: 100 | with open(temp+infile, 'rb') as afile: 101 | end = ext(afile.read(20)) 102 | buf = afile.read() 103 | h.update(buf) 104 | output = h.hexdigest() 105 | afile.close() 106 | filename, fileExtention = os.path.splitext(infile) 107 | os.chdir(path) 108 | shutil.move((temp+infile),(output+end)) 109 | except: 110 | pass 111 | else: 112 | e = str("No files found.") 113 | open(out,'ab').write(e) 114 | 115 | #parse out tcp flow for IP 116 | def parse_flow(IP): 117 | styleID = ''.join(choice(string.ascii_lowercase + string.digits) for x in range(randint(8, 12))) 118 | ssize = len(styleID) 119 | p = sub.Popen(['tcpflow', '-T %T--%A-%B', '-cJB', '-r', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap'))], stdout=sub.PIPE, stderr=sub.PIPE) 120 | stdout, stderr = p.communicate() 121 | stdout = stdout.replace('\r\n', '\n') 122 | 123 | if IP not in stdout: 124 | e = str("No tcp flows found for ")+IP 125 | open(out, 'ab').write(e) 126 | 127 | else: 128 | if os.getenv('PROCDOTPLUGIN_PluginEngineVersion') is not None: 129 | open(out,'ab').write('{{{style-id:default;color:blue;style-id:'+styleID+';color:red}}}') 130 | m = re.findall ( '\x1b\[0;31m(.*?)\x1b\[0m|\x1b\[0;34m(.*?)\x1b\[0m', stdout, re.DOTALL) 131 | m = iter(m) 132 | for b, r in m: 133 | if b == '': 134 | if IP in r: 135 | r = r[56:] 136 | r = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', r) 137 | if os.stat(out).st_size <= 53 + ssize: 138 | if os.getenv('PROCDOTPLUGIN_PluginEngineVersion') is not None: 139 | open(out,'ab').write('<'+styleID+'>'+r+'') 140 | else: 141 | open(out,'ab').write(r) 142 | else: 143 | if os.getenv('PROCDOTPLUGIN_PluginEngineVersion') is not None: 144 | open(out,'ab').write('\n\n'+'<'+styleID+'>'+r+'') 145 | else: 146 | open(out,'ab').write('\n\n'+r) 147 | else: 148 | if IP in b: 149 | b = b[56:] 150 | match = re.match( '^HTTP.*', b) 151 | try: 152 | if match: 153 | length = 1 154 | num = 0 155 | while length != num: 156 | d = zlib.decompressobj(16+zlib.MAX_WBITS) 157 | output = StringIO.StringIO(b) 158 | status_line = output.readline() 159 | msg = HTTPMessage(output, 0) 160 | isLength = msg.get('Content-Length') 161 | isGZipped = msg.get('content-encoding', '').find('gzip') >= 0 162 | isChunked = msg.get('Transfer-Encoding', '').find('chunked') >= 0 163 | if isGZipped and isChunked: 164 | offset = msg.fp.readline() 165 | body = msg.fp.read() 166 | num = int(offset, 16) 167 | encdata = '' 168 | newdata = '' 169 | encdata =body[:num] 170 | length = len(encdata) 171 | if length != num: 172 | c = next(m) 173 | d, e = c 174 | b = b + d[56:] 175 | else: 176 | newdata = d.decompress(encdata) 177 | header = str(msg) 178 | open(out,'ab').write(status_line) 179 | open(out,'ab').write(header) 180 | open(out,'ab').write('\n') 181 | open(out,'ab').write(newdata) 182 | elif isGZipped: 183 | length = int(isLength) 184 | body = msg.fp.read() 185 | num = len(body) 186 | if length != num: 187 | c = next(m) 188 | d, e = c 189 | if IP in d: 190 | b = b + d[56:] 191 | else: 192 | data = d.decompress(body) 193 | header = str(msg) 194 | open(out,'ab').write(status_line) 195 | open(out,'ab').write(header) 196 | open(out,'ab').write('\n') 197 | open(out,'ab').write(data) 198 | else: 199 | length = 1 200 | num = 1 201 | body = msg.fp.read() 202 | body = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', body) 203 | header = str(msg) 204 | open(out,'ab').write(status_line) 205 | open(out,'ab').write(header) 206 | open(out,'ab').write('\n') 207 | open(out,'ab').write(body) 208 | else: 209 | b = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', b) 210 | open(out,'ab').write(b) 211 | except: 212 | open(out,'ab').write('DECOMPRESSION ERROR') 213 | open(out,'ab').write('\n\n') 214 | b = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', b) 215 | open(out,'ab').write(b) 216 | def isTimeFormat(input): 217 | try: 218 | time.strptime(input, '%H:%M:%S.%f') 219 | return True 220 | except ValueError: 221 | return False 222 | 223 | #get packets for animation mode 224 | def get_packet(): 225 | procdottime = os.getenv('PROCDOTPLUGIN_AnimationMode_CurrentFrame_TimestampOriginalString').replace(',', '.') 226 | if len(procdottime) == 15: 227 | procdottime = '0' + procdottime 228 | with open(os.getenv('PROCDOTPLUGIN_ProcmonFileCsv'), 'rb') as f: 229 | reader = csv.DictReader(f) 230 | rows = [row for row in reader if os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') in str(row['Path']) and 'TCP' in str(row['Operation'])] 231 | irofile = iter(rows) 232 | for row in irofile: 233 | starttime = str(row['\xef\xbb\xbf"Time of Day"']).replace(',', '.') 234 | if len(starttime) == 18: 235 | starttime = '0' + starttime 236 | if starttime[:16] == procdottime: 237 | if str(row['Operation']) == 'TCP Receive' or str(row['Operation']) == 'TCP Send': 238 | if str(row['Operation']) == 'TCP Send': 239 | open(out,'ab').write('{{{style-id:default;color:red}}}') 240 | else: 241 | open(out,'ab').write('{{{style-id:default;color:blue}}}') 242 | length = str(row['Detail']).split(',')[0].split(':')[1][1:] 243 | if 'PM' in starttime: 244 | starttime = starttime[:-4] + ' PM' 245 | starttime = datetime.strptime(starttime, '%I:%M:%S.%f %p').strftime('%H:%M:%S.%f') 246 | elif 'AM' in starttime: 247 | starttime = starttime[:-4] + ' AM' 248 | starttime = datetime.strptime(starttime, '%I:%M:%S.%f %p').strftime('%H:%M:%S.%f') 249 | else: 250 | starttime = datetime.strptime(str(starttime)[:-1], '%H:%M:%S.%f').strftime('%H:%M:%S.%f') 251 | row = next(irofile) 252 | endtime = str(row['\xef\xbb\xbf"Time of Day"']).replace(',', '.') 253 | if len(endtime) == 18: 254 | endtime = '0' + endtime 255 | if 'PM' in endtime: 256 | endtime = endtime[:-4] + ' PM' 257 | endtime = datetime.strptime(endtime, '%I:%M:%S.%f %p') 258 | endtime = endtime + timedelta(milliseconds=10) 259 | endtime = endtime.strftime('%H:%M:%S.%f') 260 | elif 'AM' in endtime: 261 | endtime = endtime[:-4] + ' AM' 262 | endtime = datetime.strptime(endtime, '%I:%M:%S.%f %p') 263 | endtime = endtime + timedelta(milliseconds=10) 264 | endtime = endtime.strftime('%H:%M:%S.%f') 265 | else: 266 | endtime = datetime.strptime(str(endtime)[:-1], '%H:%M:%S.%f') 267 | endtime = endtime + timedelta(milliseconds=10) 268 | endtime = endtime.strftime('%H:%M:%S.%f') 269 | execute = os.getenv('PROCDOTPLUGIN_Path2WindumpExecutable') + ' -n -p -A -r ' + '"' + os.getenv('PROCDOTPLUGIN_WindumpFilePcap') + '"' + ' host ' + os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') 270 | p = sub.Popen(execute, stdout=sub.PIPE, stderr=sub.PIPE, shell=True) 271 | line0, line1 = itertools.tee(p.stdout) 272 | try: 273 | next(line1) 274 | except: 275 | e = str("No tcp packets found for ")+os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address')+(" in this time frame.") 276 | open(out,'wb').write(e) 277 | sys.exit(0) 278 | lines = zip(line0, line1) 279 | lines = iter(lines) 280 | for val0, val1 in lines: 281 | if 'length '+length in val0: 282 | packetstart = datetime.strptime(val0[:15], '%H:%M:%S.%f') 283 | offset = str(packetstart)[11:13] 284 | offset = int(starttime[:2]) - int(offset) 285 | packetstart = packetstart + timedelta(hours=offset) 286 | packetstart = packetstart.strftime('%H:%M:%S.%f') 287 | if packetstart >= starttime and packetstart <= endtime: 288 | packet = [] 289 | while isTimeFormat(val1[:15]) == False: 290 | packet.append(val1.replace('\r\n', '\n')) 291 | val0, val1 = next(lines) 292 | packet = ''.join(packet) 293 | open(out,'ab').write(str(packet)[40:] + '\n') 294 | elif str(row['Operation']) == 'TCP Connect': 295 | open(out,'ab').write('{{{style-id:default;color:white;background-color:red}}}') 296 | open(out,'ab').write(' \n') 297 | open(out,'ab').write(' \n') 298 | open(out,'ab').write(' TCP Connection \n') 299 | open(out,'ab').write(' \n') 300 | open(out,'ab').write(' \n') 301 | else: 302 | open(out,'ab').write('{{{style-id:default;color:white;background-color:red}}}') 303 | open(out,'ab').write(' \n') 304 | open(out,'ab').write(' \n') 305 | open(out,'ab').write(' TCP Disconnect \n') 306 | open(out,'ab').write(' \n') 307 | open(out,'ab').write(' \n') 308 | if os.stat(out).st_size == 0: 309 | e = str("No tcp packets found for ")+os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address')+(" in this time frame.") 310 | open(out,'wb').write(e) 311 | sys.exit(0) 312 | 313 | def filter_pcap(): 314 | name = os.getenv('PROCDOTPLUGIN_TempFolder')+'\\'+os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address')+'.pcap' 315 | p = sub.Popen([(os.getenv('PROCDOTPLUGIN_Path2WindumpExecutable')), '-r', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap')), '-w', name, 'host', os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') ], stdout=sub.PIPE, stderr=sub.PIPE) 316 | p.wait() 317 | try: 318 | p = sub.Popen(['wireshark', name]) 319 | except: 320 | e = str("Wireshark is missing") 321 | open(out,'wb').write(e) 322 | sys.exit(0) 323 | 324 | def on_closing(root): 325 | try: 326 | shutil.rmtree(temp) 327 | except: 328 | pass 329 | root.destroy() 330 | sys.exit(0) 331 | 332 | def gui(reply,path,tempFile): 333 | root = Tk() 334 | reply = StringVar(root) 335 | reply.set("MD5") # initial value 336 | path = StringVar(None) 337 | path.set("/") # initial value 338 | root.title("Extract Files From PCAP") 339 | # root.wm_iconbitmap('@'+tempFile) 340 | root.resizable(width=FALSE, height=FALSE) 341 | 342 | topFrame = Frame(root) 343 | topFrame.grid(row=0, column=0) 344 | middleFrame = Frame(root) 345 | middleFrame.grid(row=1, column=0) 346 | bottomFrame = Frame(root) 347 | bottomFrame.grid(row=2, column=0) 348 | root.grid_rowconfigure(3, minsize=4) 349 | 350 | Label(topFrame, text="Hash type:").grid(row=0, column=0) 351 | Radiobutton(topFrame, text="MD5", variable=reply, value="MD5").grid(row=0, column=1) 352 | Radiobutton(topFrame, text="SHA1", variable=reply, value="SHA1").grid(row=0, column=2) 353 | Radiobutton(topFrame, text="SHA256", variable=reply, value="SHA256").grid(row=0, column=3) 354 | Label(middleFrame, text="Save folder:").grid(row=0, column=0) 355 | Entry(middleFrame, width=25, textvariable=path).grid(row=0, column=1) 356 | Button(middleFrame, text='...', command=lambda:callback(path)).grid(row=0, column=3, padx=4) 357 | Button(bottomFrame, text="Extract Files", command=lambda:ok(reply, path, root)).grid(row=0, column=1) 358 | 359 | root.bind("", lambda e: root.deiconify()) 360 | root.protocol("WM_DELETE_WINDOW", lambda:on_closing(root)) 361 | root.mainloop() 362 | 363 | reply = reply.get() 364 | path = path.get() 365 | try: 366 | if path != None: 367 | if not os.path.exists(path): 368 | os.makedirs(path) 369 | return reply,path 370 | else: 371 | return reply,path 372 | except: 373 | shutil.rmtree(temp) 374 | 375 | #get save folder path 376 | def callback(path): 377 | folder = tkFileDialog.askdirectory(initialdir='C:/', title='Extract files from pcap') 378 | path.set(folder) 379 | 380 | #exit gui 381 | def ok(reply, path, root): 382 | root.quit() 383 | 384 | #icon for gui 385 | def icon(tempFile): 386 | icon = \ 387 | """ AAABAAEAECAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAA4AAAh/AAAVxAAACfIAAAnyAAAVxAAACH8AAAAO////AP///wD///8A////AP///wD///8A////AAAAAEIAAA3pAABx9wAAwP8AAO//AADv/wAAwP8AAHH3AAAN6QAAAEL///8A////AP///wD///8A////AAAAAEIAABfzAADL/wAA//8AAP//AAD//wAA//8AAP//AAD//wAAy/8AABfzAAAAQv///wD///8A////AAAAAA4AAA3pAADL/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AADL/wAADekAAAAO////AP///wAAAAh/AABx9wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAHH3AAAIf////wD///8AAAAVxAAAwP8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AADA/wAAFcT///8A////AAAACfIAAO//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA7/8AAAny////AP///wAAAAnyAADv/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAO//AAAJ8v///wD///8AAAAVxAAAwP8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AADA/wAAFcT///8A////AAAACH8AAHH3AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAAcfcAAAh/////AP///wAAAAAOAAAN6QAAy/8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAAy/8AAA3pAAAADv///wD///8A////AAAAAEIAABfzAADL/wAA//8AAP//AAD//wAA//8AAP//AAD//wAAy/8AABfzAAAAQv///wD///8A////AP///wD///8AAAAAQgAADekAAHH3AADA/wAA7/8AAO//AADA/wAAcfcAAA3pAAAAQv///wD///8A////AP///wD///8A////AP///wAAAAAOAAAIfwAAFcQAAAnyAAAJ8gAAFcQAAAh/AAAADv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAPw/AADwDwAA4AcAAMADAADAAwAAgAEAAIABAACAAQAAgAEAAMADAADAAwAA4AcAAPAPAAD8PwAA//8AAA== 388 | """ 389 | icondata= base64.b64decode(icon) 390 | tempFile= temp+"icon.ico" 391 | iconfile= open(tempFile,"wb") 392 | iconfile.write(icondata) 393 | iconfile.close() 394 | return tempFile 395 | 396 | #convert IP into tcpflow format 397 | def parse_IP(IP): 398 | try: 399 | one, two, three, four = IP.split('.') 400 | one='00'+(one) 401 | two='00'+(two) 402 | three='00'+(three) 403 | four='00'+(four) 404 | IP=one[-3:]+'.'+two[-3:]+'.'+three[-3:]+'.'+four[-3:] 405 | return IP 406 | except: 407 | e = str("No IP associated with flow.") 408 | open(out,'w').write(e) 409 | sys.exit(0) 410 | 411 | def check_tcpflow_ver(): 412 | try: 413 | p = sub.Popen(['tcpflow', '-V'], stdout=sub.PIPE, stderr=sub.PIPE) 414 | check = p.communicate()[0] 415 | if 'tcpflow 1.' not in check.lower() and 'tcpflow 2.' not in check.lower(): 416 | e = str("[ERROR] Please download 1.0 or higer\nDownload: https://github.com/simsong/tcpflow/") 417 | open(out,'ab').write(e) 418 | sys.exit(0) 419 | except: 420 | e = str("[ERROR] TCPflow missing. Please download 1.0 or higer.\nDownload: https://github.com/simsong/tcpflow/") 421 | open(out,'w').write(e) 422 | sys.exit(0) 423 | 424 | def main(): 425 | reply = None 426 | path = None 427 | IP = None 428 | tempFile = None 429 | 430 | check_tcpflow_ver() 431 | if os.getenv('PROCDOTPLUGIN_Name') == 'Extract Files From PCAP': 432 | p = sub.Popen(['tcpflow', '-T %N_%A-%B', '-o', (temp), '-ar', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap'))], stdout=sub.PIPE, stderr=sub.PIPE) 433 | stdout, stderr = p.communicate() 434 | if 'tcpflow:' in stderr: 435 | e = str("PCAP file missing. Please select a PCAP file and try again.") 436 | open(out,'ab').write(e) 437 | sys.exit(0) 438 | else: 439 | p.wait() 440 | tempFile = icon(tempFile) 441 | reply,path = gui(reply,path,tempFile) 442 | parse_files(temp,path,IP,reply) 443 | shutil.rmtree(temp) 444 | elif os.getenv('PROCDOTPLUGIN_Name') == 'Follow TCP Stream': 445 | IP = os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') 446 | IP = parse_IP(IP) 447 | if os.getenv('PROCDOTPLUGIN_AnimationMode') == None or os.getenv('PROCDOTPLUGIN_AnimationMode') == '0': 448 | parse_flow(IP) 449 | else: 450 | get_packet() 451 | elif os.getenv('PROCDOTPLUGIN_Name') == 'Open Packets in Wireshark': 452 | filter_pcap() 453 | else: 454 | p = sub.Popen(['tcpflow', '-T %N_%A-%B', '-o', (temp), '-ar', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap'))], stdout=sub.PIPE, stderr=sub.PIPE) 455 | p.wait() 456 | tempFile = icon(tempFile) 457 | reply,path = gui(reply,path,tempFile) 458 | IP = os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') 459 | IP = parse_IP(IP) 460 | parse_files(temp,path,IP,reply) 461 | shutil.rmtree(temp) 462 | 463 | if __name__ == '__main__': 464 | main() 465 | -------------------------------------------------------------------------------- /PCAP_tools/Linux/1.2/pcap_tools_Wireshark.pdp: -------------------------------------------------------------------------------- 1 | Name = Open Packets in Wireshark 2 | Author = Beercow 3 | Description = ProcDOT plugin to filter pcap 4 | Version = 1 5 | Type = ContextMenuItemForGraph 6 | Architecture = LinuxShellScript 7 | File = pcap_tools.py 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | CanBeVerified = 1 -------------------------------------------------------------------------------- /PCAP_tools/Linux/1.2/pcap_tools_files.pdp: -------------------------------------------------------------------------------- 1 | Name = Extract Files From PCAP 2 | Author = Beercow 3 | Description = ProcDOT plugin to extract files from pcap 4 | Version = 2.5 5 | Type = MainMenuItem 6 | Architecture = LinuxShellScript 7 | File = pcap_tools.py 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | -------------------------------------------------------------------------------- /PCAP_tools/Linux/1.2/pcap_tools_stream_file.pdp: -------------------------------------------------------------------------------- 1 | Name = Extract File(s) From Flow 2 | Author = Beercow 3 | Description = ProcDOT plugin to extract file from TCP stream 4 | Version = 2.5 5 | Type = ContextMenuItemForGraph 6 | Architecture = LinuxShellScript 7 | File = pcap_tools.py 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | CanBeVerified = 1 14 | -------------------------------------------------------------------------------- /PCAP_tools/Linux/1.2/pcap_tools_streams.pdp: -------------------------------------------------------------------------------- 1 | Name = Follow TCP Stream 2 | Author = Beercow 3 | Description = ProcDOT plugin to follow streams from pcap 4 | Version = 2.5 5 | Type = ContextMenuItemForGraph 6 | Architecture = LinuxShellScript 7 | File = pcap_tools.py 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | CanBeVerified = 1 14 | -------------------------------------------------------------------------------- /PCAP_tools/README.md: -------------------------------------------------------------------------------- 1 | # PCAP Tools [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=beercow&url=https://github.com/Beercow/ProcDOT-Plugins) 2 | \* Due to slight variations in the plugin engine, be sure to download the plugin for the right version of ProcDOT 3 | 4 | ## Project source can be downloaded from 5 | https://github.com/Beercow/ProcDOT-Plugins/tree/master/PCAP_tools 6 | ## Author & Contributor List 7 | Brian Maloney 8 | 9 | ## Overview 10 | PCAP_tools is a set of plugins to add functionality to ProcDOT. With this plugin, you will be able to dump files from the pcap and view flows in ProcDOT. TCPflow is used with the plugin to accomplish this. 11 | 12 | ### Setup 13 | Download files from the repository for your system. Move the pcap_tools(.py) and pdp fles into you ProcDOT plugins directory. These plugins depend on Python 2.7 and tcpflow 1.4.4 or later (http://www.digitalcorpora.org/downloads/tcpflow/). Place the tcpflow executable either in the plugin folder or from a system callable path. On Windows, make sure the pcap_tools.bat contains the rihgt path to for python. 14 | 15 | ![2016-12-16_8-08-19](https://cloud.githubusercontent.com/assets/10360919/21265427/124a660c-c367-11e6-849a-a9c5951ae267.png) 16 | 17 | Fire up ProcDOT and there should an entry in the Plugin menu called **Extract Files From PCAP**, and a right click option on a server node labeled **Follow TCP Stream** and **Extract File(s) From Flow**. 18 | 19 | #### Extract Files From PCAP 20 | Extract Files From PCAP is controled by pcap_tools_files.pdp. With this config file in the ProcDOT plugins folder, there should now be an entry in the plugins menu. 21 | 22 | ![Plugins Menu](https://cloud.githubusercontent.com/assets/10360919/12631017/e049998a-c514-11e5-9e4a-31a35ff9dc4a.png) 23 | 24 | This plugin will allow you to extract files that are contained in pcap file loaded in ProcDOT. Once selected, a new window will open asking you which hash algorithum you want to use(MD5, SHA1, SHA256). Once you are done picking a hash, it will ask for folder to save the files in. 25 | 26 | ![pcap_tools_gui](https://cloud.githubusercontent.com/assets/10360919/21141301/fc566b28-c101-11e6-8c83-ce9b6506e552.png) ![Save Folder](https://cloud.githubusercontent.com/assets/10360919/12631019/e054af64-c514-11e5-8f95-033de6bbaffd.PNG) 27 | 28 | If there are files in the pcap, they should be hashed accordingly in the save folder. 29 | ![Hashed Files](https://cloud.githubusercontent.com/assets/10360919/12631022/e05d782e-c514-11e5-9092-dda6f2d10e03.PNG) 30 | 31 | #### Follow TCP Stream 32 | Follow TCP Stream is controled by pcap_tools_stream.pdp. With this config file loaded in ProcDOT plugins folder, there should now be an entry in the right click menu when you are on a server node. 33 | ![Server Node Right Click Menu](https://cloud.githubusercontent.com/assets/10360919/12631020/e055c520-c514-11e5-9f1f-c8a7933f6453.png) 34 | 35 | The plugin will allow you to view complete flows natively in ProcDOT. They will look simular to viewing them in Wireshark. 36 | 37 | ![Wireshark Stream View](https://cloud.githubusercontent.com/assets/10360919/12631025/e069edc0-c514-11e5-8180-f44c41e74632.PNG) ![ProcDOT Stream View](https://cloud.githubusercontent.com/assets/10360919/12631023/e0626f0a-c514-11e5-8d04-4a0d5ce22cde.png) 38 | 39 | Also, if a stream contains gzipped data, Follow TCP Stream should automagically ungzip the stream. 40 | 41 | ![Wireshark gzip data](https://cloud.githubusercontent.com/assets/10360919/12631026/e0710d6c-c514-11e5-9c38-08c083045183.PNG) ![ProcDOT gzip data](https://cloud.githubusercontent.com/assets/10360919/12631024/e067964c-c514-11e5-983c-632997c5ba09.png) 42 | 43 | #### Extract File(s) From Flow 44 | Extract File(s) From Flow is controled by pcap_tools_stream_file.pdp, With this config file loaded in ProcDOT plugins folder, there should now be an entry in the right click menu when you are on a server node. 45 | 46 | The plugin will allow you to extract the files from the flow. Once selected, a new window will open asking you which hash algorithum you want to use(MD5, SHA1, SHA256). Once you are done picking a hash, it will ask for folder to save the files in. 47 | 48 | If there are files in the flow, they should be hashed accordingly in the save folder. 49 | ## Bugs 50 | -------------------------------------------------------------------------------- /PCAP_tools/Windows/1.2/pcap_tools.bat: -------------------------------------------------------------------------------- 1 | @setlocal enabledelayedexpansion && C:\Python27\python.exe -x "%~f0" %* & exit /b !ERRORLEVEL! 2 | #!/usr/bin/env python 3 | 4 | #works with windump version 3.9.5 5 | 6 | import os 7 | import sys 8 | 9 | if os.getenv('PROCDOTPLUGIN_VerificationRun') == '0' or os.getenv('PROCDOTPLUGIN_Name') == 'Extract Files From PCAP': 10 | pass 11 | else: 12 | if os.getenv('PROCDOTPLUGIN_CurrentNode_name')[:6] == 'SERVER': 13 | sys.exit(1) 14 | else: 15 | sys.exit(0) 16 | 17 | import csv 18 | import hashlib 19 | import shutil 20 | import subprocess as sub 21 | from httplib import HTTPMessage 22 | import StringIO 23 | import zlib 24 | from Tkinter import * 25 | import tkFileDialog 26 | import base64 27 | import re 28 | from datetime import datetime 29 | from datetime import timedelta 30 | import time 31 | import itertools 32 | import string 33 | from random import * 34 | 35 | out = os.getenv('PROCDOTPLUGIN_ResultTXT') 36 | temp = os.getenv('PROCDOTPLUGIN_TempFolder')+'\\tcpflow_out\\' 37 | 38 | #check for executable files 39 | def ext(header): 40 | if 'MZ' in header: 41 | return '.mz' 42 | else: 43 | return '.bin' 44 | 45 | #tcpflow file endings 46 | def extn(): 47 | ending = (('.ez', '.aw', '.atom', '.atomcat', '.atomsvc', '.ccxml', '.cdmia', '.cdmic', '.cdmid', '.cdmio', '.cdmiq', '.cu', '.davmount', '.dssc', '.xdssc', '.ecma', '.emma', '.epub', '.exi', '.pfr', '.stk', '.ipfix', '.jar', '.ser', '.class', '.js', '.json', '.lostxml', '.hqx', '.cpt', '.mads', '.mrc', '.mrcx', '.mb', '.mathml', '.mbox', '.mscml', '.meta4', '.mets', '.mods', '.mp21', '.mp4s', '.doc', '.mxf', '.oda', '.opf', '.ogx', '.onetoc', '.xer', '.pdf', '.pgp', '.asc', '.prf', '.p10', '.p7m', '.p7s', '.p8', '.ac', '.cer', '.crl', '.pkipath', '.pki', '.pls', '.ps', '.cww', '.pskcxml', '.rdf', '.rif', '.rnc', '.rl', '.rld', '.rs', '.rsd', '.rss', '.rtf', '.sbml', '.scq', '.scs', '.spq', '.spp', '.sdp', '.setpay', '.setreg', '.shf', '.smil', '.rq', '.srx', '.gram', '.grxml', '.sru', '.ssml', '.teicorpus', '.tfi', '.tsd', '.plb', '.psb', '.pvb', '.tcap', '.pwn', '.aso', '.imp', '.acu', '.atc', '.air', '.fxp', '.xdp', '.xfdf', '.ahead', '.azf', '.azs', '.azw', '.acc', '.ami', '.apk', '.cii', '.fti', '.atx', '.mpkg', '.m3u8', '.swi', '.aep', '.mpm', '.bmi', '.rep', '.cdxml', '.mmd', '.cdy', '.cla', '.rp9', '.c4g', '.c11amc', '.c11amz', '.csp', '.cdbcmsg', '.cmc', '.clkx', '.clkk', '.clkp', '.clkt', '.clkw', '.wbs', '.pml', '.ppd', '.car', '.pcurl', '.rdz', '.fe_launch', '.dna', '.mlp', '.dpg', '.dfac', '.ait', '.svc', '.geo', '.mag', '.nml', '.esf', '.msf', '.qam', '.slt', '.ssf', '.es3', '.ez2', '.ez3', '.fdf', '.mseed', '.seed', '.gph', '.ftc', '.fm', '.fnc', '.ltf', '.fsc', '.oas', '.oa2', '.oa3', '.fg5', '.bh2', '.ddd', '.xdw', '.xbd', '.fzs', '.txd', '.ggb', '.ggt', '.gex', '.gxt', '.g2w', '.g3w', '.gmx', '.kml', '.kmz', '.gqf', '.gac', '.ghf', '.gim', '.grv', '.gtm', '.tpl', '.vcg', '.hal', '.zmm', '.hbci', '.les', '.hpgl', '.hpid', '.hps', '.jlt', '.pcl', '.pclxl', '.sfd-hdstx', '.x3d', '.mpy', '.afp', '.irm', '.sc', '.icc', '.igl', '.ivp', '.ivu', '.igm', '.xpw', '.i2g', '.qbo', '.qfx', '.rcprofile', '.irp', '.xpr', '.fcs', '.jam', '.rms', '.jisp', '.joda', '.ktz', '.karbon', '.chrt', '.kfo', '.flw', '.kon', '.kpr', '.ksp', '.kwd', '.htke', '.kia', '.knp', '.skp', '.sse', '.lasxml', '.lbd', '.lbe', '.123', '.apr', '.pre', '.nsf', '.org', '.scm', '.lwp', '.portpkg', '.mcd', '.mc1', '.cdkey', '.mwf', '.mfm', '.flo', '.igx', '.mif', '.daf', '.dis', '.mbk', '.mqy', '.msl', '.plc', '.txf', '.mpn', '.mpc', '.xul', '.cil', '.cab', '.xls', '.xlam', '.xlsb', '.xlsm', '.xltm', '.eot', '.chm', '.ims', '.lrm', '.thmx', '.cat', '.stl', '.ppt', '.ppam', '.pptm', '.sldm', '.ppsm', '.potm', '.mpp', '.docm', '.dotm', '.wps', '.wpl', '.xps', '.mseq', '.mus', '.msty', '.nlu', '.nnd', '.nns', '.nnw', '.ngdat', '.n-gage', '.rpst', '.rpss', '.edm', '.edx', '.ext', '.odc', '.otc', '.odb', '.odf', '.odft', '.odg', '.otg', '.odi', '.oti', '.odp', '.otp', '.ods', '.ots', '.odt', '.odm', '.ott', '.oth', '.xo', '.dd2', '.oxt', '.pptx', '.sldx', '.ppsx', '.potx', '.xlsx', '.xltx', '.docx', '.dotx', '.mgp', '.dp', '.pdb', '.paw', '.str', '.ei6', '.efif', '.wg', '.plf', '.pbd', '.box', '.mgz', '.qps', '.ptid', '.qxd', '.bed', '.mxl', '.musicxml', '.cryptonote', '.cod', '.rm', '.link66', '.st', '.see', '.sema', '.semd', '.semf', '.ifm', '.itp', '.iif', '.ipk', '.twd', '.mmf', '.teacher', '.sdkm', '.dxp', '.sfs', '.sdc', '.sda', '.sdd', '.smf', '.sdw', '.sgl', '.sm', '.sxc', '.stc', '.sxd', '.std', '.sxi', '.sti', '.sxm', '.sxw', '.sxg', '.stw', '.sus', '.svd', '.sis', '.xsm', '.bdm', '.xdm', '.tao', '.tmo', '.tpt', '.mxs', '.tra', '.ufdl', '.utz', '.umj', '.unityweb', '.uoml', '.vcx', '.vsd', '.vis', '.vsf', '.wbxml', '.wmlc', '.wmlsc', '.wtb', '.nbp', '.wpd', '.wqd', '.stf', '.xar', '.xfdl', '.hvd', '.hvs', '.hvp', '.osf', '.osfpvg', '.saf', '.spf', '.cmp', '.zir', '.zaz', '.vxml', '.wgt', '.hlp', '.wsdl', '.wspolicy', '.7z', '.abw', '.ace', '.aam', '.aas', '.bcpio', '.torrent', '.bz', '.bz2', '.vcd', '.chat', '.pgn', '.cpio', '.csh', '.deb', '.dir', '.wad', '.ncx', '.dtb', '.res', '.dvi', '.bdf', '.gsf', '.psf', '.otf', '.pcf', '.snf', '.ttf', '.afm', '.woff', '.spl', '.gnumeric', '.gtar', '.hdf', '.jnlp', '.latex', '.mobi', '.m3u8', '.application', '.wmd', '.wmz', '.xbap', '.mdb', '.obd', '.crd', '.clp', '.mvb', '.wmf', '.mny', '.pub', '.scd', '.trm', '.wri', '.nc', '.p12', '.p7b', '.p7r', '.rar', '.sh', '.shar', '.swf', '.xap', '.sit', '.sitx', '.sv4cpio', '.sv4crc', '.tar', '.tcl', '.tex', '.tfm', '.texi', '.ustar', '.src', '.crt', '.fig', '.xpi', '.xdf', '.xenc', '.xhtml', '.xml', '.dtd', '.xop', '.xslt', '.xspf', '.xvml', '.yang', '.yin', '.zip', '.adp', '.au', '.mid', '.mp4a', '.m4a', '.mpga', '.ogg', '.uvva', '.eol', '.dra', '.dts', '.dtshd', '.lvp', '.pya', '.ecelp4800', '.ecelp7470', '.ecelp9600', '.rip', '.weba', '.aac', '.aiff', '.m3u', '.wax', '.wma', '.ram', '.rmp', '.wav', '.cdx', '.cif', '.cmdf', '.cml', '.csml', '.xyz', '.bmp', '.cgm', '.g3', '.gif', '.ief', '.jp2', '.jpg', '.ktx', '.pict', '.png', '.btif', '.svg', '.tiff', '.psd', '.uvi', '.djvu', '.sub', '.dwg', '.dxf', '.fbs', '.fpx', '.fst', '.mmr', '.rlc', '.mdi', '.npx', '.wbmp', '.xif', '.webp', '.ras', '.cmx', '.fh', '.ico', '.pntg', '.pcx', '.pict', '.pnm', '.pbm', '.pgm', '.ppm', '.qtif', '.rgb', '.xbm', '.xpm', '.xwd', '.eml', '.iges', '.mesh', '.dae', '.dwf', '.gdl', '.gtw', '.mts', '.vtu', '.vrml', '.manifest', '.ics', '.css', '.csv', '.html', '.n3', '.txt', '.dsc', '.rtx', '.sgml', '.tsv', '.roff', '.ttl', '.urls', '.curl', '.dcurl', '.mcurl', '.scurl', '.fly', '.flx', '.gv', '.3dml', '.spot', '.jad', '.wml', '.wmls', '.asm', '.c', '.f', '.java', '.pas', '.etx', '.uu', '.vcs', '.vcf', '.3gp', '.3g2', '.h261', '.h263', '.h264', '.jpgv', '.jpm', '.mj2', '.ts', '.m4v', '.mpg', '.ogv', '.mov', '.uvvh', '.uvvm', '.uvvp', '.uvvs', '.uvvv', '.fvt', '.m4u', '.pyv', '.uvvu', '.viv', '.webm', '.dv', '.f4v', '.fli', '.flv', '.m4v', '.asf', '.wm', '.wmv', '.wmx', '.wvx', '.avi', '.movie', '.ice')) 48 | return ending 49 | 50 | def parse_files(temp,path,IP,reply): 51 | #parse all files from pcap 52 | if reply == 'MD5': 53 | h = hashlib.md5() 54 | elif reply == 'SHA1': 55 | h = hashlib.sha1() 56 | elif reply == 'SHA256': 57 | h = hashlib.sha256() 58 | if IP == None: 59 | for infile in os.listdir(temp): 60 | if 'HTTPBODY' in infile: 61 | if infile.endswith(extn()): 62 | with open (temp+infile, 'rb') as afile: 63 | buf = afile.read() 64 | h.update(buf) 65 | output = h.hexdigest() 66 | afile.close() 67 | filename, fileExtention = os.path.splitext(infile) 68 | os.chdir(path) 69 | shutil.move((temp+infile),(output+fileExtention)) 70 | else: 71 | try: 72 | with open(temp+infile, 'rb') as afile: 73 | end = ext(afile.read(20)) 74 | buf = afile.read() 75 | h.update(buf) 76 | output = h.hexdigest() 77 | afile.close() 78 | filename, fileExtention = os.path.splitext(infile) 79 | os.chdir(path) 80 | shutil.move((temp+infile),(output+end)) 81 | except: 82 | pass 83 | #parse files for tcp flow 84 | else: 85 | folder = str(os.listdir(temp)) 86 | if IP in folder: 87 | for infile in os.listdir(temp): 88 | if 'HTTPBODY' in infile: 89 | if IP in infile: 90 | if infile.endswith(extn()): 91 | with open (temp+infile, 'rb') as afile: 92 | buf = afile.read() 93 | h.update(buf) 94 | output = h.hexdigest() 95 | afile.close() 96 | filename, fileExtention = os.path.splitext(infile) 97 | os.chdir(path) 98 | shutil.move((temp+infile),(output+fileExtention)) 99 | else: 100 | try: 101 | with open(temp+infile, 'rb') as afile: 102 | end = ext(afile.read(20)) 103 | buf = afile.read() 104 | h.update(buf) 105 | output = h.hexdigest() 106 | afile.close() 107 | filename, fileExtention = os.path.splitext(infile) 108 | os.chdir(path) 109 | shutil.move((temp+infile),(output+end)) 110 | except: 111 | pass 112 | else: 113 | e = str("No files found.") 114 | open(out,'ab').write(e) 115 | 116 | #parse out tcp flow for IP 117 | def parse_flow(IP): 118 | styleID = ''.join(choice(string.ascii_lowercase + string.digits) for x in range(randint(8, 12))) 119 | ssize = len(styleID) 120 | p = sub.Popen(['tcpflow', '-T %T--%A-%B', '-cgB', '-r', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap'))], stdout=sub.PIPE, stderr=sub.PIPE) 121 | stdout, stderr = p.communicate() 122 | stdout = stdout.replace('\r\n', '\n') 123 | 124 | if IP not in stdout: 125 | e = str("No tcp flows found for ")+IP 126 | open(out, 'ab').write(e) 127 | 128 | else: 129 | if os.getenv('PROCDOTPLUGIN_PluginEngineVersion') is not None: 130 | open(out,'ab').write('{{{style-id:default;color:blue;style-id:'+styleID+';color:red}}}') 131 | m = re.findall ( '\x1b\[0;31m(.*?)\x1b\[0m|\x1b\[0;34m(.*?)\x1b\[0m', stdout, re.DOTALL) 132 | m = iter(m) 133 | for b, r in m: 134 | if b == '': 135 | if IP in r: 136 | r = r[56:] 137 | r = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', r) 138 | if os.stat(out).st_size <= 53 + ssize: 139 | if os.getenv('PROCDOTPLUGIN_PluginEngineVersion') is not None: 140 | open(out,'ab').write('<'+styleID+'>'+r+'') 141 | else: 142 | open(out,'ab').write(r) 143 | else: 144 | if os.getenv('PROCDOTPLUGIN_PluginEngineVersion') is not None: 145 | open(out,'ab').write('\n\n'+'<'+styleID+'>'+r+'') 146 | else: 147 | open(out,'ab').write('\n\n'+r) 148 | else: 149 | if IP in b: 150 | b = b[56:] 151 | match = re.match( '^HTTP.*', b) 152 | try: 153 | if match: 154 | length = 1 155 | num = 0 156 | while length != num: 157 | d = zlib.decompressobj(16+zlib.MAX_WBITS) 158 | output = StringIO.StringIO(b) 159 | status_line = output.readline() 160 | msg = HTTPMessage(output, 0) 161 | isLength = msg.get('Content-Length') 162 | isGZipped = msg.get('content-encoding', '').find('gzip') >= 0 163 | isChunked = msg.get('Transfer-Encoding', '').find('chunked') >= 0 164 | if isGZipped and isChunked: 165 | offset = msg.fp.readline() 166 | body = msg.fp.read() 167 | num = int(offset, 16) 168 | encdata = '' 169 | newdata = '' 170 | encdata =body[:num] 171 | length = len(encdata) 172 | if length != num: 173 | c = next(m) 174 | d, e = c 175 | b = b + d[56:] 176 | else: 177 | newdata = d.decompress(encdata) 178 | newdata = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', newdata) 179 | header = str(msg) 180 | open(out,'ab').write(status_line) 181 | open(out,'ab').write(header) 182 | open(out,'ab').write('\n') 183 | open(out,'ab').write(newdata) 184 | elif isGZipped: 185 | length = int(isLength) 186 | body = msg.fp.read() 187 | num = len(body) 188 | if length != num: 189 | c = next(m) 190 | d, e = c 191 | if IP in d: 192 | b = b + d[56:] 193 | else: 194 | data = d.decompress(body) 195 | data = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', data) 196 | header = str(msg) 197 | open(out,'ab').write(status_line) 198 | open(out,'ab').write(header) 199 | open(out,'ab').write('\n') 200 | open(out,'ab').write(data) 201 | else: 202 | length = 1 203 | num = 1 204 | body = msg.fp.read() 205 | body = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', body) 206 | header = str(msg) 207 | open(out,'ab').write(status_line) 208 | open(out,'ab').write(header) 209 | open(out,'ab').write('\n') 210 | open(out,'ab').write(body) 211 | else: 212 | b = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', b) 213 | open(out,'ab').write(b) 214 | except: 215 | open(out,'ab').write('DECOMPRESSION ERROR') 216 | open(out,'ab').write('\n\n') 217 | b = re.sub( '[^!\"#\$%&\'\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\]\^_`a-z\{\|\}\\\~\t\n\r ]','.', b) 218 | open(out,'ab').write(b) 219 | 220 | def isTimeFormat(input): 221 | try: 222 | time.strptime(input, '%H:%M:%S.%f') 223 | return True 224 | except ValueError: 225 | return False 226 | 227 | #get packets for animation mode 228 | def get_packet(): 229 | procdottime = os.getenv('PROCDOTPLUGIN_AnimationMode_CurrentFrame_TimestampOriginalString').replace(',', '.') 230 | if len(procdottime) == 15: 231 | procdottime = '0' + procdottime 232 | with open(os.getenv('PROCDOTPLUGIN_ProcmonFileCsv'), 'rb') as f: 233 | reader = csv.DictReader(f) 234 | rows = [row for row in reader if os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') in str(row['Path']) and 'TCP' in str(row['Operation'])] 235 | irofile = iter(rows) 236 | for row in irofile: 237 | starttime = str(row['\xef\xbb\xbf"Time of Day"']).replace(',', '.') 238 | if len(starttime) == 18: 239 | starttime = '0' + starttime 240 | if starttime[:16] == procdottime: 241 | if str(row['Operation']) == 'TCP Receive' or str(row['Operation']) == 'TCP Send': 242 | if str(row['Operation']) == 'TCP Send': 243 | open(out,'ab').write('{{{style-id:default;color:red}}}') 244 | else: 245 | open(out,'ab').write('{{{style-id:default;color:blue}}}') 246 | length = str(row['Detail']).split(',')[0].split(':')[1][1:] 247 | if 'PM' in starttime: 248 | starttime = starttime[:-4] + ' PM' 249 | starttime = datetime.strptime(starttime, '%I:%M:%S.%f %p').strftime('%H:%M:%S.%f') 250 | elif 'AM' in starttime: 251 | starttime = starttime[:-4] + ' AM' 252 | starttime = datetime.strptime(starttime, '%I:%M:%S.%f %p').strftime('%H:%M:%S.%f') 253 | else: 254 | starttime = datetime.strptime(str(starttime)[:-1], '%H:%M:%S.%f').strftime('%H:%M:%S.%f') 255 | row = next(irofile) 256 | endtime = str(row['\xef\xbb\xbf"Time of Day"']).replace(',', '.') 257 | if len(endtime) == 18: 258 | endtime = '0' + endtime 259 | if 'PM' in endtime: 260 | endtime = endtime[:-4] + ' PM' 261 | endtime = datetime.strptime(endtime, '%I:%M:%S.%f %p') 262 | endtime = endtime + timedelta(milliseconds=10) 263 | endtime = endtime.strftime('%H:%M:%S.%f') 264 | elif 'AM' in endtime: 265 | endtime = endtime[:-4] + ' AM' 266 | endtime = datetime.strptime(endtime, '%I:%M:%S.%f %p') 267 | endtime = endtime + timedelta(milliseconds=10) 268 | endtime = endtime.strftime('%H:%M:%S.%f') 269 | else: 270 | endtime = datetime.strptime(str(endtime)[:-1], '%H:%M:%S.%f') 271 | endtime = endtime + timedelta(milliseconds=10) 272 | endtime = endtime.strftime('%H:%M:%S.%f') 273 | execute = os.getenv('PROCDOTPLUGIN_Path2WindumpExecutable') + ' -n -p -A -r ' + '"' + os.getenv('PROCDOTPLUGIN_WindumpFilePcap') + '"' + ' host ' + os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') 274 | p = sub.Popen(execute, stdout=sub.PIPE, stderr=sub.PIPE) 275 | line0, line1 = itertools.tee(p.stdout) 276 | try: 277 | next(line1) 278 | except: 279 | e = str("No tcp packets found for ")+os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address')+(" in this time frame.") 280 | open(out,'wb').write(e) 281 | sys.exit(0) 282 | lines = zip(line0, line1) 283 | lines = iter(lines) 284 | for val0, val1 in lines: 285 | if '(' + length + ')' in val0: 286 | packetstart = datetime.strptime(val0[:15], '%H:%M:%S.%f') 287 | offset = str(packetstart)[11:13] 288 | offset = int(starttime[:2]) - int(offset) 289 | packetstart = packetstart + timedelta(hours=offset) 290 | packetstart = packetstart.strftime('%H:%M:%S.%f') 291 | if packetstart >= starttime and packetstart <= endtime: 292 | packet = [] 293 | while isTimeFormat(val1[:15]) == False: 294 | packet.append(val1.replace('\r\n', '\n')) 295 | val0, val1 = next(lines) 296 | packet = ''.join(packet) 297 | open(out,'ab').write(str(packet)[40:] + '\n') 298 | elif str(row['Operation']) == 'TCP Connect': 299 | open(out,'ab').write('{{{style-id:default;color:white;background-color:red}}}') 300 | open(out,'ab').write(' \n') 301 | open(out,'ab').write(' \n') 302 | open(out,'ab').write(' TCP Connection \n') 303 | open(out,'ab').write(' \n') 304 | open(out,'ab').write(' \n') 305 | else: 306 | open(out,'ab').write('{{{style-id:default;color:white;background-color:red}}}') 307 | open(out,'ab').write(' \n') 308 | open(out,'ab').write(' \n') 309 | open(out,'ab').write(' TCP Disconnect \n') 310 | open(out,'ab').write(' \n') 311 | open(out,'ab').write(' \n') 312 | if os.stat(out).st_size == 0: 313 | e = str("No tcp packets found for ")+os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address')+(" in this time frame.") 314 | open(out,'wb').write(e) 315 | sys.exit(0) 316 | 317 | def filter_pcap(): 318 | name = os.getenv('PROCDOTPLUGIN_TempFolder')+'\\'+os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address')+'.pcap' 319 | p = sub.Popen([(os.getenv('PROCDOTPLUGIN_Path2WindumpExecutable')), '-r', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap')), '-w', name, 'host', os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') ], stdout=sub.PIPE, stderr=sub.PIPE) 320 | p.wait() 321 | try: 322 | try: 323 | p = sub.Popen([r'C:\Program Files (x86)\Wireshark\Wireshark.exe', name]) 324 | except: 325 | p = sub.Popen([r'C:\Program Files\Wireshark\Wireshark.exe', name]) 326 | except: 327 | e = str("Wireshark is missing") 328 | open(out,'wb').write(e) 329 | sys.exit(0) 330 | 331 | def on_closing(root): 332 | try: 333 | shutil.rmtree(temp) 334 | except: 335 | pass 336 | root.destroy() 337 | sys.exit(0) 338 | 339 | def gui(reply,path,tempFile): 340 | root = Tk() 341 | reply = StringVar(root) 342 | reply.set("MD5") # initial value 343 | path = StringVar(None) 344 | path.set("c:/") # initial value 345 | root.title("Extract Files") 346 | root.wm_iconbitmap(tempFile) 347 | root.resizable(width=FALSE, height=FALSE) 348 | 349 | topFrame = Frame(root) 350 | topFrame.grid(row=0, column=0) 351 | middleFrame = Frame(root) 352 | middleFrame.grid(row=1, column=0) 353 | bottomFrame = Frame(root) 354 | bottomFrame.grid(row=2, column=0) 355 | root.grid_rowconfigure(3, minsize=4) 356 | 357 | Label(topFrame, text="Hash type:").grid(row=0, column=0) 358 | Radiobutton(topFrame, text="MD5", variable=reply, value="MD5").grid(row=0, column=1) 359 | Radiobutton(topFrame, text="SHA1", variable=reply, value="SHA1").grid(row=0, column=2) 360 | Radiobutton(topFrame, text="SHA256", variable=reply, value="SHA256").grid(row=0, column=3) 361 | Label(middleFrame, text="Save folder:").grid(row=0, column=0) 362 | Entry(middleFrame, width=25, textvariable=path).grid(row=0, column=1) 363 | Button(middleFrame, text='...', command=lambda:callback(path)).grid(row=0, column=3, padx=4) 364 | Button(bottomFrame, text="Extract Files", command=lambda:ok(reply, path, root)).grid(row=0, column=1) 365 | 366 | root.bind("", lambda e: root.deiconify()) 367 | root.protocol("WM_DELETE_WINDOW", lambda:on_closing(root)) 368 | root.mainloop() 369 | 370 | reply = reply.get() 371 | path = path.get() 372 | try: 373 | if path != None: 374 | if not os.path.exists(path): 375 | os.makedirs(path) 376 | return reply,path 377 | else: 378 | return reply,path 379 | except: 380 | shutil.rmtree(temp) 381 | #get save folder path 382 | def callback(path): 383 | folder = tkFileDialog.askdirectory(initialdir='C:/', title='Extract files from pcap') 384 | path.set(folder) 385 | 386 | #exit gui 387 | def ok(reply, path, root): 388 | root.quit() 389 | 390 | #icon for gui 391 | def icon(tempFile): 392 | icon = \ 393 | """ AAABAAEAECAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAA4AAAh/AAAVxAAACfIAAAnyAAAVxAAACH8AAAAO////AP///wD///8A////AP///wD///8A////AAAAAEIAAA3pAABx9wAAwP8AAO//AADv/wAAwP8AAHH3AAAN6QAAAEL///8A////AP///wD///8A////AAAAAEIAABfzAADL/wAA//8AAP//AAD//wAA//8AAP//AAD//wAAy/8AABfzAAAAQv///wD///8A////AAAAAA4AAA3pAADL/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AADL/wAADekAAAAO////AP///wAAAAh/AABx9wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAHH3AAAIf////wD///8AAAAVxAAAwP8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AADA/wAAFcT///8A////AAAACfIAAO//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA7/8AAAny////AP///wAAAAnyAADv/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAO//AAAJ8v///wD///8AAAAVxAAAwP8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AADA/wAAFcT///8A////AAAACH8AAHH3AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAAcfcAAAh/////AP///wAAAAAOAAAN6QAAy/8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAAy/8AAA3pAAAADv///wD///8A////AAAAAEIAABfzAADL/wAA//8AAP//AAD//wAA//8AAP//AAD//wAAy/8AABfzAAAAQv///wD///8A////AP///wD///8AAAAAQgAADekAAHH3AADA/wAA7/8AAO//AADA/wAAcfcAAA3pAAAAQv///wD///8A////AP///wD///8A////AP///wAAAAAOAAAIfwAAFcQAAAnyAAAJ8gAAFcQAAAh/AAAADv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAPw/AADwDwAA4AcAAMADAADAAwAAgAEAAIABAACAAQAAgAEAAMADAADAAwAA4AcAAPAPAAD8PwAA//8AAA== 394 | """ 395 | icondata= base64.b64decode(icon) 396 | if not os.path.exists(temp): 397 | os.makedirs(temp) 398 | tempFile= temp+"icon.ico" 399 | iconfile= open(tempFile,"wb") 400 | iconfile.write(icondata) 401 | iconfile.close() 402 | return tempFile 403 | 404 | #convert IP into tcpflow format 405 | def parse_IP(IP): 406 | try: 407 | one, two, three, four = IP.split('.') 408 | one='00'+(one) 409 | two='00'+(two) 410 | three='00'+(three) 411 | four='00'+(four) 412 | IP=one[-3:]+'.'+two[-3:]+'.'+three[-3:]+'.'+four[-3:] 413 | return IP 414 | except: 415 | e = str("No IP associated with flow.") 416 | open(out,'w').write(e) 417 | sys.exit(0) 418 | 419 | def check_tcpflow_ver(): 420 | try: 421 | p = sub.Popen(['tcpflow', '-V'], stdout=sub.PIPE, stderr=sub.PIPE) 422 | check = p.communicate()[0] 423 | if 'tcpflow 1.' not in check.lower() and 'tcpflow 2.' not in check.lower(): 424 | e = str("[ERROR] Please download 1.0 or higer\nDownload: https://github.com/simsong/tcpflow/") 425 | open(out,'ab').write(e) 426 | sys.exit(0) 427 | except: 428 | e = str("[ERROR] TCPflow missing. Please download 1.0 or higer.\nDownload: https://github.com/simsong/tcpflow/") 429 | open(out,'w').write(e) 430 | sys.exit(0) 431 | 432 | def main(): 433 | reply = None 434 | path = None 435 | IP = None 436 | tempFile = None 437 | 438 | check_tcpflow_ver() 439 | if os.getenv('PROCDOTPLUGIN_Name') == 'Extract Files From PCAP': 440 | p = sub.Popen(['tcpflow', '-T %N_%A-%B', '-o', (temp), '-ar', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap'))], stdout=sub.PIPE, stderr=sub.PIPE) 441 | stdout, stderr = p.communicate() 442 | if 'tcpflow:' in stderr: 443 | e = str("PCAP file missing. Please select a PCAP file and try again.") 444 | open(out,'ab').write(e) 445 | sys.exit(0) 446 | else: 447 | p.wait() 448 | tempFile = icon(tempFile) 449 | reply,path = gui(reply,path,tempFile) 450 | parse_files(temp,path,IP,reply) 451 | shutil.rmtree(temp) 452 | elif os.getenv('PROCDOTPLUGIN_Name') == 'Follow TCP Stream': 453 | IP = os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') 454 | IP = parse_IP(IP) 455 | if os.getenv('PROCDOTPLUGIN_AnimationMode') == None or os.getenv('PROCDOTPLUGIN_AnimationMode') == '0': 456 | parse_flow(IP) 457 | else: 458 | get_packet() 459 | elif os.getenv('PROCDOTPLUGIN_Name') == 'Open Packets in Wireshark': 460 | filter_pcap() 461 | else: 462 | p = sub.Popen(['tcpflow', '-T %N_%A-%B', '-o', (temp), '-ar', (os.getenv('PROCDOTPLUGIN_WindumpFilePcap'))], stdout=sub.PIPE, stderr=sub.PIPE) 463 | p.wait() 464 | tempFile = icon(tempFile) 465 | reply,path = gui(reply,path,tempFile) 466 | IP = os.getenv('PROCDOTPLUGIN_CurrentNode_Details_IP_Address') 467 | IP = parse_IP(IP) 468 | parse_files(temp,path,IP,reply) 469 | shutil.rmtree(temp) 470 | 471 | if __name__ == '__main__': 472 | main() 473 | -------------------------------------------------------------------------------- /PCAP_tools/Windows/1.2/pcap_tools_Wireshark.pdp: -------------------------------------------------------------------------------- 1 | Name = Open Packets in Wireshark 2 | Author = Beercow 3 | Description = ProcDOT plugin to filter pcap 4 | Version = 1 5 | Type = ContextMenuItemForGraph 6 | Architecture = WindowsBatchScript 7 | File = pcap_tools.bat 8 | Priority = 1 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | CanBeVerified = 1 -------------------------------------------------------------------------------- /PCAP_tools/Windows/1.2/pcap_tools_files.pdp: -------------------------------------------------------------------------------- 1 | Name = Extract Files From PCAP 2 | Author = Beercow 3 | Description = ProcDOT plugin to extract files from pcap 4 | Version = 2.5 5 | Type = MainMenuItem 6 | Architecture = WindowsBatchScript 7 | File = pcap_tools.bat 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | -------------------------------------------------------------------------------- /PCAP_tools/Windows/1.2/pcap_tools_stream_file.pdp: -------------------------------------------------------------------------------- 1 | Name = Extract File(s) From Flow 2 | Author = Beercow 3 | Description = ProcDOT plugin to extract file from TCP stream 4 | Version = 2.5 5 | Type = ContextMenuItemForGraph 6 | Architecture = WindowsBatchScript 7 | File = pcap_tools.bat 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | CanBeVerified = 1 14 | -------------------------------------------------------------------------------- /PCAP_tools/Windows/1.2/pcap_tools_streams.pdp: -------------------------------------------------------------------------------- 1 | Name = Follow TCP Stream 2 | Author = Beercow 3 | Description = ProcDOT plugin to follow streams from pcap 4 | Version = 2.5 5 | Type = ContextMenuItemForGraph 6 | Architecture = WindowsBatchScript 7 | File = pcap_tools.bat 8 | Priority = 9 9 | RunHidden = 1 10 | RunExclusively = 1 11 | CanOverrideOtherPlugins = 0 12 | CanOverrideProcdot = 0 13 | CanBeVerified = 1 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProcDOT-Plugins [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=beercow&url=https://github.com/Beercow/ProcDOT-Plugins) 2 | ![(http://www.procdot.com/downloadprocdotbinaries.htm)](http://ww.procdot.com/webhelp/images/image23.png) 3 | 4 | Plugins to add functionality to ProcDOT http://www.procdot.com/ 5 | 6 | To use these plugins, copy the relavent files into the plugins folder under the ProcDOT directory. 7 | 8 | ![ProcDOT](https://cloud.githubusercontent.com/assets/10360919/12631021/e059e1c8-c514-11e5-92aa-afbba92f9854.PNG) 9 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Brian Maloney 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------