Module: Msf::Util::WindowsRegistry::Sam

Defined in:
lib/msf/util/windows_registry/sam.rb

Overview

This module include helpers for the SAM hive

Instance Method Summary collapse

Instance Method Details

#get_hboot_key(boot_key) ⇒ String

Returns the HashedBootKey from a given BootKey.

Parameters:

  • boot_key (String)

    The BootKey

Returns:

  • (String)

    The HashedBootKey or an empty string if the revision number is unknown



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/msf/util/windows_registry/sam.rb', line 19

def get_hboot_key(boot_key)
  qwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
  digits = "0123456789012345678901234567890123456789\0"

  _value_type, value_data = get_value(normalize_key('HKLM\\SAM\\SAM\\Domains\\Account'), 'F')
  revision = value_data[0x68, 4].unpack('V')[0]
  case revision
  when 1
    hash = Digest::MD5.new
    hash.update(value_data[0x70, 16] + qwerty + boot_key + digits)
    rc4 = OpenSSL::Cipher.new('rc4')
    rc4.decrypt
    rc4.key = hash.digest
    hboot_key = rc4.update(value_data[0x80, 32])
    hboot_key << rc4.final
    hboot_key
  when 2
    aes = OpenSSL::Cipher.new('aes-128-cbc')
    aes.decrypt
    aes.key = boot_key
    aes.padding = 0
    aes.iv = value_data[0x78, 16]
    aes.update(value_data[0x88, 16]) # we need only 16 bytes
  else
    elog("[Msf::Util::WindowsRegistry::Sam::get_hboot_key] Unknown hbootKey revision: #{revision}")
    ''.b
  end
end

#get_user_keys(&block) ⇒ Hash

Returns the `Users` key information under HKLMSAMDomainsAccountUsers. This includes the RID, name and `V` value for each user.

Returns:

  • (Hash)

    A hash with the following structure: {

    <User RID>: { V: <V value>, Name: <User name> },
    ...
    

    }



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/msf/util/windows_registry/sam.rb', line 56

def get_user_keys(&block)
  users = {}
  users_key = normalize_key('HKLM\\SAM\\SAM\\Domains\\Account\\Users')
  rids = enum_key(users_key)
  if rids
    rids.delete('Names')

    rids.each do |rid|
      rid = rid.to_s
      rid.encode!(::Encoding::UTF_8) unless rid.encoding == ::Encoding::UTF_8
      key = "#{users_key}\\#{rid}"
      yield key if block
      _value_type, value_data = get_value(key, 'V')
      next unless value_data
      users[rid.to_i(16)] ||= {}
      users[rid.to_i(16)][:V] = value_data

      # Attempt to get Hints
      _value_type, value_data = get_value("#{users_key}\\#{rid}", 'UserPasswordHint')
      next unless value_data

      users[rid.to_i(16)][:UserPasswordHint] =
        value_data.dup.force_encoding(::Encoding::UTF_16LE).encode(::Encoding::UTF_8).strip
    end
  end

  # Retrieve the user names for each RID
  # TODO: use a proper structure to do this, since the user names are included in V data
  names = enum_key("#{users_key}\\Names")
  if names
    names.each do |name|
      name = name.to_s
      name.encode!(::Encoding::UTF_8) unless name.encoding == ::Encoding::UTF_8
      key = "#{users_key}\\Names\\#{name}"
      yield key if block
      value_type, _value_data = get_value(key, '')
      users[value_type] ||= {}
      # Apparently, key names are ISO-8859-1 encoded
      users[value_type][:Name] = name.dup.force_encoding(::Encoding::ISO_8859_1).encode(::Encoding::UTF_8)
    end
  end

  users
end

#normalize_key(key) ⇒ Object



10
11
12
# File 'lib/msf/util/windows_registry/sam.rb', line 10

def normalize_key(key)
  @root.blank? ? key : key.delete_prefix(@root)
end