请问Delphi中有无可以不通过系统调用直接读写磁盘的函数,就象TC中的bios.c单元中的biosdisk函数(50分)

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

springwater

Unregistered / Unconfirmed
GUEST, unregistred user!
请问Delphi中有无可以不通过系统调用直接读写磁盘的函数,就象TC中的bios.c
单元中的biosdisk函数。用法如下:
"biosdisk(2,0,0,0,1,1,buf);"
表示:读软盘驱动器的0磁头、0磁道、1扇区的一个扇区的内容到缓冲区buf中。
Delphi中有类似功能的函数吗?望指点,谢谢。
 
nt/2000/xp 下可以用api: CreateFile 打开设备: "//./A:"
就可以按扇区读写软盘了
 
内嵌汇编
 
;* 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;
}
 
可以发你一个Dio函数,但千万小心使用!!!否则有可能损坏你的硬盘Boot区。你的Email?
 
感谢各位!
to IamWLJ888 谢了
我会用软盘先做实验的。
my E mail : delphibaby@163.com
 
谢谢各位
to IamWLJ888,
居然真有人用Delphi写出了如此底层的作品,值得好好研究,
写程序的人好厉害,真是个少有的Delphi高手。
谢谢您,
 
后退
顶部