Created
December 7, 2014 18:44
-
-
Save jduck/b7c289cb9e25a9e37a49 to your computer and use it in GitHub Desktop.
Test results from an experiment with optimizing Metasploit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# | |
# The goal of this script is to symlink various things into Metasploit's | |
# "lib" directory. Since it is first in the include path, putting symlinks | |
# there effectively eliminates tons of failed open(2) system calls. | |
# | |
# There are several scenarios to deal with here. Each has to be treated | |
# specially. | |
# | |
# 1. Gems - When using RVM, they are under some place in $GEM_HOME. They are | |
# often the *last* thing in the include path :-/ Some gems use a directory | |
# name that differs from the gem name. | |
# | |
# 2. Core code - These can be single ruby files, single shared objects, or | |
# a combination of the two. They might even have a directory. Those with | |
# a directory and a mix of native/script code require even more special | |
# handling. | |
# | |
# Joshua J. Drake / jduck@metasploit | |
# | |
# PS. This is not well tested and thus your mileage may vary. | |
# | |
# these are the gems we'll link | |
gems = [ | |
{ :name => 'activesupport', :dir => 'active_support' }, | |
{ :name => 'i18n' }, | |
{ :name => 'jsobfu' }, | |
{ :name => 'rkelly-remix', :dir => 'rkelly' }, | |
{ :name => 'meterpreter_bins' }, | |
{ :name => 'nokogiri' }, | |
{ :name => 'packetfu' }, | |
{ :name => 'thread_safe' }, | |
{ :name => 'tzinfo' }, | |
{ :name => 'json' }, | |
] | |
# these are the core files we'll link: | |
core_dirs = %w{ uri date rexml openssl cgi optparse } | |
core_scripts = %w{ delegate.rb abbrev.rb pp.rb prettyprint.rb find.rb shellwords.rb erb.rb tmpdir.rb timeout.rb time.rb tempfile.rb forwardable.rb socket.rb resolv.rb logger.rb securerandom.rb singleton.rb set.rb pathname.rb base64.rb fileutils.rb } | |
core_natives = %w{ readline.so bigdecimal.so zlib.so fcntl.so openssl.so socket.so iconv.so strscan.so stringio.so etc.so pathname.so date_core.so } | |
# these require special care. | |
core_hybrid = %w{ digest racc } | |
# I suspect these depend on RVM. | |
$gem_home = ENV["GEM_HOME"] | |
$ruby_home = ENV["MY_RUBY_HOME"] | |
def make_link(src, dst) | |
puts "[*] #{dst} -> #{src}" | |
if not File.exists? src | |
raise 'Source not found!' | |
end | |
if File.exists? dst | |
if File.symlink? dst | |
cur_dst = File.readlink(dst) | |
if src != cur_dst | |
puts "[!] Destination file already exists, but points to #{cur_dst}" | |
exit(1) | |
else | |
return true | |
end | |
end | |
end | |
File.symlink(src, dst) | |
end | |
def single_glob(glob) | |
ret = nil | |
Dir.glob(glob).each { |path| | |
if ret | |
raise 'Hey! Too many matches!' | |
exit(1) | |
else | |
return path | |
end | |
} | |
nil | |
end | |
def make_link_with_ext(src, dst, extension) | |
sfn = "#{src}.#{extension}" | |
dfn = "#{dst}.#{extension}" | |
if File.exists? sfn | |
make_link(sfn, dfn) | |
end | |
end | |
gems.each { |gem| | |
gem_name = gem[:name] | |
gem_dir = gem[:dir] || gem_name | |
gem_glob = File.join($gem_home, 'gems', "#{gem_name}*", 'lib', gem_dir) | |
gem_path = single_glob(gem_glob) | |
dst = File.join('lib', gem_dir) | |
make_link(gem_path, dst) | |
make_link_with_ext(gem_path, dst, 'rb') | |
} | |
core_dirs.each { |dir| | |
cd_glob = File.join($ruby_home, 'lib', 'ruby', '*', dir) | |
cd_path = single_glob(cd_glob) | |
dst = File.join('lib', dir) | |
make_link(cd_path, dst) | |
make_link_with_ext(cd_path, dst, 'rb') | |
} | |
core_scripts.each { |fn| | |
cs_glob = File.join($ruby_home, 'lib', 'ruby', '*', fn) | |
cs_path = single_glob(cs_glob) | |
make_link(cs_path, File.join('lib', fn)) | |
} | |
core_natives.each { |fn| | |
cs_glob = File.join($ruby_home, 'lib', 'ruby', '*', RUBY_PLATFORM, fn) | |
cs_path = single_glob(cs_glob) | |
make_link(cs_path, File.join('lib', fn)) | |
} | |
core_hybrid.each { |path| | |
dst = File.join('lib', path) | |
phs_glob = File.join($ruby_home, 'lib', 'ruby', '*', path) | |
phs_path = single_glob(phs_glob) | |
make_link_with_ext(phs_path, dst, 'rb') | |
phn_glob = File.join($ruby_home, 'lib', 'ruby', '*', RUBY_PLATFORM, path) | |
phn_path = single_glob(phn_glob) | |
make_link_with_ext(phn_path, dst, 'so') | |
if not File.exists? dst | |
Dir.mkdir(dst) | |
elsif not File.directory? dst | |
raise 'Entry for hybrid directory #{dst} already exists!' | |
end | |
ps_glob = File.join($ruby_home, 'lib', 'ruby', '*', path, '**') | |
Dir.glob(ps_glob).each { |fn| | |
bfn = File.basename(fn) | |
make_link(fn, File.join(dst, bfn)) | |
} | |
pn_glob = File.join($ruby_home, 'lib', 'ruby', '*', RUBY_PLATFORM, path, '**') | |
Dir.glob(pn_glob).each { |fn| | |
bfn = File.basename(fn) | |
make_link(fn, File.join(dst, bfn)) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dq:0:~/msf-git$ gem list | |
*** LOCAL GEMS *** | |
activesupport (4.1.8) | |
bigdecimal (1.1.0) | |
bundler (1.7.6) | |
bundler-unload (1.0.2) | |
executable-hooks (1.3.2) | |
factory_girl (4.5.0) | |
gem-wrappers (1.2.7) | |
i18n (0.6.11) | |
io-console (0.3) | |
jsobfu (0.2.1) | |
json (1.8.1, 1.5.5) | |
metasploit-model (0.28.0) | |
meterpreter_bins (0.0.11) | |
mini_portile (0.6.1) | |
minitest (5.4.3, 2.5.1) | |
nokogiri (1.6.5) | |
packetfu (1.1.10) | |
rake (0.9.2.2) | |
rb-readline (0.5.1) | |
rdoc (3.9.5) | |
rkelly-remix (0.0.6) | |
rubygems-bundler (1.4.4) | |
rvm (1.11.3.9) | |
thread_safe (0.3.4) | |
tzinfo (1.2.2) | |
zip (2.0.2) | |
dq:0:~/msf-git$ rm openz ; strace -s 256 -ttt -e open,write -o openz ./msfex exploit/windows/fileformat/adobe_libtiff | |
[*] Loading the Metasploit Framework base ... | |
[*] Initializing a Framework instance... | |
[*] Initializing modules ... | |
metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::Auxiliary::Report | |
[*] Loading UI ... | |
[*] Starting the console... | |
[-] *** | |
[-] * WARNING: Database support has been disabled | |
[-] *** | |
PAYLOAD => windows/meterpreter/reverse_tcp | |
NOP => x86/single_byte | |
ENCODER => x86/shikata_ga_nai | |
[*] Creating 'msf.pdf' file... | |
[+] msf.pdf stored at /home/jdrake/.msf4/local/msf.pdf | |
dq:0:~/msf-git$ grep -c ENOENT openz | |
3172 | |
dq:0:~/msf-git$ time ./msfex exploit/windows/fileformat/adobe_libtiff > /dev/null 2>&1 | |
real 0m1.019s | |
user 0m0.964s | |
sys 0m0.053s | |
dq:0:~/msf-git$ ./make-links.rb | |
[*] lib/active_support -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/activesupport-4.1.8/lib/active_support | |
[*] lib/active_support.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/activesupport-4.1.8/lib/active_support.rb | |
[*] lib/i18n -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/i18n-0.6.11/lib/i18n | |
[*] lib/i18n.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/i18n-0.6.11/lib/i18n.rb | |
[*] lib/jsobfu -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/jsobfu-0.2.1/lib/jsobfu | |
[*] lib/jsobfu.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/jsobfu-0.2.1/lib/jsobfu.rb | |
[*] lib/rkelly -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/rkelly-remix-0.0.6/lib/rkelly | |
[*] lib/rkelly.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/rkelly-remix-0.0.6/lib/rkelly.rb | |
[*] lib/meterpreter_bins -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/meterpreter_bins-0.0.11/lib/meterpreter_bins | |
[*] lib/meterpreter_bins.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/meterpreter_bins-0.0.11/lib/meterpreter_bins.rb | |
[*] lib/nokogiri -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/nokogiri-1.6.5/lib/nokogiri | |
[*] lib/nokogiri.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/nokogiri-1.6.5/lib/nokogiri.rb | |
[*] lib/packetfu -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/packetfu-1.1.10/lib/packetfu | |
[*] lib/packetfu.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/packetfu-1.1.10/lib/packetfu.rb | |
[*] lib/thread_safe -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/thread_safe-0.3.4/lib/thread_safe | |
[*] lib/thread_safe.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/thread_safe-0.3.4/lib/thread_safe.rb | |
[*] lib/tzinfo -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/tzinfo-1.2.2/lib/tzinfo | |
[*] lib/tzinfo.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/tzinfo-1.2.2/lib/tzinfo.rb | |
[*] lib/json -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/json-1.8.1/lib/json | |
[*] lib/json.rb -> /ssd/jdrake/rvm/gems/ruby-1.9.3-p551@msf-autoload/gems/json-1.8.1/lib/json.rb | |
[*] lib/uri -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/uri | |
[*] lib/uri.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/uri.rb | |
[*] lib/date -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/date | |
[*] lib/date.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/date.rb | |
[*] lib/rexml -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/rexml | |
[*] lib/openssl -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/openssl | |
[*] lib/openssl.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/openssl.rb | |
[*] lib/cgi -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/cgi | |
[*] lib/cgi.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/cgi.rb | |
[*] lib/optparse -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/optparse | |
[*] lib/optparse.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/optparse.rb | |
[*] lib/delegate.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/delegate.rb | |
[*] lib/abbrev.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/abbrev.rb | |
[*] lib/pp.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/pp.rb | |
[*] lib/prettyprint.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/prettyprint.rb | |
[*] lib/find.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/find.rb | |
[*] lib/shellwords.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/shellwords.rb | |
[*] lib/erb.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/erb.rb | |
[*] lib/tmpdir.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/tmpdir.rb | |
[*] lib/timeout.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/timeout.rb | |
[*] lib/time.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/time.rb | |
[*] lib/tempfile.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/tempfile.rb | |
[*] lib/forwardable.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/forwardable.rb | |
[*] lib/socket.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/socket.rb | |
[*] lib/resolv.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/resolv.rb | |
[*] lib/logger.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/logger.rb | |
[*] lib/securerandom.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/securerandom.rb | |
[*] lib/singleton.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/singleton.rb | |
[*] lib/set.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/set.rb | |
[*] lib/pathname.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/pathname.rb | |
[*] lib/base64.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/base64.rb | |
[*] lib/fileutils.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/fileutils.rb | |
[*] lib/readline.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/readline.so | |
[*] lib/bigdecimal.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/bigdecimal.so | |
[*] lib/zlib.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/zlib.so | |
[*] lib/fcntl.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/fcntl.so | |
[*] lib/openssl.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/openssl.so | |
[*] lib/socket.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/socket.so | |
[*] lib/iconv.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/iconv.so | |
[*] lib/strscan.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/strscan.so | |
[*] lib/stringio.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/stringio.so | |
[*] lib/etc.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/etc.so | |
[*] lib/pathname.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/pathname.so | |
[*] lib/date_core.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/date_core.so | |
[*] lib/digest.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/digest.rb | |
[*] lib/digest.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/digest.so | |
[*] lib/digest/hmac.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/digest/hmac.rb | |
[*] lib/digest/sha2.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/digest/sha2.rb | |
[*] lib/digest/md5.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/digest/md5.so | |
[*] lib/digest/sha2.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/digest/sha2.so | |
[*] lib/digest/rmd160.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/digest/rmd160.so | |
[*] lib/digest/sha1.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/digest/sha1.so | |
[*] lib/digest/bubblebabble.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/digest/bubblebabble.so | |
[*] lib/racc/parser.rb -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/racc/parser.rb | |
[*] lib/racc/cparse.so -> /ssd/jdrake/rvm/rubies/ruby-1.9.3-p551/lib/ruby/1.9.1/x86_64-linux/racc/cparse.so | |
dq:0:~/msf-git$ rm openz ; strace -s 256 -ttt -e open,write -o openz ./msfex exploit/windows/fileformat/adobe_libtiff | |
[*] Loading the Metasploit Framework base ... | |
[*] Initializing a Framework instance... | |
[*] Initializing modules ... | |
metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for Msf::Auxiliary::Report | |
[*] Loading UI ... | |
[*] Starting the console... | |
[-] *** | |
[-] * WARNING: Database support has been disabled | |
[-] *** | |
PAYLOAD => windows/meterpreter/reverse_tcp | |
NOP => x86/single_byte | |
ENCODER => x86/shikata_ga_nai | |
[*] Creating 'msf.pdf' file... | |
[+] msf.pdf stored at /home/jdrake/.msf4/local/msf.pdf | |
dq:0:~/msf-git$ grep -c ENOENT openz | |
301 | |
dq:0:~/msf-git$ time ./msfex exploit/windows/fileformat/adobe_libtiff > /dev/null 2>&1 | |
real 0m0.925s | |
user 0m0.858s | |
sys 0m0.064s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Though I only saved less than a second in this case, increasing the number of items in the load path has a far lower impact.
The biggest down side is that changing the ruby version with rvm is a bit more complicated.
NOTE: This could also be accomplished through instrumenting Kernel.require or similar.