📜 ⬆️ ⬇️

Algorithm for streamlining logical volumes in the Windows OS environment, part 2

Algorithm for streamlining logical volumes in the Windows OS environment, part 2

In the first part of the publication, the principles for implementing the algorithm were outlined, the competitive results of the sequential execution of the prototype code and diskpart.exe were given.
This part provides a brief description of each of the four steps of the algorithm, demonstrates strict adherence to the principles proclaimed in the first part. The sources of information used are given.

How the algorithm stores the data.
')
During the four steps of the algorithm, three collections are created that contain objects representing Storage Devices, the DevicesCollection, is created by the very first, in Step 1, and is constantly used in all subsequent steps to refer to the parent object. In step 2, a StorageVolumesCollection is created, and in step 3, a LogicalVolumesCollection is created. All collections are organized according to a single principle: all stored objects are indexed and in order to refer directly to the stored object, you simply need to refer to XXXXXCollection [index], where XXXXX: {Devices, StorageVolumes, LogicalVolumes}, and the index is any integer in the range [0, XXXXXCollection.Count]. The Count property contains the number of objects of the corresponding type in the collection.

Device description strings stored in a binary Data blob do not contain a DeviceGUID not only for DVD-ROM, but also for Removables. The mentioned binary blob contains detailed characteristics of the logical volume and is addressed to the Registry by:
HKU \ SID \ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ MountPoints2 \ CPC \ Volume \ GUID, where GUID is the VolumeGUID, SID is the Security Identifier of the current user. In this regard, the DevicesCollection and LogicalVolumesCollection collections contain “direct access keys” both in the form of short 8-character DeviceGUID.F1 and long, unpredictable length for DVD-ROM and Removables. Direct access keys return the index of the object corresponding to the specified key. Thus, using the long key, PnPDeviceID, to access the DevicesCollection, you can get the index of the parent device. This index is immediately assigned as the value of the ParentIndex property to that object of type StorageVolume or LogicalVolume, which must be placed in its own collection.


Description of the first step of the algorithm: creating a DevicesCollection.

Information sources:
1. Enumerations created by the cdrom and partmgr services. The hard worker partmgr not only receives information from several device drivers and performs its main task - creating an enumeration of memory volumes, in addition creates an enumeration of all devices except those serviced by the cdrom service. It is clear that we are talking about reading all REG_SZ values ​​by paths:
HKLM \ SYSTEM \ CurrentControlSet \ Services \ cdrom and
HKLM \ SYSTEM \ CurrentControlSet \ Services \ partmrg.

2. Extraction of detailed information about devices on the basis of PnPDeviceID. The time has come to supplement the description of PnPDeviceID, presented in the first part, with the mention that PnPDeviceID necessarily contains as a prefix to the device description line, another prefix indicating the interface according to which the device is connected. And I can’t say for sure whether this prefix is ​​attributed by Windows to the device description provided by the manufacturer or by the manufacturer itself. In any case, the PnPDeviceID provides accurate information on which way to read the detailed data from
HKLM \ SYSTEM \ CurrentControlSet \ Enum. Let us demonstrate this most important source of information about devices, screen shot.



Figure 4

In addition to HKLM \ SYSTEM \ CurrentControlSet \ Enum \ PnPDeviceID, two more ways are additionally used:
HKLM \ SYSTEM \ CurrentControlSet \ Enum \ PnPDeviceID \ Device Parameters \ Partmgr, which contains the value of the most important property DiskId, which was previously mentioned as DevGUID.
Once again we recall that for devices serviced by the cdrom service, DiskId is not created and therefore the algorithm sets the DevID property to the PnPDeviceID value with “\” characters replaced with “#”.

HKLM \ SYSTEM \ CurrentControlSet \ Enum \ PnPDeviceID \ Device Parameters \ Storport contains the InitialTimestamp, the date of manufacture of the device by the manufacturer in the format REG_QWORD.

Additional sources of information solely for internal disks are:

