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, dwBytesReturned, nil) then begin fOk := true; end else begin ShowMessage('Can''t send control code to device.'); end; CloseHandle(hDevice); end else begin ShowMessage('Device is not present.'); end; ControlService(hService, SERVICE_CONTROL_STOP, _ss); end else begin ShowMessage('Can''t start driver.'); end; DeleteService(hService); CloseServiceHandle(hService); end else begin ShowMessage('Can''t register driver.'); end; CloseServiceHandle(hSCManager); end else begin ShowMessage('Can''t connect to Service Control Manager.'); end; result := fOk; end;
begin liSectionSize.HighPart := 0; liSectionSize.LowPart := SECTION_SIZE; RtlInitUnicodeString(g_usSectionName, '\BaseNamedObjects\UserKernelSharedSection'); InitializeObjectAttributes(oa, @g_usSectionName, OBJ_CASE_INSENSITIVE, 0, nil); status := ZwCreateSection(@hSection, SECTION_MAP_WRITE or SECTION_MAP_READ, @oa, @liSectionSize, PAGE_READWRITE, SEC_COMMIT, 0); if status = STATUS_SUCCESS then begin pSectionBaseAddress := nil; liViewSize.HighPart := 0; liViewSize.LowPart := 0; status := ZwMapViewOfSection(hSection, HANDLE(NtCurrentProcess), pSectionBaseAddress, 0, SECTION_SIZE, nil, @liViewSize, ViewShare, 0, PAGE_READWRITE); if status = STATUS_SUCCESS then begin //RtlInitUnicodeString(g_szStrToReverse, str); strcpy(pSectionBaseAddress, PChar(str)); if CallDriver then begin strcpy(sTemp, pSectionBaseAddress); ShowMessage(sTemp); ZwUnmapViewOfSection(HANDLE(NtCurrentProcess), pSectionBaseAddress); end; end else begin ShowMessage('Can''t map section.'); end; ZwClose(hSection); end else begin ShowMessage('Can''t create section.'); end;
end.
这是个控制台应用程序,我们也只讲几个关键的地方,其他地方很容易理解。 liSectionSize.HighPart := 0; liSectionSize.LowPart := SECTION_SIZE; 建立section需要指明其大小,对于大小值使用LARGE_INTEGER类型的变量的程序来说,这个值可以超过4GB。我们将这个值初始化为一个内存页的大小即4KB。 代码:InitializeObjectAttributes(oa, @g_usSectionName, OBJ_CASE_INSENSITIVE, 0, nil); 对于宏InitializeObjectAttributes我们已经很熟悉了。后面的ZwCreateSection调用需要填充好的OBJECT_ATTRIBUTES结构体,填充工作我们用这些宏来完成。 我们准备使用的section应该取个名字,这样就可以用名字来打开它。section的名字必须就unicode字符串,通过RtlInitUnicodeString(g_usSectionName, '\BaseNamedObjects\UserKernelSharedSection');来创建。 section对象在对象管理器名字空间的BaseNamedObjects目录下,用户进程创建的命名对象一般都在这个目录下。 代码:status := ZwCreateSection(@hSection, SECTION_MAP_WRITE or SECTION_MAP_READ, @oa, @liSectionSize, PAGE_READWRITE, SEC_COMMIT, 0); 调用函数ZwCreateSection来创建命名section对象,其大小为SECTION_SIZE,访问方式为可读写。如果section创建成功,则可以从变量hSection中得到其句柄。 代码:if status = STATUS_SUCCESS then begin pSectionBaseAddress := nil; liViewSize.HighPart := 0; liViewSize.LowPart := 0; status := ZwMapViewOfSection(hSection, HANDLE(NtCurrentProcess), pSectionBaseAddress, 0, SECTION_SIZE, nil, @liViewSize, ViewShare, 0, PAGE_READWRITE); 这样就将section的所有的视图都映射到内存中。这个函数的参数够多的——所有的参数在DDK中都有详细介绍。参数pSectionBaseAddress初始化为NULL,为更方便她映射section,系统自己定义了映射section的虚拟地址,并将这个地址返给此参数。参数liViewSize初始化为零,这就定义了section将被全部映射。 代码:.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 我们将一行倒着写的文字拷贝到所得的视图中。驱动程序的任务就是将这行文字翻转,使其变为可读的形式。 代码:if status = STATUS_SUCCESS then begin strcpy(pSectionBaseAddress, PChar(str)); if CallDriver then begin strcpy(sTemp, pSectionBaseAddress); ShowMessage(sTemp); ZwUnmapViewOfSection(HANDLE(NtCurrentProcess), pSectionBaseAddress); end; CallDriver的返回值为TRUE表示驱动程序已成功完成自己的任务。我们来检查一下其工作的结果。在函数CallDriver中,我们完成通常的注册和启动驱动程序的操作并向驱动程序发送控制代码IOCTL_SHARE_MY_SECTION。 最后ZwUnmapViewOfSection(HANDLE(NtCurrentProcess), pSectionBaseAddress);把系统恢复成初始的样子。