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



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

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

  _value_type, value_data = get_value('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_keysHash

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> },
    ...
    

    }



52
53
54
55
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
# File 'lib/msf/util/windows_registry/sam.rb', line 52

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

    rids.each do |rid|
      _value_type, value_data = get_value("#{users_key}\\#{rid}", 'V')
      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|
      value_type, _value_data = get_value("#{users_key}\\Names\\#{name}", '')
      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