HKLM \ HARDWARE \ DESCRIPTION \ System \ MultifunctionAdapter \ 0 \ DiskController \ 0 \ DiskPeripheral
HKLM \ HARDWARE \ DEVICEMAP \ Scsi \ Scsi Port 1 \ Scsi Bus 0 \ Target Id 0 \ Logical Unit Id M.

For the first path, the REG_SZ Identifier property is read, which represents the disk signature for Mbr-formatted disks, and contains zeros for Mpt-formatted disks, which means that the disk contains Gpt-formatted partitions. This is very important information for the algorithm, but unfortunately, this information is available only for internal disks.

After the object representing the data storage device is fully endowed with all the properties read from the Registry and additional properties needed by the algorithm, the object is endowed with the most important property of the OrderIndex, whose value is set to DevicesCollection.Count. After that, the object is placed in the collection at an index equal to the value of the collection property Count and Count is incremented.

Additionally, direct access keys are created for all Removables and DVD-ROM, as well as group properties are initialized, the real values ​​of which are set in the second and third steps. Here we list these properties:

LVGroupStyle - formatting style, possible values ​​Mbr, Gpt.
NumberOfLV is the number of logical volumes located on device partitions.
LVGroup - list of logical volume offsets
NumberOfSV - the number of sections, Storage # Volume, placed on the device
SVGroup - section offset list

Description of the second step of the algorithm: creating a StorageVolumesCollection

Information sources:

1. HKLM \ SYSTEM \ CurrentControlSet \ services \ volsnap \ Enum Enumeration
MUST provide an ordered list of Storage # Volume, memory volumes. However, incidents happen even in such a licked system as Windows 8.1. It's time to demonstrate the saved fragment of the Registry, stored with the name of the file BecameCrazy-volsnap.reg. Here is a snippet from this file.

[HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ volsnap \ Enum]
"0" = "STORAGE \\ Volume \\ _ ?? _ SD # DISK & Generic & SA08G & 0.4 # 6 & 447d92 & 0 & 9c053461 # {53f56307-b6bf-11d0-94f2-00a0c91efb8b}"
"Count" = dword: 00000011
“NextInstance” = dword: 00000011
"1" = "STORAGE \\ Volume \\ {714ce426-d2a2-11e4-824f-806e6f6e6963} # 0000000000007E00"
"2" = "STORAGE \\ Volume \\ {714ce426-d2a2-11e4-824f-806e6f6e6963} # 0000000016260000"

Note the string “0” corresponding to the SD card. How this index was assigned to this card can be explained by the fact that a failure occurred while reading the second partition of the first internal disk, the system handled the failure, set the Dirty bit for the partition and therefore the partmgr report on the memory volume on the SD card was ahead of the volume reports memory on internal drives. To its credit, the system should clarify that it happened only once, I can even name the exact date - July 01, 2015.

But it's easier not to complain about unexpected glitches, but to create algorithms that allow you to work correctly regardless of surprises. Therefore, the incident forced the immediate revision of the algorithm: if earlier the algorithm completely trusted the order of the lines read along the specified path, then after the incident, the principle of independent ordering was laid into the algorithm in accordance with the parent index and its own offset.

The same principle applies in step 3 when creating a collection of logical volumes, and it guarantees that the ordering will be correct, unless it also starts to “fool” the partmgr service and offsets will no longer flow in ascending order. It is this (violation of the order of displacements) that happened under Windows 10 RTM TH1, in which, as already mentioned, the Volume GUID ordering algorithm was changed. Naturally, in the beginning, this made me stormy emotions and all sorts of unfriendly words addressed to MS programmers: it’s not that the algorithm used stops working, but an unordered list of offsets for LVGroup really hurt my eyes. And only a couple of hours later I realized what caused this change in the algorithm, what it brought and from that moment I only sing the praises to the author of the idea of ​​the new ordering algorithm.
2. HKLM \ SYSTEM \ CurrentControlSet \ Enum \ STORAGE \ Volume \ _ ?? _SD # DISK & Generic & SA08G & 0.4 # 6 & 447d92 & 0 & 9c053461 & 0 # {53f56307-b6bf-11d0-94f2-00a0c91efb8b}

