首页  编辑  

HD S/N

Tags: /超级猛料/Hardware.硬件相关/驱动器相关/硬盘/硬盘序列号/   Date Created:

]、。·ˉˇ¨〃々—~‖…’”〕〉》」』〗】∶!"'),.:;?]` #include <stdlib.h>

#include  <bios.h>

#include <dos.h>

#include <math.h>

#include <stdio.h>

char *GetAscii(unsigned int inData[], int offStart, int offEnd);

int main(void)

{

 unsigned int  diskData[256];    /* Disk data                  */

 unsigned int  offset;          /* Disk data offset          */

 int            loop;

 int            numDrv;          /* Number of IDE hard drives  */

 union REGS    registers;

 unsigned int  biosCyl[2];      /* Cylinders, Heads, Sectors */

 unsigned int  biosHead[2];

 unsigned int  biosSec [2];

 printf("\nCopyright 2000.02.16 IDESCAN.");

 //printf("\n                            ");

 numDrv = peekb(0x40, 0x75);      /* BIOS Data area, Number of Hard disks */

 for (loop = 0; loop < numDrv; loop++)

 {

     while (inp(0x01f7) != 0x50);  /* Wait for controller not busy        */

     outp(0x01f6, (loop == 0 ? 0xa0 : 0xb0));  /* Get first/second drive  */

     outp(0x01f7, 0xec);                      /* Get drive info data      */

     while (inp(0x1f7)!= 0x58);  /* Wait for data ready                  */

     for (offset = 0; offset != 256; offset++) /* Read "sector"            */

diskData[offset] = inpw(0x1f0);

     /* Get BIOS drive info */

     registers.h.ah = 0x08;        /* Get drive info                          */

     registers.h.dl = 0x80 + loop; /* Drive is 80H for Disk 0, 81H for Disk 1 */

     int86(0x13, &registers, &registers);

     if (!registers.x.cflag)      /* All OK if carry not set */

     {

biosHead[loop] = registers.h.dh + 1;      /* Heads are from 0GetAscii(diskData, 27, 46), */

biosSec[loop]  = registers.h.cl & 0x3f;  /* sec is bits 5 - 0 */

/* +1 because starts from 0 and +1 for FDISK leaving one out */

biosCyl[loop]  = ((registers.h.cl & 0xc0) << 2) + registers.h.ch + 2;

     } /* end of if */

     printf("\nFIX DRIVE %d:\n", loop);

     printf("Model Number______________________:%s  \n",GetAscii(diskData, 27, 46));

     printf("Serial Number_____________________::%s \n", GetAscii(diskData, 10, 19));

     printf("Controller Revision Number________: %s\n", GetAscii(diskData, 23, 26));

     printf("Able to do Double Word Transfer___: %6s\n", (diskData[48] == 0 ? "No" : "Yes"));

     printf("Controller type___________________:  %04X\n", diskData[20]);

     printf("Controller buffer size (bytes)____: %6u\n", diskData[21] * 512);

     printf("Number of ECC bytes transferred___: %6u\n", diskData[22]);

     printf("Number of sectors per interrupt___: %6u\n", diskData[47]);

     printf("Hard Disk Reports                \n");

     printf("Number of Cylinders (Fixed)_______: %6u\n", diskData[1]);

     printf("Number of Heads___________________: %6u\n", diskData[3]);

     printf("Number of Sectors per Track_______: %6u\n", diskData[6]);

     printf("BIOS Reports\n");

     printf("Number of Cylinders_______________: %6u\n", biosCyl[loop]);

     printf("Number of Heads___________________: %6u\n", biosHead[loop]);

     printf("Number of Sectors per Track_______: %6u\n", biosSec[loop]);

     printf("\n");

     //getch();

 } /* end of for */

 return 0;

} /* main() */

char *GetAscii(unsigned int inData[], int offStart, int offEnd)

{

 static char retVal[255];

 int        loop, loop1;

 for (loop = offStart, loop1 = 0; loop <= offEnd; loop++)

 {

     retVal[loop1++] = (char )(inData[loop] / 256);  /* Get High byte */

     retVal[loop1++] = (char )(inData[loop] % 256);  /* Get Low byte  */

 } /* end of for */

 retVal[loop1] = '\0';    /* Make sure it ends in a NULL character */

 return retVal;

} /* GetAscii() */

