Video Screencast Help

Working with Darwin Descriptors

Created: 17 Feb 2012 • Updated: 17 Feb 2012 | 3 comments
Language Translations
EdT's picture
+5 5 Votes
Login to vote

Although the structure of windows installer GUIDs is well documented, both for the standard and the packed formats, the information available for Darwin Descriptors is somewhat limited. 

This article is the result of many hours of experimentation and research, and describes how the Darwin Descriptor is formatted, and how to convert from standard GUIDs to Darwin Descriptors and back again, using a VBScript solution.

I offer no guarantees that the information provided here is 100% accurate, but it does appear to work with the example DDs that I have found in the registry and decoded. 

My earlier blog (https://www-secure.symantec.com/connect/blogs/guid-converter) describes the conversion of standard GUIDs to packed GUIDs and vice versa, so I will not repeat the information here.  The relationship between standard GUIDs and Darwin Descriptors is substantially more complex, but once the principals are understood, the conversion process is quite straightforward.

The following examples show a standard GUID and its DD representation.

{91140000-0011-0000-1000-0000000FF1CE}

ykG^V5!!!!4!!!!MKKSk

The source is one of the many DDs created by the Office 2010 installation, showing only one segment. The full Darwin Descriptor format appears to take one of four different forms, as shown in the table below. 

 

Number of Components

Number of Features

Darwin Descriptor Format

>1

>1

{compressed product code}{feature name}>{compressed component ID}

>1

1

{compressed product code}>{compressed component ID}

1

>1

{compressed product code}{feature name}<

1

1

{compressed product code}<

 

 

Darwin Descriptors are an important aspect of MSI resiliency, and are often found with the shell\open\command entries in the Software\Classes area of the registry (HKCR). 

So how is a standard GUID (38 characters) translated to a Darwin Descriptor (20 characters)?

Let us start with a standard GUID and see how the bytes are rearranged:

{ABCDEFGH-JKLM-NOPR-ABCD-EFGHJKLMNOPR}

The first step is to remove the brackets and hyphens and order the characters into blocks of eight

ABCDEFGH   JKLMNOPR   ABCDEFGH   JKLMNOPR

The following reordering is now applied to the eight byte blocks:

Block 1 is unchanged

Block 2 has the upper and lower four characters exchanged

Block 3 and Block 4 has the four pairs of bytes reversed in their order

The end result looks something like this:

ABCDEFGH    NOPRJKLM    GHEFCDAB    PRNOLMJK

The spaces between each block are included for clarity, but in practice we now have a 32 bit string. Note that the method of rearranging the bytes is different to that used for generating 'conventional' packed GUIDs. 

Each of these eight character hexadecimal blocks now need to be converted into five alphanumeric characters, and this is achieved using a modified Base85 character set (also known as Ascii-85). There are many sources of further information on Base85 but one I used during my research is on Wikipedia:  http://en.wikipedia.org/wiki/Ascii85

Unfortunately, the standard Base85 character set contains a number of characters which are illegal in registry keys for one reason or another, so the Base85 character set that is used for Darwin Descriptor generation looks like this:

!$%&'()*+,-.0123456789=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~

( For completeness, the nine characters excluded are:  “ # / : ; < > \ |  )

Using the GUID shown earlier: {91140000-0011-0000-1000-0000000FF1CE} I will show how this is converted into a Darwin string.

First of all, the GUID is translated into the 32 bit form, giving the following string (shown as four octets) 

91140000 00000011 00000010 CEF10F00

Each octet is then processed into a 5-character string as follows:

  1. Convert the hex number 91140000 into decimal giving us 2434007040.
  2. The decimal number 2434007040 is repeatedly divided by 85, and the remainder noted. The first division gives us a value of 28635376 and a remainder of 80. If we look for character 80 in the Base85 character set, where the first character is 0, we find that character 80 translates to y.  The second division by 85 gives a value of 336886 and a remainder of 66 which gives us the Base85 character k. The third division gives a value of 3963 and a remainder of 31 which translates to G. The fourth division gives a value of 46 and a remainder of 53, which translates to ^. The value of 46 is not divisible by 85 so becomes translated to    as the fifth character. If we put these characters together, they give us ykG^V which can be seen to match the first five characters in the Darwin Descriptor shown earlier.
  3. The next Octet is 00000011 and this gives a decimal value of 17.  This is where things get tricky, as the number is lower than 85. It is easy to make the mistake that this would translate to !!!!5 but in fact the translation is 5!!!!, for reasons which may become evident later when we look at the reverse translation process.   In essence, the initial value of the translated string can be considered to be !!!!!  and if the initial decimal value is less than one of the powers of 85 (ie  85, 7225, 614125, 52200625) then the resultant translations are shifted to the left until there is no leading !  (except if the decimal string is zero in which case all five characters will be the same: !!!!! )
  4. Using the same logic, the third octet translates to 4!!!! and the fourth octet translates to MKKSk

 So how do we convert a Darwin Descriptor back into a standard GUID?

 The first step is to take the twenty character DD string and separate it into four quintets of characters. Using the earlier example, the first quintet is ykG^V, the second is 5!!!!, the third is4!!!! and the last one is MKKSk.  For our example, I will translate the fourth and third quintets. Here are the steps: 

  1. Find the character offset of each of the five characters in the string MKKSk.   This gives us the numerals 37,35,35,43,66.
  2. Multiply character 5 by 85, add character 4, multiply by 85, add character 3, multiply by 85, add character 2, multiply by 85 and finally add character 1.  This gives us:    ((((((((37*85)+35)*85)+35)*85)+43)*85)+66) which a few moments of work with a calculator will give us a decimal result of 3471904512. Converting this to Hex will give us a value of CEF10F00.
  3. The translation of 4!!!! demonstrates why the characters need to be shifted to the left, as the initial translation of this string gives us the decimal values 16,0,0,0,0.  Using the same process as described in the previous paragraph, we get the calculation ((((((((0*85)+0)*85)+0)*85)+0)*85)+16).  The decimal value 16 becomes 00000010 when translated to an 8 character hex value. 

Once we have derived the four blocks of eight hex characters from the Darwin string, they are rearranged into a standard GUID by reversing the process described earlier. 

The actual creation of a Darwin Descriptor depends on the individual MSI as it is controlled by the number of components and features in the package.  This linkage between the content of the Darwin Descriptor and the product and component code(s) of the MSI is precisely why the capture of an MSI is not recommended. Any captured Darwin Descriptors have to be deleted as they are referencing product and component codes that will not exist in any MSI generated from the capture (since GUIDs are unique). Consequently, any resilience provided by the captured DDs would be looking for product codes and component codes from the original package, which are very unlikely to be present on any test machine.

I have written a vbscript which will convert a standard GUID into a Darwin string and vice versa.  I make no claims of coding elegance or reliability, as much of this information is not documented anywhere that I have been able to find.

Feedback welcome!

EdT 2012

Comments 3 CommentsJump to latest comment

philbenson's picture

I have not looked at the code, but as long as it works, who cares :P

0
Login to vote
piyushnasa's picture

EdT, you are really a master and I think you have done a great research on this topic and have given us a good insight on this topic. Really applaud you for doing this.

Piyush Nasa Altiris Certified Professional (ACP)

http://msiworld.blogspot.com/

0
Login to vote
CableGuy41's picture

good one. thank for sharing

Thanks,

CableGuy
Do not forget to mark a SOLUTION

0
Login to vote