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/msf/util/windows_registry/sam.rb
Views: 11784
module Msf1module Util2module WindowsRegistry34#5# This module include helpers for the SAM hive6#7module Sam89def normalize_key(key)10@root.blank? ? key : key.delete_prefix(@root)11end1213# Returns the HashedBootKey from a given BootKey.14#15# @param boot_key [String] The BootKey16# @return [String] The HashedBootKey or an empty string if the revision17# number is unknown18def get_hboot_key(boot_key)19qwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"20digits = "0123456789012345678901234567890123456789\0"2122_value_type, value_data = get_value(normalize_key('HKLM\\SAM\\SAM\\Domains\\Account'), 'F')23revision = value_data[0x68, 4].unpack('V')[0]24case revision25when 126hash = Digest::MD5.new27hash.update(value_data[0x70, 16] + qwerty + boot_key + digits)28rc4 = OpenSSL::Cipher.new('rc4')29rc4.decrypt30rc4.key = hash.digest31hboot_key = rc4.update(value_data[0x80, 32])32hboot_key << rc4.final33hboot_key34when 235aes = OpenSSL::Cipher.new('aes-128-cbc')36aes.decrypt37aes.key = boot_key38aes.padding = 039aes.iv = value_data[0x78, 16]40aes.update(value_data[0x88, 16]) # we need only 16 bytes41else42elog("[Msf::Util::WindowsRegistry::Sam::get_hboot_key] Unknown hbootKey revision: #{revision}")43''.b44end45end4647# Returns the `Users` key information under HKLM\SAM\Domains\Account\Users.48# This includes the RID, name and `V` value for each user.49#50# @return [Hash] A hash with the following structure:51# {52# <User RID>: { V: <V value>, Name: <User name> },53# ...54# }55def get_user_keys(&block)56users = {}57users_key = normalize_key('HKLM\\SAM\\SAM\\Domains\\Account\\Users')58rids = enum_key(users_key)59if rids60rids.delete('Names')6162rids.each do |rid|63rid = rid.to_s64rid.encode!(::Encoding::UTF_8) unless rid.encoding == ::Encoding::UTF_865key = "#{users_key}\\#{rid}"66yield key if block67_value_type, value_data = get_value(key, 'V')68next unless value_data69users[rid.to_i(16)] ||= {}70users[rid.to_i(16)][:V] = value_data7172# Attempt to get Hints73_value_type, value_data = get_value("#{users_key}\\#{rid}", 'UserPasswordHint')74next unless value_data7576users[rid.to_i(16)][:UserPasswordHint] =77value_data.dup.force_encoding(::Encoding::UTF_16LE).encode(::Encoding::UTF_8).strip78end79end8081# Retrieve the user names for each RID82# TODO: use a proper structure to do this, since the user names are included in V data83names = enum_key("#{users_key}\\Names")84if names85names.each do |name|86name = name.to_s87name.encode!(::Encoding::UTF_8) unless name.encoding == ::Encoding::UTF_888key = "#{users_key}\\Names\\#{name}"89yield key if block90value_type, _value_data = get_value(key, '')91users[value_type] ||= {}92# Apparently, key names are ISO-8859-1 encoded93users[value_type][:Name] = name.dup.force_encoding(::Encoding::ISO_8859_1).encode(::Encoding::UTF_8)94end95end9697users98end99end100101end102end103end104105106107