--------------

读取硬盘出厂信息

进入0级

bool CallRing0(PVOID pvRing0FuncAddr, WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)

读端口

bool GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)

写端口

bool SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize)

回复人:Searph(2000-11-28 8:38:00)  得30分

---- 硬盘的序列号只能采用对硬盘控制器直接操作的方式进行读取,也就是说只能采用CPU的I/O指令操作硬盘控制器,读取的方法如下面的C语言程序所示:

static int WaitIde()

{

 int  al;

 while ((al=inp(0x1F7)) >=0x80) ;

 return al;

}

static void ReadIDE()

{

 int  al;

 int  i;

 WORD  pw[256];

 WaitIde();

 outp(0x1F6,0xA0);

 al = WaitIde();

 if ((al&0x50)!=0x50) return;

 outp(0x1F6,0xA0);

 outp(0x1F7,0xEC);

 al = WaitIde();

 if ((al&0x58)!=0x58) return;

 for (i=0;i< 256;i++)

     pw[i] = inpw(0x1F0);

}

---- 上面的程序实际上读取了保存在硬盘控制器内的全部信息,而序列号只是其中的一部分,位于上面提到的 pw[] 数组的 10 至 20 元素内,即从 &pw[10] 开始的10个WORD内,每个WORD占两个字节,共占用了20个字节。由于该序列号保存时每个WORD的高、低字节是非Intel顺序,也就是说它的高字节在前,低字节在后,所以在使用时需要将高、低字节颠倒一下,这样就能得到完整的序列号。

不过要在ring0下,在98下可以通过以下方法得到ring0

令Win32应用程序跳入系统零层

---- 众 所 周 知, 在Windows95/98 的Win32 on Intel x86 体 系 中 利 用 了 处 理 器 的 三 环 保 护 模 型 中 的 零 环(Ring0, 最 高 权 限 级 别) 和 三 环(Ring3, 最 低 权 限 级 别)。 一 般 应 用 程 序 都 运 行 在Ring3 下, 受 到 严 格 的" 保 护", 只 能 规 矩 地 使 用Win32API。 如 果 我 们 想 进 行 一 些 系 统 级 的 操 作, 例 如 在 嵌 入 汇 编 中 使 用 诸 如"Mov EAX,CR0", 或 像 在DOS 下 那 样 调 用 一 些 必 不 可 少 的 系 统 服 务( 如BIOS,DPMI 服 务) 而 用"Int xx", 都 会 导 致" 非 法 操 作"。 但 这 种 能 力 有 时 是 必 不 可 少 的, 一 到 这 种 时 候Microsoft 就 " 建 议 编 写 一 个VxD"。VxD 大 家 早 有 所 闻 了, 在VxD 里, 不 但 可 以 执 行CPU 的 所 有 指 令, 而 且 可 以 调 用VMM( 虚 拟 机 管 理 器) 和 其 他VxD 提 供 的 上 千 个 系 统 级 服 务。 获 得 这 一 能 力 的 最 本 质 原 因 在 于 它 运 行 在Ring0, 与 系 统 内 核 同 一 级 别。 但 是 它 体 系 的 复 杂 性、 开 发 工 具 的 不 易 获 得、 帮 助 文 档 的 不 完 备, 使Microsoft 排 除 了 一 大 批 程 序 员 和 竞 争 对 手。 而 将 在Windows2000(Windows98 也 开 始 支 持) 中 取 代VxD 的WDM 对Win95 程 序 员 也 是 个 噩 梦, 它 需 要 了 解Windows NT 核 心 驱 动 模 型。

----有 没 有 简 单 一 些 的 办 法 呢 ? 我 们 可 以 令 一 个 普 通Win32 应 用 程 序 运 行 在Ring0 下, 从 而 获 得VxD 的 能 力 吗 ? 答 案 是 肯 定 的。 下 面 我 们 就 简 述 一 下 这 一 技 巧, 有 关Intel x86 保 护 模 式 的 基 础 知 识 请 大 家 看 有 关 书 籍。

