登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - C++Builder 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

在Win9x/NT下获取硬盘物理序列号
发表日期:2004-06-27作者:[转贴] 出处:CSDN  

#include <WinIOCtl.h>
#include <stdio.h>

#pragma inline
//---------------------------------------------------------------------------
// IDE NT/2000/XP专用变量
#define GETVERSIONOUTPARAMS     GETVERSIONINPARAMS
#define DFP_GET_VERSION         SMART_GET_VERSION
#define DFP_SEND_DRIVE_COMMAND  SMART_SEND_DRIVE_COMMAND
#define DFP_RCV_DRIVE_DATA      SMART_RCV_DRIVE_DATA

const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
const WORD IDE_ATA_IDENTIFY   = 0xEC;   // 读取ATA设备的命令

const int MAX_IDE_DRIVES = 4;

// SCSI专用变量
const DWORD FILE_DEVICE_SCSI             = 0x0000001B;
const DWORD IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI << 16) + 0x0501);
const DWORD IOCTL_SCSI_MINIPORT          = 0x0004D008; // see NTDDSCSI.H for definition
const DWORD SENDIDLENGTH  = sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE;

typedef struct _SRB_IO_CONTROL
{
    ULONG HeaderLength;
    UCHAR Signature[8];
    ULONG Timeout;
    ULONG ControlCode;
    ULONG ReturnCode;
    ULONG Length;
}SRB_IO_CONTROL, *PSRB_IO_CONTROL;

// 读取的主函数
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList);

// 辅助函数
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex);
// NT/2000/XP函数
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList);
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
        PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd,
        BYTE btDriveNum, PDWORD lpcbBYTEsReturned);
// Windows 9X函数
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList);
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool IsFirst, WORD BaseAddress,
        BYTE MoS, bool &IsIDEExist, bool &IsDiskExist, WORD *OutData);

