news 2026/10/28 1:07:35

汇编语言全接触-48.客户寄存器结构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汇编语言全接触-48.客户寄存器结构

我们将学习本教程中另外一个重要的结构,叫客户寄存器结构。在本文中,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喇叭发出一声响。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 22:15:28

Charticulator数据可视化终极工具完整指南

Charticulator数据可视化终极工具完整指南 【免费下载链接】charticulator Interactive Layout-Aware Construction of Bespoke Charts 项目地址: https://gitcode.com/gh_mirrors/ch/charticulator Charticulator是一款革命性的交互式图表设计工具&#xff0c;让用户无…

作者头像 李华
网站建设 2026/10/24 23:29:01

Bili-Hardcore终极指南:AI智能答题轻松获取B站硬核会员

Bili-Hardcore终极指南&#xff1a;AI智能答题轻松获取B站硬核会员 【免费下载链接】bili-hardcore bilibili 硬核会员 AI 自动答题&#xff0c;直接调用 B 站 API&#xff0c;非 OCR 实现 项目地址: https://gitcode.com/gh_mirrors/bi/bili-hardcore 还在为B站硬核会员…

作者头像 李华
网站建设 2026/10/24 18:25:36

ZIP文件密码恢复终极指南:bkcrack快速解密方案

当您遗失了ZIP压缩文件的密码时&#xff0c;传统方法往往难以应对。bkcrack工具基于Biham和Kocher的密码学研究成果&#xff0c;提供了一种创新的已知明文分析技术&#xff0c;让您无需尝试所有可能的密码组合即可重新获得对加密数据的访问权限。 【免费下载链接】bkcrack Crac…

作者头像 李华
网站建设 2026/10/21 9:04:00

高电磁干扰下JLink接线信号完整性解决方案

高电磁干扰下JLink调试为何频频掉线&#xff1f;一文讲透信号完整性实战方案 你有没有遇到过这样的场景&#xff1a; 代码写得没问题&#xff0c;硬件也通电了&#xff0c;示波器看着电源稳如老狗——可偏偏JLink就是连不上目标芯片。重启软件、换线、重焊排针……折腾半小时&…

作者头像 李华
网站建设 2026/10/27 2:14:48

拯救者Y7000系列BIOS隐藏设置完全解锁指南

拯救者Y7000系列BIOS隐藏设置完全解锁指南 【免费下载链接】LEGION_Y7000Series_Insyde_Advanced_Settings_Tools 支持一键修改 Insyde BIOS 隐藏选项的小工具&#xff0c;例如关闭CFG LOCK、修改DVMT等等 项目地址: https://gitcode.com/gh_mirrors/le/LEGION_Y7000Series_I…

作者头像 李华
网站建设 2026/10/21 11:27:50

10、使用DCGAN梦想新的户外建筑

使用DCGAN梦想新的户外建筑 1. 判别器的代码实现 判别器相较于生成器更为简单。深度卷积网络在分类研究中十分常见,但对于生成对抗网络(GAN)而言,关键在于训练应具有对抗性,直接采用最先进的分类技术可能无法让生成器学习。本质上,构建判别器需要进行平衡操作。 1.1 准…

作者头像 李华