整個驅動程序非常簡單,但它卻是個完整意義上的驅動程序,包含了一個驅動程序所必須的各個部分。程序很簡單,大家一看就明白,所以也沒加什麼注釋,只撿幾個重要的地方說明一下。
使用共享資源通常情況下需要考慮同步問題,即讀寫線程不能同時訪問共享資源。在本例中總是只有一個線程,所以不需要同步。
代碼:InitializeObjectAttributes(oa, @g_usSectionName,
OBJ_CASE_INSENSITIVE, 0, nil);
取得控制代碼IOCTL_SHARE_MY_SECTION,驅動程序嘗試打開section對象,其名字定義為變量g_usSectionName。
代碼:status := ZwOpenSection(@hSection,
SECTION_MAP_WRITE or SECTION_MAP_READ,
@oa);
if status = STATUS_SUCCESS then
begin
DbgPrint(SharedSection: Section object opened#13#10);
pSectionBaseAddress := nil;
liViewSize.HighPart := 0;
liViewSize.LowPart := 0;
status := ZwMapViewOfSection(hSection, HANDLE(NtCurrentProcess),
pSectionBaseAddress, 0,
SECTION_SIZE, nil,
@liViewSize, ViewShare, 0,
PAGE_READWRITE);
如果取得了section的句柄,我們就來映射它的視圖。這裡與應用程序中的映射視圖部分幾乎完全相同。但是在調用了ZwMapViewOfSection之後,變量pSectionBaseAddress保存的值位於用戶地址區域中,而不是核心區域中的地址,這點我們可以預料到。這可是個原則上的問題,即對這個地址的使用將只能在這個進程的上下文中,在映射section的地址空間中。由於SharedSection驅動程序是單層的(您還記得IRP_MJ_DEVICE_CONTROL類型的IRP處理要經過驅動程序進入發出該操作的線程上下文中),所以我們位於我們的應用程序的上下文中。
這裡視圖的虛擬地址與應用程序中視圖的地址將有所不同,但共享section所在的物理頁是同一個。我們這裡有一個內存頁,其中還保存著倒著寫的一行文字。
代碼:asm
push offset DefaultExceptionHandler
push fs:[0]
mov fs:[0], esp
mov sseh.SafeEip, offset SafePlace
mov sseh.PrevEbp, ebp
mov sseh.PrevEsp, esp
end;
_strrev(pSectionBaseAddress);
p_Irp^.IoStatus.Status := STATUS_SUCCESS;
DbgPrint(SharedSection: String reversed#13#10);
SafePlace:
asm
pop fs:[0]
add esp, 4
end;
以上建立SEH-frame,並調用_strrev函數將內存裡的字符串反轉過來。
下面來看看在用戶模式下如何加載和調用這個驅動程序。
代碼:program SharedSection;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows,
Dialogs,
WinSvc,
nt_status,
native,
macros,
ntdll;
const
SECTION_SIZE = $1000;
str = .revird ecived a dna sessecorp resu neewteb yromem erahs ot euqinhcet emas eht esu nac uoy ,revewoH .sessecorp resu gnoma yromem gnirahs rof desu euqinhcet nommoc a si elif gnigap eht yb dekcab elif deppam-yromem A;
_Delete = $10000;
var
hSection:HANDLE;
liSectionSize: LARGE_INTEGER;
oa:OBJECT_ATTRIBUTES;
pSectionBaseAddress:PVOID;
liViewSize: LARGE_INTEGER;
g_usSectionName: UNICODE_STRING;
status:NTSTATUS;
sTemp: array[0..255] of char;
function CallDriver: boolean;
var
fOk: boolean;
hSCManager:HANDLE;
hService:HANDLE;
acModulePath: string;
_ss:SERVICE_STATUS;
hDevice:HANDLE;
dwBytesReturned: DWORD;
IOCTL_SHARE_MY_SECTION: DWORD;
lpTemp: PChar;
begin
fOk := false;
IOCTL_SHARE_MY_SECTION := CTL_CODE(FILE_DEVICE_UNKNOWN, $800, 0, 0);
hSCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
if hSCManager <> 0 then
begin
acModulePath := GetCurrentDir + + ExtractFileName(SharedSection.sys);
hService := CreateService(hSCManager, SharedSection,
One way to share section,
SERVICE_START or SERVICE_STOP or _Delete,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_IGNORE,
PChar(acModulePath),
nil, nil, nil, nil, nil);
if hService <> 0 then
begin
if StartService(hService, 0, lpTemp) then
begin;
hDevice := CreateFile(PChar(\.SharedSection), 0, 0,
nil, OPEN_EXISTING, 0, 0);
if hDevice <> INVALID_HANDLE_VALUE then
begin
if DeviceIoControl(hDevice, IOCTL_SHARE_MY_SECTION,
nil, 0, nil, 0, dwBytesR