How to get hard disk serial number using Win32 API

Discussion in 'C' started by unmeshjoshi, May 12, 2010.

  1. unmeshjoshi

    unmeshjoshi New Member

    Joined:
    Mar 17, 2010
    Messages:
    12
    Likes Received:
    0
    Trophy Points:
    0
    Hello all,


    Can anybody tell me how can we get hard disk serial number (NOT THE VOLUME SERIAL NUMBER), which is UNIQUE for each physical hard disk, using Win32 APIs?


    Thanks in advance.
     
  2. shaju1981

    shaju1981 New Member

    Joined:
    Jan 21, 2010
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Code:
    int ReadPhysicalDriveInNT (void)
    {
    int done = FALSE;
    int drive = 0;
    
    for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
    {
    HANDLE hPhysicalDriveIOCTL = 0;
    
    // Try to get a handle to PhysicalDrive IOCTL, report failure
    // and exit if can't.
    char driveName [256];
    
    sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
    
    // Windows NT, Windows 2000, must have admin rights
    hPhysicalDriveIOCTL = CreateFile (driveName,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, 0, NULL);
    // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
    // printf ("Unable to open physical drive %d, error code: 0x%lX\n",
    // drive, GetLastError ());
    
    if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
    {
    GETVERSIONOUTPARAMS VersionParams;
    DWORD cbBytesReturned = 0;
    
    // Get the version, etc of PhysicalDrive IOCTL
    memset ((void*) &VersionParams, 0, sizeof(VersionParams));
    
    if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
    NULL,
    0,
    &VersionParams,
    sizeof(VersionParams),
    &cbBytesReturned, NULL) )
    {
    // printf ("DFP_GET_VERSION failed for drive %d\n", i);
    // continue;
    }
    
    // If there is a IDE device at number "i" issue commands
    // to the device
    if (VersionParams.bIDEDeviceMap > 0)
    {
    BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd
    SENDCMDINPARAMS scip;
    //SENDCMDOUTPARAMS OutCmd;
    
    // Now, get the ID sector for all IDE devices in the system.
    // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
    // otherwise use the IDE_ATA_IDENTIFY command
    bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? \
    IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    
    memset (&scip, 0, sizeof(scip));
    memset (IdOutCmd, 0, sizeof(IdOutCmd));
    
    if ( DoIDENTIFY (hPhysicalDriveIOCTL,
    &scip,
    (PSENDCMDOUTPARAMS)&IdOutCmd,
    (BYTE) bIDCmd,
    (BYTE) drive,
    &cbBytesReturned))
    {
    DWORD diskdata [256];
    int ijk = 0;
    USHORT *pIdSector = (USHORT *)
    ((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
    
    for (ijk = 0; ijk < 256; ijk++)
    diskdata [ijk] = pIdSector [ijk];
    
    PrintIdeInfo (drive, diskdata);
    
    done = TRUE;
    }
    }
    
    CloseHandle (hPhysicalDriveIOCTL);
    }
    }
    
    return done;
    }
    int ReadIdeDriveAsScsiDriveInNT (void)
    {
    int done = FALSE;
    int controller = 0;
    
    for (controller = 0; controller < 2; controller++)
    {
    HANDLE hScsiDriveIOCTL = 0;
    char driveName [256];
    
    // Try to get a handle to PhysicalDrive IOCTL, report failure
    // and exit if can't.
    sprintf (driveName, "\\\\.\\Scsi%d:", controller);
    
    // Windows NT, Windows 2000, any rights should do
    hScsiDriveIOCTL = CreateFile (driveName,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, 0, NULL);
    // if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE)
    // printf ("Unable to open SCSI controller %d, error code: 0x%lX\n",
    // controller, GetLastError ());
    
    if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
    {
    int drive = 0;
    
    for (drive = 0; drive < 2; drive++)
    {
    char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
    SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
    SENDCMDINPARAMS *pin =
    (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
    DWORD dummy;
    
    memset (buffer, 0, sizeof (buffer));
    p -> HeaderLength = sizeof (SRB_IO_CONTROL);
    p -> Timeout = 10000;
    p -> Length = SENDIDLENGTH;
    p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
    strncpy ((char *) p -> Signature, "SCSIDISK", 8);
    
    pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
    pin -> bDriveNumber = drive;
    
    if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,
    buffer,
    sizeof (SRB_IO_CONTROL) +
    sizeof (SENDCMDINPARAMS) - 1,
    buffer,
    sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
    &dummy, NULL))
    {
    SENDCMDOUTPARAMS *pOut =
    (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
    IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
    if (pId -> sModelNumber [0])
    {
    DWORD diskdata [256];
    int ijk = 0;
    USHORT *pIdSector = (USHORT *) pId;
    
    for (ijk = 0; ijk < 256; ijk++)
    diskdata [ijk] = pIdSector [ijk];
    
    PrintIdeInfo (controller * 2 + drive, diskdata);
    
    done = TRUE;
    }
    }
    }
    CloseHandle (hScsiDriveIOCTL);
    }
    }
    
    return done;
    }
    int ReadDrivePortsInWin9X (void)
    {
    int done = FALSE;
    int drive = 0;
    
    InitializeWinIo ();
    
    // Get IDE Drive info from the hardware ports
    // loop thru all possible drives
    for (drive = 0; drive < 8; drive++)
    {
    DWORD diskdata [256];
    WORD baseAddress = 0; // Base address of drive controller
    DWORD portValue = 0;
    int waitLoop = 0;
    int index = 0;
    
    switch (drive / 2)
    {
    case 0: baseAddress = 0x1f0; break;
    case 1: baseAddress = 0x170; break;
    case 2: baseAddress = 0x1e8; break;
    case 3: baseAddress = 0x168; break;
    }
    
    // Wait for controller not busy
    waitLoop = 100000;
    while (--waitLoop > 0)
    {
    GetPortVal ((WORD) (baseAddress + 7), &portValue, (BYTE) 1);
    // drive is ready
    if ((portValue & 0x40) == 0x40) break;
    // previous drive command ended in error
    if ((portValue & 0x01) == 0x01) break;
    }
    
    if (waitLoop < 1) continue;
    
    // Set Master or Slave drive
    if ((drive % 2) == 0)
    SetPortVal ((WORD) (baseAddress + 6), 0xA0, 1);
    else
    SetPortVal ((WORD) (baseAddress + 6), 0xB0, 1);
    
    // Get drive info data
    SetPortVal ((WORD) (baseAddress + 7), 0xEC, 1);
    
    // Wait for data ready
    waitLoop = 100000;
    while (--waitLoop > 0)
    {
    GetPortVal ((WORD) (baseAddress + 7), &portValue, 1);
    // see if the drive is ready and has it's info ready for us
    if ((portValue & 0x48) == 0x48) break;
    // see if there is a drive error
    if ((portValue & 0x01) == 0x01) break;
    }
    
    // check for time out or other error
    if (waitLoop < 1 || portValue & 0x01) continue;
    
    // read drive id information
    for (index = 0; index < 256; index++)
    {
    diskdata [index] = 0; // init the space
    GetPortVal (baseAddress, &(diskdata [index]), 2);
    }
    
    PrintIdeInfo (drive, diskdata);
    done = TRUE;
    }
    
    ShutdownWinIo ();
    
    return done;
    }
     
    Last edited by a moderator: May 13, 2010
  3. backdoor

    backdoor New Member

    Joined:
    Jan 6, 2010
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    i saw a method that used deviceiocontrolfile to spoof this value, from a program that requiered that serial number.

    here is the spoofing part

    Code:
    #define ATA_IDENTIFY_DEVICE 0xec
    #pragma pack(1)
    struct ata_identify_device {
    unsigned short words000_009[10];
    unsigned char serial_no[20];
    unsigned short words020_022[3];
    unsigned char fw_rev[8];
    unsigned char model[40];
    unsigned short words047_079[33];
    unsigned short major_rev_num;
    unsigned short minor_rev_num;
    unsigned short command_set_1;
    unsigned short command_set_2;
    unsigned short command_set_extension;
    unsigned short cfs_enable_1;
    unsigned short word086;
    unsigned short csf_default;
    unsigned short words088_255[168];
    };
    #pragma pack()
     
    NTSTATUS
    (*pNtDeviceIoControlFile)(
    IN HANDLE FileHandle,
    IN HANDLE Event OPTIONAL,
    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
    IN PVOID ApcContext OPTIONAL,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN ULONG IoControlCode,
    IN PVOID InputBuffer OPTIONAL,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer OPTIONAL,
    IN ULONG OutputBufferLength
    );
    NTSTATUS
    MyNtDeviceIoControlFile(
    IN HANDLE FileHandle,
    IN HANDLE Event OPTIONAL,
    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
    IN PVOID ApcContext OPTIONAL,
    OUT PIO_STATUS_BLOCK IoStatusBlock,
    IN ULONG IoControlCode,
    IN PVOID InputBuffer OPTIONAL,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer OPTIONAL,
    IN ULONG OutputBufferLength
    )
    {
    NTSTATUS ret = pNtDeviceIoControlFile( FileHandle, Event, ApcRoutine,
    ApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferLength,
    OutputBuffer, OutputBufferLength );
    switch( IoControlCode ) {
    case IOCTL_STORAGE_QUERY_PROPERTY: {
    PSTORAGE_DEVICE_DESCRIPTOR output = (PSTORAGE_DEVICE_DESCRIPTOR) OutputBuffer;
    if( output->SerialNumberOffset ) {
    char* serialnum = (char*)output + output->SerialNumberOffset;
    strncpy( serialnum, "FAKE SERIAL", strlen(serialnum) );
    }
    if( output->ProductIdOffset ) {
    char* productid = (char*)output + output->ProductIdOffset;
    strncpy( productid, "STUPID PB", strlen(productid) );
    }
    if( output->VendorIdOffset ) {
    char* vendorid = (char*)output + output->VendorIdOffset;
    strncpy( vendorid, "asdfghjkl", strlen(vendorid) );
    }
    }
    break;
    case SMART_RCV_DRIVE_DATA: {
    PSENDCMDINPARAMS input = (PSENDCMDINPARAMS) InputBuffer;
    PSENDCMDOUTPARAMS output = (PSENDCMDOUTPARAMS) OutputBuffer;
    if (input->irDriveRegs.bCommandReg == ATA_IDENTIFY_DEVICE) {
    struct ata_identify_device *hdid = (struct ata_identify_device*) (output->bBuffer);
    strncpy( hdid->model, "spoofed model!", 40 );
    strncpy( hdid->serial_no, "serial goes here", 20 );
    }
    }
    break;
    }
    return ret;
    }
     
    Last edited by a moderator: Jun 20, 2010
  4. mriganka

    mriganka New Member

    Joined:
    Jun 21, 2010
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    whats the purpose of this work?
    is that necessary to use C?
    :?:
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice