DeviceIoControl接口
DeviceIoControl接口
在这一节中我们将要关于学习动态VXD,特别是如何创建,加载和使用。
点击这里下载例子
VxD接口
VxD总共提供了4种接口。
l VxD services VxD服务
l V86 Interface V86接口
l Protected-mode (PM) Interface 保护模式接口
l Win32 DeviceIoControl Interface Win32设备输入输出控制接口
我们已经知道了VxD服务,V86和保护模式接口是由V86和保护模式程序调用的。因为V86和保护模式程序是16位的,我们不能在Win32应用程序中使用那两种接口。在Windows 95中,微软给Win32应用程序加了另外一个接口所以Win32应用程序可以调用VxD的服务:DeviceIoControl接口(设备输入输出控制接口)
DeviceIoControl接口
简单的说,DeviceIoControl接口是一种为Win32程序准备的调用VxD内部函数的方法。不要混淆DeviceIoControl接口调用函数和用VxD服务调用函数,这两种方法是不一样的。比如说,DeviceIoControl function1 也许和Vxd service1是不一样的。你应给把DeviceIoControl函数作为一种只为Win32应用程序提供的单独的函数。
在Win32程序方面:
首先用CreateFile来打开/加载一个VxD。如果调用成功的话,VxD将会创建/加再到内存中并且CreateFile把VxD的句柄返回到eax中。
接着你调用DeviceIoControlAPI函数来选择要运行的函数。DeviceIoControl函数遵循下面的语法:
DeviceIoControl PROTO hDevice:DWORD,/
dwIoControlCode:DWORD,/
lpInBuffer:DWORD,/
nInBufferSize:DWORD,/
lpOutBuffer:DWORD,/
nOutBufferSize:DWORD,/
lpBytesReturned:DWORD,/
lpOverlapped:DWORD
l hDevice 是从CreateFile返回的VxD句柄。
l dwIoControlCode是用来制定VxD将要进行的操作。你应该在你要选用那种操作之前得到可能的dwIoControlCode值得列表。
l lpInBuffer是包含了VxD完成dwIoControlCode所制定操作的数据的缓冲区地址。如果这个操作不需要数据,你可以传为NULL。
l nInBufferSize是由lpInBuffer所指向的缓冲区的地址的大小(byte)。
l lpOutBuffer是VxD程序在操作成功之后要将输出数据输出到的缓冲区。如果这个操作没有任何返回值,这个值可以为NULL。
l nOutBufferSize是lpOutBuffer所指向的缓冲区的大小(byte)。
l lpBytesReturned是一个dword型变量的地址。这个变量用来接收VxD在lpOutBuffer中写入数据的大小。
l 如果你想要把操作设成异步的,lpOverlapped是一个OVERLAPPED结构的指针。如果你要一直等直到操作完成,这个值为NULL。
在VxD方面:
VxD程序必须处理w32_deviceIoControl消息。当VxD收到w32_deviceIoControl消息,它的寄存器是如下值:
l ebx 是VM的句柄。
l esi 是指向DIOCParams结构的指针。DIOCParams包含了从win32程序传送的信息。
DIOCParams是按照如下定义的:
DIOCParams STRUC
Internal1 DD ?
VMHandle DD ?
Internal2 DD ?
dwIoControlCode DD ?
lpvInBuffer DD ?
cbInBuffer DD ?
lpvOutBuffer DD ?
cbOutBuffer DD ?
lpcbBytesReturned DD ?
lpoOverlapped DD ?
hDevice DD ?
tagProcess DD ?
DIOCParams ENDS
l Internal1 是指向Win32应用应用程序用户寄存器结构的指针。
l VMHandle 虚拟机句柄
l Internal2 是指向设备描述块(DDB)的句柄。
l dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped是传送到DeviceIoControl API的参数。
l hDevice是 ring-3级设备句柄。
l tagProces 是过程的标签。
在DIOCParams结构中有所有从Win32应用程序传送到你的VxD的信息。
你的VxD至少要处理DIOC_Open(传送到dwIoControlCode),那是当Win32程序调用CreateFile打开你的VxD时VWIN32发送给你的VxD的。如果你的VxD准备好了,它必须在eax中返回0而且CreateFile也会成功。如果你的VxD没有准备好,它必须在eas中返回一个非零值而且CreateFile也会失败。除了DIOC_Open,当Win32程序关闭这个设备句柄时,你的VxD将会从VWIN32收到DIOC_Closehandle。
能由CreateFile加载的最小的动态VxD框架:
.386p
include vmm.inc
include vwin32.inc
DECLARE_VIRTUAL_DEVICE DYNAVXD,1,0, DYNAVXD_Control,/
UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER
Begin_control_dispatch DYNAVXD
Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl
End_control_dispatch DYNAVXD
VxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
.endif
ret
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDS
end
;--------------------------------------------------------------------------------------------------------------------------------
; Module Definition File
;---------------------------------------------------------------------------------------------------------------------------------
VXD DYNAVXD DYNAMIC
SEGMENTS
_LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
_TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE
_TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE
_BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LMGTABLE CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL
_LMSGDATA CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL
_IMSGTABLE CLASS 'MCODE' PRELOAD DISCARDABLE IOPL
_IMSGDATA CLASS 'MCODE' PRELOAD DISCARDABLE IOPL
_ITEXT CLASS 'ICODE' DISCARDABLE
_IDATA CLASS 'ICODE' DISCARDABLE
_PTEXT CLASS 'PCODE' NONDISCARDABLE
_PMSGTABLE CLASS 'MCODE' NONDISCARDABLE IOPL
_PMSGDATA CLASS 'MCODE' NONDISCARDABLE IOPL
_PDATA CLASS 'PDATA' NONDISCARDABLE SHARED
_STEXT CLASS 'SCODE' RESIDENT
_SDATA CLASS 'SCODE' RESIDENT
_DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
_DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
_DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING
_16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE
_RCODE CLASS 'RCODE'
EXPORTS
DYNAVXD_DDB @1
完整例子:
下面是一段加载动态VxD并且通过DeviceIoControl API 来调用VxD内部函数的Win32应用程序的源代码。
; VxDLoader.asm
.386
.model flat,stdcall
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
AppName db "DeviceIoControl",0
VxDName db "//./shellmsg.vxd",0
Success db "The VxD is successfully loaded!",0
Failure db "The VxD is not loaded!",0
Unload db "The VxD is now unloaded!",0
MsgTitle db "DeviceIoControl Example",0
MsgText db "I'm called from a VxD!",0
InBuffer dd offset MsgTitle
dd offset MsgText
.data?
hVxD dd ?
.code
start:
invoke CreateFile,addr VxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0
.if eax!=INVALID_HANDLE_VALUE
mov hVxD,eax
invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION
invoke DeviceIoControl,hVxD,1,addr InBuffer,8,NULL,NULL,NULL,NULL
invoke CloseHandle,hVxD
invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION
.else
invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR
.endif
invoke ExitProcess,NULL
end start
下面这段源代码是由 vxdloader.asm 调用的动态VxD。
; ShellMsg.asm
.386p
include vmm.inc
include vwin32.inc
include shell.inc
DECLARE_VIRTUAL_DEVICE SHELLMSG,1,0, SHELLMSG_Control,/
UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER
Begin_control_dispatch SHELLMSG
Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl
End_control_dispatch SHELLMSG
VxD_PAGEABLE_DATA_SEG
pTitle dd ?
pMessage dd ?
VxD_PAGEABLE_DATA_ENDS
VxD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
.elseif [esi].dwIoControlCode==1
mov edi,[esi].lpvInBuffer
;-----------------------------------
; copy the message title to buffer
;-----------------------------------
VMMCall _lstrlen, <[edi]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pTitle,eax
pop eax
VMMCall _lstrcpyn,<pTitle,[edi],eax>
;-----------------------------------
; copy the message text to buffer
;-----------------------------------
VMMCall _lstrlen, <[edi+4]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pMessage,eax
pop eax
VMMCall _lstrcpyn,<pMessage,[edi+4],eax>
mov edi,pTitle
mov ecx,pMessage
mov eax,MB_OK
VMMCall Get_Sys_VM_Handle
VxDCall SHELL_sysmodal_Message
VMMCall _HeapFree,pTitle,0
VMMCall _HeapFree,pMessage,0
xor eax,eax
.endif
ret
EndProc OnDeviceIoControl
VxD_PAGEABLE_CODE_ENDS
end
分析:
我们从VxDLoader.asm开始。
Invoke CreateFile,addrVxDName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0
.if eax!=INVALID_HANDLE_VALUE
mov hVxD,eax
....
.else
invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR
.endif
我们调用CreateFile来加载动态VxD。注意FILE_FLAG_DELETE_ON_CLOSE标记。当从CreateFile返回的VxD句柄被关闭的时候,这个标志通知Windows卸载VxD。如果CreateFile成功,我们把VxD句柄保存起来。
invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION
invoke DeviceIoControl,hVxD,1,addr InBuffer,8,NULL,NULL,NULL,NULL
invoke CloseHandle,hVxD
invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION
当VxD加载/卸载的时候,这个程序会显示一个消息框。它令dwIoControlCode=1然后调用DeviceIoControl。将InBuffer的地址传给lpInBuffer,将InBuffer的大小传给nInBufferSize。InBuffer是一个包括两个元素的数组:每个元素都是一个字符串的地址。
MsgTitle db "DeviceIoControl Example",0
MsgText db "I'm called from a VxD!",0
InBuffer dd offset MsgTitle
dd offset MsgText
现在我们看一下这段VxD。
它只处理w32_deviceIoControl消息。当w32_deviceIoControl消息发送的时候,调用OnDeviceIoControl函数。
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
OnDeviceIoControl 处理DIOC_Open,再eas中返回0。
.elseif [esi].dwIoControlCode==1
mov edi,[esi].lpvInBuffer
它也处理control code 等于1。它做的第一件事是取出在lpyInBuffer中的数据。这个数据是传送到DeviceIoControl API 的lpInBuffer中的两个dword值。它把指向dword数组的地址放到edi中。第一个dword是作为消息框标题的字符串地址。第二个dword是作为消息框文本的字符串地址。
;-----------------------------------
; copy the message title to buffer
;-----------------------------------
VMMCall _lstrlen, <[edi]>
inc eax
push eax
VMMCall _HeapAllocate,<eax,HEAPZEROINIT>
mov pTitle,eax
pop eax
VMMCall _lstrcpyn,<pTitle,[edi],eax>
它调用VMM服务lstrlen来计算消息框标题的长度。lstrlen在eax中返回字符串的长度。我们把这个长度加1来包括结束标记NULL。下一步我们通过调用HeapAllocate来分配一块足够大可以容纳字符串和它的结束标记NULL内存。加上HEAPZEROINIT标记使HeapAllocate将这块内存清零。HeapAllocate在eax中返回这块内存的地址。我们然后从win32 app的地址空间把字符串拷贝到我们申请的内存中。我们对要做消息框文本的字符串做同样的操作。
mov edi,pTitle
mov ecx,pMessage
mov eax,MB_OK
VMMCall Get_Sys_VM_Handle
VxDCall SHELL_sysmodal_Message
我们把标题和文本的地址分别存在edi和ecx中。把想要的标记放在eax中,通过调用Get_Sys_VM_handle得到系统VM的VM 句柄。然后调用SHELL_sysbodal_Message 。SHELL_sysModal_Message是系统SHELL_Message的模式版本。它冻结系统直到用户对消息框做出反应。
VMMCall _HeapFree,pTitle,0
VMMCall _HeapFree,pMessage,0
当SHELL_sysmodal_Message返回时,我们用_HeapFree释放内存。
总结:
DeviceIoControl接口使你的win32应用程序使用动态VxD作为一个ring-0 DLL扩展非常理想。
DeviceIoControl接口相关推荐
- usbview源码阅读与总结
一.所用接口总结 整个工程里,只用了如下几种与USB驱动相关的接口: 1.DeviceIoControl HANDLE hHCDev = CreateFile("\\.\HCD0" ...
- 转 Java知识——精华总结
一.java概述与基础知识 1.何为编程? 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程. 为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路. ...
- 编程资料 -C# 多线程
编程资料 - 多线程 C#多线程编程实例实战 作者: 刘弹 www.ASPCool.com 时间:2003-5-17 上午 10:24:05 阅读次数:10996 单个写入程序/多个阅读程序在.Net ...
- 编程资料 -C# 多线程 1
编程资料 - 多线程 C#多线程编程实例实战 作者: 刘弹 www.ASPCool.com 时间:2003-5-17 上午 10:24:05 阅读次数:10996 单个写入程序/多个阅读程序在.Net ...
- 实战DeviceIoControl 之中的一个:通过API訪问设备驱动程序
Q 在NT/2000/XP中,我想用VC编写应用程序訪问硬件设备,如获取磁盘參数.读写绝对扇区数据.測试光驱实际速度等,该从哪里入手呢? A 在NT/2000/XP中,应用程序能够通过API函数Dev ...
- MFC: DeviceIoControl 通过API访问设备驱动程序
转载:http://m.blog.csdn.net/article/details?id=21602051 DeviceIoControl的其实和ReadFile和WriteFile是一样的, 不过这 ...
- Windows下usb接口驱动技术(二)
八. Windows驱动程序模型 Windows环境下驱动程序共有三类,一类是VxD( Virtual Device Driver,虚拟设备驱动程序),起源于Windows 3.1 时代 ...
- 结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址
虽然Win32_NetworkAdapter包含了属性PermanentAddress,但是在当前的WMI里只是个空值,微软目前还没有实现这个属性值.但是我们仍可以通过结合WMI和DeviceIoCo ...
- DeviceIOControl实战
实战DeviceIoControl 之一:通过API访问设备驱动程序 Q 在NT/2000/XP中,我想用VC编写应用程序访问硬件设备,如获取磁盘参数.读写绝对扇区数据.测试光驱实际速度等,该从哪里入 ...
最新文章
- 21天mysql_把整个Mysql拆分成21天,轻松掌握,搞定(下)
- Dropout层 tf.keras.layers.Dropout() 介绍
- 简单说明PHP的垃圾收集机制是怎样的?
- linux基础—课堂随笔_03 SHELL脚本编程基础
- 2021山东科技大学计算机学院,2021年3月山东科技大学计算机等级考试报名工作通知...
- 怎样设置 vmware 开放一个网络端口,使网络上的电脑能访问这个端口
- Python将类对象转换为json
- ZJOI2019 线段树
- PMP_模考三 (3A通过分享)(180题附答案及解析)
- Notepad++设置记录
- 【经验】迅雨田下载测试
- C语言-输出一个菱形图。
- CSS — 表格 和 表单
- layer打开iframe弹层,传递与接收参数
- excel matlab日期,Excel日期格式在matlab中的转换
- Latex图表中英文双标注之多个子图
- 单片机双机通信c语言实验心得,80C51单片机双机通信与多机通信的使用方法
- 抖音直播dou+与视频dou+有什么区别;超详细dou+玩法投放技巧;丨国仁网络资讯
- Docker报错误Cannot connect to the Docker daemon
- qsv视频格式转换器怎么转换视频格式
热门文章
- 淘宝新手入门视频教程哪里有?
- 2022年全国职业院校技能大赛网络安全竞赛试题 A-2样题
- 2022年全国职业院校技能大赛(中职组)网络安全竞赛试题第十套A模块解析
- camtasia studio2022电脑屏幕录像录屏剪辑
- 网络设备割接—七大步骤
- tools:replace specified at line: for attribute android:appComponentFactory, but no new value specifi
- 大数据毕设选题 - 深度学习股票预测系统(python Django)
- 大数据毕业设计 基于时间序列的股票预测与分析系统 - 大数据分析
- 使用kolla-ansible部署多节点OpenStack(T版)及对接Ceph
- Android项目模拟器提示:Unfortunately,XXX has stopped?