3

I retrieve the serial number of the physical hard-drive using the function DeviceIoControl following the suggestions from Blacktempel in this post. Getting the number works fine in principle, but I (still) have trouble with the format of the serial number as it keeps changing from computer to computer and with time. Also I experienced a format change on some computers between running the program as normal user or as admin.

For example, I retrieved a number with the following format:

WD-WCAZAF632086

when I tested the program first and after a few weeks it looks like:

2020202057202d4443575a414641333630323638

This is still the same number, only the characters have been replaced by their hex codes and swapped pair-wise. I've encountered different formats like a normal string with the characters exchanged pair-wise. Among other values, I need to check this number to verify if a software license is valid for a certain computer. Having an instable and unknown format is annoying and if the format changes to something I'm not yet aware of, I risk that the software license check fails although the license is still valid.

Does anyone know how to get the serial number in a stable format, or how to predict the format so it can be adapted for comparison?

Here is minimal C++ example of code that I used to retrieve the serial number of the first physical disc. I build it using Visual Studio 2015:

#include "stdafx.h"
#include "Windows.h"

#include <string>
#include <vector>
#include <iostream>

bool GetDeviceString(std::string &serialnumber)
{
    HANDLE deviceHandle = CreateFileW(L"//./PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);  // Get Handle to device

    if (deviceHandle == INVALID_HANDLE_VALUE) // Check if Handle is valid
        return false;

    STORAGE_PROPERTY_QUERY query{};
    query.PropertyId = StorageDeviceProperty;
    query.QueryType = PropertyStandardQuery;

    STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
    DWORD dwBytesReturned;

    if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(STORAGE_PROPERTY_QUERY),
        &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
    {

    }

    // Alloc the output buffer
    const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
    std::vector<BYTE> pOutBuffer(dwOutBufferSize,0);

    if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(STORAGE_PROPERTY_QUERY),
        pOutBuffer.data(), dwOutBufferSize,
        &dwBytesReturned, NULL))
    {
        // handle error, do cleanup and return
    }

    STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer.data();
    const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
    if (dwSerialNumberOffset != 0)
    {
        // Finally, get the serial number
        serialnumber = (char*)(pOutBuffer.data() + dwSerialNumberOffset);
    }
}

int main()
{
    std::string serialnumber;

    if (GetDeviceString(serialnumber))
    {
        std::cout << "serial number of first disc: " << serialnumber << std::endl;
    }
    else
    {
        std::cout << "Failed!" << std::endl;
    }
    std::cin.ignore();

    return 0;
}
Community
  • 1
  • 1
Paul R.
  • 678
  • 5
  • 19
  • 1
    http://stackoverflow.com/questions/14623397/hdd-serial-number-flipped-every-2-bytes-in-windows-xp-vista-and-7-but-not-in-wi – Hans Passant Feb 24 '16 at 15:02
  • 1
    @HansPassant If someone could tell me for sure that flipping and hexing are the only disturbances that I can get, I would be fine with checking, in the worst case, all 16 possibilities to find out if the license is valid. But I want to understand what is going on and most importantly, if hexing and flipping is really all that I can encounter. If there would be one more disturbance with two possible options that can be combined with the ones I already know of, I end up with up to 64 checks. Every additional disturbances will enlarge the maximum number of checks needed by a factor of 4. – Paul R. Feb 24 '16 at 15:39
  • 2
    You'll have to call Microsoft if you want a warranty. Take-away ought to be that the drive serial number is rather a useless way to obtain a fingerprint number. It is completely out of your control, buggy, trivial to copy, very easily spoofed and the first place anybody will look. Just generate your own number and write it to a file, CoCreateGuid() gives you a nice number, it is globally unique. – Hans Passant Feb 24 '16 at 15:58
  • @HansPassant Thanks for the suggestions. However, I don't understand, how a file with a unique number generated by CoCreateGuid() can be used as a secure way to verify a license which is bound to a specific computer. Everybody can copy this file. Also, I don't understand why the serial number of the physical hard drive can be easily manipulated. I know that this is easy for the serial number of a logic volume, but how can this be easily done for the hardware itself? – Paul R. Feb 25 '16 at 09:46

0 Answers0