Here is the solution that would save you hours of research without a success. I have already turned every page on google (literally but spent over 50 hours before I discovered my solution) without a success so you are in the right place right now.
There are two solutions to this so you can pick the one that fits your needs best. Both solutions works under user account on XP and Vista. Without google I wouldn’t know anything about windows registry forensic techniques that helped to find these solutions.
Solution 1: Getting the serial number from Windows Registry
The serial numbers are stored under the following path:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE
Or
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SCSI
This solution is much harder to dig out the serial number as it needs searching child keys and parsing strings.
The child nodes that are listed under the above keys can contain CDROM drives as well or any device has been categorised as IDE/SCSI but you can examine a Key value called ‘Class’ to see if the drive is ‘CDROM’ or ‘DiskDrive’. Expand the child nodes until you find the Key called ‘Class’ in the left pane of Windows Registry.
On my machine I have two hard drives… In case you never thought about this every machine that is designed to be a development machine must have two hard drives. One is used by OS and other Programs and the second one for your data/source code. You would reduce the risk of losing your source code tremendously by this setup.
Here is one of key entries for one of my hard drives:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\
DiskMaxtor_6V160E0__________________________VA111630
Model Number: DiskMaxtor_6V160E0 (The word ‘Disk’ is a prefix that is added by PnP service)
Controller Revision Number: VA111630
You should be able to see another child node below the above key. Here is mine:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\
DiskMaxtor_6V160E0__________________________VA111630\
3356333038524743202020202020202020202020
The child node 3356333038524743202020202020202020202020 is your serial number in hexadecimal. At the time I had no idea what that number was until I used Smarties2008’s Hex tool to examine the value. I can assure you if it wasn’t for the Hex tool in Smarties 2008 not in a million year I would have guessed the number I was looking at was actually my hard drive serial number.
However, there is one more thing you need to know. Once you converted the Hex value to string then you need to reverse every two characters to get the serial number in the correct order, if that was needed.
Notes:
If there is no serial number returned by the Hard Drive the PnP service would generate a serial number for the Hard Drive. You might notice the ‘&0’ characters in the serial number. Depending where they appear they mean something but I don’t know what they mean as I have decided not to use the Windows Registry solution all together. The second solution is much easier.
If you decided to use this solution then make sure you always open a key for ‘read’ that way you never face security permission issue under user account privilege.
Solution 2: Getting the serial number from WMI
Here how is done in my way that works under User Account both on XP and Vista:
ManagementScope managementScope = new ManagementScope(@"\root\cimv2");
managementScope.Options.Impersonation = system.Management.ImpersonationLevel.Impersonate;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(managementScope, new ObjectQuery("SELECT * FROM Win32_DiskDrive WHERE InterfaceType=\"IDE\" or InterfaceType=\"SCSI\""));
foreach (ManagementObject disk in searcher.Get())
{
if (disk["PNPDeviceID"] != null)
{
string pnpDeviceID = disk["PNPDeviceID"].ToString();
string[] split = pnpDeviceID.Split('\\');
}
}
The serial numbers have been hidden in PNPDeviceID property of Win32_DiskDrive class all this time and if someone knew about it he/she never gave away the secret, not even the ‘Scripting Guy’ shared the secret with us.
Here is the value of PNPDeviceID property from the same hard drive that I used in Windows Registry example:
IDE\DISKMAXTOR_6V160E0__________________________VA111630\
3356333038524743202020202020202020202020
It looks familiar doesn’t it? Now you can split this string by ‘\’ character to get the serial number in the last element of the split. Once again the 3356333038524743202020202020202020202020 value needs to be converted from Hex to string then reverse every two characters to get the serial number in the right order.
Here is a quick dirty way to reverse it:
private string ReverseSerialNumber(string serialNumber)
{
serialNumber = serialNumber.Trim();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < serialNumber.Length; i += 2)
{
sb.Append(serialNumber[i + 1].ToString() + serialNumber[i].ToString());
}
serialNumber = sb.ToString();
sb = null;
return serialNumber;
}/[code]
And here is the code to convert Hex to String
[code=csharp]private static Byte[] GetHexStringBytes(string hex)
{
try
{
if (hex.Contains(String.Empty))
{
hex = hex.Replace(" ", String.Empty);
}
if (hex.Length % 2 == 1)
{
hex = "0" + hex;
}
int size = hex.Length / 2;
Byte[] bytes = new Byte[size];
for (int i = 0; i < size; i++)
{
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return bytes;
}
catch
{
return new byte[] { };
}
}
Here how you would use the methods after splitting the PNPDeviceID
byte[] bytes = this.GetHexStringBytes(split[2]);
string serial = this.ReverseSerialNumber(Encoding.UTF8.GetString(bytes));
Notes:
If the serial number was generated by PnP service then the split[2] element needs to be handled differently. To examine the split[2] value to see if the value was generated by PnP service use the following if statement below:
Please make sure you read the follow up article to this.
Happy Coding!