利用驱动程序读取BIOS
相关的例子:下载>>> 作者:电子管 于2009-10-20上传 

     用BIOS的内容作为硬标记进行加密,应用程序可以通过检测bios的特定内容,如主板日期、厂家信息等。如果符合要求,就让程序正常运行;如不符合要求,就判断为盗版,禁止运行。这样可以

起到一定的加密锁的作用。
     如何得到bios的内容呢?我们已经通过驱动程序进入ring0,在ring0中是无所不能的,有一个简单的函数,可以帮助我们达到目的。它就是MmMapIoSpace函数,在DDK文档中看到该函数的说明如下

:
PVOID MmMapIoSpace(
IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType );
在Masm32v8中声明的有4个形参
MmMapIoSpace    proto stdcall :DWORD, :DWORD, :DWORD, :DWORD
为什么参数个数会有不同呢?
原因是MmMapIoSpace第一个参数传递的是一个结构而非结构的指针,而该结构实际的大小是 2 个双字,结果在masm32中表现为总共4个 dword 参数。
调用非常简单,invoke MmMapIoSpace,物理地址低32位,0,长度,MmNonCached
若成功该函数返回影射后的线性地址,否则返回NULL。这样就可以间接达到读取物理地址中内容的目的。

bios开始地址在实模式下是F000:0,也就是0f0000h,长度是64k,也就是10000h
这样我们就可以用一句 invoke MmMapIoSpace,0f0000h,0,64*1024,MmNonCached ;把BIOS的物理地址映射为线性地址,返回值在eax中。
然后把eax指向的线性地址中的内容复制到系统的缓冲区中,让驱动程序传给ring3下的应用程序。
bios_test.bat是驱动源码。
bios_test.asm是调用驱动的ring3级程序,它把驱动传回的bios内容写入文件bios_tst.bin,是16进制的,可以用16进制编辑器来查看。
实际使用时,可以传递一个随机的密钥给驱动程序,驱动程序负责把bios内容加密后返回,这样可以一定程度上增加解密的难度。程序中已经预留了接口,实现起来很简单,有兴趣者可以自己实现。

以下是程序源代码:已在xp和vista下调试通过。

;goto make
;文件名bios_test.bat 作者:盛玉增 2009年10月20日用masm32v8和kmdkit1.8在winxp及vista下调试成功。
.386
.model flat, stdcall
option casemap:none
include \masm32\include\w2k\ntstatus.inc
include \masm32\include\w2k\ntddk.inc
include \masm32\include\w2k\ntoskrnl.inc
includelib \masm32\lib\w2k\ntoskrnl.lib
include \masm32\Macros\Strings.mac

IOCTL_GET_INFO equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS)


.const
CCOUNTED_UNICODE_STRING    "\\Device\\bios_test", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING    "\\??\\bios_test", g_usSymbolicLinkName, 4


.data
buff1  db 128*512 dup (0f6h) ;
key_1  db 32 dup (0) ;


.code

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                   DispatchCreateClose                                            
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DispatchCreateClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

    ; CreateFile was called, to get driver handle
    ; CloseHandle was called, to close driver handle
    ; In both cases we are in user process context here

    mov eax, pIrp
    assume eax:ptr _IRP
    mov [eax].IoStatus.Status, STATUS_SUCCESS
    and [eax].IoStatus.Information, 0
    assume eax:nothing

    fastcall IofCompleteRequest, pIrp, IO_NO_INCREMENT

    mov eax, STATUS_SUCCESS
    ret

DispatchCreateClose endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                     DispatchControl                                              
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DispatchControl proc uses esi edi pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP

local status:NTSTATUS
local dwBytesReturned:DWORD    ;实际返回的字节数

    and dwBytesReturned, 0

    mov esi, pIrp
    assume esi:ptr _IRP

    IoGetCurrentIrpStackLocation esi
    mov edi, eax
    assume edi:ptr IO_STACK_LOCATION

    .if [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_INFO
        .if [edi].Parameters.DeviceIoControl.OutputBufferLength >= 30

            mov eax, [esi].AssociatedIrp.SystemBuffer
                      
                       pushad
                       push eax
                       mov esi,eax
                       mov ecx,30
                       mov edi,offset key_1
                       cld
                       rep movsb  ;保存传过来的数据到key_1,以备做密钥,加密数据后返回。
                      

                      invoke MmMapIoSpace,0f0000h,0,64*1024,MmNonCached ;物理地址映射为线性地址,返回值在eax
                      cmp eax,0   ;eax==0,失败
                      jnz   next_1
                      jmp next_2
            next_1:    
                        mov esi,eax
                        pop edi
                        mov ecx,10000h
                        rep movsb
                        popad

            mov dwBytesReturned, 128*512
            mov status, STATUS_SUCCESS
            jmp next_3
            next_2:pop eax
                   popad
                   mov status, STATUS_INVALID_DEVICE_REQUEST
            next_3:
        .else
            mov status, STATUS_BUFFER_TOO_SMALL
        .endif
    .else
        mov status, STATUS_INVALID_DEVICE_REQUEST
    .endif

    assume edi:nothing

    push status
    pop [esi].IoStatus.Status

    push dwBytesReturned
    pop [esi].IoStatus.Information

    assume esi:nothing

    fastcall IofCompleteRequest, esi, IO_NO_INCREMENT

    mov eax, status
    ret

DispatchControl endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverUnload                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverUnload proc pDriverObject:PDRIVER_OBJECT

    ; ControlService,,SERVICE_CONTROL_STOP was called
    ; We are in System process (pid = 8) context here

    invoke IoDeleteSymbolicLink, addr g_usSymbolicLinkName

    mov eax, pDriverObject
    invoke IoDeleteDevice, (DRIVER_OBJECT PTR [eax]).DeviceObject

    ret

DriverUnload endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                              D I S C A R D A B L E   C O D E                                      
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

.code INIT

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverEntry                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING

    ; StartService was called
    ; We are in System process (pid = 8) context here

local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT

    mov status, STATUS_DEVICE_CONFIGURATION_ERROR

    invoke IoCreateDevice, pDriverObject, 0, addr g_usDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, addr pDeviceObject
    .if eax == STATUS_SUCCESS
        invoke IoCreateSymbolicLink, addr g_usSymbolicLinkName, addr g_usDeviceName
        .if eax == STATUS_SUCCESS
            mov eax, pDriverObject
            assume eax:ptr DRIVER_OBJECT
            mov [eax].MajorFunction[IRP_MJ_CREATE*(sizeof PVOID)],            offset DispatchCreateClose
            mov [eax].MajorFunction[IRP_MJ_CLOSE*(sizeof PVOID)],            offset DispatchCreateClose
            mov [eax].MajorFunction[IRP_MJ_DEVICE_CONTROL*(sizeof PVOID)],    offset DispatchControl
            mov [eax].DriverUnload,offset DriverUnload
            assume eax:nothing
            mov status, STATUS_SUCCESS
        .else
            invoke IoDeleteDevice, pDeviceObject
        .endif
    .endif

    mov eax, status
    ret

DriverEntry endp

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                                                                                  
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

end DriverEntry

:make

set drv=bios_test

\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native /ignore:4078 %drv%.obj

del %drv%.obj

pause




;文件名bios_test.asm 作者:盛玉增 2009年10月20日用masm32v8和kmdkit1.8在WinXP及vista下调试成功

;在winxp下用驱动程序读取bios
.386