It contains the following properties:
"Capabilities" = dword: 000000b0
"ContainerID" = "{33b560f6-21b5-11e5-b2ff-806e6f6e6963}"
"HardwareID" = hex (7): 530054004f0052004100470045005c0056006f006c0075006d00650000000000
"ClassGUID" = "{71a27cdd-812a-11d0-bec7-08002be2092f}"
"Service" = "volsnap"
"DeviceDesc" = "@ volume.inf,% storage \\ volume.devicedesc%; Generic volume"
“Driver” = "{71a27cdd-812a-11d0-bec7-08002be2092f} \\ 0000"
"Mfg" = "@ volume.inf,% msft%; Microsoft"
"ConfigFlags" = dword: 00000000

Most of these properties can be pre-written with pens. Interest was represented only by ContainerID, a unique property, but it was too lazy to waste time searching for the application of this GUID, most likely representing the GUID of the driver. So I'm not sure that it makes sense to spend precious milliseconds to read these properties. It is much more important to immediately associate the object represented by the line describing the memory volume with the parent device. Therefore, even before the information from the HKLM \ SYSTEM \ CurrentControlSet \ Enum \ STORAGE \ Volume \ is read, the text string describing the memory volume is analyzed to determine the values ​​of the following properties:

Type = {“Partition”, “Removable”},
Subtype = {“SD”, “Flash”, “Virtual”},
Offset, DevID

The last of the properties is set to the F1 GUID field preceding the offset for Type = ”Partition”. Otherwise, the prefix “STORAGE \ Volume \” and the suffix “# {53f56307-b6bf-11d0-94f2-00a0c91efb8b}” are truncated, so the above line from the file named “crazy” for the SD card turns into:

_ ?? SD # DISK & Generic & SA08G & 0.4 # 6 & 447d92 & 0 & 9c053461 & 0

This string is assigned as a DevID property. Well, then the most important property for any of the “children”, the definition of the parent device is calculated:

obj.ParentIndex = DevicesCollection [obj.DevID]

Knowing the index of the parent device, it is possible for Removables to recognize the DevGUID parent, or rather the DevGUID algorithm is not needed, but only the F1 field value from DevGUID is needed. This value of the parent stores as the value of its own DCUniqueID property. Knowing the parent DCUniqueID, you can form the beginning of your own unique identifier:

obj.SVUniqueID = DevicesCollection [obj.ParentIndex] .DCUniqueID + obj.Offset

For “Partition” memory volumes, the real offset is used, and for memory volumes located on Removables, the offset is set to “00000000”.
Now you can update the properties of the parent object, describing the SVGroup and the number of memory volumes located on the parent device. That is, increment the DevicesCollection [obj.parentIndex] .NumberOfSV counter and include the offset of the current object in the DevicesCollection [obj.parentIndex] .SVGroup counter.

Completely similar actions are performed in step three, in relation to logical volumes.

Now let me remind you that we are in the cycle of processing the rows read from the enumeration. We have already defined all the necessary properties of the object of the StorageVolumesCollection class, but bearing in mind that we cannot trust the correctness of the enumeration, we will save the object not in the target collection, but in a simple, temporary one. But the current object is generally a member of the group, and therefore, by the parent index in the temporary collection, it is not the object itself that is allocated, but a group of objects, each of which has the same parent.

Upon completion of the enumeration reading cycle, we have the opportunity to create a properly-ordered target StorageVolemesCollection collection. To do this, we will loop through the parent collection, the DevicesCollection, and several short nested loops in groups that have the same parent. Inside the loop, we place objects from the temporary collection into the StorageVolumesCollection, using StorageVolumesCollection.Count as the index and incrementing this property after placing the object. StorageVolumesCollection is the easiest to form, it does not need to create additional direct access keys.

Description of the third step of the algorithm: creating a LogicalVolumesCollection

Information sources:

Enumeration
HKU \ SID \ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ MountPoints2 \ CPC \ Volume \ GUID

