msfvenom 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. #!/usr/bin/env ruby
  2. # -*- coding: binary -*-
  3. class MsfVenomError < StandardError; end
  4. class HelpError < StandardError; end
  5. class UsageError < MsfVenomError; end
  6. require 'optparse'
  7. require 'timeout'
  8. # Silences warnings as they only serve to confuse end users
  9. if defined?(Warning) && Warning.respond_to?(:[]=)
  10. Warning[:deprecated] = false
  11. end
  12. msfbase = __FILE__
  13. while File.symlink?(msfbase)
  14. msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
  15. end
  16. $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
  17. require 'metasploit/framework/profiler'
  18. Metasploit::Framework::Profiler.start
  19. def require_deps
  20. require 'msfenv'
  21. $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
  22. require 'rex'
  23. require 'msf/core/payload_generator'
  24. require 'msf/core/constants'
  25. @framework_loaded = true
  26. end
  27. # Creates a new framework object.
  28. #
  29. # @note Ignores any previously cached value.
  30. # @param (see ::Msf::Simple::Framework.create)
  31. # @return [Msf::Framework]
  32. def init_framework(create_opts={})
  33. require_deps unless @framework_loaded
  34. create_opts[:module_types] ||= [
  35. ::Msf::MODULE_PAYLOAD, ::Msf::MODULE_ENCODER, ::Msf::MODULE_NOP
  36. ]
  37. create_opts[:module_types].map! do |type|
  38. Msf.const_get("MODULE_#{type.upcase}")
  39. end
  40. @framework = ::Msf::Simple::Framework.create(create_opts)
  41. unless $stdout.tty?
  42. Rex::Text::Table.unwrap_tables!
  43. end
  44. end
  45. # Cached framework object
  46. #
  47. # @return [Msf::Framework]
  48. def framework
  49. return @framework if @framework
  50. init_framework
  51. @framework
  52. end
  53. def parse_args(args)
  54. opts = {}
  55. datastore = {}
  56. opt = OptionParser.new
  57. banner = "MsfVenom - a Metasploit standalone payload generator.\n"
  58. banner << "Also a replacement for msfpayload and msfencode.\n"
  59. banner << "Usage: #{$0} [options] <var=val>\n"
  60. banner << "Example: #{$0} -p windows/meterpreter/reverse_tcp LHOST=<IP> -f exe -o payload.exe"
  61. opt.banner = banner
  62. opt.separator('')
  63. opt.separator('Options:')
  64. opt.on('-l', '--list <type>', Array, 'List all modules for [type]. Types are: payloads, encoders, nops, platforms, archs, encrypt, formats, all') do |l|
  65. if l.to_s.empty?
  66. l = ["all"]
  67. end
  68. opts[:list] = l
  69. end
  70. opt.on('-p', '--payload <payload>', String,
  71. "Payload to use (--list payloads to list, --list-options for arguments). Specify '-' or STDIN for custom") do |p|
  72. if p == '-'
  73. opts[:payload] = 'stdin'
  74. else
  75. opts[:payload] = p
  76. end
  77. end
  78. opt.on('--list-options', "List --payload <value>'s standard, advanced and evasion options") do
  79. opts[:list_options] = true
  80. end
  81. opt.on('-f', '--format <format>', String, "Output format (use --list formats to list)") do |f|
  82. opts[:format] = f.downcase
  83. end
  84. opt.on('-e', '--encoder <encoder>', String, 'The encoder to use (use --list encoders to list)') do |e|
  85. opts[:encoder] = e
  86. end
  87. opt.on('--service-name <value>', String, 'The service name to use when generating a service binary') do |s|
  88. opts[:servicename] = s
  89. opts[:sub_method] = true # Needed to ensure that to_win32pe_service() will call
  90. # exe_sub_method() for x86 binaries, not needed and ignored for x64 binaries.
  91. end
  92. opt.on('--sec-name <value>', String, 'The new section name to use when generating large Windows binaries. Default: random 4-character alpha string') do |s|
  93. opts[:secname] = s
  94. end
  95. opt.on('--smallest', 'Generate the smallest possible payload using all available encoders') do
  96. opts[:smallest] = true
  97. end
  98. opt.on('--encrypt <value>', String, 'The type of encryption or encoding to apply to the shellcode (use --list encrypt to list)') do |e|
  99. opts[:encryption_format] = e
  100. end
  101. opt.on('--encrypt-key <value>', String, 'A key to be used for --encrypt') do |e|
  102. init_framework
  103. opts[:encryption_key] = Rex::Text.dehex(e)
  104. end
  105. opt.on('--encrypt-iv <value>', String, 'An initialization vector for --encrypt') do |e|
  106. opts[:encryption_iv] = e
  107. end
  108. opt.on('-a', '--arch <arch>', String, 'The architecture to use for --payload and --encoders (use --list archs to list)') do |a|
  109. opts[:arch] = a
  110. end
  111. opt.on('--platform <platform>', String, 'The platform for --payload (use --list platforms to list)') do |l|
  112. opts[:platform] = l
  113. end
  114. opt.on('-o', '--out <path>', 'Save the payload to a file') do |x|
  115. opts[:out] = x
  116. end
  117. opt.on('-b', '--bad-chars <list>', String, 'Characters to avoid example: \'\x00\xff\'') do |b|
  118. init_framework
  119. opts[:badchars] = Rex::Text.dehex(b)
  120. end
  121. opt.on('-n', '--nopsled <length>', Integer, 'Prepend a nopsled of [length] size on to the payload') do |n|
  122. opts[:nops] = n.to_i
  123. end
  124. opt.on('--pad-nops', 'Use nopsled size specified by -n <length> as the total payload size, auto-prepending a nopsled of quantity (nops minus payload length)') do
  125. opts[:padnops] = true
  126. end
  127. opt.on('-s', '--space <length>', Integer, 'The maximum size of the resulting payload') do |s|
  128. opts[:space] = s
  129. end
  130. opt.on('--encoder-space <length>', Integer, 'The maximum size of the encoded payload (defaults to the -s value)') do |s|
  131. opts[:encoder_space] = s
  132. end
  133. opt.on('-i', '--iterations <count>', Integer, 'The number of times to encode the payload') do |i|
  134. opts[:iterations] = i
  135. end
  136. opt.on('-c', '--add-code <path>', String, 'Specify an additional win32 shellcode file to include') do |x|
  137. opts[:add_code] = x
  138. end
  139. opt.on('-x', '--template <path>', String, 'Specify a custom executable file to use as a template') do |x|
  140. opts[:template] = x
  141. end
  142. opt.on('-k', '--keep', 'Preserve the --template behaviour and inject the payload as a new thread') do
  143. opts[:keep] = true
  144. end
  145. opt.on('-v', '--var-name <value>', String, 'Specify a custom variable name to use for certain output formats') do |x|
  146. opts[:var_name] = x
  147. end
  148. opt.on('-t', '--timeout <second>', Integer, "The number of seconds to wait when reading the payload from STDIN (default 30, 0 to disable)") do |x|
  149. opts[:timeout] = x
  150. end
  151. opt.on_tail('-h', '--help', 'Show this message') do
  152. raise HelpError, "#{opt}"
  153. end
  154. begin
  155. opt.parse!(args)
  156. rescue OptionParser::InvalidOption => e
  157. raise UsageError, "Invalid option\n#{opt}"
  158. rescue OptionParser::MissingArgument => e
  159. raise UsageError, "Missing required argument for option\n#{opt}"
  160. end
  161. if opts.empty?
  162. raise UsageError, "No options\n#{opt}"
  163. end
  164. if args
  165. args.each do |x|
  166. k,v = x.split('=', 2)
  167. datastore[k.upcase] = v.to_s
  168. end
  169. if opts[:payload].to_s =~ /[\_\/]reverse/ && datastore['LHOST'].nil?
  170. init_framework
  171. datastore['LHOST'] = Rex::Socket.source_address
  172. end
  173. end
  174. if opts[:payload].nil? # if no payload option is selected assume we are reading it from stdin
  175. opts[:payload] = "stdin"
  176. end
  177. if opts[:payload].downcase == 'stdin' && !opts[:list]
  178. $stderr.puts "Attempting to read payload from STDIN..."
  179. begin
  180. opts[:timeout] ||= 30
  181. ::Timeout.timeout(opts[:timeout]) do
  182. opts[:stdin] = payload_stdin
  183. end
  184. rescue Timeout::Error
  185. opts[:stdin] = ''
  186. end
  187. end
  188. opts[:datastore] = datastore
  189. opts
  190. end
  191. # Read a raw payload from stdin (or whatever IO object we're currently
  192. # using as stdin, see {#initialize})
  193. #
  194. # @return [String]
  195. def payload_stdin
  196. @in = $stdin
  197. @in.binmode
  198. payload = @in.read
  199. payload
  200. end
  201. def dump_platforms
  202. init_framework(:module_types => [])
  203. supported_platforms = []
  204. Msf::Module::Platform.subclasses.each {|c| supported_platforms << c.realname.downcase}
  205. tbl = Rex::Text::Table.new(
  206. 'Indent' => 4,
  207. 'Header' => "Framework Platforms [--platform <value>]",
  208. 'Columns' =>
  209. [
  210. "Name",
  211. ])
  212. supported_platforms.sort.each do |name|
  213. tbl << [name]
  214. end
  215. "\n" + tbl.to_s + "\n"
  216. end
  217. def dump_archs
  218. init_framework(:module_types => [])
  219. supported_archs = ARCH_ALL.dup
  220. tbl = Rex::Text::Table.new(
  221. 'Indent' => 4,
  222. 'Header' => "Framework Architectures [--arch <value>]",
  223. 'Columns' =>
  224. [
  225. "Name",
  226. ])
  227. supported_archs.sort.each do |name|
  228. tbl << [name]
  229. end
  230. "\n" + tbl.to_s + "\n"
  231. end
  232. def dump_encrypt
  233. init_framework(:module_types => [])
  234. tbl = Rex::Text::Table.new(
  235. 'Indent' => 4,
  236. 'Header' => "Framework Encryption Formats [--encrypt <value>]",
  237. 'Columns' =>
  238. [
  239. "Name",
  240. ])
  241. ::Msf::Simple::Buffer.encryption_formats.each do |name|
  242. tbl << [ name]
  243. end
  244. "\n" + tbl.to_s + "\n"
  245. end
  246. def dump_formats
  247. init_framework(:module_types => [])
  248. tbl1 = Rex::Text::Table.new(
  249. 'Indent' => 4,
  250. 'Header' => "Framework Executable Formats [--format <value>]",
  251. 'Columns' =>
  252. [
  253. "Name"
  254. ])
  255. ::Msf::Util::EXE.to_executable_fmt_formats.each do |name|
  256. tbl1 << [ name ]
  257. end
  258. tbl2 = Rex::Text::Table.new(
  259. 'Indent' => 4,
  260. 'Header' => "Framework Transform Formats [--format <value>]",
  261. 'Columns' =>
  262. [
  263. "Name"
  264. ])
  265. ::Msf::Simple::Buffer.transform_formats.each do |name|
  266. tbl2 << [ name ]
  267. end
  268. "\n" + tbl1.to_s + "\n" + tbl2.to_s + "\n"
  269. end
  270. def dump_payloads(platform = nil, arch = nil)
  271. init_framework(:module_types => [ :payload ])
  272. tbl = Rex::Text::Table.new(
  273. 'Indent' => 4,
  274. 'Header' => "Framework Payloads (#{framework.stats.num_payloads} total) [--payload <value>]",
  275. 'Columns' =>
  276. [
  277. "Name",
  278. "Description"
  279. ])
  280. framework.payloads.each_module(
  281. 'Platform' => platform ? Msf::Module::PlatformList.transform(platform.split(',')) : nil,
  282. 'Arch' => arch ? arch.split(',') : nil) do |name, mod|
  283. begin
  284. mod_info = mod.new.description.split.join(' ')
  285. rescue ::Exception, ::LoadError => e
  286. wlog("Module #{name} failed to initialize: #{e}", 'core', LEV_0)
  287. next
  288. end
  289. tbl << [ name, mod_info ]
  290. end
  291. "\n" + tbl.to_s + "\n"
  292. end
  293. def dump_encoders(arch = nil)
  294. init_framework(:module_types => [ :encoder ])
  295. tbl = Rex::Text::Table.new(
  296. 'Indent' => 4,
  297. 'Header' => "Framework Encoders" + ((arch) ? " (architectures: #{arch})" : "") + " [--encoder <value>]",
  298. 'Columns' =>
  299. [
  300. "Name",
  301. "Rank",
  302. "Description"
  303. ])
  304. cnt = 0
  305. framework.encoders.each_module(
  306. 'Arch' => arch ? arch.split(',') : nil) do |name, mod|
  307. tbl << [ name, mod.rank_to_s, mod.new.name ]
  308. cnt += 1
  309. end
  310. (cnt > 0) ? "\n" + tbl.to_s + "\n" : "\nNo compatible encoders found.\n\n"
  311. end
  312. def dump_nops
  313. init_framework(:module_types => [ :nop ])
  314. tbl = Rex::Text::Table.new(
  315. 'Indent' => 4,
  316. 'Header' => "Framework NOPs (#{framework.stats.num_nops} total)",
  317. 'Columns' =>
  318. [
  319. "Name",
  320. "Description"
  321. ])
  322. framework.nops.each_module do |name, mod|
  323. tbl << [ name, mod.new.description.split.join(' ') ]
  324. end
  325. "\n" + tbl.to_s + "\n"
  326. end
  327. begin
  328. generator_opts = parse_args(ARGV)
  329. rescue HelpError => e
  330. $stderr.puts e.message
  331. exit(1)
  332. rescue MsfVenomError => e
  333. $stderr.puts "Error: #{e.message}"
  334. exit(1)
  335. end
  336. if generator_opts[:list]
  337. generator_opts[:list].each do |mod|
  338. case mod.downcase
  339. when "payloads", "payload", "p"
  340. $stdout.puts dump_payloads(generator_opts[:platform], generator_opts[:arch])
  341. when "encoders", "encoder", "e"
  342. $stdout.puts dump_encoders(generator_opts[:arch])
  343. when "nops", "nop", "n"
  344. $stdout.puts dump_nops
  345. when "platforms", "dump_platform"
  346. $stdout.puts dump_platforms
  347. when "archs", "dump_arch"
  348. $stdout.puts dump_archs
  349. when "encrypts", "encrypt", "encryption"
  350. $stdout.puts dump_encrypt
  351. when "formats", "format", "f"
  352. $stdout.puts dump_formats
  353. when "all", "a"
  354. # Init here so #dump_payloads doesn't create a framework with
  355. # only payloads, etc.
  356. init_framework
  357. $stdout.puts dump_payloads
  358. $stdout.puts dump_encoders
  359. $stdout.puts dump_nops
  360. $stdout.puts dump_platforms
  361. $stdout.puts dump_archs
  362. $stdout.puts dump_encrypt
  363. $stdout.puts dump_formats
  364. else
  365. $stderr.puts "Invalid type (#{mod}). These are valid: payloads, encoders, nops, platforms, archs, encrypt, formats, all"
  366. end
  367. end
  368. exit(0)
  369. end
  370. if generator_opts[:list_options]
  371. payload_mod = framework.payloads.create(generator_opts[:payload])
  372. if payload_mod.nil?
  373. $stderr.puts "Invalid payload: #{generator_opts[:payload]}"
  374. exit(1)
  375. end
  376. $stderr.puts "Options for #{payload_mod.fullname}:\n" + "="*25 + "\n\n"
  377. $stdout.puts ::Msf::Serializer::ReadableText.dump_module(payload_mod, ' ')
  378. $stderr.puts "\nAdvanced options for #{payload_mod.fullname}:\n" + "="*25 + "\n\n"
  379. $stdout.puts ::Msf::Serializer::ReadableText.dump_advanced_options(payload_mod, ' ')
  380. $stderr.puts "\nEvasion options for #{payload_mod.fullname}:\n" + "="*25 + "\n\n"
  381. $stdout.puts ::Msf::Serializer::ReadableText.dump_evasion_options(payload_mod, ' ')
  382. exit(0)
  383. end
  384. generator_opts[:framework] = framework
  385. generator_opts[:cli] = true
  386. begin
  387. venom_generator = Msf::PayloadGenerator.new(generator_opts)
  388. payload = venom_generator.generate_payload
  389. rescue Msf::InvalidFormat => e
  390. $stderr.puts "Error: #{e.message}"
  391. $stderr.puts dump_formats
  392. rescue ::Exception => e
  393. elog("#{e.class} : #{e.message}\n#{e.backtrace * "\n"}")
  394. $stderr.puts "Error: #{e.message}"
  395. end
  396. # No payload generated, no point to go on
  397. exit(2) unless payload
  398. if generator_opts[:out]
  399. begin
  400. ::File.open(generator_opts[:out], 'wb') do |f|
  401. f.write(payload)
  402. end
  403. $stderr.puts "Saved as: #{generator_opts[:out]}"
  404. rescue ::Exception => e
  405. # If I can't save it, then I can't save it. I don't think it matters what error.
  406. elog("#{e.class} : #{e.message}\n#{e.backtrace * "\n"}")
  407. $stderr.puts "Error: #{e.message}"
  408. end
  409. else
  410. output_stream = $stdout
  411. output_stream.binmode
  412. output_stream.write payload
  413. # trailing newline for pretty output
  414. $stderr.puts unless payload =~ /\n$/
  415. end