iczelion Vxd cntut4

威泰克斯vxd720等数字对讲机写频软件 立即下载

VxD 程序设计入门

We 我们在上一节学会了如何编写一个什么事也不做的VxD程序。在这一节里,我们要给它增加处理控制消息的功能。

VxD的初始化和结束

VxD程序分为两种:静态的和动态的。每种的加载方法都不同,接受到的初始化和结束的控制消息也不同。

静态VxD:

下列情况下,VMM加载一个静态VxD:

  • 一个实模式常驻程序通过调用中断2FH,1605H,来调用此VxD。
  • 此VxD在注册表中的如下位置有定义:
    • HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/VxD/key/StaticVxD=VxD带路径文件名
  • 此VxD在system.ini中的[386enh]行下有定义:[386enh] section:

    • device=VxD带路径文件名

在开发的时候,我建议你从system.ini载入VxD程序,因为这样如果你的VxD程序有错而导致Windows不能启动的话,你可以在Dos下修改system.ini,而如果你使用的注册表载入的办法,就无法修改了。
当VMM加载你的静态VxD程序时,你的VxD程序会按以下顺序接收到三个系统控制消息:

  • Sys_Critical_Init  VMM在转入到保护模式后,开放中断前发出这个控制消息。大多数VxD程序到不要用到这个消息,除非:
    • 你的VxD程序要接管一些其他VxD程序或者保护模式程序要用到的中断。既然你处理这个消息的时候这个中断还没有打开,你就可以确定在你接管这个中断的时候此中断不会被调用。
    • 你的VxD程序为其他的VxD程序提供了一些VxD服务。例如,一些在你的VxD程序后加载的VxD程序在处理Device_Init控制消息时需要调用一些你的VxD服务,既然Sys_Critical_Init 控制消息在Device_Init消息之前被发送,所以你应该在Sys_Critical_Init 消息发送时初始化你的程序。
    如果你要对这消息进行处理,你应该尽可能快的做完初始化工作,以免太长的执行时间导致的硬中断丢失。(记住:中断还没打开)
  • Device_Init VMM在开放中断后发送此信息。大多数VxD程序都在得到这个消息时初始化。因为中断都开放了,所以耗时的操作也可以在这里执行而不必怕会导致硬中断的丢失。你可以在这时进行初始化(如果你需要的话)。
  • Init_Complete 在所有的VxD程序处理完Device_Init 消息之后,VMM释放初始化段(ICODE和RCODE段类)之前,VMM发出这个控制消息。只有少数几个VxD要处理这个消息。

你的VxD程序在成功地初始化后,必须将返回标志清零,反之,必须在返回之前把返回标志设为出错信息。如果你的VxD不需要初始化,你就不必对这些消息进行处理。
当要结束静态VxD的时候,VMM发送如下的控制消息:

  • System_Exit2  当你的VxD程序收到这个消息,Windows95正在关闭系统,除了系统虚拟机所有其他虚拟机都已经退出了。尽管如此,CPU仍然处于保护模式下,在系统虚拟机上执行实模式编码也是安全的。在这时Kernel32.dll也已经被卸载了。
  • Sys_Critical_Exit2  当所有的VxD完成对System_Exit2的响应处理并且中断都被关闭后,你的VxD收到到这个消息。

许多VxD程序并不要响应这两个消息,除非你要为系统做转换到实模式的准备。要知道,当Window95关闭时,它进入到实模式。所以如果你的VxD程序对实模式影像做了一些会导致它不稳定的操作,它就需要在这时进行恢复。
你也许会感到奇怪:为什么这两个消息后面都跟着个“2" ”。这是因为:在VMM加载VxD程序的时候,它是按照初始化顺序值小的VxD先加载的顺序加载的,这样VxD程序就可以使用那些在它们之前加载的VxD程序提供的服务。例如,VxD2要用到VxD1中的服务,它就必须把它的初始化顺序值定义的比VxD小。加载的顺序是:

..... VxD1 ===>  VxD2 ===> VxD3 .....

那么卸载的时候,理所当然的是初始化顺序值大的VxD程序先被卸载,这样他们仍然可以使用比它们后加载的那些VxD程序提供的服务。如上面的例子,次序是:

.... VxD3 ===> VxD2 ===> VxD1.....

在上边的例子中,如果VxD2在初始化时调用了VxD1中的某些服务,那么卸载时它可能也要再次用到一些VxD1中的服务。System_Exit2Sys_Critical_Exit2反初始化顺序发送的。这表示,当VxD2接受到这些消息时,VxD1还没有被卸载,它仍可以调用VxD1的服务,而System_ExitSys_Critical_Exit消息不是按照反初始化顺序发送的。这意味着,你不能肯定你是否仍能调用在你之前加载的VxD提供的VxD服务。新一代的VxD程序不应该使用这些消息。
还有两种退出消息:

  • Device_Reboot_Notify2  告诉VxD程序VMM正在准备重新启动系统。这时候中断还是开放的。
  • Crit_Reboot_Notify2  告诉VxD程序VMM正在准备重新启动系统。这时候中断已经被关闭了。

到这里,你可以猜到还有Device_Reboot_NotifyCrit_Reboot_Notify 消息,但它们并不是像“2”版本的消息一样按反初始化顺序发送的。

动态VxD:

动态VxD在Windows9x里可以动态的被加载和卸载。这个特点在Window3.x下是没有的。动态VxD程序的主要作用是用来支持某些动态的硬件设备的重装,比如:即插即用设备。尽管如此,你可以从你的Win32程序中加载/卸载它,也可以把它看作是你的程序的一个到ring-0的扩展。
上一节我们提到的例子是一个静态的VxD,你可以把它转换成一个动态的VxD,只要在.def文件中VxD标记的后面加上关键字DYNAMIC

VxD   FIRSTVxD   DYNAMIC

这就是你把一个静态VxD转换成一个动态的VxD所要做的一切。
一个动态的VxD可以按以下的方法被加载:

  • 把它放到你的Windows目录下的/SYSTEM/IOSUBSYS目录中。在这个目录里的VxD会被输入输出监视器(ios)加载。这些VxD必须支持层设备驱动。所以用这种方法加载你的动态VxD并不是一个好办法。
  • 用VxD加载服务。 VxDLDR是一个可以加载动态VxD的静态VxD。你可以在其他VxD里面或者在16位代码里面调用它的服务。
  • 用Win32应用程序里的 CreateFile API。你在调用CreateFile时,你的动态VxD要以下面的格式填写:

    • //./VxD完整路径名


    例如,如果你要加载一个在当前目录下名为FirstVxD的动态VxD,你需要做如下的工作:

    .data
    VxDName db "//./FirstVxD.VxD",0
    ......
    .data?
    hDevice dd ?
    .....
    .code
    .....
    invoke CreateFile, addr VxDName,0,0,0,0, FILE_FLAG_DELETE_ON_CLOSE,0
    mov hDevice,eax
    ......
    invoke CloseHandle,hDevice
    ......
     

FILE_FLAG_DELETE_ON_CLOSE 这个标志用来说明该VxD在CreateFile返回的句柄关闭时被卸载。
如果你用CreateFile来加载一个动态VxD,那么这个动态VxD必须处理w32_DeviceIoControl 消息。当你的动态VxD第一次被CreateFile函数加载的时候,VWIN32 向你的VxD发出这个消息。你的VxD响应这个消息,返回时eax中的值必须为零。当应用程序调用DeviceIoControl API来与一个动态VxD通讯时,w32_DeviceIoControl消息也被发送。我们会在下一章讲到DeviceIoControl接口。
一个动态VxD在初始化时收到一个消息:

  • Sys_Dynamic_Device_Init

在结束时也收到一个控制消息:

  • Sys_Dynamic_Device_Exit

动态VxD不会收到Sys_Critical_Init, Device_InitInit_Complete控制消息,因为这些消息是在系统虚拟机初始化时发送的。除了这三个消息,动态VxD能收到所有的控制消息,只要它还在内存里。它可以做静态VxD可以做的所有事情。简单的说,动态VxD除了加载机制和接收到的初始化/结束消息跟静态VxD不同以外,它能做静态VxD所能做的一切。

其它系统控制消息

当VxD在内存里的时候,除了接收和初始化及结束相关的消息外,它还要收到许多别的控制消息。有些消息是关于虚拟机管理器的,有的是关于各种事件的。例如,关于虚拟机的消息如下:

  • Create_VM
  • VM_Critical_Init
  • VM_Suspend
  • VM_Resume
  • Close_VM_Notify
  • Destroy_VM

选择地响应你所感兴趣的消息是你自己的责任。

在VxD内创建函数

你要在一个段里面定义你的函数。你应该首先定义一个段,然后把你的函数放进去。例如,如果你要把你的函数放到一个可调页段中。你应该先定义一个可调页段,像这样:

VxD_PAGEABLE_CODE_SEG

(你的函数写在这里)

VxD_PAGEABLE_CODE_ENDS

你可以在一个段里面插入多个的函数。作为一个VxD编写者,你必须决定每一个函数应该放到哪个段里面去。如果你的函数必须时刻存在于内存中,如某些硬件中断处理程序,就把它们放到锁定页面段里面,否则,你应该把它们放到可调页段。
你要用BeginProcEndProc 宏来定义你的函数:

BeginProc 函数名

EndProc 函数名

使用BeginProc 宏还可以加上一些参数,想了解这些细节,你可以看看Win95 DDK的文档。大多数时候,你只用填写函数的名字就够了。
因为BeginProc-EndProc 宏比proc-endp 指令的功能要强,所以你应该用BeginProc-EndProc宏来代替proc-endp指令

VxD编程约定

寄存器的使用

你的VxD程序可以使用所有的寄存器,FS和GS。但是在改动段寄存器的时候一定要小心。尤其是,一定不要改动CS和SS的内容,除非你对将发生的事情有绝对的把握。你可以使用DS和ES,但一定要记住在返回时恢复它们初值。有两个特征位尤其重要:方向和中断特征位。不要长时间的屏蔽中断。还有如果你要改动方向特征位,不要忘了在返回之前恢复它的初值。

参数传递约定

VxD服务函数有两种调用约定:寄存器法和堆栈法。调用寄存器法服务函数时,你通过各种寄存器来传递服务函数的参数。并且,在调用完成后检查寄存器的值来看操作是否成功。不要总是以为在调用服务函数后主要寄存器的值还和以前一样。当调用堆栈法服务函数时,你把要传递的参数压栈,在eax得到返回值。堆栈调用法的服务函数保存ebx,esi,edi和ebp的值。许多寄存器调用法服务函数都源于Windows3.x的时代。在大多数时候,你可以通过名字来区分这两种服务函数,如果一个函数的名字一下划线开头,如_HeapAllocate,它就是一个堆栈法的服务函数(除了少数从VWIN32.VxD导出的函数)。如果函数名不是一下划线开头,它就是一个寄存器法的服务函数。

调用VxD服务函数

你可以通过VMMCallVxDCall 宏来调用VMM和VxD服务。这两个宏的语法是一样的。当你要调用VMM导出的VxD服务函数时,用VMMCall。当你要用其它VxD程序导出的VxD服务函数时,用VxDCall

VMMCall service                ; 调用寄存器法服务函数e
VMMCall  _service, <argument list>    ; 调用堆栈法服务函数

正如我在前面所讲的,VMMCallVxDCall分解出一个跟着一个双字的20h中断,这样用起来很方便。当你调用堆栈法服务时,你必须用角括号把你的参数列括起来。

VMMCall  _HeapAllocate, <<size mybuffer>, HeapLockedIfDP>

_HeapAllocate是一个堆栈法服务函数。它有两个参数,我们必须用角括号把它们括起来。由于第一个参数是一个这个宏不能正确解释的表达式,所以我们又要用一个角括号把它括起来。

Flat地址

在老的编译工具里,当你使用offset 操作符时,编译器和联接器会生成错误地址,所以VxD编写者用offset flat:来代替offset。imm.inc包括了一个使这更简单的宏:OFFSET32 来代替offset flat:。所以如果你要用地址操作时,用OFFSET32 来代替offset操作符。

注意: 当我写这篇教程的时候,我试了一下用offset 操作符。它可以生成正确的地址。所以我想MASM6.14修正了这个bug。但是为了安全起见,你还是应该用OFFSET32宏来代替offset


威泰克斯VXD720调整软件 威泰克斯VXD720等数字对讲机、中继台调整软件 立即下载

相关推荐

VxD例程:消息框(Vxd教程5)

VxD例程:消息框VxD例程:消息框<FONT size=-1>在上一节教程里,我们讲了编写一个VxD程序的方法。现在我们要学以致用。在这一节里,我们要编写一个静态VxD,这个静态VxD在一个虚拟机创建或销毁时就会弹出一个消息框。 <FONT size=-1>在<A href="http://freeshell.org/~michael/files/VxDmessa

讲武堂-Jiangtao 2735

函数指针(C语言二)

函数指针一、函数指针的基础知识二、函数指针的声明三、函数指针在程序中的使用四、基于汇编层次的讲解 一、函数指针的基础知识 二、函数指针的声明 三、函数指针在程序中的使用 四、基于汇编层次的讲解 ...

qq_46111881的博客 327

VxD

VxD 程序设计入门We 我们在上一节学会了如何编写一个什么事也不做的VxD程序。在这一节里,我们要给它增加处理控制消息的功能。 VxD的初始化和结束<FONT face=Arial,Helvetica>VxD程序分为两种:静态的和动态的。每种的加载方法都不同,接受到的初始化和结束的控制消息也不同。 静态VxD:下列情况下,VMM加载一个静态VxD: 一

讲武堂-Jiangtao 4482

iczelion Vxd cntut4 (转)

iczelion Vxd cntut4 (转)[@more@] VxD 程序设计入门 We 我们在上一节学会了如何编写一个什么事也不做的VxD程序。在这一节里,我们要给它增加处理控制消息的功能。 VxD的初始化和结束 ...

cuiji1279的博客 164

iczelion Vxd cntut6

DeviceIoControl接口在这一节中我们将要关于学习动态VXD,特别是如何创建,加载和使用。点击这里下载例子VxD接口VxD总共提供了4种接口。l         VxD services                    VxD服务l         V86 Interface                   V86接口l         Prot

jimgreen的专栏 924

iczelion Vxd cntut2

虚拟机管理器虚拟机管理器(VMM)是Windows 95的实际操作系统,它建立和维护一个管理虚拟机的框架,同时为其他vxd程序提供许多重要的服务。其中三种重要的服务是: 内存管理 中断处理 线程调度 内存管理VMM使用Intel 80386或更新的处理器的内存调页能力来为系统虚拟机创建一个32位的虚地址空间。它把这个地址空间分为四个不同的部分: V86区 地

jimgreen的专栏 891

iczelion Vxd cntut8

 客户寄存器结构我们将学习本教程中另外一个重要的结构,叫客户寄存器结构。在本文中,V86指虚拟8086模式。在这里下载例子程序理论VxDs与正常的win32/win16/DOS应用程序有很大不同。大多数情况下,当其他应用程序正常工作时,它们是休眠的。它们象一个监管者一样工作,其作用是监视ring-3应用程序并在其出错时改正它们。下面是其工作时的典型的情况:1、中断发生时

jimgreen的专栏 1055

iczelion Vxd cntut6 (转)

iczelion Vxd cntut6 (转)[@more@]DeviceIoControl接口XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:of...

csd3176的博客 139

iczelion Vxd cntut2 (转)

