罗云彬VxD教程--客户寄存器结构

2016-02-19 15:06 8 1 收藏

最近很多朋友喜欢上设计,但是大家却不知道如何去做,别担心有图老师给你解答,史上最全最棒的详细解说让你一看就懂。

【 tulaoshi.com - 编程语言 】

  我们将学习本教程中另外一个重要的结构,叫客户寄存器结构。在本文中,V86指虚拟8086模式。在这里下载例子程序

  理论

  VxDs与正常的win32/win16/DOS应用程序有很大不同。大多数情况下,当其他应用程序正常工作时,它们是休眠的。它们象一个监管者一样工作,其作用是监视ring-3应用程序并在其出错时改正它们。下面是其工作时的典型的情况:

  1、中断发生时

  2、VMM得到控制权时

  3、VMM存贮寄存器组的值时

  4、VMM服务于中断或调用其他VxDs完成此工作时

  5、VMM交还控制权给被中断的程序时

  在以上过程中令人感兴趣的是,VMM只有这一种方式能影响被中断的应用程序,即修改存储的寄存器映象。例如,VMM认为被中断的程序应该返回到另外一个地址,它就修改存储的寄存器映象中CS:IP的值,当这个程序被重新分派时,它将在新的CS:IP处开始执行。

  VMM在客户寄存器结构中存储中断点处的寄存器值。

  Client_Reg_Struc STRUC

  Client_EDI DD ?

  Client_ESI DD ?

  Client_EBP DD ?

  Client_res0 DD ?

  Client_EBX DD ?

  Client_EDX DD ?

  Client_ECX DD ?

  Client_EAX DD ?

  Client_Error DD ?

  Client_EIP DD ?

  Client_CS DW ?

  Client_res1 DW ?

  Client_EFlags DD ?

  Client_ESP DD ?

  Client_SS DW ?

  Client_res2 DW ?

  Client_ES DW ?

  Client_res3 DW ?

  Client_DS DW ?

  Client_res4 DW ?

  Client_FS DW ?

  Client_res5 DW ?

  Client_GS DW ?

  Client_res6 DW ?

  Client_Alt_EIP DD ?

  Client_Alt_CS DW ?

  Client_res7 DW ?

  Client_Alt_EFlags DD ?

  Client_Alt_ESP DD ?

  Client_Alt_SS DW ?

  Client_res8 DW ?

  Client_Alt_ES DW ?

  Client_res9 DW ?

  Client_Alt_DS DW ?

  Client_res10 DW ?

  Client_Alt_FS DW ?

  Client_res11 DW ?

  Client_Alt_GS DW ?

  Client_res12 DW ?

  Client_Reg_Struc ENDS

  你可以看到这个结构分为两个部分:Client_xxx和Client_Alt_xxx。在这稍作说明,在一个给定的VM中,可能有两个运行的线程:V86和保护模式。当V86程序运行时,假如一个中断产生,Client_xxx将包含V86程序的寄存器映象,Client_Alt_xxx将包含保护模式程序的寄存器映象。相应的,当保护模式程序运行时,假如一个中断产生,Client_xxx将包含保护模式程序的寄存器映象,Client_Alt_xxx将包含V86程序的寄存器映象。Client_resX被保留而没有使用。

  在查看过这个结构后,你可能有一问题:怎样改变寄存器中的一个字节,比如al?上面的结构仅仅描述了字和双字大小的寄存器组。不用担心,在vmm.inc找一找。那有两个为此附加的结构:Client_Word_Reg_Struc和Client_Byte_Reg_Struc。假如你想以字或字节大小来访问寄存器,根据你的需要转换Client_Reg_Struc到Client_Word_Reg_Struc或Client_Byte_Reg_Struc。

  下一个问题:我们如何得到一个指向客户寄存器结构的指针?

  这相当简单:一般地,当VMM调用我们的VxD时,把客户寄存器结构的地址放在ebp中。在这里的客户寄存器结构是当前VM的。你可以从VM的句柄中得到这个指针。记住,VM的句柄是VM控制块的线性地址。

  cb_s STRUC

  CB_VM_Status DD ?

  CB_High_Linear DD ?

  CB_Client_Pointer DD ?

  CB_VMID DD ?

  CB_Signature DD ?

  cb_s ENDS

  CB

  CB_Client_Pointer包含指向VM的客户寄存器结构的指针。例如:你可用下边的代码得到指向当前VM中的客户寄存器结构的指针:

  VMMCall Get_Cur_VM_Handle ; return the current VM handle in ebx

  assume ebx:ptr cb_s

  mov ebp,[ebx+CB_Client_Pointer] ; pointer to client reg struct

  现在我们了解了客户寄存器结构,我们可以用它来开始工作了。我们将使用客户寄存器结构去传送寄存器组的值到一个DOS中断中,也就是,int 21h,功能2h,显示一个字符。这个DOS服务把要显示的字符放在dl中。假如我们传送响铃字符(07h)到这个服务,将通过PC喇叭发出一声响。

  记住,int 21h是一个DOS服务,因而其在V86模式下是可用的,我们如何在VxD中调用一个V86中断?一个方法是使用Exec_Int服务。这个VMM服务把要调用的中断号放在eax中。它模拟指定的中断然后返回到调用的VM。然而,它必须在一个嵌套执行块中被调用。嵌套执行块被Begin_Nest_V86_Exec (或 Begin_Nest_Exec)和End_Nest_Exec包括起来。如果我们要调用int 21h功能2h,我们需要在嵌套执行块内转换Client_Byte_Reg_Struc结构的Client_ah和Client_Dl,然后把值21h放在eax中。当一切准备好了,就调用Exec_Int。

  例子:

  例子是一个动态VxD,它调用int 21h的功能2使PC喇叭发声。

  

