阅读:1550回复:13
com1
我按照《虚拟设备驱动程序开发起步与进阶》一书中6.2.2I/O类的例子作一个监控com1口的程序,当我在应用程序中对3f8进行访问时,并没有触发handler函数。按理说VXD是可以扑捉com1口的,可为什么我的程序一点反映也没有,如果我改换378端口程序就可以正常运行,我想一定是在Win98中对com1口有什么特别的要求。
请各位多多指教,要快呀 |
|
最新喜欢:![]() |
沙发#
发布于:2002-07-16 15:07
windows自己的VxD已经虚拟了大多数的I/O port,VMM只允许VxD捕获给定的port
|
|
板凳#
发布于:2002-07-16 17:32
我按照《虚拟设备驱动程序开发起步与进阶》一书中6.2.2I/O类的例子作一个监控com1口的程序,当我在应用程序中对3f8进行访问时,并没有触发handler函数。按理说VXD是可以扑捉com1口的,可为什么我的程序一点反映也没有,如果我改换378端口程序就可以正常运行,我想一定是在Win98中对com1口有什么特别的要求。 唔,你是不是那个发过贺卡的兄弟?呵呵 帮你写了一小段: 首先Vtoolsd的类在hook时使用Install_IO_Handler,注意这么一段话:The return value is TRUE if the service successfully installs the callback procedure. If a callback procedure is already installed for the specified port or the system limit for I/O callback procedures has been reached, then the service returns FALSE. 你所要的资源被系统占了,返回是FALSE。你非要Install的话首先把系统的干掉:Remove_IO_Handler。不过这样相应的原本系统的正常服务会变得不正常。不过可满足你够挂的欲望,呵呵。 小测试: CPP文件: // PPP.cpp - main module for VxD PPP #define DEVICE_MAIN #include \"ppp.h\" Declare_Virtual_Device(PPP) #undef DEVICE_MAIN MyPort::MyPort():VIOPort(MY_PORT_NUMBER){ Remove_IO_Handler(MY_PORT_NUMBER); if(hook()) { globalEnable(); } else { SHELL_Message(Get_Cur_VM_Handle(),MB_OK,\"ERROR\",\"ERROR\",NULL,NULL,NULL); } } MyPort::~MyPort(){ unhook(); } DWORD MyPort::handler(VMHANDLE hVM,DWORD port,CLIENT_STRUCT *pRegs,DWORD iotype,DWORD outdata) { switch(iotype){ case BYTE_INPUT: return 0x55; case WORD_INPUT: return 0x55AA; } return 0; } BOOL PppDevice::OnSysDynamicDeviceInit() { pPort=new MyPort(); return TRUE; } BOOL PppDevice::OnSysDynamicDeviceExit() { delete pPort; return TRUE; } 头文件: // PPP.h - include file for VxD PPP #include <vtoolscp.h> #define DEVICE_CLASS PppDevice #define PPP_DeviceID UNDEFINED_DEVICE_ID #define PPP_Init_Order UNDEFINED_INIT_ORDER #define PPP_Major 1 #define PPP_Minor 0 class MyPort :public VIOPort { public: MyPort(); ~MyPort(); virtual DWORD handler(VMHANDLE hVM,DWORD port,CLIENT_STRUCT *pRegs,DWORD iotype,DWORD outdata); }; #define MY_PORT_NUMBER 0x3f8 class PppDevice :public VDevice { public: MyPort *pPort; virtual BOOL OnSysDynamicDeviceInit(); virtual BOOL OnSysDynamicDeviceExit(); }; test小应用程序: #include<stdio.h> #include<windows.h> void main() { DWORD a,b; HANDLE hVxd; hVxd=CreateFile(\"\\\\\\\\.\\\\ppp.vxd\",0,0,0,CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0); if(hVxd==INVALID_HANDLE_VALUE) printf(\"Error!\"); _asm{ xor eax,eax mov dx,3f8h in al,dx mov a,eax in ax,dx mov b,eax } printf(\"%x,%x\\n\",a,b); CloseHandle(hVxd); } 结果: 55,55AA 最后重复说一句:这种hook是针对Ring3应用程序而言。 |
|
地板#
发布于:2002-07-17 15:03
感谢感谢,我终于捉到com1了。请接分吧!
|
|
地下室#
发布于:2002-07-17 15:28
不过我还有几个问题不明白,请帮我解答解答吧!
你说如果我用了Remove_IO_Handler,原本系统的正常服务会变得不正常。而且你在最后还一再说明“这种hook是针对Ring3应用程序而言。” 是这样的,我在捉到com1口后,我就在handler函数了写了一些东西,开始系统好好的,后来就莫名其妙的自动重启。而且我在vc环境下编的Vxd,打开编辑菜单应该有“构件*.VXD”,也变为“构件*.EXE”了。 我做的改动如下:(其他的和你给我的代码一样) DWORD MyPort::handler(VMHANDLE hVM,DWORD port,CLIENT_STRUCT *pRegs,DWORD iotype,DWORD outdata) {switch(iotype){ case BYTE_OUTPUT: { dout<<\"in byte data:\"<<(BYTE)outdata<<endl; Simulate_VM_IO( MY_PORT_NUMBER, WORD_OUTPUT, 0x40); break;} case WORD_OUTPUT:dout<<\"in word data:\"<<(WORD) outdata<<endl;break; case DWORD_OUTPUT:dout<<\"in dword data:\"<<(DWORD)outdata<<endl;break; default:break; } return 0; } 我只是想把3f8端口的字节转化为字操作,我发现我的VXD仍会捕捉 Simulate_VM_IO( MY_PORT_NUMBER, WORD_OUTPUT, 0x40)对3f8的操作,而不是执行这个输出操作。以后就只要我执行这个程序,系统就自动重启。 我的问题是: 1。系统自动重启,是因为我用Remove_IO_Handler使系统变得不正常了,还是我在handler里写得不对 2。为什么我在case BYTE_OUTPUT:用Simulate_VM_IO(MY_PORT_NUMBER, WORD_OUTPUT, 0x40);输出数据,还会被我的vxd的 case WORD_OUTPUT:再次捕获,而无法完成我想要的输出呢? 3。如果我想在vxd中也就是在ring0层,实现端口读写,怎么办呢? 我曾在一个VXD中单独用过simulate_VM_IO(0x3f8,WORD_OUTPUT,0x40) 是好用的呀,为什么在这里就不行呢? 麻烦你了!急切盼望你的回音。 [编辑 - 7/17/02 by amei] |
|
5楼#
发布于:2002-07-17 16:36
我这儿没有问题:
DWORD MyPort::handler(VMHANDLE hVM,DWORD port,CLIENT_STRUCT *pRegs,DWORD iotype,DWORD outdata) { switch(iotype){ case BYTE_OUTPUT: SHELL_Message(Get_Cur_VM_Handle(),MB_OK,\"OUTPUT\",\"BYTE\",NULL,NULL,NULL); Simulate_VM_IO( MY_PORT_NUMBER, WORD_OUTPUT, 0x40); break; case WORD_OUTPUT: break; case DWORD_OUTPUT: break; default: break; } return 0; } 你看看其他地方有何问题? 我没98,在2000下编译了vxd还得跑N远去运行,很ft |
|
6楼#
发布于:2002-07-19 10:53
昨天出了一趟近差,今早回来第一件事就是看帖子。看到你给我回帖很高兴。在你handler改动如下:
case BYTE_OUTPUT: SHELL_Message(Get_Cur_VM_Handle(),MB_OK,\"OUTPUT\",\"BYTE\",NULL,NULL,NULL); Simulate_VM_IO( MY_PORT_NUMBER, WORD_OUTPUT, 0x40); break; case WORD_OUTPUT: SHELL_Message(Get_Cur_VM_Handle(),MB_OK,\"OUTPUT\",\"WORD\",NULL,NULL,NULL); break; 测试程序: _asm {mov dx,3f8h mov al,34h out dx,al } 当你执行程序后,你会看到执行了两次SHELL_Message函数,一次是BYTE的,一次是WORD的,也就是说VXD捕获了一次字节输出,捕获了一次,字输出。 你测试你的3f8端口了吗?你保证输入了一个40h的字吗? 要使3f8可读写首先要往3fb里输入80h. [编辑 - 7/19/02 by amei] |
|
7楼#
发布于:2002-07-19 15:26
还有一个问题就是
win32程序是在系统虚拟机,dos程序是在虚拟机,vxd 程序在虚拟机之外,当我在vxd中对端口进行访问(比如,往3f8送一个40h),那我在dos下用debug的i,o命令对端口访问(i 3f8), 结果是00 ,是正常的吗? |
|
8楼#
发布于:2002-07-20 21:29
昨天出了一趟近差,今早回来第一件事就是看帖子。看到你给我回帖很高兴。在你handler改动如下: 两三天没上网了,好忙。 捕获两次是因为你用的是Simulate_VM_IO,它并不简单执行out指令。你将其改为_outpw就不会这样了,它就是直接在ring0发端口指令。 |
|
9楼#
发布于:2002-07-20 21:33
还有一个问题就是 v86模式下相当于一个更受限制的ring3环境,但是v86监控机有可能在捕获异常后帮助其访问端口,模拟一个正确访问的过程。 |
|
10楼#
发布于:2002-07-23 14:33
多谢多谢!
后来我也用_outpd了。 |
|
11楼#
发布于:2002-07-23 14:38
多谢多谢!
高人呀,你怎么对vxd的函数那么精通呢?能否指点一二! |
|
12楼#
发布于:2002-07-23 18:13
高手高手,我也来灌灌 :D :P
|
|
|
13楼#
发布于:2002-07-23 19:12
多谢多谢! 精通?才不行呢,一用2000就没写过vxd了,好遥远的东西。 |
|