// SCSI读取函数(for NT/2000/XP)
String __fastcall ReadIDEDriveAsScsiDriveOnNT();
//---------------------------------------------------------------------------
// ReadPhysicalDrive
void __fastcall ReadPhysicalDrive(TStrings *pSerList, TStrings *pModeList)
{
    switch(Win32Platform)
    {
        case VER_PLATFORM_WIN32_WINDOWS:
            ReadPhysicalDriveOnW9X(pSerList, pModeList);
            break;
        case VER_PLATFORM_WIN32_NT:
            ReadPhysicalDriveOnNT(pSerList, pModeList);
            break;
        default:
            break;
    }
}
//---------------------------------------------------------------------------
// ConvertToString
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
{
    static char szResBuf[1024];
    int nIndex = 0;
    int nPosition = 0;

    // Each integer has two characters stored in it backwards
    for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
    {
        // Get high BYTE for 1st character
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] / 256);
        nPosition++;

        // Get low BYTE for 2nd character
        szResBuf[nPosition] = (char)(dwDiskData[nIndex] % 256);
        nPosition++;
    }

    // End the string
    szResBuf[nPosition] = '';

    // Cut off the trailing blanks
    for(nIndex = nPosition - 1; nIndex > 0 && ' ' == szResBuf[nIndex]; nIndex--)
        szResBuf[nIndex] = '';

    return szResBuf;
}
//---------------------------------------------------------------------------
// Winndows NT4/2000/XP 代码
//---------------------------------------------------------------------------
// ReadPhysicalDriveOnNT
void __fastcall ReadPhysicalDriveOnNT(TStrings *pSerList, TStrings *pModeList)
{
    // 输出参数
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];

    for(int nDrive=0; nDrive < MAX_IDE_DRIVES; nDrive++)
    {
        HANDLE hPhysicalDriveIOCTL;
        char szDriveName[32];

        sprintf(szDriveName, "\\.\PhysicalDrive%d", nDrive);
        hPhysicalDriveIOCTL = CreateFile(szDriveName,
                        GENERIC_READ | GENERIC_WRITE,
                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                        OPEN_EXISTING, 0, NULL);

        if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
        {
            DWORD dwBytesReturned = 0;
            GETVERSIONOUTPARAMS gvopVersionParams;

            // Get the version, etc of PhysicalDrive IOCTL
            ZeroMemory(&gvopVersionParams, sizeof(GETVERSIONOUTPARAMS));

            if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION,
                    NULL, 0, &gvopVersionParams, sizeof(gvopVersionParams),
                    &dwBytesReturned, NULL))
            {
                continue;
            }

            if(gvopVersionParams.bIDEDeviceMap > 0)
            {
                // IDE or ATAPI IDENTIFY cmd
                BYTE btIDCmd = 0;
                SENDCMDINPARAMS InParams;
                // 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
                // 具体所得结果请参考头文件中的说明
                btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ?
                        IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
                ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));
                ZeroMemory(btIDOutCmd, sizeof(btIDOutCmd));

                if(DoIdentify(hPhysicalDriveIOCTL,
                     &InParams, (PSENDCMDOUTPARAMS)btIDOutCmd,
                     (BYTE)btIDCmd, (BYTE)nDrive, &dwBytesReturned))
                {
                    DWORD dwDiskData[256];
                    USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
                    char szSerialNumber[21];
                    char szModelNumber[41];

                    pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;
                    for(int i=0; i < 256; i++)
                        dwDiskData[i] = pIDSector[i];
                    // 取系列号
                    ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
                    strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

                    // 取模型号
                    ZeroMemory(szModelNumber, sizeof(szModelNumber));
                    strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

                    pSerList->Add(szSerialNumber);
                    pModeList->Add(szModelNumber);
                }
            }
            CloseHandle (hPhysicalDriveIOCTL);
        }
    }
}
//---------------------------------------------------------------------------
// DoIdentify
bool __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
              PSENDCMDOUTPARAMS pSCOP, BYTE btIDCmd, BYTE btDriveNum,
              PDWORD pdwBytesReturned)
{
    // 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 = (btDriveNum & 1) ? 0xB0 : 0xA0;

    // The command can either be IDE identify or ATAPI identify.
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    pSCIP->bDriveNumber = btDriveNum;
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;

    return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA,
           (LPVOID)pSCIP,
           sizeof(SENDCMDINPARAMS) - 1,
           (LPVOID)pSCOP,
           sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
           pdwBytesReturned, NULL);
}
//---------------------------------------------------------------------------
// Windows 95/98/ME 代码
//---------------------------------------------------------------------------
// ReadPhysicalDriveOnW9X
void __fastcall ReadPhysicalDriveOnW9X(TStrings *pSerList, TStrings *pModeList)
{
    WORD wOutData[256];
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);

    // 经过测试,发现第一次调用而且Drive >= 2时会在Ring0代码中出现错误,导致蓝屏。
    // 经过N(N > 15)次的蓝屏后仍找不到原因:(,不得不在这里增加一段无用代码以
    // 避免蓝屏的出现。(期待高人能指出原因)
    for(int nDrive = 0; nDrive < 8; nDrive++)
    {
        WORD dwBaseAddress;
        BYTE btMasterSlave;         // Master Or Slave
        bool bIsIDEExist;
        bool IsDiskExist;

        switch(nDrive / 2)
        {
            case 0: dwBaseAddress = 0x01F0; break;
            case 1: dwBaseAddress = 0x0170; break;
            case 2: dwBaseAddress = 0x01E8; break;
            case 3: dwBaseAddress = 0x0168; break;
        }

        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);

        // 进入Ring0
        ReadPhysicalDriveOnW9X_Ring0(true, dwBaseAddress, btMasterSlave,
                bIsIDEExist, IsDiskExist, wOutData);
    }

    // 开始读取
    for(int nDrive = 0; nDrive < 8; nDrive++)
    {
        WORD dwBaseAddress;
        BYTE btMasterSlave;         // Master Or Slave
        bool bIsIDEExist;
        bool bIsDiskExist;
        switch(nDrive / 2)
        {
            case 0: dwBaseAddress = 0x01F0; break;
            case 1: dwBaseAddress = 0x0170; break;
            case 2: dwBaseAddress = 0x01E8; break;
            case 3: dwBaseAddress = 0x0168; break;
        }

        btMasterSlave = (BYTE)(((nDrive % 2) == 0) ? 0xA0 : 0xB0);

        // 进入Ring0
        bIsIDEExist  = false;
        bIsDiskExist = false;
        ZeroMemory(wOutData, sizeof(wOutData));

        ReadPhysicalDriveOnW9X_Ring0(false, dwBaseAddress, btMasterSlave,
                bIsIDEExist, bIsDiskExist, wOutData);

        if(bIsIDEExist && bIsDiskExist)
        {
            DWORD dwDiskData[256];
            char  szSerialNumber[21];
            char  szModelNumber[41];

            for(int k=0; k < 256; k++)
                dwDiskData[k] = wOutData[k];

            // 取系列号
            ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
            strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

            // 取模型号
            ZeroMemory(szModelNumber, sizeof(szModelNumber));
            strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

            pSerList->Add(szSerialNumber);
            pModeList->Add(szModelNumber);
        }
    }
    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
}
//---------------------------------------------------------------------------
// 为防止不负责任的转载者,在此注明原出处信息,请见谅。
// 资料收集整理:ccrun(老妖),欢迎光临C++Builder研究: http://www.ccrun.com
//---------------------------------------------------------------------------
// ReadPhysicalDriveOnW9X_Ring0()
//
// dwBaseAddress = IDE(0,1,2,3) : 1F0h, 170h, 1E8h, 168h
// btMasterSlave = Master(0xA0) Or Slave(0xB0)
//---------------------------------------------------------------------------
void __fastcall ReadPhysicalDriveOnW9X_Ring0(bool bIsFirst, WORD dwBaseAddress,
        BYTE btMasterSlave, bool &bIsIDEExist, bool &bIsDiskExist, WORD *pOutData)
{
    BYTE  btIDTR1[6];
    DWORD dwOldExceptionHook;
    const int nHookExceptionNo = 5;

    BYTE  btIsIDEExist = 0;
    BYTE  btIsDiskExist = 0;
    WORD  wOutDataBuf[256];

    BYTE  btIsFirst = (BYTE)bIsFirst;

    const BYTE btBit00 = 0x01;
    // const BYTE btBit02 = 0x04;
    const BYTE btBit06 = 0x40;
    const BYTE btBit07 = 0x80;
    // const BYTE btERR  = btBit00;
    const BYTE btBusy = btBit07;
    const BYTE btAtaCmd   = 0xEC;
    const BYTE btAtapiCmd = 0xA1;

    __asm
    {
        // 必须先执行这条语句
        JMP EnterRing0

        // 定义过程
        // 等待IDE设备直到其不为忙为止
        WaitWhileBusy proc

        MOV  EBX, 100000
        MOV  DX, dwBaseAddress
        ADD  DX, 7

        LoopWhileBusy:

        DEC  EBX
        CMP  EBX, 0
        JZ   Timeout
        in   AL, DX
        TEST AL, btBusy
        JNZ  LoopWhileBusy
        JMP  DriveReady

        // 超时,直接退出
        Timeout:
        JMP  LeaveRing0
        DriveReady:
        RET
        ENDP   // End of WaitWhileBusy Procedure

        // 设置主盘和从盘标志
        SelectDevice proc

        MOV  DX, dwBaseAddress
        ADD  DX, 6
        MOV  AL, btMasterSlave

        out  DX, AL
        RET

        ENDP  // End of SelectDevice Procedure

        // 向IDE设备发送存取指令
        SendCmd proc

        MOV DX, dwBaseAddress
        ADD DX, 7
        MOV AL, BL // BL是主从盘标识,在过程外设置
        out DX, AL
        RET
        ENDP  // End of SendCmd Procedure

        // Ring0代码
        Ring0Proc:
        PUSHAD
        // 查询IDE设备是否存在
        MOV DX, dwBaseAddress
        ADD DX, 7
        in  AL,DX

        // 当AL的值是0xFF或者0x7F时,IDE设备不存在,这时候直接返回
        CMP AL,0xFF
        JZ  LeaveRing0
        CMP AL, 0x7F
        JZ  LeaveRing0

        // 设置IDE设备存在标志
        MOV btIsIDEExist, 1

        // 查询IDE设备上的驱动器是否存在(有IDE插槽在主板上,但是却不一定有硬盘插在上面)
        CALL WaitWhileBusy
        CALL SelectDevice

        // 如果是第一次调用,则直接返回,否则执行下行语句时会出现蓝屏
        CMP  btIsFirst, 1
        JZ   LeaveRing0

        // 第一次调用时,如果执行这行语句会导致蓝屏,Why???
        CALL WaitWhileBusy

        // AL的值等于cBit06时,不存在驱动器,直接返回
        TEST AL, btBit06
        JZ   LeaveRing0

        // 设置驱动器存在标志
        MOV  btIsDiskExist, 1

        // 发送存取端口命令
        // 无法像NT/2000/XP那样可以通过查询VERSION的值得到驱动器的类型,
        // 所以只能一步一步地测试,如果不是ATA设备,再尝试使用ATAPI设备命令
        CALL WaitWhileBusy
        CALL SelectDevice    // 设置主从盘标识
        MOV  BL, btAtaCmd      // 发送读取命令
        CALL SendCmd
        CALL WaitWhileBusy

        // 检查是否出错
        MOV  DX, dwBaseAddress
        ADD  DX, 7

        in   AL, DX

        TEST AL, btBit00
        JZ   RetrieveInfo   // 没有错误时则读数据

        // 如果出错,则进一步尝试使用ATAPI设备命令
        CALL WaitWhileBusy
        CALL SelectDevice
        MOV  BL, btAtapiCmd
        CALL SendCmd
        CALL WaitWhileBusy

        // 检查是否还出错
        MOV  DX, dwBaseAddress
        ADD  DX, 7
        in   AL, DX
        TEST AL, btBit00
        JZ   RetrieveInfo   // 没有错误时则读数据
        JMP  LeaveRing0     // 如果还是出错,直接返回

        // 读取数据
        RetrieveInfo:

        LEA  EDI, wOutDataBuf
        MOV  ECX, 256
        MOV  DX, dwBaseAddress
        CLD

        REP  INSW

        // 退出Ring0代码
        LeaveRing0:

        POPAD
        IRETD

        // 激活Ring0代码
        EnterRing0:

        // 修改中断门
        SIDT FWORD PTR btIDTR1
        MOV EAX, DWORD PTR btIDTR1 + 02h
        ADD EAX, nHookExceptionNo * 08h + 04h
        CLI

        // 保存原异常处理例程入口
        MOV ECX, DWORD PTR [EAX]
        MOV CX, WORD PTR [EAX-04h]
        MOV dwOldExceptionHook, ECX

        // 指定新入口
        LEA EBX, Ring0Proc
        MOV WORD PTR [EAX-04h],BX
        SHR EBX, 10h
        MOV WORD PTR[EAX+02h], BX

        // 激活Ring0代码
        INT nHookExceptionNo

        // 复原入口
        MOV ECX,dwOldExceptionHook
        MOV WORD PTR[EAX-04h], CX
        SHR ECX,10h
        MOV WORD PTR[EAX+02h], CX
        STI
    }
    if(!bIsFirst)
    {
        bIsIDEExist  = (bool)btIsIDEExist;
        bIsDiskExist = (bool)btIsDiskExist;
        CopyMemory(pOutData, wOutDataBuf, sizeof(wOutDataBuf));
    }
}
//---------------------------------------------------------------------------
// 调用方法:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    ReadPhysicalDrive(Memo1->Lines, Memo2->Lines);
}

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 在Win9x/NT下获取硬盘物理序列号

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00188