msfencode 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. #!/usr/bin/env ruby
  2. # -*- coding: binary -*-
  3. #
  4. # $Id$
  5. # $Revision$
  6. #
  7. $stderr.puts "[!] ************************************************************************"
  8. $stderr.puts "[!] * The utility msfencode is deprecated! *"
  9. $stderr.puts "[!] * It will be removed on or about 2015-06-08 *"
  10. $stderr.puts "[!] * Please use msfvenom instead *"
  11. $stderr.puts "[!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 *"
  12. $stderr.puts "[!] ************************************************************************"
  13. msfbase = __FILE__
  14. while File.symlink?(msfbase)
  15. msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
  16. end
  17. $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
  18. require 'msfenv'
  19. $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
  20. require 'rex'
  21. require 'msf/ui'
  22. require 'msf/base'
  23. OutStatus = "[*] "
  24. OutError = "[-] "
  25. # Load supported formats
  26. supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
  27. $args = Rex::Parser::Arguments.new(
  28. "-h" => [ false, "Help banner" ],
  29. "-l" => [ false, "List available encoders" ],
  30. "-v" => [ false, "Increase verbosity" ],
  31. # input/output
  32. "-i" => [ true, "Encode the contents of the supplied file path" ],
  33. "-m" => [ true, "Specifies an additional module search path" ],
  34. "-o" => [ true, "The output file" ],
  35. # architecture/platform
  36. "-a" => [ true, "The architecture to encode as" ],
  37. "-p" => [ true, "The platform to encode for" ],
  38. # format options
  39. "-t" => [ true, "The output format: #{supported_formats.join(',')}" ],
  40. # encoder options
  41. "-e" => [ true, "The encoder to use" ],
  42. "-n" => [ false, "Dump encoder information" ],
  43. "-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ],
  44. "-s" => [ true, "The maximum size of the encoded data" ],
  45. "-c" => [ true, "The number of times to encode the data" ],
  46. # EXE generation options
  47. "-d" => [ true, "Specify the directory in which to look for EXE templates" ],
  48. "-x" => [ true, "Specify an alternate executable template" ],
  49. "-k" => [ false, "Keep template working; run payload in new thread (use with -x)" ]
  50. )
  51. #
  52. # Dump the list of encoders
  53. #
  54. def dump_encoders(arch = nil)
  55. tbl = Rex::Ui::Text::Table.new(
  56. 'Indent' => 4,
  57. 'Header' => "Framework Encoders" + ((arch) ? " (architectures: #{arch})" : ""),
  58. 'Columns' =>
  59. [
  60. "Name",
  61. "Rank",
  62. "Description"
  63. ])
  64. cnt = 0
  65. $framework.encoders.each_module(
  66. 'Arch' => arch ? arch.split(',') : nil) { |name, mod|
  67. tbl << [ name, mod.rank_to_s, mod.new.name ]
  68. cnt += 1
  69. }
  70. (cnt > 0) ? "\n" + tbl.to_s + "\n" : "\nNo compatible encoders found.\n\n"
  71. end
  72. #
  73. # Returns the list of encoders to try
  74. #
  75. def get_encoders(arch, encoder)
  76. encoders = []
  77. if (encoder)
  78. encoders << $framework.encoders.create(encoder)
  79. else
  80. $framework.encoders.each_module_ranked(
  81. 'Arch' => arch ? arch.split(',') : nil) { |name, mod|
  82. encoders << mod.new
  83. }
  84. end
  85. encoders
  86. end
  87. #
  88. # Nuff said.
  89. #
  90. def usage
  91. $stderr.puts("\n" + " Usage: #{$0} <options>\n" + $args.usage)
  92. exit
  93. end
  94. def write_encoded(buf)
  95. if (not $output)
  96. $stdout.write(buf)
  97. else
  98. File.open($output, "wb") do |fd|
  99. fd.write(buf)
  100. end
  101. end
  102. end
  103. # Defaults
  104. verbose = 0
  105. cmd = "encode"
  106. arch = nil
  107. badchars = ''
  108. space = nil
  109. encoder = nil
  110. fmt = nil
  111. input = $stdin
  112. options = ''
  113. delim = '_|_'
  114. output = nil
  115. ecount = 1
  116. plat = nil
  117. altexe = nil
  118. inject = false
  119. exedir = nil # use default
  120. # Parse the argument and rock it
  121. $args.parse(ARGV) { |opt, idx, val|
  122. case opt
  123. when "-i"
  124. begin
  125. input = File.open(val, 'rb')
  126. rescue
  127. $stderr.puts(OutError + "Failed to open file #{val}: #{$!}")
  128. exit
  129. end
  130. when "-m"
  131. $framework.modules.add_module_path(val)
  132. when "-l"
  133. cmd = "list"
  134. when "-n"
  135. cmd = "dump"
  136. when "-a"
  137. arch = val
  138. when "-c"
  139. ecount = val.to_i
  140. when "-b"
  141. badchars = Rex::Text.hex_to_raw(val)
  142. when "-p"
  143. plat = Msf::Module::PlatformList.transform(val)
  144. when "-s"
  145. space = val.to_i
  146. when "-t"
  147. if supported_formats.include?(val)
  148. fmt = val
  149. else
  150. $stderr.puts(OutError + "Invalid format: #{val}")
  151. exit
  152. end
  153. when "-o"
  154. $output = val
  155. when "-e"
  156. encoder = val
  157. when "-d"
  158. exedir = val
  159. when "-x"
  160. altexe = val
  161. when "-k"
  162. inject = true
  163. when "-h"
  164. usage
  165. when "-v"
  166. verbose += 1
  167. else
  168. if (val =~ /=/)
  169. options += ((options.length > 0) ? delim : "") + "#{val}"
  170. end
  171. end
  172. }
  173. if(not fmt and output)
  174. pre,ext = output.split('.')
  175. if(ext and not ext.empty?)
  176. fmt = ext
  177. end
  178. end
  179. if inject and not altexe
  180. $stderr.puts "[*] Error: the injection option must use a custom EXE template via -x, otherwise the injected payload will immediately exit when the main process dies."
  181. exit(1)
  182. end
  183. exeopts = {
  184. :inject => inject,
  185. :template => altexe,
  186. :template_path => exedir
  187. }
  188. # Initialize the simplified framework instance.
  189. $framework = Msf::Simple::Framework.create(
  190. :module_types => [ Msf::MODULE_ENCODER, Msf::MODULE_NOP ],
  191. 'DisableDatabase' => true
  192. )
  193. # Get the list of encoders to try
  194. encoders = get_encoders(arch, encoder)
  195. # Process the actual command
  196. case cmd
  197. when "list"
  198. $stderr.puts(dump_encoders(arch))
  199. when "dump"
  200. enc = encoder ? $framework.encoders.create(encoder) : nil
  201. if (enc)
  202. $stderr.puts(Msf::Serializer::ReadableText.dump_module(enc))
  203. else
  204. $stderr.puts(OutError + "Invalid encoder specified.")
  205. end
  206. when "encode"
  207. input.binmode # ensure its in binary mode
  208. buf = input.read
  209. encoders.each { |enc|
  210. next if not enc
  211. begin
  212. # Imports options
  213. enc.datastore.import_options_from_s(options, delim)
  214. skip = false
  215. eout = buf.dup
  216. raw = nil
  217. 1.upto(ecount) do |iteration|
  218. # Encode it up
  219. raw = enc.encode(eout, badchars, nil, plat)
  220. # Is it too big?
  221. if (space and space > 0 and raw.length > space)
  222. $stderr.puts(OutError + "#{enc.refname} created buffer that is too big (#{raw.length})")
  223. skip = true
  224. break
  225. end
  226. # Print it out
  227. $stderr.puts(OutStatus + "#{enc.refname} succeeded with size #{raw.length} (iteration=#{iteration})\n\n")
  228. eout = raw
  229. end
  230. next if skip
  231. output = Msf::Util::EXE.to_executable_fmt($framework, arch, plat, raw, fmt, exeopts)
  232. if not output
  233. fmt ||= "ruby"
  234. output = Msf::Simple::Buffer.transform(raw, fmt)
  235. end
  236. if exeopts[:fellback]
  237. $stderr.puts(OutError + "Warning: Falling back to default template: #{exeopts[:fellback]}")
  238. end
  239. write_encoded(output)
  240. exit
  241. #
  242. # These exception codes are fatal, we shouldn't expect them to succeed on the next
  243. # iteration, nor the next encoder.
  244. #
  245. rescue ::Errno::ENOENT, ::Errno::EINVAL
  246. $stderr.puts(OutError + "#{enc.refname} failed: #{$!}")
  247. break
  248. rescue => e
  249. $stderr.puts(OutError + "#{enc.refname} failed: #{e}")
  250. if verbose > 0
  251. e.backtrace.each { |el|
  252. $stderr.puts(OutError + el.to_s)
  253. }
  254. end
  255. end
  256. }
  257. $stderr.puts(OutError + "No encoders succeeded.")
  258. end