📄 hdisksn.cpp
字号:
wait_addr = base_addr + 0x07;
masl_para = IDE_MASL_PARA[nWhich % 2];
for(i=0; i<2; i++) // 若不是ATA型,则试一试ATAPI型
{
// 等待硬盘空闲状态,以检测其是否存在
WaitHardDiskIde(wait_addr);
__asm
{
mov dx, order_addr
mov al, masl_para // 选择主从盘
out dx, al
inc dx // 加1为0x07
mov al, 0x10
out dx, al // 返到00磁道
}
// 若直接在Ring3级执行等待命令,会进入死循环
xx = WaitHardDiskIde(wait_addr);
if((xx & 0x50) != 0x50) {i = 2; break;}
// 试着两次分别发送ATA/ATAPI设备类型
dev_type = IDE_DEV_TYPE[i];
__asm
{
mov dx, order_addr
mov al, masl_para // 选择主从硬盘
out dx, al
inc dx // 加1为0x07
mov al, dev_type
out dx, al // 发送读参数命令
}
// 等待读驱动器参数命令返回有效
xx = WaitHardDiskIde(wait_addr);
if((xx & 0x58) == 0x58) break;
}
if(i >= 2) continue; // 硬盘尚未安装或无法处理
// 读取硬盘控制器的全部信息:共512字节
for(i=0; i<256; i++)
{
__asm
{
mov dx, base_addr
in ax, dx
mov temp, ax
}
SCK_HD_INFO[i] = temp;
}
if(!pHdInfo->sModelNumber[0]) continue;
HD_OPER_ISOK = TRUE; END_HDNO = nWhich; return;
}
}
//-------------------------------------------------------------------------//
// 中断内:读写磁盘扇区,通过Int 20h/Vx=0010h的第0004号服务
static void OpenHardDiskSectorByIOS(void)
{
BYTE iorBuffer[0x104] = {0x00}; // 0x104 = 0xAC + 0x58, sizeof(IOR)=0x58
memset(iorBuffer, 0x00, sizeof(iorBuffer)); // I/O Request Descriptor
IOR *ior = (IOR *)(&iorBuffer[0xAC]);
ior->IOR_vol_designtr = IOR_WHICH_DISK; // Init IOR structor data
ior->IOR_func = IOR_R2W_OPERATE ? IOR_WRITE : IOR_READ;
ior->IOR_flags = IORF_PHYS_CMD | IORF_VERSION_002 | IORF_SYNC_COMMAND | IORF_HIGH_PRIORITY;
ior->IOR_buffer_ptr = (ULONG)(&SCK_IO_BUFF[0]); // Buffer pointer 1 sector
ior->IOR_xfer_count = 1; // counts for transfer
HD_OPER_ISOK = FALSE; // Indicates oper result
DWORD dwStartSector = IOR_START_SECTOR;
BYTE *lpBuffer = IOR_OUT_BUFFER; // Pointer to out buffer
for(DWORD i=0; i<IOR_XFER_COUNT; i++) // Handle all sectors to oper
{
ior->IOR_start_addr[0] = dwStartSector++; // Sector number <= 4GB
ior->IOR_start_addr[1] = 0x00;
ior->IOR_next = 1;
if(IOR_R2W_OPERATE) memcpy(SCK_IO_BUFF, lpBuffer, DISK_SECTOR_SIZE);
__asm
{
push es // Protect registers
push ds
pushad
mov esi, ior // Send IOR pointer para
mov ax, ss
mov es, ax
mov ds, ax
int 20h // IOS_SendCommand(ior, NULL)
_emit 0x04
_emit 0x00
_emit 0x10
_emit 0x00 // 5 lines == The order above
popad
pop ds
pop es // Restore registers
}
if(ior->IOR_status != 0) break;
if(!IOR_R2W_OPERATE) memcpy(lpBuffer, SCK_IO_BUFF, DISK_SECTOR_SIZE);
lpBuffer += DISK_SECTOR_SIZE; // Move to next sector
}
if(i >= IOR_XFER_COUNT) HD_OPER_ISOK = TRUE; // Return if oper success
}
//-------------------------------------------------------------------------//
// 自定义新的中断:Win9x下专用中断服务程序
static void __declspec(naked) InterruptProcessSck007(void)
{
__asm // 保存寄存器值
{
push eax
push ebx
push ecx
push edx
push esi
}
switch(CURR_WORK_TYPE)
{
// 读取IDE硬盘控制器的主从硬盘信息
case SCK_SN_INFOR: ReadHardDiskInfoFromCtrlIDE(); break;
// 读写指定(逻辑/物理)磁盘扇区数据
case SCK_RW_HDISK: OpenHardDiskSectorByIOS(); break;
}
__asm
{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
} // 中断的返回处理
}
// 在Win9x下,启动专用的中断程序,以获得Ring 0级权限
static BOOL StartInterruptProcess(void)
{
if(SCK_INT_ENABLE) return FALSE;
DWORD OldInterruptAddress;
DWORDLONG IDTR;
HD_OPER_ISOK = FALSE;
SCK_INT_ENABLE = TRUE; // 标记中断已经打开
__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, InterruptProcessSck007
mov WORD PTR [eax - 04h], bx
shr ebx, 10h
mov WORD PTR [eax + 02h], bx
pop ebx
// 执行中断,由Ring 3级转到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
}
SCK_INT_ENABLE = FALSE; // 标记中断已经关闭
return HD_OPER_ISOK; // 返回此次提取成功标志
}
//-------------------------------------------------------------------------//
// 由已经打开的设备驱动句柄,来提取各硬盘的详细信息,不负责关闭句柄
static BOOL ReadHardDiskInfoByHandle(HANDLE hSmartDrv, LONG nWhich = -1)
{
if(hSmartDrv == INVALID_HANDLE_VALUE) return FALSE; // Handle is invalid
if(nWhich < 0 || nWhich > 3) return FALSE; // Parameter Input Incorrect
SENDCMDINPARAMS in; // Define variables
SENDCMDOUTPARAMS out;
DWORD dwReturn = 0L; // Return from device
GETVERSIONOUTPARAMS vers;
memset(&vers, 0, sizeof(vers)); // Clear area content
BYTE byAtApi = 0;
memset(SCK_HD_INFO, 0x00, sizeof(SCK_HD_INFO)); // Clear hdisk infor
IDSECTOR *pHdInfo = (IDSECTOR *)out.bBuffer; // HDisk Infor data area
if(!DeviceIoControl(hSmartDrv, DFP_GET_VERSION, NULL, 0, &vers, sizeof(vers),
&dwReturn, NULL)) return FALSE; // failed:DFP_GET_VERSION
if(((vers.bIDEDeviceMap >> nWhich) & 1) == 0) // Detect if exist a IDE device
return FALSE; // And Check if is a ATAPI type
byAtApi = !((vers.bIDEDeviceMap >> nWhich) & 0x10) ? 0 : 1;
memset(&in, 0, sizeof(in)); // Clear I/O area content
memset(&out, 0, sizeof(out)); // Try to Enable ATA SMART driver
// Set up data structures for Enable SMART Command.
in.cBufferSize = 0;
in.irDriveRegs.bFeaturesReg = SMART_ENABLE_SMART_OPERATIONS;
in.irDriveRegs.bSectorCountReg = 1;
in.irDriveRegs.bSectorNumberReg = 1;
in.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
in.irDriveRegs.bCylHighReg = SMART_CYL_HI;
in.bDriveNumber = (BYTE)nWhich;
in.irDriveRegs.bDriveHeadReg = IDE_MASL_PARA[nWhich % 2]; // Master or Slave
in.irDriveRegs.bCommandReg = IDE_EXECUTE_SMART_FUNCTION;
if(!DeviceIoControl(hSmartDrv, DFP_SEND_DRIVE_COMMAND,
&in, sizeof(in), &out, sizeof(out) - IDENTIFY_BUFFER_SIZE,
&dwReturn, NULL)) return FALSE; // failed:Enable SMART driver
SckMsDelay(100);
memset(&in, 0, sizeof(in)); // Clear I/O area content
memset(&out, 0, sizeof(out));
in.cBufferSize = IDENTIFY_BUFFER_SIZE; // 512 Bytes HDisk Info
in.irDriveRegs.bSectorCountReg = 1;
in.irDriveRegs.bSectorNumberReg = 1;
in.bDriveNumber = (BYTE)nWhich;
in.irDriveRegs.bDriveHeadReg = IDE_MASL_PARA[nWhich % 2]; // Master or Slave
in.irDriveRegs.bCommandReg = IDE_DEV_TYPE[byAtApi]; // ATA or ATAPI
if(!DeviceIoControl(hSmartDrv, DFP_RECEIVE_DRIVE_DATA,
&in, sizeof(in), &out, sizeof(out),
&dwReturn, NULL)) return FALSE; // failed:RECEIVE_DRIVE_DATA
if(!pHdInfo->sModelNumber[0]) return FALSE; // Read HDisk Infor failed
memcpy(SCK_HD_INFO, out.bBuffer, sizeof(SCK_HD_INFO));
return TRUE; // Success read hard disk info
}
// 读取在Win9x环境下的硬盘信息:ASM中断直接操作内存地址
static BOOL ReadWin9xHardDiskInfoAsm(void)
{
if(SCK_INT_ENABLE) return FALSE;
CURR_WORK_TYPE = SCK_SN_INFOR;
return StartInterruptProcess();
}
// 检测并提取Win9x下的硬盘物理信息:采用SmartVsd.VXD驱动
static BOOL ReadWin9xHardDiskInfoVxd(void)
{
char chPath[MAX_PATH] = "SYSTEM\\IOSUBSYS\\SmartVsd.VXD";
MakeSureDrvExist(chPath, IDR_SMARTVSDVXD); // 获取驱动程序目录
END_HDNO = -1; // Which HDisk Found
memset(SCK_HD_INFO, 0x00, sizeof(SCK_HD_INFO)); // Clear hdisk infor
HANDLE hSmartDrv = CreateFile("\\\\.\\SMARTVSD", 0, 0, 0, CREATE_NEW, 0, 0);
if(hSmartDrv == INVALID_HANDLE_VALUE) return FALSE; // Open SmartVsd.VXD failed
BOOL bSuccess = FALSE; // Search if Success
// Identify the IDE[0, 1] Controler Get four Hard Drives all, Odd for Slave
for(BYTE j=(BYTE)FROM_HDNO; j<=(BYTE)TO_HDNO; j++)
{
bSuccess= ReadHardDiskInfoByHandle(hSmartDrv, j);
if(bSuccess == TRUE) {END_HDNO = j; break;}
}
CloseHandle(hSmartDrv); return bSuccess; // Return result of read info
}
// 用S.M.A.R.T驱动读取WinNT下的IDE硬盘的设备信息,必须有足够权限
static BOOL ReadWinNTHardDiskInfoPhysic(void)
{
char chDevFile[MAX_PATH] = ""; // The device file name
HANDLE hSmartDrv = INVALID_HANDLE_VALUE; // Handle of device driver
BOOL bSuccess = FALSE; // Result of read info
END_HDNO = -1; // Which HDisk Found
memset(SCK_HD_INFO, 0x00, sizeof(SCK_HD_INFO)); // Clear hdisk infor
// Identify the two controller all, administrator right needed
for(BYTE j=(BYTE)FROM_HDNO; j<=(BYTE)TO_HDNO; j++)
{
sprintf(chDevFile, "\\\\.\\PhysicalDrive%d", j);
hSmartDrv = CreateFile(chDevFile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if(hSmartDrv == INVALID_HANDLE_VALUE) continue; // Open failed
bSuccess = ReadHardDiskInfoByHandle(hSmartDrv, j);
CloseHandle(hSmartDrv);
if(bSuccess == TRUE) {END_HDNO = j; break;}
}
return bSuccess; // Return result of read info
}
// 用SCSI驱动读取WinNT下的IDE硬盘的设备信息,不受权限制约
static BOOL ReadWinNTHardDiskInfoAsScsi(void)
{
char chDevFile[MAX_PATH] = ""; // The device file name
HANDLE hScsiDrv = INVALID_HANDLE_VALUE; // Handle of device driver
BYTE bySRBIO[SRB_IOBUFF_SIZE]; // SCSI输入输出共用数据
PSRB_IO_CONTROL pSRBIO = (PSRB_IO_CONTROL)bySRBIO;
PSENDCMDINPARAMS pSCIP = (PSENDCMDINPARAMS)(bySRBIO + sizeof(SRB_IO_CONTROL));
PSENDCMDOUTPARAMS pSCOP = (PSENDCMDOUTPARAMS)(bySRBIO + sizeof(SRB_IO_CONTROL));
IDSECTOR *pHdInfo = (IDSECTOR *)pSCOP->bBuffer; // HDisk Infor data area
DWORD dwReturn = 0L, i = 0; // Return from device
memset(SCK_HD_INFO, 0x00, sizeof(SCK_HD_INFO)); // Clear hdisk infor
END_HDNO = -1; // Which HDisk Found
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -