发信人: black()
整理人: wenbobo(2002-12-27 15:48:51), 站内信件
|
近日在水木清华看到如下文章,给愿意分析VXD的参考:
发信人: Shuanshuan (阿涮), 信区: Programming 标 题: windows9x下绝对读写硬盘扇区的例程 发信站: BBS 水木清华站 (Sat Aug 21 17:32:04 1999)
由于win9x下由win32程序对硬盘的写操作被屏蔽,所以绝对硬盘的读写的思路在于 设法转入16位程序,因此有两种方法可以达到这种目的:使用THUNK机制调用16位DLL 或用VxD转到16位方式,我觉得用THUNK太麻烦,其实VxD挺好编的,而且用起来也方便, 当时也是出于学习目的,编了这么一个VxD,还是挺好用的,我看精华区对这个问题的讨 论好像没有什么结果,就把它贴出来,算是班门弄斧吧! 我是用DDK编的,主要是因为我当时是出于学习.
//这是程序的主要部分,其中有一些宏定义,从字面上就能知道是干什么的,我就不罗嗦 //了 DWORD _stdcall CVXD_W32_DeviceIOControl(LPDIOC lpDIOCParms, CLIENT_STRUCT *pRegs) { DWORD dwRetVal = 0,retu; DWORD *i; PVMMCB hVM; DIOC_REGISTERS *lpReg,*lpOutReg; CLIENT_STRUCT saveregs; DWORD PageNum; WORD PageOff; DWORD Address; DWORD V86PageNum,MyPage; WORD seg,offset; hVM=Get_Cur_VM_Handle(); i=(DWORD *)(lpDIOCParms->lpvOutBuffer); lpReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvInBuffer); lpOutReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvOutBuffer); switch(lpDIOCParms->dwIoControlCode) { . . . case 2: if(lpDIOCParms->cbInBuffer!=sizeof(DIOC_REGISTERS)) return dwRetVal=-1;
//保存当前虚拟机的寄存器状态 _asm push edi _asm lea edi,saveregs VMMCall(Save_Client_State); _asm pop edi
//输入的参数,具体怎么用看INT13的说明吧 _ClientEAX=lpReg->reg_EAX; _ClientEDX=lpReg->reg_EDX; _ClientECX=lpReg->reg_ECX; _ClientEFlags=lpReg->reg_Flags;
/* 以下这一段是编写这个VxD时要考虑的主要问题:把缓冲区的地址映射入虚拟86的地址 区,Win32中用的都是线性地址,先根据它求出页面号,再把缓冲区所在的页映射到虚拟86区 中去,下面程序中有一个Bug,它没有考虑到缓冲区所占页面大于一页时的情形,事实上,缓 冲区可能处在叶面的边界上,而且它的大小可能超过一页,这些都要根据上面参数中给出 的缓冲区大小计算,当时我嫌麻烦,随便应付了一下.用的时候要把这段代码改一下 */ PageNum=(lpReg->reg_EBX)>>12; PageOff=(lpReg->reg_EBX)&0xfff; _asm{ push 0 push 1 push 10 push hVM push PageNum } VMMCall(_LinMapIntoV86); _asm add esp,14h _asm mov retu,eax _asm mov MyPage,edx //返回的页面号在edx寄存器中 if(retu==0) return 3;//这是我自己胡乱选的错误码,你可以自己定成 //其它值 Address=(MyPage<<12)+PageOff;//计算新的线性地址 seg=LOWORD(Address>>4); //把线性地址转化成传统的段:偏 offset=LOWORD(Address-(seg<<4)); //移量的形式 _ClientAltES=seg;//这里一定不能弄错了,在Win32 Ring3程序中用的 //是_ClientES,而虚拟86方式下用的段寄存器则在 //_ClientAltES中,所以要用它 _ClientBX=offset;
//xixi,好戏开始了 VMMCall(Begin_Nest_V86_Exec);//这一句使得系统转入虚拟86方式 _asm mov eax,13h VMMCall(Exec_Int);//发出int 13h中断调用 //保存返回值 if(lpDIOCParms->cbOutBuffer==sizeof(DIOC_REGISTERS)) { lpOutReg->reg_Flags=_ClientEFlags; lpOutReg->reg_EAX=_ClientEAX; lpOutReg->reg_EBX=_ClientEBX; lpOutReg->reg_ECX=_ClientECX; lpOutReg->reg_EDX=_ClientEDX; } End_Nest_Exec();//退出虚拟86方式 //轻轻地我走了,正如我轻轻地来,我挥一挥衣袖,不带走一片云彩 _asm push esi _asm lea esi,saveregs VMMCall(Restore_Client_State); _asm pop esi //这一段取消原来的映射 VMMCall(_GetNulPageHandle); _asm mov PageNum,eax _asm{ push 0 push 0 push 1 push 10 push hVM push PageNum } VMMCall(_MapIntoV86); _asm add esp,18h //OK return dwRetVal=0; } return dwRetVal; }
-- 6m※ 修改:·Shuanshuan 於 Aug 21 17:34:10 修改本文·[FROM: 162.105.23.174]m m5m※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 162.105.23.174]m
-- ------------------------------------------------------------------------------- 黑夜给了我黑色的眼睛,我用它寻找光明 Email : [email protected]
※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.173.119]
|
|