kmd--8共享内存区通讯(Share section)

 这是学习kernel model driver(KMD)时翻译的一篇文章,大体意思差不多,但表达不好,欢迎指出其中的不足。。源码是用汇编写的。

翻译的比较匆忙,没有校对。希望不会有太多的错误。

在直接进入文章的主题前,先来简单看一下结构化异常处理,(Structured Exception Handling, SEH),因为我们需要用到他。
8.1 构造异常处理
如果你还不知道什么是 SHE 的话,建议你去阅读这篇文章“汇编环境下 Win32 异常处理 ”,作者是 Jeremy Gordon 。这篇文章介绍的是用户模式的异常处理,但是在内核模式下原理也是完全相同的。但是必须清楚的是:在内核模式下 SHE 不是所有的异常都能处理,例如:即使你已经安装 SHE 处理的情况下,一个除零错误也会导致蓝屏死机 BSOD (Blue Screen of Death) 。更糟糕的是我们不能引用一个无效的内核模式内存。 而在用户模式是很容易处理的用 SHE 。因此避免系统崩溃唯一的方式就是让程序不会出现不能处理的异常。
按照 Gary Nebbet 的研究, IRQL 低于或等于 DISPATCH_LEVEL SHE 异常才会被激发,任何的异常都是通过 ExRaiseStatus 和相关的函数抛出的。包括的异常有:无效内存访问,断点异常,整型溢出,无效指令。
 
8.1.1 驱动进行 she 处理的代码
;@echo off
;goto make
; :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; :::::::::::::::::::::::::::::::
;                                                                                                   
;  SEH – Structural handling exceptions.                              
;                                                                                                   
; :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; :::::::::::::::::::::::::::::::
.386
.model flat, stdcall
option casemap:none
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                  I N C L U D E   F I L E S                                       
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
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
include seh0.inc
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                     S T R U C T U R E S                                           
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SEH STRUCT
SafeEip         dd ?   ; Point, which will be continued execution   
PrevEsp         dd ?   ; The previous value of esp     
PrevEbp         dd ?   ; The previous value of ebp  
SEH ENDS
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                              U N I N I T I A L I Z E D D A T A                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.data?
seh     SEH     <>
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                         C O D E                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       BuggyReader                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
BuggyReader proc
        xor eax, eax
        mov eax, [eax]         ; !!! Without SEH this causes BSOD !!!
        ret
BuggyReader endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       BuggyWriter                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
BuggyWriter proc
        mov eax, MmUserProbeAddress
        mov eax, [eax]
        mov eax, [eax]
        mov byte ptr [eax], 0      ; !!! Without SEH this causes BSOD !!!
        ret
BuggyWriter endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                      ExceptionHandler                                             
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ExceptionHandler proc uses esi pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
mov esi, pExcept
    invoke DbgPrint, $CTA0("/nSEH: An exception %08X has occured/n"), /
                                              [esi][EXCEPTION_RECORD.ExceptionCode]
.if [esi][EXCEPTION_RECORD.ExceptionCode] == 0C0000005h                     
        ; EXCEPTION_ACCESS_VIOLATION   
        ; if EXCEPTION_ACCESS_VIOLATION we have some additional info
invoke DbgPrint, $CTA0("     Access violation at address: %08X/n"), /
               [esi][EXCEPTION_RECORD.ExceptionAddress]
 
      .if [esi][EXCEPTION_RECORD.ExceptionInformation][0]   
                       ; Read or write ?
invoke DbgPrint, $CTA0("The code tried to write to address %08X/n/n"), /
         [esi][EXCEPTION_RECORD.ExceptionInformation][4]
     .else
invoke DbgPrint, $CTA0("     The code tried to read from address %08X/n/n"), /
                [esi][EXCEPTION_RECORD.ExceptionInformation][4]
               .endif
.endif
    lea eax, seh
    push (SEH PTR [eax]).SafeEip
    push (SEH PTR [eax]).PrevEsp
    push (SEH PTR [eax]).PrevEbp
    mov eax, pContext
    pop (CONTEXT PTR [eax]).regEbp
    pop (CONTEXT PTR [eax]).regEsp
    pop (CONTEXT PTR [eax]).regEip
    xor eax, eax        ; return ExceptionContinueExecution
    ret 
ExceptionHandler endp 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverEntry                                                 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
        invoke DbgPrint, $CTA0("/nSEH: Entering DriverEntry/n")
        ;::::::::::::::::::::::::::::::::
        ; Manually set/remove seh-frame :
        ;::::::::::::::::::::::::::::::::
        assume fs:nothing
        push offset ExceptionHandler
        push fs:[0]
        mov fs:[0], esp
        assume fs:error
        mov seh.SafeEip, offset SafePlace
        mov seh.PrevEbp, ebp
        mov seh.PrevEsp, esp
        invoke BuggyReader
SafePlace:
        ; Remove seh-frame 
        assume fs:nothing
        pop fs:[0]
        add esp, sizeof DWORD
        assume fs:error
        ;:::::::::::::::::::::::::::::::::::::::::::::::
        ; SEH works using macro. It's a bit easier ;-) :
        ;:::::::::::::::::::::::::::::::::::::::::::::::
       _try
        invoke BuggyWriter
        _finally
        invoke DbgPrint, $CTA0("/nSEH: Leaving DriverEntry/n")
        ; Remove driver from the memory.
        mov eax, STATUS_DEVICE_CONFIGURATION_ERROR
        ret
DriverEntry endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                                                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
end DriverEntry
:make
set drv=seh
/masm32/bin/ml /nologo /c /coff %drv%.bat
/masm32/bin/link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj
del %drv%.obj
echo.
Pause
8.1.2注册SHE结构
      assume fs:nothing
由于MASM编译器默认是禁止使用fs寄存器,所以通过assume来启用fs
        push offset ExceptionHandler
        push fs:[0]
        mov fs:[0], esp
设置SHE结构回调函数,即当异常发生时进行处理的地址。然后异常发生时通过异常链(每个定义的SHE结构,都要自己的异常处理函数)激发系统异常处理。例如ExceptionHandler异常处理函数的代码稍后进行解释。可以通过调试器SoftIce提供的命令xframe得到所有当前异常链中以注册的异常处理。
        assume fs:error
使fs寄存器为不可用状态
        mov seh.SafeEip, offset SafePlace
        mov seh.PrevEbp, ebp
        mov seh.PrevEsp, esp
为了通过异常处理使我们的程序能够继续运行,必须保留寄存器espebp的值,在结构中保存这三个的值,调用会发生读错误的函数BuggyReader,函数试着读四个字节在地址0处。
        BuggyReader proc
               xor eax, eax
               mov eax, [eax]
               ret
        BuggyReader endp
对空指针的处理是个经常发生的错误,因为Microsoft规定范围从00000000-0000FFFFh64k大小内存是不可访问的,对这个范围任何字节进行存取都会导致一个EXCEPTION_ACCESS_VIOLATION类型的异常。
8.1.3异常处理
BuggyReader函数中试着读数据从地址00000000处激发异常,进入我们设置的异常处理函数
mov esi, pExcept
 
    invoke DbgPrint, $CTA0("/nSEH: An exception %08X has occured/n"), /
                        [esi][EXCEPTION_RECORD.ExceptionCode]
 
    .if [esi][EXCEPTION_RECORD.ExceptionCode] == 0C0000005h
 
        invoke DbgPrint, $CTA0("     Access violation at address: %08X/n"), /
                        [esi][EXCEPTION_RECORD.ExceptionAddress]
 
        .if [esi][EXCEPTION_RECORD.ExceptionInformation][0]
 
            invoke DbgPrint, $CTA0("     The code tried to write to address %08X/n/n"), /
                        [esi][EXCEPTION_RECORD.ExceptionInformation][4]
        .else
            invoke DbgPrint, $CTA0("     The code tried to read from address %08X/n/n"), /
                        [esi][EXCEPTION_RECORD.ExceptionInformation][4]
        .endif
