| 1 |
#!/usr/bin/env ruby |
|---|
| 2 |
|
|---|
| 3 |
msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__ |
|---|
| 4 |
$:.unshift(File.join(File.dirname(msfbase), 'lib')) |
|---|
| 5 |
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] |
|---|
| 6 |
|
|---|
| 7 |
require 'rex' |
|---|
| 8 |
require 'msf/ui' |
|---|
| 9 |
require 'msf/base' |
|---|
| 10 |
|
|---|
| 11 |
OutStatus = "[*] " |
|---|
| 12 |
OutError = "[-] " |
|---|
| 13 |
|
|---|
| 14 |
$args = Rex::Parser::Arguments.new( |
|---|
| 15 |
"-i" => [ true, "Encode the contents of the supplied file path" ], |
|---|
| 16 |
"-m" => [ true, "Specifies an additional module search path" ], |
|---|
| 17 |
"-a" => [ true, "The architecture to encode as" ], |
|---|
| 18 |
"-t" => [ true, "The format to display the encoded buffer with (raw, ruby, perl, c)" ], |
|---|
| 19 |
"-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ], |
|---|
| 20 |
"-s" => [ true, "The maximum size of the encoded data" ], |
|---|
| 21 |
"-e" => [ true, "The encoder to use" ], |
|---|
| 22 |
"-o" => [ true, "The output file" ], |
|---|
| 23 |
"-n" => [ false, "Dump encoder information" ], |
|---|
| 24 |
"-h" => [ false, "Help banner" ], |
|---|
| 25 |
"-l" => [ false, "List available encoders" ]) |
|---|
| 26 |
|
|---|
| 27 |
# |
|---|
| 28 |
# Dump the list of encoders |
|---|
| 29 |
# |
|---|
| 30 |
def dump_encoders(arch = nil) |
|---|
| 31 |
tbl = Rex::Ui::Text::Table.new( |
|---|
| 32 |
'Indent' => 4, |
|---|
| 33 |
'Header' => "Framework Encoders" + ((arch) ? " (architectures: #{arch})" : ""), |
|---|
| 34 |
'Columns' => |
|---|
| 35 |
[ |
|---|
| 36 |
"Name", |
|---|
| 37 |
"Rank", |
|---|
| 38 |
"Description" |
|---|
| 39 |
]) |
|---|
| 40 |
cnt = 0 |
|---|
| 41 |
|
|---|
| 42 |
$framework.encoders.each_module( |
|---|
| 43 |
'Arch' => arch ? arch.split(',') : nil) { |name, mod| |
|---|
| 44 |
tbl << [ name, mod.rank_to_s, mod.new.name ] |
|---|
| 45 |
|
|---|
| 46 |
cnt += 1 |
|---|
| 47 |
} |
|---|
| 48 |
|
|---|
| 49 |
(cnt > 0) ? "\n" + tbl.to_s + "\n" : "\nNo compatible encoders found.\n\n" |
|---|
| 50 |
end |
|---|
| 51 |
|
|---|
| 52 |
# |
|---|
| 53 |
# Returns the list of encoders to try |
|---|
| 54 |
# |
|---|
| 55 |
def get_encoders(arch, encoder) |
|---|
| 56 |
encoders = [] |
|---|
| 57 |
|
|---|
| 58 |
if (encoder) |
|---|
| 59 |
encoders << $framework.encoders.create(encoder) |
|---|
| 60 |
else |
|---|
| 61 |
$framework.encoders.each_module_ranked( |
|---|
| 62 |
'Arch' => arch ? arch.split(',') : nil) { |name, mod| |
|---|
| 63 |
encoders << mod.new |
|---|
| 64 |
} |
|---|
| 65 |
end |
|---|
| 66 |
|
|---|
| 67 |
encoders |
|---|
| 68 |
end |
|---|
| 69 |
|
|---|
| 70 |
# |
|---|
| 71 |
# Nuff said. |
|---|
| 72 |
# |
|---|
| 73 |
def usage |
|---|
| 74 |
$stderr.puts("\n" + " Usage: #{$0} <options>\n" + $args.usage) |
|---|
| 75 |
exit |
|---|
| 76 |
end |
|---|
| 77 |
|
|---|
| 78 |
# Initialize the simplified framework instance. |
|---|
| 79 |
$framework = Msf::Simple::Framework.create |
|---|
| 80 |
|
|---|
| 81 |
# Defaults |
|---|
| 82 |
cmd = "encode" |
|---|
| 83 |
arch = nil |
|---|
| 84 |
badchars = '' |
|---|
| 85 |
space = nil |
|---|
| 86 |
encoder = nil |
|---|
| 87 |
fmt = "c" |
|---|
| 88 |
input = $stdin |
|---|
| 89 |
options = '' |
|---|
| 90 |
delim = '_|_' |
|---|
| 91 |
output = nil |
|---|
| 92 |
|
|---|
| 93 |
# Parse the argument and rock that shit. |
|---|
| 94 |
$args.parse(ARGV) { |opt, idx, val| |
|---|
| 95 |
case opt |
|---|
| 96 |
when "-i" |
|---|
| 97 |
begin |
|---|
| 98 |
input = File.new(val) |
|---|
| 99 |
rescue |
|---|
| 100 |
$stderr.puts(OutError + "Failed to open file #{val}: #{$!}") |
|---|
| 101 |
exit |
|---|
| 102 |
end |
|---|
| 103 |
when "-m" |
|---|
| 104 |
$framework.modules.add_module_path(val) |
|---|
| 105 |
when "-l" |
|---|
| 106 |
cmd = "list" |
|---|
| 107 |
when "-n" |
|---|
| 108 |
cmd = "dump" |
|---|
| 109 |
when "-a" |
|---|
| 110 |
arch = val |
|---|
| 111 |
when "-b" |
|---|
| 112 |
badchars = Rex::Text.hex_to_raw(val) |
|---|
| 113 |
when "-s" |
|---|
| 114 |
space = val.to_i |
|---|
| 115 |
when "-t" |
|---|
| 116 |
if (val =~ /^(perl|ruby|raw|c|exe)$/) |
|---|
| 117 |
fmt = val |
|---|
| 118 |
else |
|---|
| 119 |
$stderr.puts(OutError + "Invalid format: #{val}") |
|---|
| 120 |
exit |
|---|
| 121 |
end |
|---|
| 122 |
when "-o" |
|---|
| 123 |
output = val |
|---|
| 124 |
when "-e" |
|---|
| 125 |
encoder = val |
|---|
| 126 |
when "-h" |
|---|
| 127 |
usage |
|---|
| 128 |
else |
|---|
| 129 |
if (val =~ /=/) |
|---|
| 130 |
options += ((options.length > 0) ? delim : "") + "#{val}" |
|---|
| 131 |
end |
|---|
| 132 |
end |
|---|
| 133 |
} |
|---|
| 134 |
|
|---|
| 135 |
# Get the list of encoders to try |
|---|
| 136 |
encoders = get_encoders(arch, encoder) |
|---|
| 137 |
|
|---|
| 138 |
# Process the actual command |
|---|
| 139 |
case cmd |
|---|
| 140 |
when "list" |
|---|
| 141 |
$stderr.puts(dump_encoders(arch)) |
|---|
| 142 |
when "dump" |
|---|
| 143 |
enc = encoder ? $framework.encoders.create(encoder) : nil |
|---|
| 144 |
|
|---|
| 145 |
if (enc) |
|---|
| 146 |
$stderr.puts(Msf::Serializer::ReadableText.dump_module(enc)) |
|---|
| 147 |
else |
|---|
| 148 |
$stderr.puts(OutError + "Invalid encoder specified.") |
|---|
| 149 |
end |
|---|
| 150 |
when "encode" |
|---|
| 151 |
buf = input.read |
|---|
| 152 |
|
|---|
| 153 |
encoders.each { |enc| |
|---|
| 154 |
next if not enc |
|---|
| 155 |
begin |
|---|
| 156 |
# Imports options |
|---|
| 157 |
enc.datastore.import_options_from_s(options, delim) |
|---|
| 158 |
|
|---|
| 159 |
# Encode it up |
|---|
| 160 |
raw = enc.encode(buf, badchars) |
|---|
| 161 |
|
|---|
| 162 |
# Is it too big? |
|---|
| 163 |
if (space and space > 0 and raw.length > space) |
|---|
| 164 |
$stderr.puts(OutError + "#{enc.refname} created buffer that is too big (#{raw.length})") |
|---|
| 165 |
next |
|---|
| 166 |
end |
|---|
| 167 |
|
|---|
| 168 |
# Print it out |
|---|
| 169 |
$stderr.puts(OutStatus + "#{enc.refname} succeeded, final size #{raw.length}\n\n") |
|---|
| 170 |
|
|---|
| 171 |
if(fmt != "exe") |
|---|
| 172 |
if(not output) |
|---|
| 173 |
$stdout.print(Msf::Simple::Buffer.transform(raw, fmt)) |
|---|
| 174 |
else |
|---|
| 175 |
File.open(output, "wb") do |fd| |
|---|
| 176 |
fd.write(Msf::Simple::Buffer.transform(raw, fmt)) |
|---|
| 177 |
end |
|---|
| 178 |
end |
|---|
| 179 |
else |
|---|
| 180 |
exe = Rex::Text.to_win32pe(buf, "") |
|---|
| 181 |
if(not output) |
|---|
| 182 |
$stdout.write(exe) |
|---|
| 183 |
else |
|---|
| 184 |
File.open(output, "wb") do |fd| |
|---|
| 185 |
fd.write(exe) |
|---|
| 186 |
end |
|---|
| 187 |
end |
|---|
| 188 |
end |
|---|
| 189 |
|
|---|
| 190 |
exit |
|---|
| 191 |
|
|---|
| 192 |
rescue |
|---|
| 193 |
$stderr.puts(OutError + "#{enc.refname} failed: #{$!}") |
|---|
| 194 |
end |
|---|
| 195 |
} |
|---|
| 196 |
|
|---|
| 197 |
$stderr.puts(OutError + "No encoders succeeded.") |
|---|
| 198 |
end |
|---|