GetHDSerial.cpp
上传用户:cjw5120
上传日期:2022-05-11
资源大小:5032k
文件大小:12k
源码类别:

网络截获/分析

开发平台:

Visual C++

  1. // GetHDSerial.cpp: implementation of the CGetHDSerial class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "GetHDSerial.h"
  6. /*
  7.  作者:海啸 lyyer English Name: Jack 
  8.   blog:http://lyyer.blog.sohu.com
  9.   website:http://www.cnGSG.com
  10.   海啸网络安全组织
  11. */
  12. char  m_buffer[256];
  13. WORD  m_serial[256];
  14. DWORD m_OldInterruptAddress;
  15. DWORDLONG m_IDTR;
  16. // 等待硬盘空闲
  17. static unsigned int WaitHardDiskIdle() 
  18. BYTE byTemp;
  19. Waiting:
  20. _asm
  21. {
  22. mov dx, 0x1f7
  23. in al, dx
  24. cmp al, 0x80
  25. jb Endwaiting
  26. jmp Waiting
  27. }
  28. Endwaiting:
  29. _asm
  30. {
  31. mov byTemp, al
  32. }
  33. return byTemp; 
  34. //中断服务程序
  35. void  _declspec( naked )InterruptProcess(void)
  36. {
  37.  int   byTemp;
  38.      int   i;
  39.  WORD temp;
  40.  //保存寄存器值
  41.      _asm
  42.      {
  43.          push eax
  44.          push ebx
  45.          push ecx
  46.          push edx
  47.          push esi
  48.      }
  49.       
  50.      WaitHardDiskIdle();//等待硬盘空闲状态
  51.      _asm
  52.  {
  53.      mov dx, 0x1f6
  54.  mov al, 0xa0
  55.  out dx, al
  56.  }
  57.  byTemp = WaitHardDiskIdle(); //若直接在Ring3级执行等待命令,会进入死循环
  58.  if ((byTemp&0x50)!=0x50) 
  59.  {
  60. _asm  // 恢复中断现场并退出中断服务程序
  61. {
  62.             pop esi
  63.             pop edx
  64. pop ecx
  65. pop ebx
  66. pop eax
  67. iretd
  68. }
  69.  }
  70.  _asm
  71.  {
  72.  mov dx, 0x1f6 //命令端口1f6,选择驱动器0
  73.  mov al, 0xa0
  74.    out dx, al
  75.  inc dx
  76.  mov al, 0xec
  77.  out dx, al //发送读驱动器参数命令
  78.  }
  79.  byTemp = WaitHardDiskIdle(); 
  80.  if ((byTemp&0x58)!=0x58) 
  81.      {
  82. _asm  // 恢复中断现场并退出中断服务程序
  83. {
  84.  pop esi
  85.  pop edx
  86.  pop ecx
  87.  pop ebx
  88.  pop eax
  89.  iretd
  90. }
  91.  }
  92.      //读取硬盘控制器的全部信息
  93.  for (i=0;i<256;i++) 
  94.  {
  95.  _asm
  96.  {
  97.  mov dx, 0x1f0
  98.  in ax, dx
  99.    mov temp, ax
  100.  }
  101.  m_serial[i] = temp; 
  102.  }                                
  103.    _asm
  104.  {
  105.          pop esi
  106.      pop edx
  107.          pop ecx
  108.          pop ebx
  109.          pop eax
  110.  iretd
  111.      }
  112. }
  113. //////////////////////////////////////////////////////////////////////
  114. // Construction/Destruction
  115. //////////////////////////////////////////////////////////////////////
  116. CGetHDSerial::CGetHDSerial()
  117. {
  118. }
  119. CGetHDSerial::~CGetHDSerial()
  120. {
  121. }
  122. // 读取硬盘序列号函数
  123. char* CGetHDSerial::GetHDSerial()
  124. {
  125.   m_buffer[0]='n';
  126.   // 得到当前操作系统版本
  127.   OSVERSIONINFO OSVersionInfo;
  128.   OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  129.   GetVersionEx( &OSVersionInfo);
  130.   if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
  131.   {   
  132.   // Windows 9x/ME下读取硬盘序列号
  133.   WORD m_wWin9xHDSerial[256];
  134.   Win9xReadHDSerial(m_wWin9xHDSerial);  
  135.       strcpy (m_buffer, WORDToChar (m_wWin9xHDSerial, 10, 19));
  136.   }
  137.   else
  138.   {
  139.       // Windows NT/2000/XP下读取硬盘序列号
  140.   DWORD m_wWinNTHDSerial[256];  
  141.   // 判断是否有SCSI硬盘
  142.       if ( ! WinNTReadIDEHDSerial(m_wWinNTHDSerial)) 
  143.        WinNTReadSCSIHDSerial(m_wWinNTHDSerial);  
  144.       strcpy (m_buffer, DWORDToChar (m_wWinNTHDSerial, 10, 19));
  145.   }
  146.   return m_buffer;
  147. }
  148. // Windows9X/ME系统下读取硬盘序列号
  149. void _stdcall CGetHDSerial::Win9xReadHDSerial(WORD * buffer)
  150. {
  151. int i;
  152. for(i=0;i<256;i++) 
  153. buffer[i]=0;
  154.     _asm
  155.     {
  156.        push eax        
  157.         //获取修改的中断的中断描述符(中断门)地址
  158.         sidt m_IDTR
  159.         mov eax,dword ptr [m_IDTR+02h]        
  160.         add eax,3*08h+04h
  161.         cli
  162.         //保存原先的中断入口地址
  163.         push ecx
  164.         mov ecx,dword ptr [eax]
  165.         mov cx,word ptr [eax-04h]
  166.         mov dword ptr m_OldInterruptAddress,ecx
  167.         pop ecx
  168.         //设置修改的中断入口地址为新的中断处理程序入口地址
  169.         push ebx
  170.         lea ebx,InterruptProcess
  171.         mov word ptr [eax-04h],bx
  172.         shr ebx,10h
  173.         mov word ptr [eax+02h],bx
  174.         pop ebx
  175.         //执行中断,转到Ring 0(类似CIH病毒原理)
  176. int 3h
  177.         //恢复原先的中断入口地址
  178.         push ecx
  179.         mov ecx,dword ptr m_OldInterruptAddress
  180.         mov word ptr [eax-04h],cx
  181.         shr ecx,10h
  182.         mov word ptr [eax+02h],cx
  183.         pop ecx
  184.         sti
  185.         pop eax
  186.     } 
  187. for(i=0;i<256;i++)
  188. buffer[i]=m_serial[i];
  189. }
  190. // Windows 9x/ME系统下,将字类型(WORD)的硬盘信息转换为字符类型(char)
  191. char * CGetHDSerial::WORDToChar (WORD diskdata [256], int firstIndex, int lastIndex)
  192. {
  193.    static char string [1024];
  194.    int index = 0;
  195.    int position = 0;
  196.    // 按照高字节在前,低字节在后的顺序将字数组diskdata 中内容存入到字符串string中 
  197.    for (index = firstIndex; index <= lastIndex; index++)
  198.    {
  199.       // 存入字中的高字节
  200.       string [position] = (char) (diskdata [index] / 256);
  201.       position++;
  202.       // 存入字中的低字节
  203.       string [position] = (char) (diskdata [index] % 256);
  204.       position++;
  205.    }
  206.    //  添加字符串结束标志
  207.    string [position] = '';
  208.    //  删除字符串中空格
  209.    for (index = position - 1; index > 0 && ' ' == string [index]; index--)
  210.       string [index] = '';
  211.    return string;
  212. }
  213. // Windows NT/2000/XP系统下,将双字类型(DWORD)的硬盘信息转换为字符类型(char)
  214. char* CGetHDSerial::DWORDToChar (DWORD diskdata [256], int firstIndex, int lastIndex)
  215. {
  216.    static char string [1024];
  217.    int index = 0;
  218.    int position = 0;
  219.    // 按照高字节在前,低字节在后的顺序将双字中的低字存入到字符串string中 
  220.    for (index = firstIndex; index <= lastIndex; index++)
  221.    {
  222.       // 存入低字中的高字节
  223.       string [position] = (char) (diskdata [index] / 256);
  224.       position++;
  225.       // 存入低字中的低字节
  226.       string [position] = (char) (diskdata [index] % 256);
  227.       position++;
  228.    }
  229.    //  添加字符串结束标志
  230.    string [position] = '';
  231.    //  删除字符串中空格
  232.    for (index = position - 1; index > 0 && ' ' == string [index]; index--)
  233.       string [index] = '';
  234.    return string;
  235. }
  236. // Windows NT/2000/XP下读取IDE硬盘序列号
  237. BOOL CGetHDSerial::WinNTReadIDEHDSerial(DWORD * buffer)
  238. {
  239.    BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
  240.    BOOL bFlag = FALSE;
  241.    int  drive = 0;
  242.    char driveName [256];
  243.    HANDLE hPhysicalDriveIOCTL = 0;    
  244.       
  245.    sprintf (driveName, "\\.\PhysicalDrive%d", drive);
  246.    //  Windows NT/2000/XP下创建文件需要管理员权限
  247.    hPhysicalDriveIOCTL = CreateFile (driveName,
  248.                             GENERIC_READ | GENERIC_WRITE, 
  249.                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  250.                             OPEN_EXISTING, 0, NULL);
  251.    if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
  252.    {
  253.        GETVERSIONOUTPARAMS VersionParams;
  254.        DWORD               cbBytesReturned = 0;
  255.        // 得到驱动器的IO控制器版本
  256.        memset ((void*) &VersionParams, 0, sizeof(VersionParams));
  257.        if(DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_VERSION,
  258.                                NULL, 0, &VersionParams,
  259.                                sizeof(VersionParams),
  260.                                &cbBytesReturned, NULL) )
  261.    {        
  262.           if (VersionParams.bIDEDeviceMap > 0)
  263.   {
  264.               BYTE             bIDCmd = 0;   // IDE或者ATAPI识别命令
  265.               SENDCMDINPARAMS  scip;
  266.  
  267.               // 如果驱动器是光驱,采用命令IDE_ATAPI_IDENTIFY, command,
  268.               // 否则采用命令IDE_ATA_IDENTIFY读取驱动器信息
  269.               bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10)?
  270.                       IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
  271.               memset (&scip, 0, sizeof(scip));
  272.               memset (IdOutCmd, 0, sizeof(IdOutCmd));
  273.               // 获取驱动器信息
  274.               if (WinNTGetIDEHDInfo (hPhysicalDriveIOCTL, 
  275.                                       &scip, 
  276.                                       (PSENDCMDOUTPARAMS)&IdOutCmd, 
  277.                                       (BYTE) bIDCmd,
  278.                                       (BYTE) drive,
  279.                                       &cbBytesReturned))
  280.   {
  281.                   int m = 0;
  282.                   USHORT *pIdSector = (USHORT *)
  283.                              ((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;
  284.                   for (m = 0; m < 256; m++)
  285.                        buffer[m] = pIdSector [m];
  286.                   bFlag = TRUE;  // 读取硬盘信息成功
  287.   }
  288.   }
  289.    }
  290.        CloseHandle (hPhysicalDriveIOCTL);  // 关闭句柄
  291.    }
  292.    return bFlag;
  293. }
  294. // WindowsNT/2000/XP系统下读取SCSI硬盘序列号
  295. BOOL CGetHDSerial::WinNTReadSCSIHDSerial (DWORD * buffer)
  296. {
  297.       buffer[0]='n';
  298.       int controller = 0;
  299.       HANDLE hScsiDriveIOCTL = 0;
  300.       char   driveName [256];
  301.       sprintf (driveName, "\\.\Scsi%d:", controller);
  302.      //  Windows NT/2000/XP下任何权限都可以进行
  303.       hScsiDriveIOCTL = CreateFile (driveName,
  304.                                GENERIC_READ | GENERIC_WRITE, 
  305.                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  306.                                OPEN_EXISTING, 0, NULL);
  307.  
  308.       if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
  309.       {
  310.          int drive = 0;
  311.          DWORD dummy;
  312.          for (drive = 0; drive < 2; drive++)
  313.          {
  314.             char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
  315.             SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
  316.             SENDCMDINPARAMS *pin =
  317.                    (SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));           
  318.             // 准备参数
  319.             memset (buffer, 0, sizeof (buffer));
  320.             p -> HeaderLength = sizeof (SRB_IO_CONTROL);
  321.             p -> Timeout = 10000;
  322.             p -> Length = SENDIDLENGTH;
  323.             p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
  324.             strncpy ((char *) p -> Signature, "SCSIDISK", 8);  
  325.             pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
  326.             pin -> bDriveNumber = drive;
  327.             // 得到SCSI硬盘信息
  328.             if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, 
  329.                                  buffer,
  330.                                  sizeof (SRB_IO_CONTROL) +
  331.                                          sizeof (SENDCMDINPARAMS) - 1,
  332.                                  buffer,
  333.                                  sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
  334.                                  &dummy, NULL))
  335.             {
  336.                SENDCMDOUTPARAMS *pOut =
  337.                     (SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
  338.                IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
  339.                if (pId -> sModelNumber [0])
  340.                {
  341.                   int n = 0;
  342.                   USHORT *pIdSector = (USHORT *) pId;
  343.           
  344.                   for (n = 0; n < 256; n++)
  345.                       buffer[n] =pIdSector [n];
  346.                   return TRUE;  // 读取成功                               
  347.    }
  348.             }
  349.  }
  350.          CloseHandle (hScsiDriveIOCTL);  // 关闭句柄
  351.   }
  352.    return FALSE;   // 读取失败
  353. }
  354. // Windows NT/2000/XP下读取IDE设备信息
  355. BOOL CGetHDSerial::WinNTGetIDEHDInfo (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
  356.                  PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
  357.                  PDWORD lpcbBytesReturned)
  358. {
  359.    // 为读取设备信息准备参数
  360.    pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
  361.    pSCIP -> irDriveRegs.bFeaturesReg = 0;
  362.    pSCIP -> irDriveRegs.bSectorCountReg = 1;
  363.    pSCIP -> irDriveRegs.bSectorNumberReg = 1;
  364.    pSCIP -> irDriveRegs.bCylLowReg = 0;
  365.    pSCIP -> irDriveRegs.bCylHighReg = 0;
  366.    // 计算驱动器位置
  367.    pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);
  368.    // 设置读取命令
  369.    pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
  370.    pSCIP -> bDriveNumber = bDriveNum;
  371.    pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
  372.    
  373.    // 读取驱动器信息
  374.    return ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_DRIVE_INFO,
  375.                (LPVOID) pSCIP,
  376.                sizeof(SENDCMDINPARAMS) - 1,
  377.                (LPVOID) pSCOP,
  378.                sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
  379.                lpcbBytesReturned, NULL) );
  380. }