.endif
        进入异常处理函数内,首先显示一个异常发生类型信息,如果是EXCEPTION_ACCESS_VIOLATION类型异常,显示更多的信息,继续进行合适的异常处理。
        lea eax, seh
        push (SEH PTR [eax]).SafeEip
        push (SEH PTR [eax]).PrevEsp
        push (SEH PTR [eax]).PrevEbp
        mov eax, pContext
        pop (CONTEXT PTR [eax]).regEbp
        pop (CONTEXT PTR [eax]).regEsp
        pop (CONTEXT PTR [eax]).regEip
在这个例子中只是简单的恢复继续正常运行的esp,ebp的值,和eip地址。恢复的寄存器值来自于注册SHE回调函数是保存在she结构中的值,并改变CONTEXT 结构中寄存器的值。
               xor eax, eax
               ret
        修改ExceptionContinueExecution的值为零返回,告诉系统程序继续正常执行,改变eipSafePlace的地址,并恢复espebp的值,程序从SafePlace处开始执行。
8.1.4 恢复原来的SHE框架
        SafePlace:
    assume fs:nothing
    pop fs:[0]
    add esp, sizeof DWORD
    assume fs:error
使fs:[0]恢复为原来的值,并且调整堆栈结构指针(要了解详细情况请看上面提到的文章)。
8.1.5定义宏进行SHE结构的注册和恢复
     对于一些相同的操作,定义宏可以简化程序,我定义一个简单的宏来操作SHEseh0.inc文件中有宏的具体定义,我不会解释他们,因为他们的作用和我们刚刚说明的一样。如果异常处理没有特别的要求,用宏调用_try / _finally代替上面对寄存器处理的代码,其中SafePlace地址就是宏调用的_finally
        _try
    invoke BuggyWriter
_finally
这次我们调用BuggyWriter函数来触发异常,这个函数企图向地址7FFF0000h处写入四字节的数据。
BuggyWriter proc
    mov eax, MmUserProbeAddress
    mov eax, [eax]
    mov eax, [eax]
    mov byte ptr [eax], 0
    ret
BuggyWriter endp
从范围7FFF0000h - 7FFFFFFFh大小64k的内存区域,保留作为用户和系统空间交换数据的缓冲边界。这个范围的开始地址在内核变量MmUserProbeAddress中输出。
    有了这些结构化异常处理的知识我们继续进行下一个例子。这个例子中我们用驱动请求用户模式地址范围的内存。这样的处理必须要注册SHE结构。
