iczelion Vxd cntut8

vxd 专栏收录该内容
17 篇文章 0 订阅

 

客户寄存器结构


我们将学习本教程中另外一个重要的结构,叫客户寄存器结构。在本文中,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 /masm/include/vmm.inc 
include /masm/include/vwin32.inc 
include /masm/include/v86mmgr.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
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去模拟中断。

VMMCall End_Nest_Exec
Pop_Client_State

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


<script language=JavaScript1.1 src="../lion-tut-c13.files/textclick"></script>
<script language=JavaScript1.1 src="../lion-tut-c13.files/c21.htm"></script>

翻译:吕骏,整理:LuoYunBin's Win32 ASM Page, http://asm.yeah.net
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
程序员的必经之路! 【限时优惠】 现在下单,还享四重好礼: 1、教学课件免费下载 2、课程案例代码免费下载 3、专属VIP学员群免费答疑 4、下单还送800元编程大礼包 【超实用课程内容】  根据《2019-2020年中国开发者调查报告》显示,超83%的开发者都在使用MySQL数据库。使用量大同时,掌握MySQL早已是运维、DBA的必备技能,甚至部分IT开发岗位也要求对数据库使用和原理有深入的了解和掌握。 学习编程,你可能会犹豫选择 C++ 还是 Java;入门数据科学,你可能会纠结于选择 Python 还是 R;但无论如何, MySQL 都是 IT 从业人员不可或缺的技能!   套餐中一共包含2门MySQL数据库必学的核心课程(共98课时)   课程1:《MySQL数据库从入门到实战应用》   课程2:《高性能MySQL实战课》   【哪些人适合学习这门课程?】  1)平时只接触了语言基础,并未学习任何数据库知识的人;  2)对MySQL掌握程度薄弱的人,课程可以让你更好发挥MySQL最佳性能; 3)想修炼更好的MySQL内功,工作中遇到高并发场景可以游刃有余; 4)被面试官打破沙锅问到底的问题问到怀疑人生的应聘者。 【课程主要讲哪些内容?】 课程一:《MySQL数据库从入门到实战应用》 主要从基础篇,SQL语言篇、MySQL进阶篇三个角度展开讲解,帮助大家更加高效的管理MySQL数据库。 课程二:《高性能MySQL实战课》主要从高可用篇、MySQL8.0新特性篇,性能优化篇,面试篇四个角度展开讲解,帮助大家发挥MySQL的最佳性能的优化方法,掌握如何处理海量业务数据和高并发请求 【你能收获到什么?】  1.基础再提高,针对MySQL核心知识点学透,用对; 2.能力再提高,日常工作中的代码换新貌,不怕问题; 3.面试再加分,巴不得面试官打破沙锅问到底,竞争力MAX。 【课程如何观看?】  1、登录CSDN学院 APP 在我的课程中进行学习; 2、移动端:CSDN 学院APP(注意不是CSDN APP哦)  本课程为录播课,课程永久有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化。  下载方式:电脑登录课程观看页面,点击右侧课件,可进行课程资料的打包下载。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值