|
用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
- .model flat, stdcall
- option casemap:none
- ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- ; I N C L U D E F I L E S
- ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- include \masm32\include\windows.inc
- include \masm32\include\kernel32.inc
- include \masm32\include\user32.inc
- include \masm32\include\advapi32.inc
- includelib \masm32\lib\kernel32.lib
- includelib \masm32\lib\user32.lib
- includelib \masm32\lib\advapi32.lib
- include \masm32\include\winioctl.inc
- include \masm32\Macros\Strings.mac
- IOCTL_GET_INFO equ CTL_CODE(FILE_DEVICE_UNKNOWN, 800h, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS)
- ; Macro definition for defining IOCTL and FSCTL function control codes. Note
- ; that function codes 0-2047 are reserved for Microsoft Corporation, and
- ; 2048-4095 are reserved for customers.
- ;CTL_CODE MACRO DeviceType:=<0>, Function:=<0>, Method:=<0>, Access:=<0>
- ; EXITM %(((DeviceType) SHL 16) OR ((Access) SHL 14) OR ((Function) SHL 2) OR (Method))
- ;ENDM
- .const
- .data
- sysname db "bios_test.sys",0 ;驱动程序名
- device db "bios_test",0
- driver db "bios_test Driver",0
- abyInBuffer db 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,111,128,128,180,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16;传输试验数据用
- abyOutBuffer db 128*512 dup(0) ;用于存放驱动传回的64kbios数据
- name_buffer db 'bios_tst.bin',0 ;读取的bios数据保存到bios_tst.bin
- ok_1 db "读取成功,请查看bios_tst.bin",0
- dwBytesReturned dd 0
- .data?
- hFile HANDLE ? ;文件句柄
- SizeReadWrite DWORD ? ;文件中实际写入的字节数
- .code
- ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- ; start
- ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- start proc uses esi edi
- local hSCManager:HANDLE
- local hService:HANDLE
- local acModulePath[MAX_PATH]:CHAR
- local _ss:SERVICE_STATUS
- local hDevice:HANDLE
- local acVersion[16]:CHAR
- ; Open a handle to the SC Manager database
- invoke OpenSCManager, NULL, NULL, SC_MANAGER_ALL_ACCESS
- .if eax != NULL
- mov hSCManager, eax
- ;invoke GetCurrentDirectory, sizeof g_acBuffer, addr g_acBuffer
- push eax
- invoke GetFullPathName, addr sysname, sizeof acModulePath, addr acModulePath, esp
- pop eax
- ; Install service
- invoke CreateService, hSCManager, addr device, addr driver, \
- SERVICE_START + SERVICE_STOP + DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, \
- SERVICE_ERROR_IGNORE, addr acModulePath, NULL, NULL, NULL, NULL, NULL
- .if eax != NULL
- mov hService, eax
- ; Driver's DriverEntry procedure will be called
- invoke StartService, hService, 0, NULL
- .if eax != 0
- ; Driver will receive I/O request packet (IRP) of type IRP_MJ_CREATE
- invoke CreateFile, $CTA0("\\\\.\\bios_test"), GENERIC_READ + GENERIC_WRITE, \
- 0, NULL, OPEN_EXISTING, 0, NULL
- .if eax != INVALID_HANDLE_VALUE
- mov hDevice, eax
- ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- ; Driver will receive IRP of type IRP_MJ_DEVICE_CONTROL
- invoke DeviceIoControl, hDevice, IOCTL_GET_INFO, addr abyInBuffer, sizeof abyInBuffer, addr abyOutBuffer, sizeof abyOutBuffer, addr dwBytesReturned, NULL
- .if ( eax != 0 ) && ( dwBytesReturned != 0 )
-
- invoke MessageBox, NULL, addr ok_1, $CTA0("bios_test"), MB_OK + MB_ICONINFORMATION
- invoke CreateFile,ADDR name_buffer,\
- GENERIC_READ or GENERIC_WRITE ,\
- FILE_SHARE_READ or FILE_SHARE_WRITE,\
- NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,\
- NULL
- mov hFile,eax
- invoke WriteFile,hFile,ADDR abyOutBuffer,128*512,\
- ADDR SizeReadWrite,NULL
- invoke CloseHandle,hFile
- tt_3:
- .else
- invoke MessageBox, NULL, $CTA0("发送控制失败."), NULL, MB_OK + MB_ICONSTOP
- .endif
- ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- invoke CloseHandle, hDevice ; Driver will received IRP of type IRP_MJ_CLOSE
- .else
- invoke MessageBox, NULL, $CTA0("Device is not present."), NULL, MB_ICONSTOP
- .endif
-
- invoke ControlService, hService, SERVICE_CONTROL_STOP, addr _ss
- ; DriverUnload proc in our driver will be called
- .else
- invoke MessageBox, NULL, $CTA0("Can't start driver."), NULL, MB_OK + MB_ICONSTOP
- .endif
- invoke DeleteService, hService
- invoke CloseServiceHandle, hService
- .else
- invoke MessageBox, NULL, $CTA0("Can't register driver."), NULL, MB_OK + MB_ICONSTOP
- .endif
- invoke CloseServiceHandle, hSCManager
- .else
- invoke MessageBox, NULL, $CTA0("Can't connect to Service Control Manager."), NULL, MB_OK + MB_ICONSTOP
- .endif
- invoke ExitProcess, 0
- start endp
- end start
复制代码
这里读取的bios是经过启动过程初始化后的内容,并不是主板上的bios闪存芯片内的内容,芯片内一般是压缩的,启动过程中自己解压。
通过查看得到的bios_tst.bin,发现有的机器用本程序读出的bios里面有本机的硬盘和光驱型号,这说明bios在启动的过程中,被写入了当前机器的一些信息。机器配置变了,这部分内容也会相应变化,使用bios加密时尽量不要用可变的部分,防止用户换个光驱后被判为盗版软件。
本文是电子管(qq5611409)专为aogo汇编论坛(网址http://www.aogosoft.com/bbs/)所写,转载请保留作者信息和出处。 |
评分
-
查看全部评分
|