8.2 用共享内存区进行交换数据
Windows 提供了多种在两个或多个进程之间进行通信的机制( InterprocessCommunications, IPC ):剪贴板, DDE ,窗口消息(例如: WM_COPYDATA ),邮槽套接字,等等所有这些机制,一种或多种,基于对象——“映射文件( file-mapping object ),两个或多个进程共享的内存块 , DDK 中的解释文件是对象,“内存区对象” (section object) 区块间是按顺序访问的(不要把这个区块和 PE 文件中的区块混淆)。
“内存区”对象是底层的数据共享机制,用来加载系统可执行映像到内存中,缓冲控制器用他来访问缓冲文件中的数据;“内存区”对象可以被映射到页面文件中或者磁盘上的另一个文件中。但是他还是作为一个内存块。
共享数据在一个“内存区”上用以下的方法:通过函数 CreateFileMapping ,进程创建文件映射在内存中,然后用 MapViewOfFile 函数(如果是在底层调用 NtMapViewOfSection )映射到一个地址空间,其他的进程就可以通过函数 OpenFileMapping 打开相同的文件并显示在其他的地址空间。相同的物理内存页对进程是可用的允许通过这个区域传递数据,因为一个进程对这个页面任何数据的改变影响其它进程。
共同使用内存区作为交换数据的工具,不仅用于用户模式,也可用于驱动模式。在下面的例子中,一个命名的内存区用来在用户进程和驱动间交换数据。
8.2.1 sharesection 驱动管理程序源码
;@echo off
;goto make
.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/w2k/native.inc
include /masm32/include/w2k/ntstatus.inc
include /masm32/include/winioctl.inc
include /masm32/include/kernel32.inc
include /masm32/include/user32.inc
include /masm32/include/advapi32.inc
include /masm32/include/w2k/ntdll.inc
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/user32.lib
includelib /masm32/lib/advapi32.lib
includelib /masm32/lib/w2k/ntdll.lib
include /masm32/Macros/Strings.mac
include ../common.inc
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       C O D E                                                     
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.code 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                    CallDriver                                                     
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CallDriver proc
local fOk:BOOL
local hSCManager:HANDLE
local hService:HANDLE
local acModulePath[MAX_PATH]:CHAR
local _ss:SERVICE_STATUS
local hDevice:HANDLE
local abyOutBuffer[4]:BYTE
local dwBytesReturned:DWORD
    and fOk, FALSE                           ; assume error
    invoke OpenSCManager, NULL, NULL, SC_MANAGER_ALL_ACCESS
    .if eax != NULL
        mov hSCManager, eax
 
        push eax
        invoke GetFullPathName, $CTA0("SharedSection.sys"), sizeof acModulePath, addr acModulePath, esp
        pop eax
        invoke CreateService, hSCManager, $CTA0("SharedSection"), $CTA0("One way to share section"), /
               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
              invoke StartService, hService, 0, NULL
               .if eax != 0
               invoke CreateFile, $CTA0("////.//SharedSection"), 0, /
 			 0, NULL, OPEN_EXISTING, 0, NULL
              .if eax != INVALID_HANDLE_VALUE
                               mov hDevice, eax
                           ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
       invoke DeviceIoControl, hDevice, IOCTL_SHARE_MY_SECTION, NULL, 0, NULL, 0, addr dwBytesReturned, NULL                                                               addr dwBytesReturned, NULL
                               .if eax != 0
                                      inc fOk                      
                               .else
        invoke MessageBox, NULL, $CTA0("Can't send control code to device."), NULL, MB_OK + MB_ICON
                               .endif
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
                               invoke CloseHandle, hDevice
                       .else
                   invoke MessageBox, NULL, $CTA0("Device is not present."), NULL, MB_ICONSTOP
                       .endif
                       invoke ControlService, hService, SERVICE_CONTROL_STOP, addr _ss
               .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
    mov eax, fOk
    ret
CallDriver end
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                         start                                                     
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
start proc
local hSection:HANDLE
local liSectionSize:_LARGE_INTEGER
local oa:OBJECT_ATTRIBUTES
local pSectionBaseAddress:PVOID
local liViewSize:_LARGE_INTEGER
 
    and liSectionSize.HighPart, 0
    mov liSectionSize.LowPart, SECTION_SIZE
 
    lea ecx, oa
    InitializeObjectAttributes ecx, offset g_usSectionName, OBJ_CASE_INSENSITIVE, NULL, NULL
 
    invoke ZwCreateSection, addr hSection, SECTION_MAP_WRITE + SECTION_MAP_READ, addr oa, /
                                              addr liSectionSize, PAGE_READWRITE, SEC_COMMIT, NULL
    .if eax == STATUS_SUCCESS
 
        and pSectionBaseAddress, NULL ; The system itself should choose the address
        and liViewSize.HighPart, 0            ; Map whole section
        and liViewSize.LowPart, 0
        ; NtCurrentProcess equ -1
        invoke ZwMapViewOfSection, hSection, NtCurrentProcess, addr pSectionBaseAddress, 0, SECTION_SIZE, /
