Class: MiqWin32::System
- Inherits:
-
Object
- Object
- MiqWin32::System
- Defined in:
- lib/metadata/util/win32/Win32System.rb
Constant Summary collapse
- OS_MAPPING =
[ 'ProductName', :product_name, 'CurrentVersion', :version, 'CurrentBuildNumber', :build, 'SystemRoot', :system_root, 'CSDVersion', :service_pack, 'ProductId', :productid, 'DigitalProductId', :product_key, 'Vendor', :distribution, 'EditionID', :edition_id, ]
- COMPUTER_NAME_MAPPING =
[ 'ComputerName', :machine_name, ]
- PRODUCT_OPTIONS_MAPPING =
[ 'ProductType', :product_type, 'ProductSuite', :product_suite, ]
- ENVIRONMENT_MAPPING =
[ 'PROCESSOR_ARCHITECTURE', :architecture ]
- TCPIP_MAPPING =
[ "Hostname", :hostname, ]
- NETWORK_CARDS_MAPPING =
[ "ServiceName", :guid, "Description", :description, ]
- DHCP_MAPPING =
[ "EnableDHCP", :dhcp_enabled, "DhcpIPAddress", :ipaddress, "DhcpSubnetMask", :subnet_mask, "LeaseObtainedTime", :lease_obtained, "LeaseTerminatesTime", :lease_expires, "DhcpDefaultGateway", :default_gateway, "DhcpServer", :dhcp_server, "DhcpNameServer", :dns_server, "DhcpDomain", :domain, ]
- STATIC_MAPPING =
[ "EnableDHCP", :dhcp_enabled, "IPAddress", :ipaddress, "SubnetMask", :subnet_mask, "DefaultGateway", :default_gateway, "NameServer", :dns_server, "Domain", :domain, ]
- SAM_STRUCT_ACCT_POLICY =
Definition derived from www.beginningtoseethelight.org/ntsecurity/#BB4F910C0FFA1E43 HKEY_LOCAL_MACHINESAMSAMDomainsAccountF
BinaryStruct.new([ 'a16', nil, # UNKNOWN 'Q', :auto_increment, # Auto-increment 'Q', :max_pw_age, # Maximum password age (>=0 & <=999) days - minus from qword:ff + 1 = seconds x 10 million 'Q', :min_pw_age, # Minimum password age (>=0 & <=999) days - minus from qword:ff + 1 = seconds x 10 million 'a8', nil, # UNKNOWN 'Q', :lockout_duration, # Account lockout duration (>=0 & <=99,999) minutes - minus from qword:ff + 1 = seconds x 10 million 'Q', :reset_lockout_counter, # Reset account lockout counter after (>=1 & <=99,999) minutes - minus from qword:ff + 1 = seconds x 10 million 'a8', nil, # UNKNOWN 'I', :next_rid, # Next created users RID 'C', :pw_encrypt_pw_complex, # High nibble # Store password using reversible encryption for all users in the domain (enabled=1/disabled=0) # Low nibble # Password must meet complexity requirements (enabled=1/disabled=0) 'a3', nil, # UNKNOWN 'C', :min_pw_len, # Minimum password length (>=0 & <=14) characters 'a1', nil, # UNKNOWN 'C', :pw_hist, # Enforce password history (>=0 & <=24) passwords remembered 'a1', nil, # UNKNOWN 'S', :lockout_threshold, # Account lockout threshold (>=0 & <=999) attempts 'a26', nil, # UNKNOWN 'a48', :syskey, # Part of syskey 'a8', nil, # UNKNOWN ])
Instance Attribute Summary collapse
-
#account_policy ⇒ Object
readonly
Returns the value of attribute account_policy.
-
#networks ⇒ Object
readonly
Returns the value of attribute networks.
-
#os ⇒ Object
readonly
Returns the value of attribute os.
Instance Method Summary collapse
- #accountPolicyToXml(doc = nil) ⇒ Object
- #architecture_to_string(architecture) ⇒ Object
-
#initialize(_c, fs) ⇒ System
constructor
A new instance of System.
- #networksToXml(doc = nil) ⇒ Object
-
#os_product_suite(hash) ⇒ Object
Parse product edition and append to product_name if needed.
- #osToXml(doc = nil) ⇒ Object
- #process_acct_policy_f(data) ⇒ Object
- #process_acct_policy_f_date(data) ⇒ Object
- #process_acct_policy_f_pw_encrypt_pw_complex(data) ⇒ Object
- #to_xml(doc = nil) ⇒ Object
Constructor Details
#initialize(_c, fs) ⇒ System
Returns a new instance of System.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/metadata/util/win32/Win32System.rb', line 78 def initialize(_c, fs) @networks = [] regHnd = RemoteRegistry.new(fs, true) software_doc = regHnd.loadHive("software", [ {:key => "Microsoft/Windows NT/CurrentVersion", :depth => 1, :value => OS_MAPPING_VALUES}, {:key => "Microsoft/Windows NT/CurrentVersion/NetworkCards", :depth => 0, :value => NETWORK_CARDS_VALUES} ]) regHnd.close regHnd = RemoteRegistry.new(fs, true) sys_doc = regHnd.loadHive("system", [ {:key => 'CurrentControlSet/Control/ComputerName/ComputerName', :value => COMPUTER_NAME_VALUES}, {:key => 'CurrentControlSet/Control/Session Manager/Environment', :value => ENVIRONMENT_VALUES}, {:key => 'CurrentControlSet/Control/ProductOptions', :value => PRODUCT_OPTIONS_VALUES}, {:key => 'CurrentControlSet/Services/Tcpip/Parameters', :value => TCPIP_VALUES}, ]) regHnd.close # Get the OS information attrs = {:type => "windows"} reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", software_doc.root) attrs.merge!(XmlFind.decode(reg_node, OS_MAPPING)) if reg_node reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName", sys_doc.root) attrs.merge!(XmlFind.decode(reg_node, COMPUTER_NAME_MAPPING)) if reg_node reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions", sys_doc.root) attrs.merge!(XmlFind.decode(reg_node, PRODUCT_OPTIONS_MAPPING)) if reg_node reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", sys_doc.root) attrs.merge!(XmlFind.decode(reg_node, ENVIRONMENT_MAPPING)) if reg_node attrs[:product_key] = MiqWin32::Software.DecodeProductKey(attrs[:product_key]) if attrs[:product_key] attrs[:architecture] = architecture_to_string(attrs[:architecture]) # Parse product edition and append to product_name if needed. os_product_suite(attrs) @os = attrs # Get the network card information # Hold onto the parameters common to all network cards reg_tcpip = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", sys_doc.root) if reg_tcpip tcpip_params = XmlFind.decode(reg_tcpip, TCPIP_MAPPING) tcpip_params[:domain] = XmlFind.findNamedElement_hash("Domain", reg_tcpip) tcpip_params[:domain] = XmlFind.findNamedElement_hash("DhcpDomain", reg_tcpip) if tcpip_params[:domain].blank? tcpip_params[:domain] = nil if tcpip_params[:domain].blank? # Find each netword card, and get it's individual parameters reg_networkCards = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", software_doc.root) if reg_networkCards.kind_of?(Hash) reg_networkCards.each_element do |networkCard| attrs = XmlFind.decode(networkCard, NETWORK_CARDS_MAPPING) params = XmlFind.findElement("Interfaces/#{attrs[:guid]}", reg_tcpip) next if params.nil? # Add the common parameters attrs.merge!(tcpip_params) # Blank out fields that are not shared between network types attrs[:lease_obtained] = attrs[:lease_expires] = attrs[:dhcp_server] = nil # Get the rest of the parameters based on whether this network is DHCP enabled dhcp = XmlFind.findNamedElement_hash("EnableDHCP", params) attrs.merge!(XmlFind.decode(params, dhcp.to_i == 1 ? DHCP_MAPPING : STATIC_MAPPING)) # Remove the extra curly braces from the guid attrs[:guid] = attrs[:guid][1..-2] unless attrs[:guid].nil? # Clean the lease times and check they are in a reasonable range [:lease_obtained, :lease_expires].each do |t| attrs[t] = Time.at(attrs[t].to_i).getutc.iso8601 if attrs[t] && attrs[t].to_i >= 0 && attrs[t].to_i < 0x80000000 end @networks << attrs end end end # Extracted data also built into a human-readable format if uncommented # @debug_str = '' # Force memory cleanup software_doc = nil; sys_doc = nil; GC.start regHnd = RemoteRegistry.new(fs, true) sam_doc = regHnd.loadHive("sam", [{:key => "SAM/Domains/Account", :depth => 1, :value => ['F']}]) regHnd.close # Extract the local account policy from the registry @debug_str += "Account Policy:\n" if @debug_str reg_node = MIQRexml.findRegElement("HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account", sam_doc.root) if reg_node reg_node.each_element(:value) do |e| acct_policy_f = process_acct_policy_f(e.text) if e.attributes[:name] == "F" unless acct_policy_f.nil? # Remove unused elements acct_policy_f.delete(:auto_increment) acct_policy_f.delete(:next_rid) acct_policy_f.delete(:pw_encrypt_pw_complex) acct_policy_f.delete(:syskey) @account_policy = acct_policy_f end end end # Dump the debug string to a file if we are collecting that data # File.open('C:/Temp/reg_extract_full_system.txt', 'w') { |f| f.write(@debug_str) } if @debug_str if $log os_dup = @os.dup [:productid, :product_key].each { |k| os_dup.delete(k) } $log.info "VM OS information: [#{os_dup.inspect}]" end end |
Instance Attribute Details
#account_policy ⇒ Object (readonly)
Returns the value of attribute account_policy.
7 8 9 |
# File 'lib/metadata/util/win32/Win32System.rb', line 7 def account_policy @account_policy end |
#networks ⇒ Object (readonly)
Returns the value of attribute networks.
7 8 9 |
# File 'lib/metadata/util/win32/Win32System.rb', line 7 def networks @networks end |
#os ⇒ Object (readonly)
Returns the value of attribute os.
7 8 9 |
# File 'lib/metadata/util/win32/Win32System.rb', line 7 def os @os end |
Instance Method Details
#accountPolicyToXml(doc = nil) ⇒ Object
215 216 217 218 219 |
# File 'lib/metadata/util/win32/Win32System.rb', line 215 def accountPolicyToXml(doc = nil) doc = MiqXml.createDoc(nil) unless doc doc.add_element(:account_policy, @account_policy) unless @account_policy.blank? doc end |
#architecture_to_string(architecture) ⇒ Object
230 231 232 233 234 235 |
# File 'lib/metadata/util/win32/Win32System.rb', line 230 def architecture_to_string(architecture) case architecture when "x86" then 32 when "AMD64" then 64 end end |
#networksToXml(doc = nil) ⇒ Object
221 222 223 224 225 226 227 228 |
# File 'lib/metadata/util/win32/Win32System.rb', line 221 def networksToXml(doc = nil) doc = MiqXml.createDoc(nil) unless doc unless @networks.empty? node = doc.add_element(:networks) @networks.each { |n| node.add_element(:network, n) } end doc end |
#os_product_suite(hash) ⇒ Object
Parse product edition and append to product_name if needed.
238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/metadata/util/win32/Win32System.rb', line 238 def os_product_suite(hash) eid = hash.delete(:edition_id) ps = hash.delete(:product_suite) # If edition_id is populated then the edition will already be part of the product_name string if eid.nil? && !hash[:product_name].nil? ps = ps.to_s.split("\n") if ps.length > 1 && !hash[:product_name].include?(ps.first) hash[:product_name] = "#{hash[:product_name].strip} #{ps.first} Edition" end end end |
#osToXml(doc = nil) ⇒ Object
209 210 211 212 213 |
# File 'lib/metadata/util/win32/Win32System.rb', line 209 def osToXml(doc = nil) doc = MiqXml.createDoc(nil) unless doc doc.add_element(:os, @os) unless @os.empty? doc end |
#process_acct_policy_f(data) ⇒ Object
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
# File 'lib/metadata/util/win32/Win32System.rb', line 278 def process_acct_policy_f(data) bin = MSRegHive.regBinaryToRawBinary(data) f = SAM_STRUCT_ACCT_POLICY.decode(bin) @debug_str += " auto_increment - %s\n" % f[:auto_increment] if @debug_str @debug_str += " max_pw_age - %s - " % f[:max_pw_age] if @debug_str f[:max_pw_age] = process_acct_policy_f_date(f[:max_pw_age]) / 86400 @debug_str += "%s days\n" % f[:max_pw_age] if @debug_str @debug_str += " min_pw_age - %s - " % f[:min_pw_age] if @debug_str f[:min_pw_age] = process_acct_policy_f_date(f[:min_pw_age]) / 86400 @debug_str += "%s days\n" % f[:min_pw_age] if @debug_str @debug_str += " lockout_duration - %s - " % f[:lockout_duration] if @debug_str f[:lockout_duration] = process_acct_policy_f_date(f[:lockout_duration]) / 60 @debug_str += "%s minutes\n" % f[:lockout_duration] if @debug_str @debug_str += " reset_lockout_counter - %s - " % f[:reset_lockout_counter] if @debug_str f[:reset_lockout_counter] = process_acct_policy_f_date(f[:reset_lockout_counter]) / 60 @debug_str += "%s minutes\n" % f[:reset_lockout_counter] if @debug_str @debug_str += " next_rid - %s\n" % f[:next_rid] if @debug_str @debug_str += " pw_encrypt_pw_complex - 0x%02x\n" % f[:pw_encrypt_pw_complex] if @debug_str f[:pw_encrypt], f[:pw_complex] = process_acct_policy_f_pw_encrypt_pw_complex(f[:pw_encrypt_pw_complex]) @debug_str += " pw_encrypt - %s\n" % f[:pw_encrypt] if @debug_str @debug_str += " pw_complex - %s\n" % f[:pw_complex] if @debug_str if @debug_str @debug_str += " min_pw_len - %s characters\n" % f[:min_pw_len] @debug_str += " pw_hist - %s passwords remembered\n" % f[:pw_hist] @debug_str += " lockout_threshold - %s attempts\n" % f[:lockout_threshold] @debug_str += " syskey - %s\n" % Accounts.rawBinaryToRegBinary(f[:syskey]) end f end |
#process_acct_policy_f_date(data) ⇒ Object
317 318 319 320 321 |
# File 'lib/metadata/util/win32/Win32System.rb', line 317 def process_acct_policy_f_date(data) return 0 if data == 0 || data == 0x8000000000000000 # minus from qword:ff + 1 = seconds x 10 million (0x10000000000000000 - data) / 10000000 end |
#process_acct_policy_f_pw_encrypt_pw_complex(data) ⇒ Object
323 324 325 326 327 328 329 330 331 |
# File 'lib/metadata/util/win32/Win32System.rb', line 323 def process_acct_policy_f_pw_encrypt_pw_complex(data) pw_encrypt = data >> 4 pw_encrypt = (pw_encrypt == 1) pw_complex = data & 0x0F pw_complex = (pw_complex == 1) return pw_encrypt, pw_complex end |
#to_xml(doc = nil) ⇒ Object
201 202 203 204 205 206 207 |
# File 'lib/metadata/util/win32/Win32System.rb', line 201 def to_xml(doc = nil) doc = MiqXml.createDoc(nil) unless doc osToXml(doc) accountPolicyToXml(doc) networksToXml(doc) doc end |