iczelion Vxd cntut2 (转)[@more@] 虚拟机管理器 虚拟机管理器(VMM)是windows 95的实际操作系统,它建立和维护一个管理虚拟机的框架,同时为其他vxd程序提供许多重要的服务。其中三种重要...

csd3176的博客 116

游戏任务解谜全攻略:从断档排查到机关拆解的通用思路

在游戏任务与解谜设计中,任务链逻辑与机关机制是核心基础。任务链由前置条件、目标描述、环境线索等环节构成,其断裂常因玩家忽略关键NPC对话、未完成前置任务或遗漏道具所致。解谜机制则涉及顺序激活、符号对应、元素互动等类型,需通过识别规则提示、建立假设并小范围测试来拆解。掌握系统化的排查方法,如重建任务链、扫描环境线索、验证前置完整性,能显著提升自主解谜效率与游戏体验。本文以实战案例,具体解析如何应对任务断档、逻辑卡壳等常见问题,帮助玩家形成通用的解谜思维框架。

cuiji1279的博客 411

iczelion Vxd cntut8 (转)

iczelion Vxd cntut8 (转)[@more@] 客户寄存器结构 我们将学习本教程中另外一个重要的结构,叫客户寄存器结构。在本文中,V86指虚拟8086模式。在这里下载DOWNLOAD/new/asm...

csd3176的博客 95

c++ 虚函数基础1

初识虚函数 虚函数 源码如下 #include <iostream> using namespace std; class A{ public: virtual void printAA(){cout<<"print A";} }; class B:public A{ public: virtual void printAA(){cout<<"print B";} }; int main() { A* a = new B(); a->printAA

西门吹雪 482

实战DeviceIoControl 之七:在Windows 9X中读写磁盘扇区

Windows NT/2K/XP中,直接用CreateFile打开名称类似于"\\.\A:"的”文件”,就可以与设备驱动打交道,通过ReadFile/WriteFile以绝对地址方式访问磁盘了。但Windows 9X不支持这样的简单方法。本文介绍一种在Windows 9X中实现磁盘直接访问的方法:利用系统的vwin32.vxd,通过DeviceIoControl调用DOS INT21 7305H...

weixin_33829657的博客 138

C++20:列表初始化,聚合初始化,强制省略拷贝优化,指定初始化......

变量的初始化是C++标准的一个重要组成部分,C++初始化按照是否存在拷贝,可将初始化划分为直接初始化和拷贝初始化;其他初始化均可以归类为此两大类。本文围绕此分类标准,分别介绍了:C++98标准的直接初始化,拷贝初始化,聚合初始化,圆括号初始化;C++11标准的列表初始化和initializer_list; C++17标准的强制省略拷贝优化,列表初始化类型推导,聚合初始化扩展(允许基类);C++20标准的聚合初始化的扩展,指定初始化器初始化。

一鸣惊人的博客 1880

【分析】C++中通过溢出覆盖虚函数指针列表执行代码

◆ C++中通过溢出覆盖虚函数指针列表执行代码 作者:watercloud 主页:http://www.nsfocus.com 日期:2002-4-15      目录:  1.  C++中虚函数的静态联编和动态联编  2.  VC中对象的空间组织和溢出试验  3.  GCC中对象的空间组织和溢出试验  4.  参考 C++中虚函数的静态联编和动态联编      C++中的一大法宝就是虚函数,简

FreeXploiT 1441

VxD认识

一.  .vxd文件是什么?vb中如何用它? VXD是虚拟设备驱动,它通常完成一些系统底层的工作。调用VXD一般时利用Windows API的CreateFile打开设备,然后利用DeviceIoControl来调用VXD。具体的调用办法是由VXD的设计者规定的,需要查看有关的文档说明。  二.  怎样生成.vxd文件? VxD入门教程               1.

憨憨小姐的ITBlog 1802
上一篇: iczelion Vxd cntut3
下一篇: iczelion Vxd cntut5
jimgreen
博客等级 码龄26年 1粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值