NULL, addr liViewSize, ViewShare, 0, PAGE_READWRITE
        .if eax == STATUS_SUCCESS
       ; The reversed string you will able to read if everithing goes fine
               CTA ".revird ecived a dna sessecorp resu neewteb yromem ", g_szStrToReverse
               CTA "erahs ot euqinhcet emas eht esu nac uoy ,revewoH "
               CTA ".sessecorp resu gnoma yromem gnirahs rof desu euqinhcet "
               CTA0 "nommoc a si elif gnigap eht yb dekcab elif deppam-yromem A"
               invoke strcpy, pSectionBaseAddress, addr g_szStrToReverse
               invoke CallDriver
               .if eax == TRUE
                       invoke MessageBox, NULL, pSectionBaseAddress, /
                                         $CTA0("HOWTO: Share Memory Between User Mode and Kernel Mode"), /
MB_OK + MB_ICONINFORMATION
               .endif
               invoke ZwUnmapViewOfSection, NtCurrentProcess, pSectionBaseAddress
        .else
               invoke MessageBox, NULL, $CTA0("Can't map section."), NULL, MB_OK + MB_ICONSTOP
        .endif
        invoke ZwClose, hSection
    .else
        invoke MessageBox, NULL, $CTA0("Can't create section."), NULL, MB_OK + MB_ICONSTOP
    .endif
    invoke ExitProcess, 0
    ret
start endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                                                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
end start
:make 
set exe=SharedSection
if exist ../%exe%.exe del ../%exe%.exe
/masm32/bin/ml /nologo /c /coff %exe%.bat
/masm32/bin/link /nologo /subsystem:windows %exe%.obj
del %exe%.obj
move %exe%.exe ..
if exist %exe%.exe del %exe%.exe
echo.
Pause
下面只说明关键点,许多应该是清楚的即使没有注释。
        and liSectionSize.HighPart, 0
        mov liSectionSize.LowPart, SECTION_SIZE
内存区必须说明大小。他的数量可以扩展到4GB大小,也就是LARGE_INTEGER类型变量的范围,我们初始化SECTION_SIZE大小的值等于一页的大小(4KB),SECTION_SIZE常量在文件common.inc中定义。
        lea ecx, oa
 InitializeObjectAttributes ecx, offset g_usSectionName, OBJ_CASE_INSENSITIVE, NULL, NULL
通过我们已经熟悉的一个宏调用InitializeObjectAttributes,初始化ZwCreateSection所要用的 OBJECT_ATTRIBUTES结构。
    对共享内存区进行命名,这样我们就可以通过名字打开,命名内存区定义在文件common.inc
.const
CCOUNTED_UNICODE_STRING
"//BaseNamedObjects//UserKernelSharedSection", g_usSectionName, 4
内存区对象存放在目录BaseNamedObjects,命名空间控制对象通常存放用户进程创建的命名对象。
invoke ZwCreateSection, addr hSection, SECTION_MAP_WRITE + SECTION_MAP_READ, addr oa, /
addr liSectionSize, PAGE_READWRITE, SEC_COMMIT, NULL
调用ZwCreateSection函数创建一个命名内存区对象,大小为SECTION_SIZE,读写访问权限,如果创建成功,变量hSection描述这个内存区。
        and pSectionBaseAddress, NULL
        and liViewSize.HighPart, 0
        and liViewSize.LowPart, 0
        invoke ZwMapViewOfSection, hSection, NtCurrentProcess, addr pSectionBaseAddress, 0, SECTION_SIZE, /
                NULL, addr liViewSize, ViewShare, 0, PAGE_READWRITE
内存区对象映射到内存地址空间中,有许多参数在DDK中有详细的描述。由于pSectionBaseAddress变量初始值为零,系统会自动在一个地址映射,并且返回这个地址给pSectionBaseAddress变量。LiViewSize变量初始化为零表示内存区对象会被完全映射。
CTA ".revird ecived a dna sessecorp resu neewteb yromem ", g_szStrToReverse
         CTA "erahs ot euqinhcet emas eht esu nac uoy ,revewoH "
         CTA ".sessecorp resu gnoma yromem gnirahs rof desu euqinhcet "
       CTA0 "nommoc a si elif gnigap eht yb dekcab elif deppam-yromem A"
            invoke strcpy, pSectionBaseAddress, addr g_szStrToReverse
    复制这些被翻转的字符串,驱动的作用就是把这些字符串翻转。
invoke CallDriver
            .if eax == TRUE
                invoke MessageBox, NULL, pSectionBaseAddress, /
                                $CTA0("HOWTO: Share Memory Between User Mode and Kernel Mode"), /
                                MB_OK + MB_ICONINFORMATION
            .endif
CallDriver的返回值为TRUE表示驱动复制数据完成,并且显示结果。 CallDriver 函数用来注册,启动驱动,和发送 IOCTL_SHARE_MY_SECTION 控制代码。
invoke ZwUnmapViewOfSection, NtCurrentProcess, pSectionBaseAddress
        .endif
        invoke ZwClose, hSection
卸载映射文件,返回原来的状态。
8.2.2 SharedSection驱动程序源码
;@echo off
;goto make
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;
; SharedSection - How to share section between kernel-mode driver and its user-mode client
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;:::::::::::::::::::::::::::::::
.386
.model flat, stdcall
option casemap:none
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                  I N C L U D E   F I L E S                                        
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;:::::::::::::::::::::::::::::::
 
include /masm32/include/w2k/ntstatus.inc
include /masm32/include/w2k/ntddk.inc
include /masm32/include/w2k/ntoskrnl.inc
include /masm32/include/w2k/native.inc
 
includelib /masm32/lib/w2k/ntoskrnl.lib
 
include /masm32/Macros/Strings.mac
 
include ../common.inc
include seh0.inc
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                 R E A D O N L Y    D A T A                                        
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
.const
 
CCOUNTED_UNICODE_STRING        "//Device//SharedSection", g_usDeviceName, 4
CCOUNTED_UNICODE_STRING        "//DosDevices//SharedSection", g_usSymbolicLinkName, 4
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                         C O D E                                                   
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
.code
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                   DispatchCreateClose                                             
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
DispatchCreateClose proc pDeviceObject:PDEVICE_OBJECT, pIrp:PIRP
 
    mov eax, pIrp
    mov (_IRP PTR [eax]).IoStatus.Status, STATUS_SUCCESS
    and (_IRP PTR [eax]).IoStatus.Information, 0
 
    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 hSection:HANDLE
local oa:OBJECT_ATTRIBUTES
local pSectionBaseAddress:PVOID
local liViewSize:LARGE_INTEGER
 
    invoke DbgPrint, $CTA0("/nSharedSection: Entering DispatchControl/n")
 
    mov esi, pIrp
    assume esi:ptr _IRP
 
    ; Assume unsuccess
    mov [esi].IoStatus.Status, STATUS_UNSUCCESSFUL
    ; We copy nothing
    and [esi].IoStatus.Information, 0
 
    IoGetCurrentIrpStackLocation esi
    mov edi, eax
    assume edi:ptr IO_STACK_LOCATION
 
    .if [edi].Parameters.DeviceIoControl.IoControlCode == IOCTL_SHARE_MY_SECTION
 
        invoke DbgPrint, $CTA0("SharedSection: Opening section object/n")
 
        lea ecx, oa
        InitializeObjectAttributes ecx, offset g_usSectionName, OBJ_CASE_INSENSITIVE, NULL, NULL
        invoke ZwOpenSection, addr hSection, SECTION_MAP_WRITE + SECTION_MAP_READ, addr oa
        .if eax == STATUS_SUCCESS
 
               invoke DbgPrint, $CTA0("SharedSection: Section object opened/n")
 
               and pSectionBaseAddress, NULL                 
