Delphi研究之驱动开发篇(六)--利用Section与用户模式程序通讯(下)
整个驱动程序非常简单,但它却是个完整意义上的驱动程序,包含了一个驱动程序所必须的各个部分。程序很简单,大家一看就明白,所以也没加什么注释,只捡几个重要的地方说明一下。
使用共享资源通常情况下需要考虑同步问题,即读写线程不能同时访问共享资源。在本例中总是只有一个线程,所以不需要同步。
代码: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], espmov 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
补充:软件开发 , Delphi ,