用驱动直接显存抓屏

 ;goto make           ;直接将显存数据保存为BMP图片,注意:是实验代码!
.386                 ;注意:保存后的BMP图片是垂直倒了90度.不知道怎么弄哈~
.model flat, stdcall;显卡物理地址可以用PCI配置空间获取,这里实验从设备管理器中获取的.
option casemap:none ;作者:成松林   QQ:179641795 Email:cheng_5103@126.com
                     ;转贴请保留作者信息,文章发篇不容易!请大家尊重下吧!!!!!
include d:\masm32\include\w2k\ntstatus.inc
include d:\masm32\include\w2k\hal.inc
include d:\masm32\include\w2k\ntddk.inc
include d:\masm32\include\w2k\win32k.inc
include d:\masm32\include\w2k\ntoskrnl.inc
includelib d:\masm32\lib\w2k\ntoskrnl.lib
includelib d:\masm32\lib\w2k\hal.lib
includelib d:\masm32\lib\w2k\win32k.lib
include d:\masm32\Macros\Strings.mac
.const
       CCOUNTED_UNICODE_STRING   "\\??\\C:\\aa.bmp",uFile_Name,4     ;将显存数据写入文件
.data
       bmphd db 42h,4dh,36h,00h,24h,0,0000,000,0,0,036h,000,000,00,28h,0
             db 000,000,000,04h,000,0,0000,003,0,0,0001,000,18h,00,000,0
             db 000,000,000,00h,24h,0,0c4h,0eh,0,0,0c4h,0eh,000,00,000,0
             db 000,000,000,000,000,0,0000
       DataSize                   dd 1024*768*4               ;注意:显存屏幕数据大小,显示色彩为32位色!
       BmpSize                   dd 0
       File_Handle               dd 0
       ScrnBuffer                 dd 0
       ScrnPhysicalAddress       dd 0f0000000h               ;显存物理地地址,可用PCI配置空间端口CF8、CFC获取.
       ScrnSizeMemory             dd 1280*1024*4             ;显存大小,可在PCI空间获取.这里用支持的最大分辨率.
       DisplayLineAddr           dd 0                       ;调用MmMapIoSpace函数映射的虚拟地址.
       DisplayMDLAddr             dd 0
       OB_AB   OBJECT_ATTRIBUTES <>
       Status   IO_STATUS_BLOCK <>
       ByteOffset LARGE_INTEGER<>
      
.code
;****************************************************************************************************************
DriverEntry proc uses ebx ecx edx esi edi pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
       invoke MmMapIoSpace,ScrnPhysicalAddress,0,ScrnSizeMemory,FALSE       ;建立显存物理地址到线性地址映射
       mov     DisplayLineAddr,eax                                           ;保存线性地址
       invoke IoAllocateMdl,DisplayLineAddr,ScrnSizeMemory,FALSE,FALSE,NULL;分配显存MDL描述,以便锁定
       .if     eax == 0                                                     ;注意:发现分配太大的内存会失败! 
             invoke MmUnmapIoSpace,DisplayLineAddr,ScrnSizeMemory         ;释放显存映射资源
             ret
       .endif 
       mov     DisplayMDLAddr,eax                                           ;保存分配的显存MDL描述
       invoke MmProbeAndLockPages,DisplayMDLAddr,KernelMode,IoReadAccess OR IoWriteAccess;锁存内存操作
       invoke ExAllocatePool,PagedPool,DataSize                             ;分配内存缓冲,拷贝显存数据
       .if     eax == 0                                                     ;分配失败
               invoke MmUnlockPages,DisplayMDLAddr                         ;解出显存锁定
               invoke IoFreeMdl,DisplayMDLAddr                             ;释放分配的显存MDL描述
               invoke MmUnmapIoSpace,DisplayLineAddr,ScrnSizeMemory         ;释放显存映射资源
               ret
       .endif
       mov     ScrnBuffer,eax                                               ;保存分配的内存缓冲
       mov     edi,ScrnBuffer
       mov     esi,DisplayLineAddr                           ;esi->显存线性地址(手动获取的仅为实验)
       mov     ecx,DisplayLineAddr
       add     ecx,DataSize
       .while   esi < ecx                                   ;拷贝显存数据到本地
               mov   eax,[esi]
               mov   [edi],eax
               add   edi,3                                   ;BMP数据每个象素点=32位色下显存4个字节的最后一个字节去掉.
               add   esi,4
       .endw
       invoke MmUnlockPages,DisplayMDLAddr                   ;解出显存MDL描述锁定
       invoke IoFreeMdl,DisplayMDLAddr                       ;释放分配的显存MDL描述
       invoke MmUnmapIoSpace,DisplayLineAddr,ScrnSizeMemory ;释放显存映射资源
       InitializeObjectAttributes addr OB_AB,addr uFile_Name,OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE,NULL,NULL;宏native.inc:InitializeObjectAttributes
       invoke ZwCreateFile,addr File_Handle,GENERIC_WRITE,addr OB_AB,addr Status,NULL,FILE_ATTRIBUTE_NORMAL,0,FILE_OVERWRITE_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0
       .if     eax !=0                                       ;建立打开文件失败
             ret
       .endif
       mov     ByteOffset.HighPart,0
       mov     ByteOffset.LowPart,0
       invoke ZwWriteFile,File_Handle,NULL,NULL,NULL,addr Status,addr bmphd,36h,NULL,NULL
       mov     ByteOffset.LowPart,36h
       mov     esi,DataSize                                   ;每个象素点占4个字节,最后一个字节0,bmp不保存的.
       shr     esi,2                                         ;esi=有多少个象素
       mov     edi,DataSize
       sub     edi,esi                                       ;edi=BMP应该保存的字节数
       mov     BmpSize,edi
       invoke ZwWriteFile,File_Handle,NULL,NULL,NULL,addr Status,ScrnBuffer,BmpSize,addr ByteOffset,NULL
       invoke ZwClose,File_Handle
       invoke ExFreePool,ScrnBuffer                         ;释放分分配的保存显存数据的缓冲区
mov eax, 0
ret
DriverEntry endp
end DriverEntry
:make
set drv=DRRamScreen
..\bin\ml /nologo /c /coff %drv%.bat
..\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native   %drv%.obj
del %drv%.obj
pause
原文地址:https://www.cnblogs.com/qintangtao/p/2918059.html