; The system itself should choose the address
               and liViewSize.HighPart, 0
               and liViewSize.LowPart, 0
               ; NtCurrentProcess equ -1
               invoke ZwMapViewOfSection, hSection, NtCurrentProcess, addr pSectionBaseAddress, 0, SECTION_SIZE, /
    NULL, addr liViewSize, ViewShare, 0, PAGE_READWRITE
               .if eax == STATUS_SUCCESS
 
                       invoke DbgPrint, $CTA0("SharedSection: Section mapped at address %08X/n"), pSectionBaseAddress
 
                       _try
 
                       invoke _strrev, pSectionBaseAddress
                       mov [esi].IoStatus.Status, STATUS_SUCCESS
 
                       invoke DbgPrint, $CTA0("SharedSection: String reversed/n")
 
                       _finally
 
                       invoke ZwUnmapViewOfSection, NtCurrentProcess, pSectionBaseAddress
 
                       invoke DbgPrint, $CTA0("SharedSection: Section at address %08X unmapped /n"), pSectionBaseAddress
 
               .else
                      invoke DbgPrint, $CTA0("SharedSection: Couldn't map view of section. Status: %08X/n"), eax
               .endif
               invoke ZwClose, hSection
               invoke DbgPrint, $CTA0("SharedSection: Section object handle closed/n")
        .else
               invoke DbgPrint, $CTA0("SharedSection: Couldn't open section. Status: %08X/n"), eax
        .endif
 
    .else
        mov [esi].IoStatus.Status, STATUS_INVALID_DEVICE_REQUEST
    .endif
 
    assume edi:nothing
 
    fastcall IofCompleteRequest, esi, IO_NO_INCREMENT
 
    invoke DbgPrint, $CTA0("SharedSection: Leaving DispatchControl/n")
 
    mov eax, [esi].IoStatus.Status
    assume esi:nothing
 
    ret
 
DispatchControl endp
 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;                                       DriverUnload                                                
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 
DriverUnload proc pDriverObject:PDRIVER_OBJECT
 
    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
 
local status:NTSTATUS
local pDeviceObject:PDEVICE_OBJECT
 
    mov status, STATUS_DEVICE_CONFIGURATION_ERROR
 
    invoke IoCreateDevice, pDriverObject, 0, addr g_usDeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, 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=SharedSection
 
/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
move %drv%.sys ..
 
echo.
pause
    一般当处理共享资源的时候,要求必须是同步的,如果对共享资源的写和读不能同时访问,流操作不能进行。
        lea ecx, oa
        InitializeObjectAttributes ecx, offset g_usSectionName, OBJ_CASE_INSENSITIVE, NULL, NULL
        invoke ZwOpenSection, addr hSection, SECTION_MAP_WRITE + SECTION_MAP_READ, addr oa
接收IOCTL_SHARE_MY_SECTION控制代码后,驱动程序试着打开一个内存区对象通过g_usSectionName,作为内存区对象名。
.if eax == STATUS_SUCCESS
            and pSectionBaseAddress, NULL
            and liViewSize.HighPart, 0
            and liViewSize.LowPart, 0
            invoke ZwMapViewOfSection, hSection, NtCurrentProcess, addr pSectionBaseAddress, 0, SECTION_SIZE, /
                                   NULL, addr liViewSize, ViewShare, 0, PAGE_READWRITE
            .if eax == STATUS_SUCCESS
    如果映射的内存区成功打开,跟从程序的地址空间中的读数据是没有区别的。但是...
    通过调用ZwMapViewOfSection函数,变量pSectionBaseAddress被赋予用户地址范围的一个值,而不是内核地址范围。因为在这个地址仅内存区映射的进程地址空间环境中用到。当共享内存区处于驱动平台(传入IRP_MJ_DEVICE_CONTROL控制码到驱动环境中流操作会被触发),然后在程序环境中。
    虚拟地址是不同的在内核模式和我们的用户程序环境中,但是被映射的内存区物理页面是相同的。在我们的例子中就是一页和要翻转的数据。
_try
 
                invoke _strrev, pSectionBaseAddress
                mov [esi].IoStatus.Status, STATUS_SUCCESS
 
                _finally
通过设置SHE结构,调用_strrev转换字符串,现在很容易被读出来。
     invoke ZwUnmapViewOfSection, NtCurrentProcess, pSectionBaseAddress
            .endif
            invoke ZwClose, hSection
        .endif
释放被分配的资源,在驱动管理程序中返回代码表示DeviceIoControl成功,并且显示翻转后的行。
 
 
 

你可能感兴趣的:(kmd--8共享内存区通讯(Share section))