Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/metasploit/framework/ntds/account.rb
Views: 11784
module Metasploit1module Framework2module NTDS3# This class represents an NTDS account structure as sent back by Meterpreter's4# priv extension.5class Account67# Size of an NTDS Account Struct on the Wire8ACCOUNT_SIZE = 30169# Size of a Date or Time Format String on the Wire10DATE_TIME_STRING_SIZE = 3011# Size of the AccountDescription Field12DESCRIPTION_SIZE =102413# Size of a Hash History Record14HASH_HISTORY_SIZE = 79215# Size of a Hash String16HASH_SIZE = 3317# Size of the samAccountName field18NAME_SIZE = 1281920#@return [String] The AD Account Description21attr_accessor :description22#@return [Boolean] If the AD account is disabled23attr_accessor :disabled24#@return [Boolean] If the AD account password is expired25attr_accessor :expired26#@return [String] Human Readable Date for the account's password expiration27attr_accessor :expiry_date28#@return [String] The LM Hash of the current password29attr_accessor :lm_hash30#@return [Array<String>] The LM hashes for previous passwords, up to 2431attr_accessor :lm_history32#@return [Integer] The count of historical LM hashes33attr_accessor :lm_history_count34#@return [Boolean] If the AD account is locked35attr_accessor :locked36#@return [Integer] The number of times this account has logged in37attr_accessor :logon_count38#@return [String] Human Readable Date for the last time the account logged in39attr_accessor :logon_date40#@return [String] Human Readable Time for the last time the account logged in41attr_accessor :logon_time42#@return [String] The samAccountName of the account43attr_accessor :name44#@return [Boolean] If the AD account password does not expire45attr_accessor :no_expire46#@return [Boolean] If the AD account does not require a password47attr_accessor :no_pass48#@return [String] The NT Hash of the current password49attr_accessor :nt_hash50#@return [Array<String>] The NT hashes for previous passwords, up to 2451attr_accessor :nt_history52#@return [Integer] The count of historical NT hashes53attr_accessor :nt_history_count54#@return [String] Human Readable Date for the last password change55attr_accessor :pass_date56#@return [String] Human Readable Time for the last password change57attr_accessor :pass_time58#@return [Integer] The Relative ID of the account59attr_accessor :rid60#@return [String] Byte String for the Account's SID61attr_accessor :sid6263# @param raw_data [String] the raw 3948 byte string from the wire64# @raise [ArgumentErrror] if a 3948 byte string is not supplied65def initialize(raw_data)66raise ArgumentError, "No Data Supplied" unless raw_data.present?67raise ArgumentError, "Invalid Data" unless raw_data.length == ACCOUNT_SIZE68data = raw_data.dup69@name = get_string(data,NAME_SIZE)70@description = get_string(data,DESCRIPTION_SIZE)71@rid = get_int(data)72@disabled = get_boolean(data)73@locked = get_boolean(data)74@no_pass = get_boolean(data)75@no_expire = get_boolean(data)76@expired = get_boolean(data)77@logon_count = get_int(data)78@nt_history_count = get_int(data)79@lm_history_count = get_int(data)80@expiry_date = get_string(data,DATE_TIME_STRING_SIZE)81@logon_date = get_string(data,DATE_TIME_STRING_SIZE)82@logon_time = get_string(data,DATE_TIME_STRING_SIZE)83@pass_date = get_string(data,DATE_TIME_STRING_SIZE)84@pass_time = get_string(data,DATE_TIME_STRING_SIZE)85@lm_hash = get_string(data,HASH_SIZE)86@nt_hash = get_string(data,HASH_SIZE)87@lm_history = get_hash_history(data)88@nt_history = get_hash_history(data)89@sid = data90end9192# @return [String] String representation of the account data93def to_s94<<-EOS.strip_heredoc95#{@name} (#{@description})96#{@name}:#{@rid}:#{ntlm_hash}97Password Expires: #{@expiry_date}98Last Password Change: #{@pass_time} #{@pass_date}99Last Logon: #{@logon_time} #{@logon_date}100Logon Count: #{@logon_count}101#{uac_string}102Hash History:103#{hash_history}104EOS105end106107# @return [String] the NTLM hash string for the current password108def ntlm_hash109"#{@lm_hash}:#{@nt_hash}"110end111112# @return [String] Each historical NTLM Hash on a new line113def hash_history114history_string = ''115@lm_history.each_with_index do | lm_hash, index|116history_string << "#{@name}:#{@rid}:#{lm_hash}:#{@nt_history[index]}\n"117end118history_string119end120121private122123def get_boolean(data)124get_int(data) == 1125end126127def get_hash_history(data)128raw_history = data.slice!(0,HASH_HISTORY_SIZE)129split_history = raw_history.scan(/.{1,33}/)130split_history.map!{ |hash| hash.gsub(/\x00/,'')}131split_history.reject!{ |hash| hash.blank? }132end133134def get_int(data)135data.slice!(0,4).unpack('L').first136end137138def get_string(data,length)139data.slice!(0,length).force_encoding("UTF-8").gsub(/\x00/,'')140end141142def uac_string143status_string = ''144if @disabled145status_string << " - Account Disabled\n"146end147if @expired148status_string << " - Password Expired\n"149end150if @locked151status_string << " - Account Locked Out\n"152end153if @no_expire154status_string << " - Password Never Expires\n"155end156if @no_pass157status_string << " - No Password Required\n"158end159status_string160end161end162end163end164end165166167