這是學習kernel model driver(KMD)時翻譯的一篇文章,大體意思差不多,但表達不好,歡迎指出其中的不足。。源碼是用匯編寫的。
翻譯的比較匆忙,沒有校對。希望不會有太多的錯誤。
;@echo off
;goto make
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; S T R U C T U R E S
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; 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
爲了通過異常處理使我們的程序能夠繼續運行,必須保留寄存器esp和ebp的值,在結構中保存這三個的值,調用會發生讀錯誤的函數BuggyReader,函數試着讀四個字節在地址0處。
BuggyReader proc
xor eax, eax
mov eax, [eax]
ret
BuggyReader endp
對空指針的處理是個經常發生的錯誤,因爲Microsoft規定範圍從00000000-0000FFFFh的64k大小內存是不可訪問的,對這個範圍任何字節進行存取都會導致一個EXCEPTION_ACCESS_VIOLATION類型的異常。
8.1.3異常處理
BuggyReader函數中試着讀數據從地址00000000處激發異常,進入我們設置的異常處理函數
進入異常處理函數內,首先顯示一個異常發生類型信息,如果是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的值爲零返回,告訴系統程序繼續正常執行,改變eip爲SafePlace的地址,並恢復esp和ebp的值,程序從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結構的註冊和恢復
對於一些相同的操作,定義宏可以簡化程序,我定義一個簡單的宏來操作SHE,seh0.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結構。
;@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 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成功,並且顯示翻轉後的行。