📄 settimer.asm
字号:
.386p
.xlist
include vmm.inc
include shell.inc;利用外壳进行消息输出使用(类似于MessageBox)
include VKD.Inc;键盘服务过程
include Debug.inc;调试信息输出
include vwin32.inc
.list
;============================================================================
; 常量定义
;============================================================================
SETTIMERName EQU <'SETTIMER VXD '> ;必须为16个字符串
SETTIMERRev EQU 00H
SETTIMER_MAJOR_VERSION EQU 1
SETTIMER_MINOR_VERSION EQU 0
ErrorCode EQU 0FFFFFFFFh
;============================================================================
; 公有数据---在vxd运行期间始终有效
;============================================================================
VXD_LOCKED_DATA_SEG
FLAGS dd 0
SYS_VM dd 0
LDT dd 0
; Ctrl +加速、Ctrl -减速、Ctrl *超速、Ctrl /刹车、Ctrl 0恢复
; + - *键均为小键盘区按键 / 为键盘区按键
hHotKey_0 dd ?
hHotKey_Multiply dd ?
hHotKey_Add dd ?
hHotKey_Devide dd ?
hHotKey_Subtract dd ?
VK_NUMPAD0 equ 52H ;NumBoard 0
VK_MULTIPLY equ 37h ;NumBoard *
VK_ADD equ 4eh ;NumBoard +
VK_SUBTRACT equ 4ah ;NumBoard -
VK_DIVIDE equ 35h ;Main KeyBoard / 因为不知道小键盘区的/扫描码
refdata_NUMPAD0 dw 1770h;默认值
;==============================================================
;下面的值可以根据需要修改
;==============================================================
refdata_Add dw 019bh ;稍快
refdata_Subtract dw 4a7eh;稍慢
refdata_Multiply dw 0046h;更快
refdata_Divide dw 0d9c6h;更慢
DOS_INT EQU 21h
ORIG_PM_INT_SEL dd ? ;保护模式原来的中断的选择符和偏移量
ORIG_PM_INT_OFF dd ?
VXD_LOCKED_DATA_ENDS
;============================================================================
; 公有代码段---在vxd运行期间始终有效
;============================================================================
VXD_LOCKED_CODE_SEG
DECLARE_VIRTUAL_DEVICE SETTIMER,SETTIMER_MAJOR_VERSION,SETTIMER_MINOR_VERSION,\
SETTIMER_Control, ,UNDEFINED_INIT_ORDER
;========================================================================
;入口:eax控制调用标识
;出口:成功清carry
;否则置carry
;========================================================================
public SETTIMER_Control
SETTIMER_Control PROC NEAR
Control_Dispatch DEVICE_INIT, SETTIMER_Device_Init
Control_Dispatch SYS_DYNAMIC_DEVICE_INIT, SETTIMER_Device_Init
Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT, SETTIMER_Device_Exit
Control_Dispatch W32_DEVICEIOCONTROL, SETTIMER_ioctl
Clc ;不能忘记这两行
Ret ;
SETTIMER_Control ENDP
;============================================================================
; Win32 DeviceIoControl 接口
; 入口:esi 只想一个DIOCPARAMETERS结构
;出口:成功时,EAX 为零,清Carry 标志
; 失败时,EAX 为错误码,置Carry 标志
;仅提供一个框架
;============================================================================
Public SETTIMER_ioctl
BeginProc SETTIMER_ioctl
mov ecx,[esi].dwIoControlCode ; 获得IO控制码
cmp ecx,1
je Function1
cmp ecx,2
je Function2
jmp RetSuccess
Function1: ;接口1
jmp RetSuccess
Function2: ;接口2
jmp RetSuccess
RetSuccess:
xor eax, eax ;返回0成功
clc
ret
RetFail:mov eax,ErrorCode
stc
ret
EndProc SETTIMER_ioctl
;========================================================================
;Ctrl+ 0热键处理程序
; 入口:
;AL : 键的扫描码
; AH : 0 热键按下
; 1 热键释放
; 2 热键重复
; 3 热键完成
;EBX 热键句柄
;ECX 全局shift 状态
;EDX 指向参考数据
;EDI 以毫秒为单位指示延迟通知时间
;回调函数可以修改寄存器值及标志寄存器
;========================================================================
;SendData 过程 入口 bx=输入数据
;================================================================
SendData macro
mov al,34h;请参考有关微机原理书籍
out 43h,al
mov ax,bx
out 40h,al
mov al,ah
out 40h,al
ret
EndM
BeginProc HotKeyProc_NUMPAD0
mov bx,word ptr refdata_NUMPAD0;
SendData
VMMCall Get_Cur_VM_Handle;获得当前的虚拟机句柄
mov eax, hHotKey_0 ;把热键反映给指定的虚拟机,取消热键状态
VxDCall VKD_Reflect_Hot_Key
ret
EndProc HotKeyProc_NUMPAD0
BeginProc HotKeyProc_Add;Ctrl + 热键处理程序
mov bx,word ptr refdata_Add;[edx]
SendData
VMMCall Get_Cur_VM_Handle
mov eax, hHotKey_Add
VxDCall VKD_Reflect_Hot_Key
ret
EndProc HotKeyProc_Add
BeginProc HotKeyProc_Subtract;Ctrl -热键处理程序
mov bx,word ptr refdata_Subtract;[edx]
SendData
VMMCall Get_Cur_VM_Handle
mov eax, hHotKey_Subtract
VxDCall VKD_Reflect_Hot_Key
ret
EndProc HotKeyProc_Subtract
BeginProc HotKeyProc_Multiply
mov bx,word ptr refdata_Multiply;[edx]
SendData
VMMCall Get_Cur_VM_Handle
mov eax, hHotKey_Multiply
VxDCall VKD_Reflect_Hot_Key
ret
EndProc HotKeyProc_Multiply
BeginProc HotKeyProc_Divide
mov bx,word ptr refdata_Divide ;[edx]
SendData
VMMCall Get_Cur_VM_Handle
mov eax, hHotKey_Devide
VxDCall VKD_Reflect_Hot_Key
ret
EndProc HotKeyProc_Divide
;=====================================================================
;v86 模式的 21h中断处理程序
;入口:eax 为中断号码
; ebx 为当前虚拟机句柄
; ebp 指向Client_Reg_Struc结构
;出口:置carry 标志传递中断到下一个钩子过程
;如果钩子过程服务了这个中断,它必须清除carry 标志防止系统把中断;递到下一个钩子过程,
;不管系统安装了几个虚拟设备,系统总是最先调用最后一个钩子过程。一个钩子过程要么服务
;这个中断,要么把控制直接传递给下一个钩子过程。如果这个中断没有安装任何钩子过程,系
;统就会把这个中断反映给虚拟机
;=====================================================================
BeginProc Our_Int_Handler
pushad
mov eax,[ebp.Client_EAX]
cmp ax,2A00h ;获得时间功能调用
jne Let_DOS_Work ;非,转下一个钩子过程
xor eax,eax
mov FLAGS,eax
VxDCall VWIN32_GetCurrentProcessHandle;获得当前进程句柄
mov eax,[eax+38h]
or al,7
mov LDT,eax
VmmCall Get_Sys_VM_Handle
mov SYS_VM,ebx
VmmCall _SelectorMapFlat <SYS_VM,LDT,FLAGS>
add eax,0F2h ;eax 指向调用进程的名字首字母大写,其余小写
mov ebx,[eax]
cmp ebx,'dnuR' ;Rundll32TD 系统调用
je Let_DOS_Work
cmp ebx,'lpxE' ;ExplorerTD系统调用
je Let_DOS_Work
cmp ebx,'zniW' ;Winzip 无法实现
je Let_DOS_Work
;mov ecx,eax; 下面的注释代码主要说明如何输出信息,以便调试
;mov ecx, OFFSET32 MessageOk ; 窗口消息文本
; mov edi,eax
;mov edi, OFFSET32 Caption ; 窗口标题
; mov esi, 0 ; 回调地址
; mov edx, 0 ; 回调参考数据指针
; mov eax, 0 ; 消息框标志, MB_OK
; mov ebx,SYS_VM ;虚拟机句柄
; VxDcall SHELL_Message
popad ;返回虚假日期均为BCD码
mov [ebp.Client_AX],1 ;星期
mov [ebp.Client_CX],1999 ;年
mov [ebp.Client_DX],0101h ;日 月
clc ;不再传递中断到下一个钩子过程
ret
Let_DOS_Work:
popad
stc ; 传递中断到下一个钩子过程
ret
EndProc Our_Int_Handler
;=====================================================================
;保护模式的 21h中断处理程序
;入口:eax 为中断号码
; ebx 为当前虚拟机句柄
; ebp 指向Client_Reg_Struc结构
;出口:
;如果钩子过程服务了这个中断,它必须模拟中断
; 否则它必须把控制跳转到原来的中断
;=====================================================================
BeginProc Our_PM_Int_Handler
pushad
mov eax,[ebp.Client_EAX]
cmp ax,2A00h ;获得时间功能调用
jne Let_PM_Work
xor eax,eax
mov FLAGS,eax
VxDCall VWIN32_GetCurrentProcessHandle
mov eax,[eax+38h]
or al,7
mov LDT,eax
VmmCall Get_Sys_VM_Handle
mov SYS_VM,ebx
VmmCall _SelectorMapFlat <SYS_VM,LDT,FLAGS>
add eax,0F2h
mov ebx,[eax]
cmp ebx,'dnuR'
je Let_PM_Work
cmp ebx,'lpxE'
je Let_PM_Work
cmp ebx,'zniW'
je Let_PM_Work
popad
mov [ebp.Client_AX],1
mov [ebp.Client_CX],1999
mov [ebp.Client_DX],0101h
VmmCall Simulate_Iret ;模拟中断返回
ret
Let_PM_Work:
popad
mov ecx ,[Orig_PM_INT_Sel]
mov edx ,[Orig_PM_INT_Off]
Vmmjmp Simulate_Far_Jmp
EndProc Our_PM_Int_Handler
;===============================================================
;恢复原来中断处理程序
;===============================================================
Public SETTIMER_Device_Exit
BeginProc SETTIMER_Device_Exit
mov eax, hHotKey_0
VxDCall VKD_Remove_Hot_Key
mov eax, hHotKey_Add
VxDCall VKD_Remove_Hot_Key
mov eax, hHotKey_Multiply
VxDCall VKD_Remove_Hot_Key
mov eax, hHotKey_Devide
VxDCall VKD_Remove_Hot_Key
mov eax, hHotKey_Subtract
VxDCall VKD_Remove_Hot_Key
mov eax, DOS_INT
mov esi, OFFSET32 Our_Int_Handler
VMMCall UnHook_V86_Int_Chain
mov Ecx,ORIG_PM_INT_SEL
mov edx,ORIG_PM_INT_OFF
mov eax,DOS_INT
VMMCall Set_PM_Int_Vector
Clc;置成功标志
ret
EndProc SETTIMER_Device_Exit
VXD_LOCKED_CODE_ENDS
;===============================================================
;初始化代码段,初始化完毕,该内存区域被释放
;===============================================================
VXD_ICODE_SEG
BeginProc SETTIMER_Device_Init
mov eax, DOS_INT;安装v86 模式的21H中断
mov esi, OFFSET32 Our_Int_Handler
VMMCall Hook_V86_Int_Chain
jnc hook_PM_int
;Debug_out 'Hook_v86_int_chain Failed' ;说明如何输出调试信息
jmp Error_Handler
hook_PM_int: ;下面说明如何挂接保护模式中断
mov EAX,DOS_INT ;中断号
VMMCall Get_PM_Int_Vector;获得保护模式中断向量
mov [Orig_PM_Int_Sel],ecx
mov [Orig_PM_Int_Off],edx
mov Esi,Offset32 Our_PM_Int_Handler;分配保护模式的回调,es指向保护模式的中断程序
VMMCall Allocate_PM_Call_Back ;EDX指向参考数据
jnc Alloc_Ok
;Debug_Out 'Allocate_PM_Call_Back Failed'
jmp Error_Handler
Alloc_Ok:
Mov Ecx,Eax ;eax为返回的sel :offset
Movzx edx,cx ;dx: offset
shr ecx,16 ;cx: selector
mov eax,DOS_INT
VMMCall Set_PM_Int_Vector ;设置保护模式中断向量
mov al, VK_NUMPAD0 ;键的扫描码
mov ah, 0 ;类型为正常模式
mov ebx, HKss_Ctrl ;CTRL键
mov cl, CallOnPress ;检测到按下时执行回调
mov esi, OFFSET32 HotKeyProc_NUMPAD0;热键处理回调函数地址
mov edx, OFFSET32 refdata_NUMPAD0 ;参考数据
mov edi, 0 ;以毫秒为单位最大通知延迟时间, 为零按键总被通知
VxDCall VKD_Define_Hot_Key
jnc Next_1
jmp Error_Handler
Next_1:
mov hHotKey_0,eax
mov al,VK_ADD
mov ah, 00
mov ebx, HKss_Ctrl
mov cl, CallOnPress
mov esi, OFFSET32 HotKeyProc_ADD
mov edx, OFFSET32 refdata_ADD
mov edi, 0
VxDCall VKD_Define_Hot_Key
jnc Next_2
jmp Error_Handler
Next_2:
mov hHotKey_Add,eax
mov al,VK_SUBTRACT
mov ah, 00
mov ebx, HKss_Ctrl
mov cl, CallOnPress
mov esi, OFFSET32 HotKeyProc_SUBTRACT
mov edx, OFFSET32 refdata_SUBTRACT
mov edi, 0
VxDCall VKD_Define_Hot_Key
jnc Next_3
jmp Error_Handler
Next_3:
mov hHotKey_Subtract,eax
mov al,VK_MULTIPLY
mov ah, 00
mov ebx, HKss_Ctrl
mov cl, CallOnPress
mov esi, OFFSET32 HotKeyProc_MULTIPLY
mov edx, OFFSET32 refdata_MULTIPLY
mov edi, 0
VxDCall VKD_Define_Hot_Key
jnc Next_4
jmp Error_Handler
Next_4:
mov hHotKey_Multiply,eax
mov al, VK_DIVIDE
mov ah, 00
mov ebx, HKss_Ctrl
mov cl, CallOnPress
mov esi, OFFSET32 HotKeyProc_DIVIDE
mov edx, OFFSET32 refdata_Divide
mov edi, 0
VxDCall VKD_Define_Hot_Key
jnc Next_OK
jmp Error_Handler
Next_OK:
mov hHotKey_Devide,eax
VMMCall Get_Cur_VM_Handle
Clc; 成功清Carry标志
ret
Error_Handler:
VMMCall Get_Cur_VM_Handle
stc ;失败置标志
ret
EndProc SETTIMER_Device_Init
VXD_ICODE_ENDS
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -