manageiq-smartstate 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +4 -0
- data/.rspec_ci +4 -0
- data/.travis.yml +15 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +202 -0
- data/README.md +45 -0
- data/Rakefile +23 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/MiqContainerGroup/MiqContainerGroup.rb +31 -0
- data/lib/MiqVm/MiqLocalVm.rb +50 -0
- data/lib/MiqVm/MiqRhevmVm.rb +179 -0
- data/lib/MiqVm/MiqVm.rb +355 -0
- data/lib/MiqVm/miq_azure_vm.rb +96 -0
- data/lib/MiqVm/miq_scvmm_vm.rb +38 -0
- data/lib/MiqVm/test/camcorder_fleece_test.rb +60 -0
- data/lib/MiqVm/test/localVm.rb +45 -0
- data/lib/MiqVm/test/partitionAlignmentCheck.rb +76 -0
- data/lib/MiqVm/test/remoteVm.rb +65 -0
- data/lib/MiqVm/test/rhevmNfsTest.rb +62 -0
- data/lib/MiqVm/test/rhevmNfsTest2.rb +66 -0
- data/lib/MiqVm/test/rhevmTest.rb +70 -0
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackCommon.rb +107 -0
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackImage.rb +67 -0
- data/lib/OpenStackExtract/MiqOpenStackVm/MiqOpenStackInstance.rb +182 -0
- data/lib/Scvmm/miq_hyperv_disk.rb +273 -0
- data/lib/Scvmm/miq_scvmm_parse_powershell.rb +75 -0
- data/lib/Scvmm/miq_scvmm_vm_ssa_info.rb +135 -0
- data/lib/Scvmm/test/miq_hyperv_disk_test.rb +33 -0
- data/lib/Scvmm/test/miq_scvmm_vm_ssa_info_test.rb +41 -0
- data/lib/VmLocalDiskAccess/test/localCfg.rb +97 -0
- data/lib/VolumeManager/LVM/logical_volume.rb +75 -0
- data/lib/VolumeManager/LVM/lv_segment.rb +43 -0
- data/lib/VolumeManager/LVM/lvm2disk.rb +158 -0
- data/lib/VolumeManager/LVM/parser.rb +138 -0
- data/lib/VolumeManager/LVM/physical_volume.rb +19 -0
- data/lib/VolumeManager/LVM/scanner.rb +156 -0
- data/lib/VolumeManager/LVM/thin/btree.rb +83 -0
- data/lib/VolumeManager/LVM/thin/constants.rb +86 -0
- data/lib/VolumeManager/LVM/thin/data_map.rb +44 -0
- data/lib/VolumeManager/LVM/thin/mapping_tree.rb +19 -0
- data/lib/VolumeManager/LVM/thin/space_maps.rb +58 -0
- data/lib/VolumeManager/LVM/thin/superblock.rb +136 -0
- data/lib/VolumeManager/LVM/thin.rb +6 -0
- data/lib/VolumeManager/LVM/volume_group.rb +97 -0
- data/lib/VolumeManager/LVM.rb +8 -0
- data/lib/VolumeManager/MiqLdm.rb +546 -0
- data/lib/VolumeManager/MiqLvm.rb +17 -0
- data/lib/VolumeManager/MiqNativeVolumeManager.rb +150 -0
- data/lib/VolumeManager/MiqVolumeManager.rb +277 -0
- data/lib/VolumeManager/VolMgrPlatformSupport.rb +18 -0
- data/lib/VolumeManager/VolMgrPlatformSupportLinux.rb +77 -0
- data/lib/VolumeManager/VolMgrPlatformSupportWin.rb +17 -0
- data/lib/VolumeManager/test/blockDevTest.rb +40 -0
- data/lib/VolumeManager/test/ldm.rb +97 -0
- data/lib/blackbox/VmBlackBox.rb +103 -0
- data/lib/blackbox/xmlStorage.rb +180 -0
- data/lib/db/MiqBdb/MiqBdb.rb +309 -0
- data/lib/db/MiqBdb/MiqBdbBtree.rb +219 -0
- data/lib/db/MiqBdb/MiqBdbHash.rb +199 -0
- data/lib/db/MiqBdb/MiqBdbPage.rb +159 -0
- data/lib/db/MiqBdb/MiqBdbUtil.rb +18 -0
- data/lib/db/MiqSqlite/MiqSqlite3.rb +330 -0
- data/lib/db/MiqSqlite/MiqSqlite3Cell.rb +167 -0
- data/lib/db/MiqSqlite/MiqSqlite3Page.rb +151 -0
- data/lib/db/MiqSqlite/MiqSqlite3Table.rb +124 -0
- data/lib/db/MiqSqlite/MiqSqlite3Util.rb +32 -0
- data/lib/disk/DiskProbe.rb +68 -0
- data/lib/disk/MiqDisk.rb +317 -0
- data/lib/disk/camcorder_test.rb +90 -0
- data/lib/disk/dos_mbr.img +0 -0
- data/lib/disk/modules/AzureBlobDisk.rb +101 -0
- data/lib/disk/modules/LocalDevMod.rb +47 -0
- data/lib/disk/modules/LocalDevProbe.rb +6 -0
- data/lib/disk/modules/MSCommon.rb +352 -0
- data/lib/disk/modules/MSVSDiffDisk.rb +91 -0
- data/lib/disk/modules/MSVSDiskProbe.rb +61 -0
- data/lib/disk/modules/MSVSDynamicDisk.rb +42 -0
- data/lib/disk/modules/MSVSFixedDisk.rb +45 -0
- data/lib/disk/modules/MiqLargeFile.rb +63 -0
- data/lib/disk/modules/MiqLargeFileWin32.rb +107 -0
- data/lib/disk/modules/QcowDisk.rb +692 -0
- data/lib/disk/modules/QcowDiskProbe.rb +34 -0
- data/lib/disk/modules/RawBlockIO.rb +116 -0
- data/lib/disk/modules/RawDisk.rb +45 -0
- data/lib/disk/modules/RawDiskProbe.rb +7 -0
- data/lib/disk/modules/RhevmDescriptor.rb +167 -0
- data/lib/disk/modules/RhevmDiskProbe.rb +52 -0
- data/lib/disk/modules/VMWareCowdDisk.rb +207 -0
- data/lib/disk/modules/VMWareDescriptor.rb +214 -0
- data/lib/disk/modules/VMWareDiskProbe.rb +74 -0
- data/lib/disk/modules/VMWareSparseDisk.rb +189 -0
- data/lib/disk/modules/VhdxDisk.rb +625 -0
- data/lib/disk/modules/VhdxDiskProbe.rb +46 -0
- data/lib/disk/modules/VixDiskMod.rb +54 -0
- data/lib/disk/modules/VixDiskProbe.rb +6 -0
- data/lib/disk/modules/miq_disk_cache.rb +135 -0
- data/lib/disk/modules/miq_dummy_disk.rb +41 -0
- data/lib/disk/modules/vhdx_bat_entry.rb +10 -0
- data/lib/disk/test.rb +66 -0
- data/lib/fs/MetakitFS/MetakitFS.rb +530 -0
- data/lib/fs/MetakitFS/test/Makefile +14 -0
- data/lib/fs/MetakitFS/test/MkCollectFiles.rb +165 -0
- data/lib/fs/MetakitFS/test/MkSelectFiles.rb +30 -0
- data/lib/fs/MetakitFS/test/collect_files.yaml +70 -0
- data/lib/fs/MetakitFS/test/init.rb +3 -0
- data/lib/fs/MetakitFS/test/mk2vmdk.rb +64 -0
- data/lib/fs/MetakitFS/test/mk4test.c +92 -0
- data/lib/fs/MetakitFS/test/mkFsTest.rb +113 -0
- data/lib/fs/MetakitFS/test/proto.rb +97 -0
- data/lib/fs/MiqFS/FsProbe.rb +39 -0
- data/lib/fs/MiqFS/MiqFS.rb +515 -0
- data/lib/fs/MiqFS/modules/AUFSProbe.rb +26 -0
- data/lib/fs/MiqFS/modules/Ext3.rb +305 -0
- data/lib/fs/MiqFS/modules/Ext3Probe.rb +25 -0
- data/lib/fs/MiqFS/modules/Ext4.rb +304 -0
- data/lib/fs/MiqFS/modules/Ext4Probe.rb +25 -0
- data/lib/fs/MiqFS/modules/Fat32.rb +318 -0
- data/lib/fs/MiqFS/modules/Fat32Probe.rb +30 -0
- data/lib/fs/MiqFS/modules/HFSProbe.rb +18 -0
- data/lib/fs/MiqFS/modules/Iso9660.rb +293 -0
- data/lib/fs/MiqFS/modules/Iso9660Probe.rb +18 -0
- data/lib/fs/MiqFS/modules/LocalFS.rb +105 -0
- data/lib/fs/MiqFS/modules/NTFS.rb +287 -0
- data/lib/fs/MiqFS/modules/NTFSProbe.rb +21 -0
- data/lib/fs/MiqFS/modules/NativeFS.rb +155 -0
- data/lib/fs/MiqFS/modules/ReFSProbe.rb +17 -0
- data/lib/fs/MiqFS/modules/RealFS.rb +79 -0
- data/lib/fs/MiqFS/modules/RealFSProbe.rb +6 -0
- data/lib/fs/MiqFS/modules/Reiser4Probe.rb +18 -0
- data/lib/fs/MiqFS/modules/ReiserFS.rb +315 -0
- data/lib/fs/MiqFS/modules/ReiserFSProbe.rb +42 -0
- data/lib/fs/MiqFS/modules/UnionFSProbe.rb +18 -0
- data/lib/fs/MiqFS/modules/WebDAV.rb +127 -0
- data/lib/fs/MiqFS/modules/WebDAVFile.rb +68 -0
- data/lib/fs/MiqFS/modules/XFS.rb +300 -0
- data/lib/fs/MiqFS/modules/XFSProbe.rb +26 -0
- data/lib/fs/MiqFS/modules/ZFSProbe.rb +18 -0
- data/lib/fs/MiqFS/test.rb +59 -0
- data/lib/fs/MiqFsUtil.rb +383 -0
- data/lib/fs/MiqMountManager.rb +209 -0
- data/lib/fs/MiqNativeMountManager.rb +101 -0
- data/lib/fs/MountManagerProbe.rb +29 -0
- data/lib/fs/ReiserFS/block.rb +209 -0
- data/lib/fs/ReiserFS/directory.rb +136 -0
- data/lib/fs/ReiserFS/directory_entry.rb +140 -0
- data/lib/fs/ReiserFS/file_data.rb +111 -0
- data/lib/fs/ReiserFS/superblock.rb +140 -0
- data/lib/fs/ReiserFS/utils.rb +95 -0
- data/lib/fs/VimDatastoreFS/VimDatastoreFS.rb +192 -0
- data/lib/fs/ext3/alloc_bitmap.rb +38 -0
- data/lib/fs/ext3/block_pointers_path.rb +130 -0
- data/lib/fs/ext3/directory.rb +51 -0
- data/lib/fs/ext3/directory_entry.rb +67 -0
- data/lib/fs/ext3/ex_attrib_header.rb +14 -0
- data/lib/fs/ext3/ex_attrib_name.rb +23 -0
- data/lib/fs/ext3/file_data.rb +130 -0
- data/lib/fs/ext3/group_descriptor_entry.rb +65 -0
- data/lib/fs/ext3/group_descriptor_table.rb +54 -0
- data/lib/fs/ext3/hash_tree_entry.rb +18 -0
- data/lib/fs/ext3/hash_tree_header.rb +15 -0
- data/lib/fs/ext3/inode.rb +228 -0
- data/lib/fs/ext3/posix_acl_entry.rb +29 -0
- data/lib/fs/ext3/posix_acl_header.rb +11 -0
- data/lib/fs/ext3/superblock.rb +406 -0
- data/lib/fs/ext3/test/tc_Ext3BlockPointersPath.rb +74 -0
- data/lib/fs/ext4/alloc_bitmap.rb +38 -0
- data/lib/fs/ext4/directory.rb +87 -0
- data/lib/fs/ext4/directory_entry.rb +77 -0
- data/lib/fs/ext4/ex_attrib_header.rb +14 -0
- data/lib/fs/ext4/ex_attrib_name.rb +23 -0
- data/lib/fs/ext4/extent.rb +35 -0
- data/lib/fs/ext4/extent_header.rb +40 -0
- data/lib/fs/ext4/extent_index.rb +33 -0
- data/lib/fs/ext4/group_descriptor_entry.rb +69 -0
- data/lib/fs/ext4/group_descriptor_table.rb +54 -0
- data/lib/fs/ext4/hash_tree_entry.rb +58 -0
- data/lib/fs/ext4/hash_tree_header.rb +35 -0
- data/lib/fs/ext4/inode.rb +465 -0
- data/lib/fs/ext4/posix_acl_entry.rb +29 -0
- data/lib/fs/ext4/posix_acl_header.rb +11 -0
- data/lib/fs/ext4/superblock.rb +412 -0
- data/lib/fs/fat32/boot_sect.rb +379 -0
- data/lib/fs/fat32/directory.rb +222 -0
- data/lib/fs/fat32/directory_entry.rb +540 -0
- data/lib/fs/fat32/file_data.rb +128 -0
- data/lib/fs/iso9660/boot_sector.rb +170 -0
- data/lib/fs/iso9660/directory.rb +90 -0
- data/lib/fs/iso9660/directory_entry.rb +147 -0
- data/lib/fs/iso9660/file_data.rb +78 -0
- data/lib/fs/iso9660/rock_ridge.rb +329 -0
- data/lib/fs/iso9660/util.rb +57 -0
- data/lib/fs/modules/LinuxMount.rb +300 -0
- data/lib/fs/modules/LinuxMountProbe.rb +29 -0
- data/lib/fs/modules/WinMount.rb +97 -0
- data/lib/fs/modules/WinMountProbe.rb +24 -0
- data/lib/fs/ntfs/attrib_attribute_list.rb +131 -0
- data/lib/fs/ntfs/attrib_bitmap.rb +26 -0
- data/lib/fs/ntfs/attrib_data.rb +74 -0
- data/lib/fs/ntfs/attrib_file_name.rb +110 -0
- data/lib/fs/ntfs/attrib_header.rb +194 -0
- data/lib/fs/ntfs/attrib_index_allocation.rb +19 -0
- data/lib/fs/ntfs/attrib_index_root.rb +247 -0
- data/lib/fs/ntfs/attrib_object_id.rb +40 -0
- data/lib/fs/ntfs/attrib_standard_information.rb +107 -0
- data/lib/fs/ntfs/attrib_type.rb +49 -0
- data/lib/fs/ntfs/attrib_volume_information.rb +53 -0
- data/lib/fs/ntfs/attrib_volume_name.rb +31 -0
- data/lib/fs/ntfs/boot_sect.rb +253 -0
- data/lib/fs/ntfs/data_run.rb +358 -0
- data/lib/fs/ntfs/directory_index_node.rb +114 -0
- data/lib/fs/ntfs/index_node_header.rb +69 -0
- data/lib/fs/ntfs/index_record_header.rb +85 -0
- data/lib/fs/ntfs/mft_entry.rb +288 -0
- data/lib/fs/ntfs/utils.rb +43 -0
- data/lib/fs/test/camcorder_fs_test.rb +108 -0
- data/lib/fs/test/collect_files_direct.yaml +22 -0
- data/lib/fs/test/collect_files_in.yaml +24 -0
- data/lib/fs/test/collect_files_in_nc.yaml +22 -0
- data/lib/fs/test/collect_files_out.yaml +6 -0
- data/lib/fs/test/collect_files_rm.yaml +6 -0
- data/lib/fs/test/copyTest.rb +126 -0
- data/lib/fs/test/fsTest.rb +87 -0
- data/lib/fs/test/updateTest.rb +184 -0
- data/lib/fs/xfs/allocation_group.rb +160 -0
- data/lib/fs/xfs/bmap_btree_block.rb +125 -0
- data/lib/fs/xfs/bmap_btree_record.rb +80 -0
- data/lib/fs/xfs/bmap_btree_root_node.rb +72 -0
- data/lib/fs/xfs/directory.rb +133 -0
- data/lib/fs/xfs/directory2_data_header.rb +27 -0
- data/lib/fs/xfs/directory3_data_header.rb +34 -0
- data/lib/fs/xfs/directory_block_tail.rb +22 -0
- data/lib/fs/xfs/directory_data_header.rb +46 -0
- data/lib/fs/xfs/directory_entry.rb +106 -0
- data/lib/fs/xfs/inode.rb +532 -0
- data/lib/fs/xfs/inode_map.rb +100 -0
- data/lib/fs/xfs/short_form_directory_entry.rb +91 -0
- data/lib/fs/xfs/short_form_header.rb +44 -0
- data/lib/fs/xfs/superblock.rb +556 -0
- data/lib/lib/tasks/azure.rake +52 -0
- data/lib/manageiq/smartstate/version.rb +5 -0
- data/lib/manageiq/smartstate.rb +7 -0
- data/lib/manageiq-smartstate.rb +1 -0
- data/lib/metadata/MIQExtract/MIQExtract.rb +297 -0
- data/lib/metadata/MIQExtract/test/extractTest.rb +41 -0
- data/lib/metadata/MIQExtract/test/full_extract_test.rb +68 -0
- data/lib/metadata/ScanProfile/HostScanItem.rb +4 -0
- data/lib/metadata/ScanProfile/HostScanProfile.rb +4 -0
- data/lib/metadata/ScanProfile/HostScanProfiles.rb +41 -0
- data/lib/metadata/ScanProfile/ScanItemBase.rb +63 -0
- data/lib/metadata/ScanProfile/ScanProfileBase.rb +51 -0
- data/lib/metadata/ScanProfile/ScanProfilesBase.rb +60 -0
- data/lib/metadata/ScanProfile/VmScanItem.rb +4 -0
- data/lib/metadata/ScanProfile/VmScanProfile.rb +4 -0
- data/lib/metadata/ScanProfile/VmScanProfiles.rb +38 -0
- data/lib/metadata/ScanProfile/modules/HostScanItemFile.rb +51 -0
- data/lib/metadata/ScanProfile/modules/HostScanItemNteventlog.rb +84 -0
- data/lib/metadata/ScanProfile/modules/VmScanItemFile.rb +39 -0
- data/lib/metadata/ScanProfile/modules/VmScanItemNteventlog.rb +34 -0
- data/lib/metadata/ScanProfile/modules/VmScanItemRegistry.rb +64 -0
- data/lib/metadata/VMMount/VMMount.rb +81 -0
- data/lib/metadata/VMMount/VMPlatformMount.rb +18 -0
- data/lib/metadata/VMMount/VMPlatformMountLinux.rb +75 -0
- data/lib/metadata/VMMount/VMPlatformMountWin.rb +13 -0
- data/lib/metadata/VmConfig/GetNativeCfg.rb +45 -0
- data/lib/metadata/VmConfig/VmConfig.rb +947 -0
- data/lib/metadata/VmConfig/cfgConfig.rb +45 -0
- data/lib/metadata/VmConfig/ovfConfig.rb +99 -0
- data/lib/metadata/VmConfig/test/GetVMwareCfgTest.rb +40 -0
- data/lib/metadata/VmConfig/vmcConfig.rb +116 -0
- data/lib/metadata/VmConfig/vmtxConfig.rb +4 -0
- data/lib/metadata/VmConfig/vmxConfig.rb +162 -0
- data/lib/metadata/VmConfig/xmlConfig.rb +79 -0
- data/lib/metadata/VmConfig/xmlMsHyperVConfig.rb +41 -0
- data/lib/metadata/linux/InitProcHash.rb +632 -0
- data/lib/metadata/linux/LinuxInitProcs.rb +142 -0
- data/lib/metadata/linux/LinuxOSInfo.rb +237 -0
- data/lib/metadata/linux/LinuxPackages.rb +209 -0
- data/lib/metadata/linux/LinuxSystemd.rb +130 -0
- data/lib/metadata/linux/LinuxUsers.rb +289 -0
- data/lib/metadata/linux/LinuxUtils.rb +197 -0
- data/lib/metadata/linux/MiqConaryPackages.rb +41 -0
- data/lib/metadata/linux/MiqRpmPackages.rb +160 -0
- data/lib/metadata/linux/test/Name +0 -0
- data/lib/metadata/linux/test/Packages +0 -0
- data/lib/metadata/linux/test/rpoTest.rb +5 -0
- data/lib/metadata/linux/test/tc_LinuxUtils.rb +4157 -0
- data/lib/metadata/util/event_log_filter.rb +61 -0
- data/lib/metadata/util/md5deep.rb +280 -0
- data/lib/metadata/util/win32/Win32Accounts.rb +764 -0
- data/lib/metadata/util/win32/Win32EventLog.rb +743 -0
- data/lib/metadata/util/win32/Win32Services.rb +86 -0
- data/lib/metadata/util/win32/Win32Software.rb +326 -0
- data/lib/metadata/util/win32/Win32System.rb +333 -0
- data/lib/metadata/util/win32/boot_info_win.rb +59 -0
- data/lib/metadata/util/win32/fleece_hives.rb +220 -0
- data/lib/metadata/util/win32/ms-registry.rb +650 -0
- data/lib/metadata/util/win32/peheader.rb +868 -0
- data/lib/metadata/util/win32/remote-registry.rb +142 -0
- data/lib/metadata/util/win32/system_path_win.rb +103 -0
- data/lib/metadata/util/win32/versioninfo.rb +17 -0
- data/manageiq-smartstate.gemspec +35 -0
- metadata +486 -0
@@ -0,0 +1,764 @@
|
|
1
|
+
# encoding: US-ASCII
|
2
|
+
|
3
|
+
require 'util/miq-xml'
|
4
|
+
require 'util/miq-logger'
|
5
|
+
require 'enumerator'
|
6
|
+
|
7
|
+
module MiqWin32
|
8
|
+
class Accounts
|
9
|
+
attr_reader :users, :groups
|
10
|
+
|
11
|
+
def initialize(_c, fs)
|
12
|
+
@users = []
|
13
|
+
@groups = []
|
14
|
+
|
15
|
+
# Extracted data also built into a human-readable format if uncommented
|
16
|
+
# @debug_str = ''
|
17
|
+
|
18
|
+
regHnd = RemoteRegistry.new(fs, true)
|
19
|
+
reg_doc = regHnd.loadHive("sam", nil)
|
20
|
+
regHnd.close
|
21
|
+
|
22
|
+
# Collect a mapping of user SIDs to user names for user-group relationships
|
23
|
+
users_by_sids = {}
|
24
|
+
|
25
|
+
# Extract the users data from the registry
|
26
|
+
@debug_str += "Users:\n" if @debug_str
|
27
|
+
sections = [
|
28
|
+
"HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users",
|
29
|
+
# "SAM/SAM/Domains/Builtin/Users"
|
30
|
+
]
|
31
|
+
sections.each do |section|
|
32
|
+
reg_node = MIQRexml.findRegElement("#{section}\\Names", reg_doc.root)
|
33
|
+
if reg_node
|
34
|
+
reg_node.each_element_with_attribute(:keyname) do |e|
|
35
|
+
username = e.attributes[:keyname]
|
36
|
+
user_data = {}
|
37
|
+
@debug_str += " %s:\n" % username if @debug_str
|
38
|
+
|
39
|
+
e.each_element(:value) do |e2|
|
40
|
+
@debug_str += " %s - %s - %s\n" % [e2.attributes[:name], e2.attributes[:type], e2.text] if @debug_str
|
41
|
+
|
42
|
+
# Find the rest of the user's data based on the hex value stored in the type
|
43
|
+
reg_node2 = MIQRexml.findRegElement("#{section}/#{e2.attributes[:type]}", reg_doc.root)
|
44
|
+
if reg_node2
|
45
|
+
reg_node2.each_element(:value) do |e3|
|
46
|
+
@debug_str += " %s - %s - %s\n" % [e3.attributes[:name], e3.attributes[:type], e3.text] if @debug_str
|
47
|
+
if e3.attributes[:name] == "F"
|
48
|
+
users_f = process_users_f(e3.text)
|
49
|
+
|
50
|
+
# Do a sanity check on the return data
|
51
|
+
if users_f.nil?
|
52
|
+
# Set the user_data to nil to signify a parsing problem
|
53
|
+
user_data = nil
|
54
|
+
elsif !user_data.nil?
|
55
|
+
user_data.merge!(users_f)
|
56
|
+
end
|
57
|
+
elsif e3.attributes[:name] == "V"
|
58
|
+
users_v = process_users_v(e3.text)
|
59
|
+
|
60
|
+
# Do a sanity check on the return data
|
61
|
+
if users_v.nil? || users_v['username'] != username
|
62
|
+
# Set the user_data to nil to signify a parsing problem
|
63
|
+
user_data = nil
|
64
|
+
$log.warn "Unable to process data for user account [#{username}]"
|
65
|
+
elsif !user_data.nil?
|
66
|
+
user_data.merge!(users_v)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get the pertinent data from out of that
|
74
|
+
nh = {"name" => username}
|
75
|
+
unless user_data.nil? || user_data.length == 0
|
76
|
+
nh.merge!(
|
77
|
+
"userid" => user_data['user_num'],
|
78
|
+
"display_name" => user_data['fullname'],
|
79
|
+
"comment" => user_data['comment'],
|
80
|
+
"homedir" => user_data['homedir'],
|
81
|
+
"enabled" => user_data['account_active'],
|
82
|
+
"expires" => user_data['account_expires'].nil? ? "never" : user_data['account_expires'],
|
83
|
+
"last_logon" => user_data['last_logon'],
|
84
|
+
"groups" => []
|
85
|
+
)
|
86
|
+
|
87
|
+
# Check for the SID in the permissions block by looking for a certain set of permissions.
|
88
|
+
# Checking is done in reverse, since the last permission set tends to be the right one.
|
89
|
+
user_data['num_permissions'].downto(1) do |x|
|
90
|
+
if user_data["perm#{x}_sid"] && ["D\000\002\000", "\004\000\002\000"].include?(user_data["perm#{x}_perms"])
|
91
|
+
users_by_sids[user_data["perm#{x}_sid"]] = nh['name']
|
92
|
+
break
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
@users << nh
|
97
|
+
end
|
98
|
+
@debug_str += "\n\n" if @debug_str
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Extract the groups data from the registry
|
103
|
+
@debug_str += "Groups:\n" if @debug_str
|
104
|
+
sections = [
|
105
|
+
"HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Builtin\\Aliases",
|
106
|
+
# "SAM/SAM/Domains/Builtin/Groups",
|
107
|
+
"HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Aliases",
|
108
|
+
# "SAM/SAM/Domains/Account/Groups"
|
109
|
+
]
|
110
|
+
sections.each do |section|
|
111
|
+
reg_node = MIQRexml.findRegElement("#{section}\\Names", reg_doc.root)
|
112
|
+
if reg_node
|
113
|
+
reg_node.each_element_with_attribute(:keyname) do |e|
|
114
|
+
groupname = e.attributes[:keyname]
|
115
|
+
group_data = {}
|
116
|
+
@debug_str += " %s:\n" % groupname if @debug_str
|
117
|
+
|
118
|
+
e.each_element(:value) do |e2|
|
119
|
+
@debug_str += " %s - %s - %s\n" % [e2.attributes[:name], e2.attributes[:type], e2.text] if @debug_str
|
120
|
+
|
121
|
+
# Find the rest of the group's data based on the hex value stored in the type
|
122
|
+
reg_node2 = MIQRexml.findRegElement("#{section}/#{e2.attributes[:type]}", reg_doc.root)
|
123
|
+
if reg_node2
|
124
|
+
reg_node2.each_element(:value) do |e3|
|
125
|
+
@debug_str += " %s - %s - %s\n" % [e3.attributes[:name], e3.attributes[:type], e3.text] if @debug_str
|
126
|
+
if e3.attributes[:name] == "C"
|
127
|
+
groups_c = process_groups_c(e3.text)
|
128
|
+
|
129
|
+
# Do a sanity check on the return data
|
130
|
+
if groups_c.nil? || groups_c['group_name'] != groupname
|
131
|
+
# Set the group_data to nil to signify a parsing problem
|
132
|
+
group_data = nil
|
133
|
+
elsif !group_data.nil?
|
134
|
+
group_data.merge!(groups_c)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get the pertinent data from out of that
|
142
|
+
nh = {"name" => groupname}
|
143
|
+
unless group_data.nil? || group_data.length == 0
|
144
|
+
nh.merge!(
|
145
|
+
"groupid" => group_data['group_num'],
|
146
|
+
"comment" => group_data['group_desc']
|
147
|
+
)
|
148
|
+
|
149
|
+
nh['users'] = []
|
150
|
+
group_data['sids'].each do |sid|
|
151
|
+
if users_by_sids.include?(sid)
|
152
|
+
# Add this user to the set of users for this group
|
153
|
+
nh['users'] << users_by_sids[sid]
|
154
|
+
|
155
|
+
# Add this group to the original user's set of groups
|
156
|
+
found = @users.find { |u| u['name'] == users_by_sids[sid] }
|
157
|
+
found['groups'] << nh['name'] if found
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
@groups << nh
|
162
|
+
end
|
163
|
+
@debug_str += "\n\n" if @debug_str
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Force memory cleanup
|
168
|
+
reg_doc = nil; GC.start
|
169
|
+
|
170
|
+
# Dump the debug string to a file if we are collecting that data
|
171
|
+
# File.open('C:/Temp/reg_extract_full_accounts.txt', 'w') { |f| f.write(@debug_str) } if @debug_str
|
172
|
+
end
|
173
|
+
|
174
|
+
def to_xml(doc = nil)
|
175
|
+
doc = MiqXml.createDoc(nil) unless doc
|
176
|
+
usersToXml(doc)
|
177
|
+
groupsToXml(doc)
|
178
|
+
doc
|
179
|
+
end
|
180
|
+
|
181
|
+
def usersToXml(doc = nil)
|
182
|
+
doc = MiqXml.createDoc(nil) unless doc
|
183
|
+
unless @users.empty?
|
184
|
+
node = doc.add_element("users")
|
185
|
+
@users.each do |u|
|
186
|
+
u_groups = u.delete('groups')
|
187
|
+
user = node.add_element("user", u)
|
188
|
+
|
189
|
+
u_groups.each do |g|
|
190
|
+
user.add_element('member_of_group', 'name' => g)
|
191
|
+
end unless u_groups.nil?
|
192
|
+
end
|
193
|
+
end
|
194
|
+
doc
|
195
|
+
end
|
196
|
+
|
197
|
+
def groupsToXml(doc = nil)
|
198
|
+
doc = MiqXml.createDoc(nil) unless doc
|
199
|
+
unless @groups.empty?
|
200
|
+
node = doc.add_element("groups")
|
201
|
+
@groups.each do |g|
|
202
|
+
g_users = g.delete('users')
|
203
|
+
group = node.add_element("group", g)
|
204
|
+
|
205
|
+
g_users.each do |u|
|
206
|
+
group.add_element('member_users', 'name' => u)
|
207
|
+
end unless g_users.nil?
|
208
|
+
end
|
209
|
+
end
|
210
|
+
doc
|
211
|
+
end
|
212
|
+
|
213
|
+
# Definition derived from http://www.beginningtoseethelight.org/ntsecurity/#8603CF0AFBB170DD
|
214
|
+
# \HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\%RID%\F (fixed length, 80)
|
215
|
+
SAM_STRUCT_USERS_F = [
|
216
|
+
'a8', nil, # UNKNOWN
|
217
|
+
'Q', 'last_logon', # Last logon (WinNT format), 0 if never logged on
|
218
|
+
'a8', nil, # UNKNOWN
|
219
|
+
'Q', 'last_pw_set', # Password last set (WinNT format), 0 if not changed
|
220
|
+
'Q', 'account_expires', # Account expires (WinNT format), 0 if set not to expire
|
221
|
+
'Q', 'last_wrong_pw', # Last incorrect password (WinNT format), 0 if not
|
222
|
+
'I', 'user_num', # User number
|
223
|
+
'a4', nil, # UNKNOWN
|
224
|
+
'C', 'logon_ok_account_active',
|
225
|
+
# High nibble
|
226
|
+
# Unsure - 0/2/6/8/A/C/E=pwd/username invalid
|
227
|
+
# 1/3/4=logonokay
|
228
|
+
# 5/7/D/F=Logon Message
|
229
|
+
# The system can not log you on due to the following error:
|
230
|
+
# The account used is an interdomain trust account. Use your global user
|
231
|
+
# account or local user account to access this server.
|
232
|
+
# Please try again or consult your system administrator.
|
233
|
+
# 9/B=Logon Message
|
234
|
+
# The system can not log you on due to the following error:
|
235
|
+
# The account used is a computer account. Use your global user account
|
236
|
+
# or local user account to access this server.
|
237
|
+
# Please try again or consult your system administrator.
|
238
|
+
# Low nibble
|
239
|
+
# Account active - 0=active 1=not active.
|
240
|
+
# Password required - 0=yes 4=no
|
241
|
+
# 0/2/4/6/8/A/C/E=logonokay - 1/2/5/7/9/B/D/F=accountdisabled/inactive
|
242
|
+
'C', 'pw_never_expire', # High nibble
|
243
|
+
# UNKNOWN
|
244
|
+
# Low nibble
|
245
|
+
# Password never expire - 0=secpoltime 2=never
|
246
|
+
# For some unknown reason this value is set to 4 on a lockout and 0 on
|
247
|
+
# unlocking. If the password is set never to expire the option to force
|
248
|
+
# the user to change their password on next logon is greyed out.
|
249
|
+
# 2/3/6/7/A/B/E/F=Password never expires (2=GUI setting)
|
250
|
+
#
|
251
|
+
# 0/2/8/A=logonokay
|
252
|
+
# 1/3/5/7/9/B/D/F=Logon Message
|
253
|
+
# The system can not log you on due to the following error:
|
254
|
+
# The account used is a server trust account. Use your global user
|
255
|
+
# account or local user account to access this server.
|
256
|
+
# Please try again or consult your system administrator.
|
257
|
+
# 4/6/C/E=logonokay - reset to X-4 though.
|
258
|
+
'a2', nil, # UNKNOWN
|
259
|
+
'S', 'country_code', # Country code
|
260
|
+
'a2', nil, # UNKNOWN
|
261
|
+
'S', 'invalid_pw_count', # Invalid password count, reset after a correct logon
|
262
|
+
'S', 'num_logons', # Number of logons, gets stuck at FF,FF
|
263
|
+
]
|
264
|
+
SIZEOF_SAM_STRUCT_USERS_F = BinaryStruct.sizeof(SAM_STRUCT_USERS_F)
|
265
|
+
|
266
|
+
# Definition derived from http://www.beginningtoseethelight.org/ntsecurity/#D3BC3F5643A17823
|
267
|
+
# \HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\%RID%\V (fixed length, 80)
|
268
|
+
SAM_STRUCT_USERS_V_HEADER = [
|
269
|
+
'a12', nil, # UNKNOWN
|
270
|
+
'I', 'username_offset', # Offset to username in V data section
|
271
|
+
'I', 'username_length', # Length of username in V data section
|
272
|
+
'a4', nil, # UNKNOWN
|
273
|
+
'I', 'fullname_offset', # Offset to fullname in V data section
|
274
|
+
'I', 'fullname_length', # Length of fullname in V data section
|
275
|
+
'a4', nil, # UNKNOWN
|
276
|
+
'I', 'comment_offset', # Offset to comment in V data section
|
277
|
+
'I', 'comment_length', # Length of comment in V data section
|
278
|
+
'a4', nil, # UNKNOWN
|
279
|
+
'I', 'user_comment_offset', # Offset to user comment in V data section
|
280
|
+
'I', 'user_comment_length', # Length of user comment in V data section
|
281
|
+
'a4', nil, # UNKNOWN
|
282
|
+
'I', 'unknown1_offset', # Offset to unknown1 in V data section
|
283
|
+
'I', 'unknown1_length', # Length of unknown1 in V data section
|
284
|
+
'a4', nil, # UNKNOWN
|
285
|
+
'I', 'homedir_offset', # Offset to homedir in V data section
|
286
|
+
'I', 'homedir_length', # Length of homedir in V data section
|
287
|
+
'a4', nil, # UNKNOWN
|
288
|
+
'I', 'homedir_conn_offset', # Offset to homedir connect in V data section
|
289
|
+
'I', 'homedir_conn_length', # Length of homedir connect in V data section
|
290
|
+
'a4', nil, # UNKNOWN
|
291
|
+
'I', 'script_path_offset', # Offset to script path in V data section
|
292
|
+
'I', 'script_path_length', # Length of script path in V data section
|
293
|
+
'a4', nil, # UNKNOWN
|
294
|
+
'I', 'profile_path_offset', # Offset to profile path in V data section
|
295
|
+
'I', 'profile_path_length', # Length of profile path in V data section
|
296
|
+
'a4', nil, # UNKNOWN
|
297
|
+
'I', 'workstations_offset', # Offset to workstations in V data section
|
298
|
+
'I', 'workstations_length', # Length of workstations in V data section
|
299
|
+
'a4', nil, # UNKNOWN
|
300
|
+
'I', 'hours_allowed_offset', # Offset to hours allowed in V data section
|
301
|
+
'I', 'hours_allowed_length', # Length of hours allowed in V data section
|
302
|
+
'a4', nil, # UNKNOWN
|
303
|
+
'I', 'unknown2_offset', # Offset to unknown2 in V data section
|
304
|
+
'I', 'unknown2_length', # Length of unknown2 in V data section
|
305
|
+
'a4', nil, # UNKNOWN
|
306
|
+
'I', 'LM_pw_hash_offset', # Offset to LM pw hash in V data section
|
307
|
+
'I', 'LM_pw_hash_length', # Length of LM pw hash in V data section
|
308
|
+
'a4', nil, # UNKNOWN
|
309
|
+
'I', 'NT_pw_hash_offset', # Offset to NT pw hash in V data section
|
310
|
+
'I', 'NT_pw_hash_length', # Length of NT pw hash in V data section
|
311
|
+
'a4', nil, # UNKNOWN
|
312
|
+
'I', 'unknown3_offset', # Offset to unknown3 in V data section
|
313
|
+
'I', 'unknown3_length', # Length of unknown3 in V data section
|
314
|
+
'a4', nil, # UNKNOWN
|
315
|
+
'I', 'unknown4_offset', # Offset to unknown4 in V data section
|
316
|
+
'I', 'unknown4_length', # Length of unknown4 in V data section
|
317
|
+
'a4', nil, # UNKNOWN
|
318
|
+
|
319
|
+
'a72', nil, # UNKNOWN (WinXP, 2003, Vista, 2008)
|
320
|
+
# 'a52', nil, # UNKNOWN (Win2K)
|
321
|
+
'I', 'num_permissions', # Number of permissions
|
322
|
+
]
|
323
|
+
SIZEOF_SAM_STRUCT_USERS_V_HEADER = BinaryStruct.sizeof(SAM_STRUCT_USERS_V_HEADER)
|
324
|
+
|
325
|
+
# Definition derived from http://www.beginningtoseethelight.org/ntsecurity/#D98C08727B08B0CB
|
326
|
+
# \HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Aliases\%RID%\C (variable length) (custom groups)
|
327
|
+
# \HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Builtin\Aliases\00000220\C (variable length) (builtin groups)
|
328
|
+
SAM_STRUCT_GROUPS_C_HEADER = [
|
329
|
+
'I', 'group_num', # Group (user) number
|
330
|
+
'a12', nil, # UNKNOWN
|
331
|
+
'I', 'group_name_offset', # Offset to group name in C data section
|
332
|
+
'I', 'group_name_length', # Length of group name in C data section
|
333
|
+
'a4', nil, # UNKNOWN
|
334
|
+
'I', 'group_desc_offset', # Offset to group description in C data section
|
335
|
+
'I', 'group_desc_length', # Length of group description in C data section
|
336
|
+
'a4', nil, # UNKNOWN
|
337
|
+
'I', 'sids_offset', # Offset to sids in C data section
|
338
|
+
'I', 'sids_length', # Length of sids in C data section
|
339
|
+
'I', 'num_users', # Number of users in sids data
|
340
|
+
'a72', nil, # UNKNOWN (WinXP, 2003, Vista, 2008)
|
341
|
+
# 'a52', nil, # UNKNOWN (Win2K)
|
342
|
+
'I', 'num_permissions', # Number of permissions
|
343
|
+
]
|
344
|
+
SIZEOF_SAM_STRUCT_GROUPS_C_HEADER = BinaryStruct.sizeof(SAM_STRUCT_GROUPS_C_HEADER)
|
345
|
+
|
346
|
+
# Definition derived from http://www.beginningtoseethelight.org/ntsecurity/#3C091C8F1BF2345C and
|
347
|
+
# http://www.beginningtoseethelight.org/ntsecurity/#B1945830FA4449A5
|
348
|
+
SAM_STRUCT_SID_HEADER = [
|
349
|
+
'C', 'part1', # First part of SID: S-[here]-?-...
|
350
|
+
'C', 'num_sections', # Number of 4-byte sections following second part of SID
|
351
|
+
'a5', nil, # UNKNOWN
|
352
|
+
'C', 'part2', # Second part of SID: S-?-[here]-...
|
353
|
+
]
|
354
|
+
SIZEOF_SAM_STRUCT_SID_HEADER = BinaryStruct.sizeof(SAM_STRUCT_SID_HEADER)
|
355
|
+
|
356
|
+
def self.rawBinaryToSids(data)
|
357
|
+
sids = []
|
358
|
+
while data && data.length > 0
|
359
|
+
# Determine the full structure for this SID
|
360
|
+
header = BinaryStruct.decode(data, SAM_STRUCT_SID_HEADER)
|
361
|
+
sam_struct_sid_footer = []
|
362
|
+
1.upto(header['num_sections']) { |x| sam_struct_sid_footer << 'I' << "section#{x}" }
|
363
|
+
sam_struct_sid = [] + SAM_STRUCT_SID_HEADER + sam_struct_sid_footer
|
364
|
+
|
365
|
+
# Get the parts and build the SID string
|
366
|
+
sid_parts = BinaryStruct.decode(data, sam_struct_sid)
|
367
|
+
sid = "S-#{sid_parts['part1']}-#{sid_parts['part2']}"
|
368
|
+
'section1'.upto("section#{sid_parts['num_sections']}") do |x|
|
369
|
+
break if sid_parts[x].nil?
|
370
|
+
sid += '-' + sid_parts[x].to_s
|
371
|
+
end
|
372
|
+
sids << sid
|
373
|
+
|
374
|
+
# Process the next SID
|
375
|
+
data = data[BinaryStruct.sizeof(sam_struct_sid)..-1]
|
376
|
+
end
|
377
|
+
sids
|
378
|
+
end
|
379
|
+
|
380
|
+
def self.regBinaryToSid(data)
|
381
|
+
rawBinaryToSids(MSRegHive.regBinaryToRawBinary(data))
|
382
|
+
end
|
383
|
+
|
384
|
+
def self.rawBinaryToRegBinary(a)
|
385
|
+
b = ''
|
386
|
+
a.each_byte { |c| b += "%02x," % c } unless a.nil?
|
387
|
+
b.chop
|
388
|
+
end
|
389
|
+
|
390
|
+
def process_users_f(data)
|
391
|
+
f = BinaryStruct.decode(MSRegHive.regBinaryToRawBinary(data), SAM_STRUCT_USERS_F)
|
392
|
+
|
393
|
+
@debug_str += " last_logon - %s - " % f['last_logon'].to_s if @debug_str
|
394
|
+
f['last_logon'] = process_users_f_date(f['last_logon'])
|
395
|
+
@debug_str += "%s\n" % (f['last_logon'].nil? ? "Never" : f['last_logon']) if @debug_str
|
396
|
+
|
397
|
+
@debug_str += " last_pw_set - %s - " % f['last_pw_set'].to_s if @debug_str
|
398
|
+
f['last_pw_set'] = process_users_f_date(f['last_pw_set'])
|
399
|
+
@debug_str += "%s\n" % (f['last_pw_set'].nil? ? "Not Change" : f['last_pw_set']) if @debug_str
|
400
|
+
|
401
|
+
@debug_str += " account_expires - %s - " % f['account_expires'].to_s if @debug_str
|
402
|
+
f['account_expires'] = process_users_f_date(f['account_expires'])
|
403
|
+
@debug_str += "%s\n" % (f['account_expires'].nil? ? "Not set to expire" : f['account_expires']) if @debug_str
|
404
|
+
|
405
|
+
@debug_str += " last_wrong_pw - %s - " % f['last_wrong_pw'].to_s if @debug_str
|
406
|
+
f['last_wrong_pw'] = process_users_f_date(f['last_wrong_pw'])
|
407
|
+
@debug_str += "%s\n" % (f['last_wrong_pw'].nil? ? "Not Wrong" : f['last_wrong_pw']) if @debug_str
|
408
|
+
|
409
|
+
@debug_str += " user_num - %s\n" % f['user_num'].to_s if @debug_str
|
410
|
+
|
411
|
+
@debug_str += " logon_ok_account_active - 0x%02x\n" % f['logon_ok_account_active'] if @debug_str
|
412
|
+
f['logon_ok'], f['account_active'] = process_users_f_logon_ok_account_active(f['logon_ok_account_active'])
|
413
|
+
@debug_str += " logon_ok - %s\n" % f['logon_ok'].to_s if @debug_str
|
414
|
+
@debug_str += " account_active - %s\n" % f['account_active'].to_s if @debug_str
|
415
|
+
|
416
|
+
@debug_str += " pw_never_expire - 0x%02x\n" % f['pw_never_expire'] if @debug_str
|
417
|
+
f['pw_never_expire'] = process_users_f_pw_never_expire(f['pw_never_expire'])
|
418
|
+
@debug_str += " pw_never_expire - %s\n" % f['pw_never_expire'].to_s if @debug_str
|
419
|
+
|
420
|
+
@debug_str += " country_code - %s - " % f['country_code'] if @debug_str
|
421
|
+
f['country_code'] = process_users_f_country_code(f['country_code'])
|
422
|
+
@debug_str += "%s\n" % (f['country_code'].nil? ? "Unknown" : f['country_code']) if @debug_str
|
423
|
+
|
424
|
+
@debug_str += " invalid_pw_count - %s\n" % f['invalid_pw_count'].to_s if @debug_str
|
425
|
+
@debug_str += " num_logons - %s\n" % f['num_logons'].to_s if @debug_str
|
426
|
+
|
427
|
+
f
|
428
|
+
end
|
429
|
+
|
430
|
+
def process_users_f_date(date)
|
431
|
+
date == 0 || date == 0x7FFFFFFFFFFFFFFF ? nil : MSRegHive.wtime2time(date)
|
432
|
+
end
|
433
|
+
|
434
|
+
def process_users_f_logon_ok_account_active(data)
|
435
|
+
logon_ok = data >> 4
|
436
|
+
logon_ok = case logon_ok
|
437
|
+
when 0, 2, 6, 8, 10, 12, 14 then false # Username or Password invalid
|
438
|
+
when 1, 3, 4 then true # Logon OK
|
439
|
+
when 5, 7, 13, 15 then false # Logon error message 1
|
440
|
+
when 9, 11 then false # Logon error message 2
|
441
|
+
end
|
442
|
+
|
443
|
+
account_active = data & 0x0F
|
444
|
+
account_active = case account_active
|
445
|
+
when 0 then true # Active; Password Required; Logon OK
|
446
|
+
when 4 then true # Password Not Required; Logon OK
|
447
|
+
when 2, 6, 8, 10, 12, 14 then true # Logon OK
|
448
|
+
when 1 then false # Not Active; Account Disabled / Inactive
|
449
|
+
when 3, 5, 7, 9, 11, 13, 15 then false # Account Disabled / Inactive"
|
450
|
+
end
|
451
|
+
|
452
|
+
return logon_ok, account_active
|
453
|
+
end
|
454
|
+
|
455
|
+
def process_users_f_pw_never_expire(data)
|
456
|
+
pw_never_expire = data & 0x0F
|
457
|
+
pw_never_expire = case pw_never_expire
|
458
|
+
when 0 then true # Secpol Time; Unlocking; Logon OK
|
459
|
+
when 2 then true # Never; GUI Setting; Password Never Expires; Logon OK
|
460
|
+
when 8 then true # Logon OK
|
461
|
+
when 10 then true # Password Never Expires; Logon OK
|
462
|
+
when 3, 7, 11, 15 then true # Password Never Expires; Logon Error Message"
|
463
|
+
when 1, 5, 9, 13 then false # Logon Error Message
|
464
|
+
when 6, 14 then true # Password Never Expires; Logon OK - Reset to X-4 though
|
465
|
+
when 4 then true # Lockout; Password Never Expires; Logon OK - Reset to X-4 though
|
466
|
+
when 12 then true # Logon OK - Reset to X-4 though
|
467
|
+
end
|
468
|
+
|
469
|
+
pw_never_expire
|
470
|
+
end
|
471
|
+
|
472
|
+
def process_users_f_country_code(data)
|
473
|
+
country_code = case data
|
474
|
+
when 0 then 'System Default'
|
475
|
+
when 1 then 'United States'
|
476
|
+
when 2 then 'Canada (French)'
|
477
|
+
when 3 then 'Latin America'
|
478
|
+
when 31 then 'Netherlands'
|
479
|
+
when 32 then 'Belgium'
|
480
|
+
when 33 then 'France'
|
481
|
+
when 34 then 'Spain'
|
482
|
+
when 39 then 'Italy'
|
483
|
+
when 41 then 'Switzerland'
|
484
|
+
when 44 then 'United Kingdom'
|
485
|
+
when 45 then 'Denmark'
|
486
|
+
when 46 then 'Sweden'
|
487
|
+
when 47 then 'Norway'
|
488
|
+
when 49 then 'Germany'
|
489
|
+
when 61 then 'Australia'
|
490
|
+
when 81 then 'Japan'
|
491
|
+
when 82 then 'Korea'
|
492
|
+
when 86 then 'China (PRC)'
|
493
|
+
when 88 then 'Taiwan'
|
494
|
+
when 99 then 'Asia'
|
495
|
+
when 351 then 'Portugal'
|
496
|
+
when 358 then 'Finland'
|
497
|
+
when 785 then 'Arabic'
|
498
|
+
when 972 then 'Hebrew'
|
499
|
+
end
|
500
|
+
|
501
|
+
country_code
|
502
|
+
end
|
503
|
+
|
504
|
+
def process_users_v(data)
|
505
|
+
bin = MSRegHive.regBinaryToRawBinary(data)
|
506
|
+
header_size = SIZEOF_SAM_STRUCT_USERS_V_HEADER
|
507
|
+
v = BinaryStruct.decode(bin[0...header_size], SAM_STRUCT_USERS_V_HEADER)
|
508
|
+
|
509
|
+
if @debug_str
|
510
|
+
@debug_str += " Header:\n"
|
511
|
+
@debug_str += " username_offset - 0x%08x\n" % v['username_offset']
|
512
|
+
@debug_str += " username_length - %s\n" % v['username_length'].to_s
|
513
|
+
@debug_str += " fullname_offset - 0x%08x\n" % v['fullname_offset']
|
514
|
+
@debug_str += " fullname_length - %s\n" % v['fullname_length'].to_s
|
515
|
+
@debug_str += " comment_offset - 0x%08x\n" % v['comment_offset']
|
516
|
+
@debug_str += " comment_length - %s\n" % v['comment_length'].to_s
|
517
|
+
@debug_str += " user_comment_offset - 0x%08x\n" % v['user_comment_offset']
|
518
|
+
@debug_str += " user_comment_length - %s\n" % v['user_comment_length'].to_s
|
519
|
+
@debug_str += " unknown1_offset - 0x%08x\n" % v['unknown1_offset']
|
520
|
+
@debug_str += " unknown1_length - %s\n" % v['unknown1_length'].to_s
|
521
|
+
@debug_str += " homedir_offset - 0x%08x\n" % v['homedir_offset']
|
522
|
+
@debug_str += " homedir_length - %s\n" % v['homedir_length'].to_s
|
523
|
+
@debug_str += " homedir_conn_offset - 0x%08x\n" % v['homedir_conn_offset']
|
524
|
+
@debug_str += " homedir_conn_length - %s\n" % v['homedir_conn_length'].to_s
|
525
|
+
@debug_str += " script_path_offset - 0x%08x\n" % v['script_path_offset']
|
526
|
+
@debug_str += " script_path_length - %s\n" % v['script_path_length'].to_s
|
527
|
+
@debug_str += " profile_path_offset - 0x%08x\n" % v['profile_path_offset']
|
528
|
+
@debug_str += " profile_path_length - %s\n" % v['profile_path_length'].to_s
|
529
|
+
@debug_str += " workstations_offset - 0x%08x\n" % v['workstations_offset']
|
530
|
+
@debug_str += " workstations_length - %s\n" % v['workstations_length'].to_s
|
531
|
+
@debug_str += " hours_allowed_offset - 0x%08x\n" % v['hours_allowed_offset']
|
532
|
+
@debug_str += " hours_allowed_length - %s\n" % v['hours_allowed_length'].to_s
|
533
|
+
@debug_str += " unknown2_offset - 0x%08x\n" % v['unknown2_offset']
|
534
|
+
@debug_str += " unknown2_length - %s\n" % v['unknown2_length'].to_s
|
535
|
+
@debug_str += " LM_pw_hash_offset - 0x%08x\n" % v['LM_pw_hash_offset']
|
536
|
+
@debug_str += " LM_pw_hash_length - %s\n" % v['LM_pw_hash_length'].to_s
|
537
|
+
@debug_str += " NT_pw_hash_offset - 0x%08x\n" % v['NT_pw_hash_offset']
|
538
|
+
@debug_str += " NT_pw_hash_length - %s\n" % v['NT_pw_hash_length'].to_s
|
539
|
+
@debug_str += " unknown3_offset - 0x%08x\n" % v['unknown3_offset']
|
540
|
+
@debug_str += " unknown3_length - %s\n" % v['unknown3_length'].to_s
|
541
|
+
@debug_str += " unknown4_offset - 0x%08x\n" % v['unknown4_offset']
|
542
|
+
@debug_str += " unknown4_length - %s\n" % v['unknown4_length'].to_s
|
543
|
+
@debug_str += " num_permissions - %s\n" % v['num_permissions'].to_s
|
544
|
+
end
|
545
|
+
|
546
|
+
# Build middle section based on the num_permissions
|
547
|
+
sam_struct_users_v_middle = []
|
548
|
+
|
549
|
+
# Do a sanity check for the permissions section
|
550
|
+
return nil if v['num_permissions'] > 100 || v['num_permissions'] <= 0
|
551
|
+
|
552
|
+
sect_start = header_size
|
553
|
+
'perm1'.upto("perm#{v['num_permissions']}") do |sect_name|
|
554
|
+
bin_data = bin[sect_start + 2...sect_start + 4]
|
555
|
+
return nil if bin_data.nil?
|
556
|
+
sect_size = bin_data.unpack('S')[0]
|
557
|
+
|
558
|
+
sam_struct_users_v_middle += [
|
559
|
+
'a2', nil, # UNKNOWN
|
560
|
+
'S', "#{sect_name}_length", # Length of block for permissions?
|
561
|
+
'a4', "#{sect_name}_perms", # Permissions
|
562
|
+
"a#{sect_size - 8}", "#{sect_name}_sid", # SID
|
563
|
+
]
|
564
|
+
|
565
|
+
sect_start += sect_size
|
566
|
+
end
|
567
|
+
|
568
|
+
sam_struct_users_v_middle += [
|
569
|
+
'a16', 'admins_group_sidA', # Administrators group SID
|
570
|
+
'a16', 'admins_group_sidB', # Administrators group SID again
|
571
|
+
]
|
572
|
+
|
573
|
+
# Build footer section based on sizes in header section
|
574
|
+
sam_struct_users_v_footer = [
|
575
|
+
'a%d' % v['username_length'], 'username',
|
576
|
+
'a%d' % (v['fullname_offset'] - v['username_offset'] - v['username_length']), nil,
|
577
|
+
'a%d' % v['fullname_length'], 'fullname',
|
578
|
+
'a%d' % (v['comment_offset'] - v['fullname_offset'] - v['fullname_length']), nil,
|
579
|
+
'a%d' % v['comment_length'], 'comment',
|
580
|
+
'a%d' % (v['user_comment_offset'] - v['comment_offset'] - v['comment_length']), nil,
|
581
|
+
'a%d' % v['user_comment_length'], 'user_comment',
|
582
|
+
'a%d' % (v['unknown1_offset'] - v['user_comment_offset'] - v['user_comment_length']), nil,
|
583
|
+
'a%d' % v['unknown1_length'], 'unknown1',
|
584
|
+
'a%d' % (v['homedir_offset'] - v['unknown1_offset'] - v['unknown1_length']), nil,
|
585
|
+
'a%d' % v['homedir_length'], 'homedir',
|
586
|
+
'a%d' % (v['homedir_conn_offset'] - v['homedir_offset'] - v['homedir_length']), nil,
|
587
|
+
'a%d' % v['homedir_conn_length'], 'homedir_conn',
|
588
|
+
'a%d' % (v['script_path_offset'] - v['homedir_conn_offset'] - v['homedir_conn_length']), nil,
|
589
|
+
'a%d' % v['script_path_length'], 'script_path',
|
590
|
+
'a%d' % (v['profile_path_offset'] - v['script_path_offset'] - v['script_path_length']), nil,
|
591
|
+
'a%d' % v['profile_path_length'], 'profile_path',
|
592
|
+
'a%d' % (v['workstations_offset'] - v['profile_path_offset'] - v['profile_path_length']), nil,
|
593
|
+
'a%d' % v['workstations_length'], 'workstations',
|
594
|
+
'a%d' % (v['hours_allowed_offset'] - v['workstations_offset'] - v['workstations_length']), nil,
|
595
|
+
'a%d' % v['hours_allowed_length'], 'hours_allowed',
|
596
|
+
'a%d' % (v['unknown2_offset'] - v['hours_allowed_offset'] - v['hours_allowed_length']), nil,
|
597
|
+
'a%d' % v['unknown2_length'], 'unknown2',
|
598
|
+
'a%d' % (v['LM_pw_hash_offset'] - v['unknown2_offset'] - v['unknown2_length']), nil,
|
599
|
+
'a%d' % v['LM_pw_hash_length'], 'LM_pw_hash',
|
600
|
+
'a%d' % (v['NT_pw_hash_offset'] - v['LM_pw_hash_offset'] - v['LM_pw_hash_length']), nil,
|
601
|
+
'a%d' % v['NT_pw_hash_length'], 'NT_pw_hash',
|
602
|
+
'a%d' % (v['unknown3_offset'] - v['NT_pw_hash_offset'] - v['NT_pw_hash_length']), nil,
|
603
|
+
'a%d' % v['unknown3_length'], 'unknown3',
|
604
|
+
'a%d' % (v['unknown4_offset'] - v['unknown3_offset'] - v['unknown3_length']), nil,
|
605
|
+
'a%d' % v['unknown4_length'], 'unknown4',
|
606
|
+
]
|
607
|
+
|
608
|
+
struct_sam_users_v = [] + SAM_STRUCT_USERS_V_HEADER + sam_struct_users_v_middle + sam_struct_users_v_footer
|
609
|
+
v = BinaryStruct.decode(bin, struct_sam_users_v)
|
610
|
+
|
611
|
+
@debug_str += " Middle:\n" if @debug_str
|
612
|
+
|
613
|
+
'perm1'.upto("perm#{v['num_permissions']}") do |sect_name|
|
614
|
+
# Clean up the SID values
|
615
|
+
v["#{sect_name}_sid"] = Accounts.rawBinaryToSids(v["#{sect_name}_sid"])[0]
|
616
|
+
|
617
|
+
if @debug_str
|
618
|
+
@debug_str += " #{sect_name}_length#{' ' * (9 - sect_name.length + 5)}- %s\n" % v["#{sect_name}_length"].to_s
|
619
|
+
@debug_str += " #{sect_name}_perms#{' ' * (9 - sect_name.length + 6)}- %s\n" % Accounts.rawBinaryToRegBinary(v["#{sect_name}_perms"])
|
620
|
+
@debug_str += " #{sect_name}_sid#{' ' * (9 - sect_name.length + 8)}- %s\n" % v["#{sect_name}_sid"].to_s
|
621
|
+
end
|
622
|
+
end
|
623
|
+
if @debug_str
|
624
|
+
@debug_str += " admins_group_sidA - %s\n" % Accounts.rawBinaryToSids(v['admins_group_sidA'])
|
625
|
+
@debug_str += " admins_group_sidB - %s\n" % Accounts.rawBinaryToSids(v['admins_group_sidB'])
|
626
|
+
end
|
627
|
+
|
628
|
+
# Clean up Unicode string fields
|
629
|
+
v['username'].UnicodeToUtf8!.tr!("\0", "")
|
630
|
+
v['username'] = nil if v['username'].length == 0
|
631
|
+
v['fullname'].UnicodeToUtf8!.tr!("\0", "")
|
632
|
+
v['fullname'] = nil if v['fullname'].length == 0
|
633
|
+
v['comment'].UnicodeToUtf8!.tr!("\0", "")
|
634
|
+
v['comment'] = nil if v['comment'].length == 0
|
635
|
+
v['user_comment'].UnicodeToUtf8!.tr!("\0", "")
|
636
|
+
v['user_comment'] = nil if v['user_comment'].length == 0
|
637
|
+
v['homedir'].UnicodeToUtf8!.tr!("\0", "")
|
638
|
+
v['homedir'] = nil if v['homedir'].length == 0
|
639
|
+
v['homedir_conn'].UnicodeToUtf8!.tr!("\0", "")
|
640
|
+
v['homedir_conn'] = nil if v['homedir_conn'].length == 0
|
641
|
+
v['script_path'].UnicodeToUtf8!.tr!("\0", "")
|
642
|
+
v['script_path'] = nil if v['script_path'].length == 0
|
643
|
+
v['profile_path'].UnicodeToUtf8!.tr!("\0", "")
|
644
|
+
v['profile_path'] = nil if v['profile_path'].length == 0
|
645
|
+
v['workstations'].UnicodeToUtf8!.tr!("\0", "")
|
646
|
+
v['workstations'] = nil if v['workstations'].length == 0
|
647
|
+
|
648
|
+
if @debug_str
|
649
|
+
@debug_str += " Footer:\n"
|
650
|
+
@debug_str += " username - '%s'\n" % v['username']
|
651
|
+
@debug_str += " fullname - '%s'\n" % v['fullname']
|
652
|
+
@debug_str += " comment - '%s'\n" % v['comment']
|
653
|
+
@debug_str += " user_comment - '%s'\n" % v['user_comment']
|
654
|
+
@debug_str += " unknown1 - '%s'\n" % v['unknown1']
|
655
|
+
@debug_str += " homedir - '%s'\n" % v['homedir']
|
656
|
+
@debug_str += " homedir_conn - '%s'\n" % v['homedir_conn']
|
657
|
+
@debug_str += " script_path - '%s'\n" % v['script_path']
|
658
|
+
@debug_str += " profile_path - '%s'\n" % v['profile_path']
|
659
|
+
@debug_str += " workstations - '%s'\n" % v['workstations']
|
660
|
+
@debug_str += " hours_allowed - '%s'\n" % v['hours_allowed']
|
661
|
+
@debug_str += " unknown2 - '%s'\n" % v['unknown2']
|
662
|
+
@debug_str += " LM_pw_hash - %s\n" % Accounts.rawBinaryToRegBinary(v['LM_pw_hash'])
|
663
|
+
@debug_str += " NT_pw_hash - %s\n" % Accounts.rawBinaryToRegBinary(v['NT_pw_hash'])
|
664
|
+
@debug_str += " unknown3 - '%s'\n" % v['unknown3']
|
665
|
+
@debug_str += " unknown4 - '%s'\n" % v['unknown4']
|
666
|
+
|
667
|
+
@debug_str += "\n\n"
|
668
|
+
end
|
669
|
+
|
670
|
+
v
|
671
|
+
end
|
672
|
+
|
673
|
+
def process_groups_c(data)
|
674
|
+
bin = MSRegHive.regBinaryToRawBinary(data)
|
675
|
+
header_size = SIZEOF_SAM_STRUCT_GROUPS_C_HEADER
|
676
|
+
c = BinaryStruct.decode(bin, SAM_STRUCT_GROUPS_C_HEADER)
|
677
|
+
|
678
|
+
if @debug_str
|
679
|
+
@debug_str += " Header:\n"
|
680
|
+
@debug_str += " group_num - %s\n" % c['group_num']
|
681
|
+
@debug_str += " group_name_offset - 0x%08x\n" % c['group_name_offset']
|
682
|
+
@debug_str += " group_name_length - %s\n" % c['group_name_length']
|
683
|
+
@debug_str += " group_desc_offset - 0x%08x\n" % c['group_desc_offset']
|
684
|
+
@debug_str += " group_desc_length - %s\n" % c['group_desc_length']
|
685
|
+
@debug_str += " sids_offset - 0x%08x\n" % c['sids_offset']
|
686
|
+
@debug_str += " sids_length - %s\n" % c['sids_length']
|
687
|
+
@debug_str += " num_users - %s\n" % c['num_users']
|
688
|
+
@debug_str += " num_permissions - %s\n" % c['num_permissions']
|
689
|
+
end
|
690
|
+
|
691
|
+
# Build middle section based on the num_permissions
|
692
|
+
sam_struct_groups_c_middle = []
|
693
|
+
|
694
|
+
# Do a sanity check for the permissions section
|
695
|
+
return nil if c['num_permissions'] > 100 || c['num_permissions'] <= 0
|
696
|
+
|
697
|
+
sect_start = header_size
|
698
|
+
'perm1'.upto("perm#{c['num_permissions']}") do |sect_name|
|
699
|
+
sect_size = bin[sect_start + 2...sect_start + 4].unpack('S')[0]
|
700
|
+
|
701
|
+
sam_struct_groups_c_middle += [
|
702
|
+
'a2', nil, # UNKNOWN
|
703
|
+
'S', "#{sect_name}_length", # Length of block for permissions?
|
704
|
+
'a4', "#{sect_name}_perms", # Permissions
|
705
|
+
"a#{sect_size - 8}", "#{sect_name}_sid", # SID
|
706
|
+
]
|
707
|
+
|
708
|
+
sect_start += sect_size
|
709
|
+
end
|
710
|
+
|
711
|
+
sam_struct_groups_c_middle += [
|
712
|
+
'a16', 'admins_group_sidA', # Administrators group SID
|
713
|
+
'a16', 'admins_group_sidB', # Administrators group SID again
|
714
|
+
]
|
715
|
+
|
716
|
+
# Build footer section based on sizes in header section
|
717
|
+
sam_struct_groups_c_footer = [
|
718
|
+
'a%d' % c['group_name_length'], 'group_name',
|
719
|
+
'a%d' % (c['group_desc_offset'] - c['group_name_offset'] - c['group_name_length']), nil,
|
720
|
+
'a%d' % c['group_desc_length'], 'group_desc',
|
721
|
+
'a%d' % (c['sids_offset'] - c['group_desc_offset'] - c['group_desc_length']), nil,
|
722
|
+
'a%d' % c['sids_length'], 'sids'
|
723
|
+
]
|
724
|
+
|
725
|
+
sam_struct_groups_c = [] + SAM_STRUCT_GROUPS_C_HEADER + sam_struct_groups_c_middle + sam_struct_groups_c_footer
|
726
|
+
c = BinaryStruct.decode(bin, sam_struct_groups_c)
|
727
|
+
|
728
|
+
@debug_str += " Middle:\n" if @debug_str
|
729
|
+
'perm1'.upto("perm#{c['num_permissions']}") do |sect_name|
|
730
|
+
# Clean up the SID values
|
731
|
+
c["#{sect_name}_sid"] = Accounts.rawBinaryToSids(c["#{sect_name}_sid"])[0]
|
732
|
+
|
733
|
+
if @debug_str
|
734
|
+
@debug_str += " #{sect_name}_length#{' ' * (9 - sect_name.length + 2)}- %s\n" % c["#{sect_name}_length"].to_s
|
735
|
+
@debug_str += " #{sect_name}_perms#{' ' * (9 - sect_name.length + 3)}- %s\n" % Accounts.rawBinaryToRegBinary(c["#{sect_name}_perms"])
|
736
|
+
@debug_str += " #{sect_name}_sid#{' ' * (9 - sect_name.length + 5)}- %s\n" % c["#{sect_name}_sid"].to_s
|
737
|
+
end
|
738
|
+
end
|
739
|
+
if @debug_str
|
740
|
+
@debug_str += " admins_group_sidA - %s\n" % Accounts.rawBinaryToSids(c['admins_group_sidA'])
|
741
|
+
@debug_str += " admins_group_sidB - %s\n" % Accounts.rawBinaryToSids(c['admins_group_sidB'])
|
742
|
+
end
|
743
|
+
|
744
|
+
# Clean up Unicode string fields
|
745
|
+
c['group_name'].UnicodeToUtf8!.tr!("\0", "")
|
746
|
+
c['group_name'] = nil if c['group_name'].length == 0
|
747
|
+
c['group_desc'].UnicodeToUtf8!.tr!("\0", "")
|
748
|
+
c['group_desc'] = nil if c['group_desc'].length == 0
|
749
|
+
|
750
|
+
# Clean up SID values
|
751
|
+
c['sids'] = Accounts.rawBinaryToSids(c['sids'])
|
752
|
+
|
753
|
+
if @debug_str
|
754
|
+
@debug_str += " Footer:\n"
|
755
|
+
@debug_str += " group_name - '%s'\n" % c['group_name']
|
756
|
+
@debug_str += " group_desc - '%s'\n" % c['group_desc']
|
757
|
+
@debug_str += " sids - #{c['sids'].length == 0 ? "None" : "%s#{"\n %s" * (c['sids'].length - 1)}" % c['sids']}\n"
|
758
|
+
@debug_str += "\n\n"
|
759
|
+
end
|
760
|
+
|
761
|
+
c
|
762
|
+
end
|
763
|
+
end
|
764
|
+
end
|