.386p
include masmincludevmm.inc
include masmincludevwin32.inc
include masmincludev86mmgr.inc
VxDName TEXTEQU 
ControlName TEXTEQU 
VxDMajorVersion TEXTEQU 1
VxDMinorVersion TEXTEQU 0
VxD_STATIC_DATA_SEG
VxD_STATIC_DATA_ENDS
VXD_LOCKED_CODE_SEG
;----------------------------------------------------------------------------
; Remember: The name of the vxd MUST be uppercase else it won't work/unload
;----------------------------------------------------------------------------
DECLARE_VIRTUAL_DEVICE %VxDName,%VxDMajorVersion,%VxDMinorVersion, %ControlName,UNDEFINED_DEVICE_ID,UNDEFINED_INIT_ORDER
Begin_control_dispatch %VxDName
    Control_Dispatch W32_DEVICEIOCONTROL, OnDeviceIoControl
End_control_dispatch %VxDName
VXD_LOCKED_CODE_ENDS
VXD_PAGEABLE_CODE_SEG
BeginProc OnDeviceIoControl
assume esi:ptr DIOCParams
.if [esi].dwIoControlCode==1
 Push_Client_State
 VMMCall Begin_Nest_V86_Exec
 assume ebp:ptr Client_Byte_Reg_Struc
 mov [ebp].Client_dl,7
 mov [ebp].Client_ah,2
 mov eax,21h
 VMMCall Exec_Int
 VMMCall End_Nest_Exec
 Pop_Client_State
EndI:
.endif
xor eax,eax
ret
EndProc OnDeviceIoControl
VXD_PAGEABLE_CODE_ENDS
end

  讲解

  Push_Client_State

  这没什么好讲解的。当一个VxD接收到一个DeviceIoControl消息,ebp已经指向了当前VM的客户寄存器结构。我们调用Push_Client_State宏在堆栈中存储客户寄存器结构的状态。然后用Pop_Client_State宏恢复客户寄存器。

  VMMCall Begin_Nest_V86_Exec

  通过调用Begin_Nest_V86_Exec开始嵌套执行块。

  assume ebp:ptr Client_Byte_Reg_Struc

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  mov [ebp].Client_dl,7

  mov [ebp].Client_ah,2

  改变在客户寄存器中的dl和ah寄存器的映象。这个改变的值将由中断使用。

  mov eax,21h

  VMMCall Exec_Int

  Exec_Int要求在eax存有一个中断号。我们想使用int 21h。等会我们调用Exec_Int去模拟中断。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  VMMCall End_Nest_Exec

  Pop_Client_State

  当Exec_Int返回,我们完成了嵌套执行块,并且由堆栈中恢复了客户寄存器结构的值。 你将听到你的PC喇叭发出一声响。

来源:http://www.tulaoshi.com/n/20160219/1608835.html

延伸阅读
带着小宝贝去旅行 0-2岁的宝宝对外界的感知是最强烈的阶段,根据医学研究,小宝宝的听力和视力,在这个阶段会突飞猛进地发展。并且,宝宝会无时无刻地以我们想象不到 的方式学习。因此,带宝宝观赏有趣的景色,倾听有趣的声音,比如瀑布、海浪,就在协助宝宝建立脑部永久神经中枢连接的回路。 推敲旅游线路 考虑到小宝宝的接...
标签: 软件教程
云帆影视浏览器是快播公司开发的一款影视浏览播放器,但是由于经常被捆绑在其他软件里面,很是让用户反感。那么云帆影视浏览器怎么卸载呢?小编整理了一份卸载教程给大家 云帆影视浏览器怎么卸载? 一、使用浏览器自带卸载程序进行卸载 1、右键桌面快捷方式,点击属性,打开文件位置 2、找到下图标记的 u...
网易云阅读客户端上如何购买   网易云阅读Android和iPhone客户端支持直接购买,在书籍详情页或书籍内点击购买,若账户内余额不足需要先充值。
标签: flash教程
1. 最基本的Class定义方面我不多说了, 就举个例子直接开始: class Flash8 { private var user:String; //定义变量 private var pass:String; private var age:Number; public function Flash8(x:String, y:String) { //class的结构函数 user = x; pass = y; trace("用户名 = "+user+", 密码 = "+pass); } public function setAge(x:Num...
标签: 软件教程
安全狗服云是一款服务器安全管理云平台,主要是管理服务器,把服务器添加到服云是一个非常关键的步骤,那安全狗服云怎么添加服务器呢?小编给大家分享下安全狗服云添加服务器教程,如果你还不会添加服务器的话一定要看看哦! 1、在您的服务器上安装最新版本服务器安全狗,安装完成,点击弹出窗口上的【立即加入】...

经验教程

858

收藏

26
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部