----首 先 此 技 巧 基 于 以 下 理 论 根 据:

----一、SIDT 指 令( 将 中 断 描 述 符 表 寄 存 器 IDTR - -64 位 宽,16 ~47Bit 存 有 中 断 描 述 符 表IDT 基 地 址 - - 的 内 容 存 入 指 定 地 址 单 元) 不 是 特 权 指 令, 就 是 说 我 们 可 以 在Ring3 下 执 行 该 指 令, 获 得IDT 的 基 地 址, 从 而 修 改IDT, 增 加 一 个 中 断 门 安 置 我 们 的 中 断 服 务, 一 旦Ring3 程 序 中 产 生 此 中 断,VMM 就 会 调 用 此 中 断 服 务 程 序, 而 此 中 断 服 务 程 序 就 运 行 在Ring0 下 了。 这 一 点 与 在DOS 下 非 常 相 似。

----二、Windows95 Win32 应 用 程 序 运 行 一 个 映 射 到 全 部4G 内 存 的 段 中, 选 择 子 为0137h,Ring0 中 的VxD 运 行 在 另 一 个 映 射 到 全 部4G 内 存 的 段 中, 选 择 子028h, 这 两 个 段 除 了 选 择 子 决 定 的 访 问 权 限 不 同 外, 没 什 么 不 同, 各 自 段 中 相 同 的 偏 移 量 对 应 了 相 同 的 线 性 地 址。 所 以 我 们 放 在Win32 应 用 程 序 中 的 中 断 服 务 程 序 可 以 以Ring3 的 段 偏 移 量 被Ring0 中 的VMM 寻 址。

----下 面 我 们 以 具 体 例 子 进 一 步 说 明, 程 序 中 有 详 细 注 释。

----这 是 一 个Win32 Console Program( 控 制 台 应 用 程 序), 虽 然 运 行 中 看 起 来 很 像DOS 筐 中 运 行 的 实 模 式DOS 程 序, 但 它 是 货 真 价 实 的 运 行 在Ring3 下 的Win32 程 序。 用Visual C + + 5.0 AppWizard 创 建 一 个Win32 Console Program 项 目, 添 加 以 下.CPP 文 件, 编 译 即 可。

#include

#include

#include

#include

 // 若 无DDK 带 下 划 线 的 可 略 去,

 这 些 语 句 演 示 了 调 用VMM/VXD 服 务

DWORDLONG IDTR,SavedGate;

WORD OurGate[4]={0,0x0028,0xee00,0x0000};

// 中 断 门 描 述 符 格 式 如 下:

DWORD _eax,_ecx,_cr0;

WORD vmmver;

HVM sysvm;

void nothing()

{

     //Used to test call in Ring0

     sysvm=Get_Sys_VM_Handle();

}

void __declspec( naked ) Ring0Proc(void)

 // 中 断 例 程, 运 行 在Ring0

{

     _asm{

           mov  _eax,eax    //

           mov  _ecx,ecx    //

           mov  eax, CR0    

 // 测 试Ring3 中 不 能 执 行 的 特 权 指 令

           mov  _cr0,eax    //

     }

           VMMCall(Get_VMM_Version);

 // 调 用VMM 服 务

     _asm{

           mov vmmver,ax

     }

     nothing();  

 // 测 试 在 运 行 于Ring0 的

   中 断 例 程 中 调 用 子

           _asm  iretd  

 // 中 断 返 回, 与 在 实 模 式

   编 程 无 本 质 区 别

}

void main() // 主 程 序

