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_LEVELSHE異常纔會被激發,任何的異常都是通過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成功,並且顯示翻轉後的行。
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章