汇编仿FDISK及PQMAGIC列出分区逻辑盘符的prw.asm实现
2007-11-13 09:31:21 来源:WEB开发网核心提示: (8) 论V86下,直寻硬盘扇区,只能靠VxDVToolsD建的C级VxD,有读/写DOS分区的R0_ReadAbsoluteDisk/R0_Write...函数.例如,响应自32位C的W32_DEVICEIOCONTROL事件时,用格式R0_Read...(2,1,0,buf,&w),读相对DOS分区的逻辑扇号是1
(8) 论V86下,直寻硬盘扇区,只能靠VxD
VToolsD建的C级VxD,有读/写DOS分区的R0_ReadAbsoluteDisk/R0_Write...函数.
例如,响应自32位C的W32_DEVICEIOCONTROL事件时,用格式R0_Read...(2,1,0,buf,&w),读相对DOS分区的逻辑扇号是1的分区引导扇区PBS.这时,当前虚拟机hVM,是系统(证于Test_Sys_VM_Handle测事件实参IOCTLPARAMS.dioc_hvm).VxD不改hVM身份.
又如,响应自16位ASM程序的V86_API_Entry入口调用时,同上,读PBS,这时,hVM是DOS(证于Test_...测入口实参VMHANDLE).
均读PBS含"MSWIN4...".
但VxD,也能在V86下,用Exec_Int(0x13),法如13h,直寻硬盘,如PBS之前MBR.
笔者c.cpp+a.exe,直读MBR连续5扇.需cfg.sys,隐dev=EMM386
(8.1) 用QuickVxD,建C++级VxD,设备名=C,设备ID=0x3180,选动态装
选API页Standard App Entry Points框Real/V86 Mode.体,见(8.3).
选OnSysDynamicDevice的Init及Exit.体中:
选发SHELL_SYSMODAL_Message(Get_Cur_VM_Handle(),MB_SYSTEMMODAL,"m","cap")
必发return(true)
(8.2) 写a.asm,汇编时,/DNPAGE=5,指明5扇.读变写,需debug下,改r2w3处的2为3.
VxD查客户这5扇缓区,囿V86空间1页(4K字节)的整体性,未全囿,bp返回<4k的修正量.
IF2
IF NPAGE LT 1 or NPAGE GT 8
%OUT 0 .ERR
ENDIF
ENDIF
d segment
buf db NPAGE*512*2-1 dup(9);留足修区
entry dd 0
d ends
c segment
assume cs:c,ds:d
@: mov bp,d
mov ds,bp
mov ax,1684h 功能号
mov bx,3180h 接口ID
int 2fh
mov ax,es es/di=API_Entry入口段/偏移
or ax,di
jz @3 ;es及di全为零,失败
mov word ptr [entry],di
mov word ptr [entry+2],es
mov ax,ds 设exec_int参数
mov es,ax
lea bx,buf es:bx,指向缓区首
r2w3: mov ah,2 读80h硬盘MBR处NPAGE扇
mov al,NPAGE
mov cx,1 0:0:1(chs)
mov dx,128
std VxD出兰屏,写修
call [entry]
cmp bp,4096 VxD按(8.3)返bp值
jae @2
add bx,bp 修缓区首址
test ah,1 查读/写
jz @1 此例ah=2,读盘
lea si,buf 写入时,从后向前,移NPAGE*256字
add si,NPAGE*512-1 si指向原缓区尾
mov di, si
add di,bp di指向新缓区尾
mov cx, NPAGE*256
rep movsw ds:si所指cx字,移到es:di
mov cx,1
@1: call [entry]
cmp bp,4096
@2: je @3
cmp bp,1010h
jne @3
xor ah,ah ;释它页
call [entry]
@3: xor ax,ax
mov es,ax
mov ax,[bx+1beh] 成功/失败,72h矢量=分区表首字/9
mov es:[1c8h],ax
mov ah,4ch
int 21h
c ends
end @
(8.3) ...V86_API_Entry(VMHANDLE hVM, CLIENT_STRUCT* pRegs)体
DWORD h,t;
CLIENT_STRUCT s;
if(pRegs->CBRS.Client_AH){//2读3写
h=(DWORD)Map_Flat(CLIENT_ES,CLIENT_BX);//h=客户缓区首es:bx的32位线性址
t=h+pRegs->CBRS.Client_AL*512-1;//t=尾的线性址
if((h>>12)!=(t>>12)){
pRegs->CWRS.Client_BP=(4096-(h&4095));//首尾未囿同页,bp返客户增bx量
return;
}
if((h>>12)<0x110)//缓区能被V86寻,bp返4096
pRegs->CWRS.Client_BP=4096;
else
if(LinMapIntoV86(h>>12,hVM,0x10,1,0,&t)){
//缓区所在页,成功映入V86第0x10页,bp返0x1010
pRegs->CWRS.Client_BP=0x1010;
h=(16<<12)+(h&4095);//由t及偏移,得缓区V86址h
}else{//无页等,bp返0x1110
pRegs->CWRS.Client_BP=0x1110;
return;
}
Save_Client_State(&s);//存reg
Begin_Nest_V86_Exec();//当前虚拟机,能寻V86
pRegs->CRS.Client_ES=(h>>4);//es=址h的段值
pRegs->CRS.Client_EBX=(h&15);//bx=址h的偏移
Exec_Int(0x13);
End_Nest_Exec();//复原
Restore_Client_State(&s);
if(pRegs->CWRS.Client_Flags&1024){//方向,控兰屏
sprintf((char*)s.CBRS.Client_res30,"%x",pRegs->CWRS.Client_BP);
SHELL_SYSMODAL_Message(hVM,MB_SYSTEMMODAL,(char*)s.CBRS.Client_res30,"bp");
}
}else//知bp返0x1010时,客户释它页
MapIntoV86(GetNulPageHandle(),hVM,16,1,0,0);
(8.4) 装VxD法
静态:
放C.VXD于c:\windows\system,在c:\windows\system.ini的386Enh,写device=C.VxD,再reboot
动态4法:
用VxD_Loader,选C.VXD
用DriverMonitor,先打开C.VXD,再Start
放C.VXD于c:\windows\system\iosubsys,再reboot
用笔者DOS窗口a的exe
#include
#define pre "\\\\.\\"
main(int ac,char *av[]){
char *vxd;
HANDLE h;
if (ac==1) printf("vxd_load ?.vxd\n");
else{
vxd=malloc(strlen(pre)+strlen(av[1]));
sprintf(vxd,"%s%s",pre,av[1]);
h=CreateFile(vxd,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0);
if(h!=INVALID_HANDLE_VALUE){
printf("To unload,hit Enter");
getch();
CloseHandle(h);
}
}
}
装C.VXD,事毕,敲回车到窗a,卸此VXD
更多精彩
赞助商链接