{

     _asm{

     mov  eax, offset Ring0Proc

     mov  [OurGate], ax  // 将 中 断 函 数 的 地 址

     shr  eax, 16  // 填 入 新 造 的 中 断 门

     mov  [OurGate +6], ax // 描 述 符

     sidt  fword ptr IDTR    

 // 将 中 断 描 述 符 表 寄 存 器(IDTR)

   的 内 容 取 出

     mov  ebx, dword ptr [IDTR +2]

 // 取 出 中 断 描 述 符 表(IDT) 基 地 址

     add  ebx, 8 *9  

 // 计 算Int 9 的 描 述 符 应 放 置 的 地 址 选 用

   Int9 是 因 为 它 在Win32 保 护 模 式 下 未 占 用

     mov      edi, offset SavedGate

     mov      esi, ebx

     movsd  // 保 存 原 来 的Int 9 描 述 符 到

     movsd  //SavedGate 以 便 恢 复

     mov      edi, ebx

     mov      esi, offset OurGate

     movsd  // 替 换 原 来 的 中 断 门 描 述 符

     movsd  // 以 安 装 中 断 服 务 例 程

     mov  eax,0x6200

 // 用 以 测 试 放 在EAX 中 的 数 据

   能 否 正 确 传 到Ring0 中 断

     mov  ecx,0

 // 用 以 测 试 放 在ECX 中 的 数 据

   能 否 正 确 传 到Ring0 中 断

     mov  ecx,0

 // 用 以 测 试 放 在ECX 中 的 数 据

   能 否 正 确 传 到Ring0 中 断

             // 因 为 很 多VxD 服 务 都 用

               此 二 寄 存 器 传 递 参 数

     int  9h  

   // 人 为 触 发 中 断, 平 时 会 出 现

     保 护 错 误 蓝 屏 或 非 法 操

           // 作 对 话 框, 现 在 安 装 了

           // 中 断 服 务 例 程 后, 就 会 通 过

           //VMM 在Ring0 调 用 中 断 服 务 例 程

               - -Ring0Proc

     mov    edi, ebx

     mov    esi, offset SavedGate

     movsd // 恢 复 原 来 的 中 断 门 描 述 符

     movsd

     }

     cout<<"CR0="<<_cr0<

*********************************************

/* 程序1: 获得IDE硬盘C的序列号 */

#include <stdio.h>

#include <stdlib.h>

#include <dos.h>

#include <conio.h>

#include <string.h>

char *getascii (unsigned int in_data [], int off_start, int off_end);

void main (void)

{

 unsigned int dd [256]; /* DiskData */

 unsigned int dd_off;   /* DiskData offset */

 while (inp (0x1F7) != 0x50)  /* Wait for controller not busy */

       ;

 outp (0x1F6, 0xA0);          /* Get first/second drive */

 outp (0x1F7, 0xEC);          /* Get drive info data */

 while (inp (0x1F7) != 0x58)  /* Wait for data ready */

       ;

 for (dd_off = 0; dd_off != 256; dd_off++) /* Read "sector" */

       dd [dd_off] = inpw (0x1F0);

 printf ("The Serial Number Hard Disk [C] is %s", getascii (dd, 10, 19));

}

char *getascii (unsigned int in_data [], int off_start, int off_end)

{

 static char ret_val [255];

 int loop, loop1;

 for (loop = off_start, loop1 = 0; loop <= off_end; loop++)

   {

     ret_val [loop1++] = (char) (in_data [loop] / 256);  /* Get High byte */

     ret_val [loop1++] = (char) (in_data [loop] % 256);  /* Get Low byte */

   }

 ret_val [loop1] = '\0';  /* Make sure it ends in a NULL character */

 return (ret_val);

}

/* 程序2: 获得逻辑盘C的序列号 */

#include <stdio.h>

#include <stdlib.h>

#include <ctype.h>

#include <dos.h>

void main(void)

{

     char serial_no[10];

     union REGS r;

     struct SREGS s;

     unsigned sno1, sno2;

     r.x.ax = 0x6900;

     r.h.bl = 3;        /* A:=1, B:=2, C:=3 etc. */

     segread(&s);

     intdosx(&r, &r, &s);

     if (r.x.cflag)

           *serial_no = '\0';

     else

     {

           sno2 = *((unsigned far *)MK_FP(s.ds, r.x.dx+2));

           sno1 = *((unsigned far *)MK_FP(s.ds, r.x.dx+4));

           sprintf(serial_no, "%04X-%04X\n", sno1, sno2);

     }

     printf("The Serial Number of Login Disk [C] is %s", serial_no );

}