请帮我分析这个软件是如何获取计算机硬盘物理序列号的ftp://minervasoft.com/tools/证券交易/webstock3000.exe

解决方案 »

  1.   

    #define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
    #define  IDENTIFY_BUFFER_SIZE  512
    #define  FILE_DEVICE_SCSI              0x0000001b
    #define  IOCTL_SCSI_MINIPORT_IDENTIFY  ((FILE_DEVICE_SCSI << 16) + 0x0501)
    #define  IOCTL_SCSI_MINIPORT 0x0004D008  //  see NTDDSCSI.H for definition
    #define  IDE_ATAPI_IDENTIFY  0xA1  //  Returns ID sector for ATAPI.
    #define  IDE_ATA_IDENTIFY    0xEC  //  Returns ID sector for ATA.
    #define  DFP_RECEIVE_DRIVE_DATA   0x0007c088
    typedef struct _IDSECTOR
    {
       USHORT  wGenConfig;
       USHORT  wNumCyls;
       USHORT  wReserved;
       USHORT  wNumHeads;
       USHORT  wBytesPerTrack;
       USHORT  wBytesPerSector;
       USHORT  wSectorsPerTrack;
       USHORT  wVendorUnique[3];
       CHAR    sSerialNumber[20];
       USHORT  wBufferType;
       USHORT  wBufferSize;
       USHORT  wECCSize;
       CHAR    sFirmwareRev[8];
       CHAR    sModelNumber[40];
       USHORT  wMoreVendorUnique;
       USHORT  wDoubleWordIO;
       USHORT  wCapabilities;
       USHORT  wReserved1;
       USHORT  wPIOTiming;
       USHORT  wDMATiming;
       USHORT  wBS;
       USHORT  wNumCurrentCyls;
       USHORT  wNumCurrentHeads;
       USHORT  wNumCurrentSectorsPerTrack;
       ULONG   ulCurrentSectorCapacity;
       USHORT  wMultSectorStuff;
       ULONG   ulTotalAddressableSectors;
       USHORT  wSingleWordDMA;
       USHORT  wMultiWordDMA;
       BYTE    bReserved[128];
    } IDSECTOR, *PIDSECTOR;typedef struct _DRIVERSTATUS
    {
       BYTE  bDriverError;  //  Error code from driver, or 0 if no error.
       BYTE  bIDEStatus;    //  Contents of IDE Error register.
                            //  Only valid when bDriverError is SMART_IDE_ERROR.
       BYTE  bReserved[2];  //  Reserved for future expansion.
       DWORD  dwReserved[2];  //  Reserved for future expansion.
    } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; typedef struct _SENDCMDOUTPARAMS
    {
       DWORD         cBufferSize;   //  Size of bBuffer in bytes
       DRIVERSTATUS  DriverStatus;  //  Driver status structure.
       BYTE          bBuffer[1];    //  Buffer of arbitrary length in which to store the data read from the                                                       // drive.
    } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
    typedef struct _SRB_IO_CONTROL
    {
       ULONG HeaderLength;
       UCHAR Signature[8];
       ULONG Timeout;
       ULONG ControlCode;
       ULONG ReturnCode;
       ULONG Length;
    } SRB_IO_CONTROL, *PSRB_IO_CONTROL;
    typedef struct _IDEREGS
    {
       BYTE bFeaturesReg;       // Used for specifying SMART "commands".
       BYTE bSectorCountReg;    // IDE sector count register
       BYTE bSectorNumberReg;   // IDE sector number register
       BYTE bCylLowReg;         // IDE low order cylinder value
       BYTE bCylHighReg;        // IDE high order cylinder value
       BYTE bDriveHeadReg;      // IDE drive/head register
       BYTE bCommandReg;        // Actual IDE command.
       BYTE bReserved;          // reserved for future use.  Must be zero.
    } IDEREGS, *PIDEREGS, *LPIDEREGS;typedef struct _SENDCMDINPARAMS
    {
       DWORD     cBufferSize;   //  Buffer size in bytes
       IDEREGS   irDriveRegs;   //  Structure with drive register values.
       BYTE bDriveNumber;       //  Physical drive number to send 
                                //  command to (0,1,2,3).
       BYTE bReserved[3];       //  Reserved for future expansion.
       DWORD     dwReserved[4]; //  For future use.
       BYTE      bBuffer[1];    //  Input buffer.
    } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
    typedef struct _GETVERSIONOUTPARAMS
    {
       BYTE bVersion;      // Binary driver version.
       BYTE bRevision;     // Binary driver revision.
       BYTE bReserved;     // Not used.
       BYTE bIDEDeviceMap; // Bit map of IDE devices.
       DWORD fCapabilities; // Bit mask of driver capabilities.
       DWORD dwReserved[4]; // For future use.
    } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;WORD serial[256];
    DWORD OldInterruptAddress;
    DWORDLONG IDTR;
    void _stdcall ReadIdeSerialNumber();
    static unsigned int WaitHardDiskIde() 

    BYTE xx;Waiting:
    __asm{
    mov dx, 0x1f7
    in al, dx
    cmp al, 0x80
    jb Endwaiting
    jmp Waiting
    }
    Endwaiting:
    __asm{
    mov xx, al
    } return xx; 

    void __declspec( naked ) InterruptProcess(void)//中断服务程序
    {
    int   xx;
        int   i;
    WORD temp;
    //保存寄存器值
         __asm
          {
            push eax
            push ebx
            push ecx
            push edx
            push esi
          }
          
          WaitHardDiskIde();//等待硬盘空闲状态
          __asm{
    mov dx, 0x1f6
    mov al, 0xa0
    out dx, al
    }
    xx = WaitHardDiskIde(); //若直接在Ring3级执行等待命令,会进入死循环
    if ((xx&0x50)!=0x50) 
    {
    __asm{
            pop esi
            pop edx
            pop ecx
            pop ebx
            pop eax
    iretd
    }
    }

    __asm{
    mov dx, 0x1f6 //命令端口1f6,选择驱动器0
    mov al, 0xa0
    out dx, al
    inc dx
    mov al, 0xec
    out dx, al //发送读驱动器参数命令
    }

    xx = WaitHardDiskIde(); 
    if ((xx&0x58)!=0x58) 
        {
    __asm{
            pop esi
            pop edx
            pop ecx
            pop ebx
            pop eax
    iretd
    }
    }
        //读取硬盘控制器的全部信息
    for (i=0;i<256;i++) {
    __asm{
    mov dx, 0x1f0
    in ax, dx
    mov temp, ax
    }
    serial[i] = temp; 

                                   
    __asm{
            pop esi
            pop edx
            pop ecx
            pop ebx
            pop eax
    iretd
        }

           //_asm iretd
    }
      

  2.   

    int Win9xHDSerialNumRead(WORD * buffer)
    {
    int i;
    for(i=0;i<256;i++) buffer[i]=0;
    ReadIdeSerialNumber();
    for(i=0;i<256;i++)  buffer[i]=serial[i];
    return 1;
    }
    void _stdcall ReadIdeSerialNumber()
    { _asm
          {   push eax        
            //获取修改的中断的中断描述符(中断门)地址
            sidt IDTR
            mov eax,dword ptr [IDTR+02h]        
            add eax,3*08h+04h
            cli    //保存原先的中断入口地址
            push ecx
            mov ecx,dword ptr [eax]
            mov cx,word ptr [eax-04h]
            mov dword ptr OldInterruptAddress,ecx
            pop ecx   //设置修改的中断入口地址为新的中断处理程序入口地址
            push ebx
            lea ebx,InterruptProcess
            mov word ptr [eax-04h],bx
            shr ebx,10h
            mov word ptr [eax+02h],bx
            pop ebx      //执行中断,转到Ring 0(类似CIH病毒原理)
    int 3h       //恢复原先的中断入口地址
            push ecx
            mov ecx,dword ptr OldInterruptAddress
            mov word ptr [eax-04h],cx
            shr ecx,10h
            mov word ptr [eax+02h],cx
            pop ecx
            sti
            pop eax
           }
    }
    char *ConvertToString (WORD diskdata [256], int firstIndex, int   lastIndex){  
     static char string [1024];
    int index = 0;
    int position = 0;
    //  each integer has two characters stored in it backwards
       for (index = firstIndex; index <= lastIndex; index++)
       {       //  get high byte for 1st character
          string [position] = (char) (diskdata [index] / 256);
          position++;         //  get low byte for 2nd character
          string [position] = (char) (diskdata [index] % 256);
          position++;
       }  //  end the string 
       string [position] = '\0';    //  cut off the trailing blanks
       for (index = position - 1; index > 0 && ' ' == string [index]; index--)
          string [index] = '\0';   return string;
    }
      

  3.   

    char *ConvertToString2 (DWORD diskdata [256], int firstIndex, int lastIndex){
       static char string [1024];
       int index = 0;
       int position = 0;
          //  each integer has two characters stored in it backwards
       for (index = firstIndex; index <= lastIndex; index++)
       {         //  get high byte for 1st character
          string [position] = (char) (diskdata [index] / 256);
          position++;         //  get low byte for 2nd character
          string [position] = (char) (diskdata [index] % 256);
          position++;
       }     //  end the string 
       string [position] = '\0';
          //  cut off the trailing blanks
       for (index = position - 1; index > 0 && ' ' == string [index]; index--)      string [index] = '\0';
       return string;
    }
    int WinNTHDSerialNumAsScsiRead (DWORD * buffer)
    {
      buffer[0]='\n';
       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);
    //      driveName="\\\\.\\Scsi0";
             //  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])
                   {               int ijk = 0;
                      USHORT *pIdSector = (USHORT *) pId;
    for (ijk = 0; ijk < 256; ijk++)  buffer[ijk] =pIdSector [ijk];
    //                  PrintIdeInfo (controller * 2 + drive, diskdata);
             return 1;                            }
                }
             }
             CloseHandle (hScsiDriveIOCTL);
          }  }   return -1;
    }
    BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
                     PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,PDWORD lpcbBytesReturned){
          // Set up data structures for IDENTIFY command.
       pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
       pSCIP -> irDriveRegs.bFeaturesReg = 0;
       pSCIP -> irDriveRegs.bSectorCountReg = 1;
       pSCIP -> irDriveRegs.bSectorNumberReg = 1;
       pSCIP -> irDriveRegs.bCylLowReg = 0;
    pSCIP -> irDriveRegs.bCylHighReg = 0; // Compute the drive number.
    pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
         // The command can either be IDE identify or ATAPI identify.
       pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
       pSCIP -> bDriveNumber = bDriveNum;
       pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
       return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA,(LPVOID) pSCIP,sizeof(SENDCMDINPARAMS) - 1,
                   (LPVOID) pSCOP,sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, lpcbBytesReturned, NULL) );
    }
    int WinNTHDSerialNumAsPhysicalRead (DWORD * buffer)
    {
    #define  DFP_GET_VERSION          0x00074080
    BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE- 1];
       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++)
                     buffer[ijk] = pIdSector [ijk];
                //   PrintIdeInfo (drive, diskdata);
                   done = TRUE;
                }     }
             CloseHandle (hPhysicalDriveIOCTL);
          }   }   return done;
    }
    LPCWSTR FAR HDSerialNumRead()
    {
    char  buffer[256];
     buffer[0]='\n';
      OSVERSIONINFO OSVersionInfo;
      OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
      GetVersionEx( &OSVersionInfo);
      if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
      {   
      WORD m_wSeri[256];
      Win9xHDSerialNumRead(m_wSeri);  
          strcpy (buffer, ConvertToString (m_wSeri, 10, 19));
      } else{  DWORD m_wStr[256];
        if ( ! WinNTHDSerialNumAsPhysicalRead(m_wStr)) WinNTHDSerialNumAsScsiRead;
        strcpy (buffer, ConvertToString2 (m_wStr, 10, 19));
      } ;  return LPCWSTR(LPCSTR(buffer));   
    }
    int WEP(int nParam)
    {return 1;}