where the GUID is the VolumeGUID, the SID is the Security Identifier of the current user, provides a VolumeGUID list, and the content of a binary blob with the name Data, addressed by the specified key, contains detailed data. The Blob Data has a rather complex structure containing both UTF-16 text strings and binary data. In addition, the size and offset of text fields inside this blob depend on the version of Windows that is lower than build 9600 or older. In the prototype code, the GetBlobs function performs the disassembly of the content of this blob. The algorithm used is constructed in such a way that there is no dependency on the Windows version, no already known text field offsets are used. To the above, when describing step two, I will add only that in this case devices like DVD-ROM are not ignored, since they contain a logical volume.

In step three, the creation of direct access keys of the form is crucial:

for Mbr-formatted: disk signature + offset
for Mbr-formatted: VolGUID.F1 + offset
for gpt-formatted: VolumeGUID.F1

However, at the moment when the object processing cycle is performed for inclusion in the LogicalVolumesCollection collection, no signature for USB drives is known yet and, besides, the Mbr / Gpt formatting styles for both partitions on VHDs and external drives are unknown.

Therefore, it is worth mentioning a special type of VolumeGUID, which appeared originally in the WMI class MSFT_Volume in the Path field, where, along with the actual VolumeGUID, there was also a dummy format {1036c1c4-0000-0000-007e-000000000000}. Then, in one of the assemblies, maybe even 9926, such a GUID format appeared and existed in all assemblies from 9879 to 10166, but in 10240 it disappeared again due to the change in the generation algorithm for VolumeGUID.

I mention this format because the F1 field of this GUID is a disk signature, and the F4, F5 fields is the offset of the logical volume. So, having found such a VolumeGUID in the system, it became possible to assign unique keys of direct access to the LogicalVolumesCollection objects to all LVGroup members. Another reason why I mention the VolumeGUID format given here is that despite the undoubtedly revolutionary idea of ​​streamlining the VolumeGUID in accordance with the mounting order of logical volumes, first introduced in build 10240, the algorithm for generating GUIDs themselves was unsuccessful in the sense that for Mbr-disks having four partitions and, respectively, four logical volumes, the last two arrive in the WRONG order: the latter has a LESS offset than the last one.

Such a serious accusation must be proved by facts, therefore the content of the Data blob for the penultimate “child” is given below, Offset = 000020789000000

Windows Registry Editor Version 5.00

[HKEY_USERS \ S-1-5-21-1478854878-1022661374-1075113013-1004 \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Explorer
\ MountPoints2 \ CPC \ Volume \ {714ce432-d2a2-11e4-824f-806e6f6e6963}]
"Data" = hex: 000000000df0adba0100000008000000000000800000 \
0000000000300000000000000000ff00e703ff000000160000 \
0026980b421f000000040000000000000000000000000000 \
0000000000005c005c003f005c00530054004f005200410047 \ \ \? \ \ STORAG
004500230056006f006c0075006d00650023007b0037003100 \ E # Volume # {71
3400630065003400320036002d0064003200610032002d0031 \ 4ce426-d2a2-1
003100650034002d0038003200340066002d00380030003600 \ 1e4-824f-806
6500360066003600650036003900360033007d002300300030 \ f6e6963} # 00
00300030003000300032003000370038003900300030003000 \ 0000207890000
3000300023007b00350033006600350036003300300064002d \ 00 # {5
0062003600620066002d0031003100640030002d0039003400 \
660032002d0030003000610030006300390031006500660062 \

And now the content of the Data blob for the last “child”, Offset = 000000001620000

Windows Registry Editor Version 5.00

[HKEY_USERS \ S-1-5-21-1478854878-1022661374-1075113013-1004 \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Explorer \
MountPoints2 \ CPC \ Volume \ {f0fd3322-2d89-11e5-82e0-806e6f6e6963}]
"Data" = hex: 000000000df0adba0100000008000000000000800000 \
0000000000300000000000000000ff00e703ff000000160000 \
00cd14ff0e1f000000040000000000000000000000000000 \
0000000000005c005c003f005c00530054004f005200410047 \ \ \? \ \ STORAG
004500230056006f006c0075006d00650023007b0037003100 \ E # Volume # {71
3400630065003400320036002d0064003200610032002d0031 \ 4ce426-d2a2-1
003100650034002d0038003200340066002d00380030003600 \ 1e4-824a-806
6500360066003600650036003900360033007d002300300030 \ e6f6e963} # 00
00300030003000300030003000310036003200360030003000 \ 000000162600
3000300023007b00350033006600350036003300300064002d \ 00 # {5
0062003600620066002d0031003100640030002d0039003400 \
660032002d0030003000610030006300390031006500660062 \
00380062007d000000000000000000000000000000000000 \

And, finally, a snapshot of the Registry branch containing the above VolumeGUIDs to prove that I was not mistaken in the order of the children.



In conclusion, it is worth noting that at the end of the cycle on objects intended for placement in a collection of logical volumes, we have the opportunity to finally understand the formatting styles of partitions on external disks and on VHD. To do this, it is enough to compare the values ​​of the NumberOfSV and NumberOfLV properties. The coincidence of the values ​​clearly indicates that the partitions on the disk have the Mbr formatting style, but the NumberOfLV <NumberOfSV uniquely indicates the Gpt formatting style, since the first of the Gpt partitions, MSR, cannot contain a logical volume.

Description of the fourth step of the algorithm: assignment of letters to logical volumes

Source of information: HKLM \ SYSTEM \ MountedDevices

Even novice Windows users are well aware of this path, which stores, but along with the necessary information, there is also a lot of completely unnecessary. This is especially true of USB-flash drives, as well as phones, most of which are now equipped with micro-SD. Information about all such devices clogs MountedDevices very quickly. It should be borne in mind that each of such devices in MountedDevices has two entries: one in which the name field has the value \ ?? \ Volume \ VolumeGUID and the second in which the name field has the value of the format \ DosDevices \ Q :. The value field for both records has a very long hexadecimal text, representing in UTF-16 the well-known PnPDeviceID already known to us, and in the format with “\” replaced by “#”. Such direct access keys were created in the LogicalVolumesCollection and therefore it becomes easy and simple to filter out unnecessary Removables.

All of the above applies to disk partitions, both internal and external: you changed one of your internal disks, but information about all its sections continues to be stored in MountedDevices until you install, for example, Windows from scratch, there is not destroy the existing Registry, and with all the updates, the content of MountedDevices will move from the updated system to the updated one.

Now how can we distinguish logical volumes corresponding to Mbr-formatted disks and Gpt-formatted ones by the values ​​of the value field in the MountedDevices records? It is extremely simple: if the value field has a length of 24 characters, then it is a Signature, the signature of the parent disk, 8 characters and an offset, 16 characters.

LogicalVolumesCollection , Signature Offset, , . , , , LogicalVolumesCollection.

MountedDevices \DosDevices\x:, , , , VolumeGUID.F1 + value. VolumeGUID.F1 + , , + .

Gpt- . value 48 , 16 , 8- utf-16 32 16- , QWORD, VolumeGUID. :

String.prototype.ConvertQWORD = function()// converts 32-bytes heximal string
{
//.... xxyyzztttttt
// 00 02 04 06 08 10 12 14 16 18 20 22 24 26 28 30
// 3ab0aea1c467eb4fb392a1a746d349a7 3a b0 ae a1 c4 67 eb 4f b3 92 a1 a7 46 d3 49 a7
var t = this.toLowerCase();
return t.substr( 06, 02 ) + t.substr( 04, 02 ) + t.substr( 02, 02 ) + t.substr( 00, 02 ) +
t.substr( 10, 02 ) + t.substr( 08, 02 ) + // 4 xx
t.substr( 14, 02 ) + t.substr( 12, 02 ) + // 4 yy
t.substr( 16, 02 ) + t.substr( 18, 02 ) + // 4 zz
t.substr( 20, 12 ); // 12 }

Mbr- , Gpt- MountedDevices . Gpt- , , MountedDevices . VolumeGUID , F1 .


5.

5 4: MountedDevices, VolumeGUID, Signature+Offset, DosDevices, “SetMountNameForMountPoint”.

. Github , EnumerateVolumes-LLD.docx, EnumerateVolumes-LLD.pdf. . , , . Github , , , . , 99.5% JS- Web-, . PShell vbs.

, 10 : , . , , . DevicesCollection, StorageVolumesCollection LogicalVolumesCollection , , . , , , .

,

, , , , TopGear, 1 . , . . , diskpart.exe , , . , . Windows . , , diskpart EnumDevicesAndVolumes.wsf . , .

GUID

, Github , GUID, : Volume GUID Gpt- Volume GUID Mbr-, 3? : , Field 3 Volume GUID “11e4” “11e5”, , MS GUID .

StdRegWrapperClass, Registry

, “”, , , Registry, TestCase. , Set, Delete — Set / Delete . StdRegProv. , .



4 , MountedDevices: , VolumeGUID , , , DosDevices. , , , . , , VolumeGUID , DosDevices . N , . .

REG_QWORD . , . , - Registry, REG_QWORD. “ ”, .

, Identifier, HKLM\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\DiskController\0\DiskPeripheral, «Identifier»=«9cb5ff90-00000000-A». , Registry . - , .

Data MountPoints2\CPC\Volume. , . , , , . .



www.script-coding.com/WMI.html — WMI coding, , Scripting, .

WSF- “” JS. .

www.microsoft.com/en-us/download/details.aspx?id=12028 — “” WMI-, ScriptomaticV2.hta. MUST HAVE JS, VBS, Perl WMI-. WMI- .

www.forensicmag.com

www.forensicmag.com/articles/2011/12/windows-7-registry-forensics-part-2
www.forensicmag.com/articles/2012/02/windows-7-registry-forensics-part-3
www.forensicmag.com/articles/2012/06/retrieving-digital-evidence-methods-techniques-and-issues-part-3
www.forensicmag.com/articles/2012/04/windows-7-registry-forensics-part-4

, , . , , “” , Registry , “”, , . , Registry, , , .

winintro.ru/diskmgt.ru/html/ebd2bd6e-8b1e-43b6-a2e3-483def6ad763.htm — (Spanned Volumes) .

xp-7.ru/blog/2011-01-13-101 — , .

www.webtropy.com/articles/art14-2.asp?Interop=WbemScripting — Reference WbemScripting C# and VB.NET

, , , reference Microsoft. , .

“ ”

, , , , . , , , .

2015.03.24 22:10:19 — 2015.03.31 15:45:14 Windows 8.1 Pro 9600
2015.03.31 16:26:15 — 2015.04.23 02:56:17 Windows 10 Pro Technical Preview 10049
2015.04.23 03:44:13 — 2015.04.29 06:36:13 Windows 10 Pro Technical Preview 10061
2015.04.29 07:25:43 — 2015.05.21 11:32:07 Windows 10 Pro Insider Preview 10074
2015.05.21 14:21:40 — 2015.05.28 21:13:37 Windows 10 Pro Insider Preview 10122
2015.05.28 22:04:16 — 2015.05.30 19:11:22 Windows 10 Pro Insider Preview 10125
2015.05.30 20:16:43 — 2015.07.01 11:17:37 Windows 10 Pro Insider Preview 10130
2015.07.01 12:11:53 — 2015.07.01 13:25:29 Windows 10 Pro Insider Preview 10158
2015.07.01 23:22:08 — 2015.07.03 22:25:40 Windows 10 Pro Insider Preview 10159
2015.07.03 23:21:16 — 2015.07.09 24:24:29 Windows 10 Pro Insider Preview 10162
2015.07.10 01:21:50 — Windows 10 Pro Insider Preview 10166

github:

github.com/sysprg-46/EnumerateDevicesAndVolumes/tree/master

.

Source: https://habr.com/ru/post/264127/


All Articles