上篇教程我们学习了通过Section在用户进程和内核驱动程序之间共享信息的方法,但是这种方法有一个缺点,就是驱动程序被硬性限制在具体进程的地址上下文中,即驱动程序所使用的虚拟地址位于此进程的地址空间中。我们在本例中使用的方法将没有这个缺点。对于驱动程序来说,这种方法更为自然些。
首先来看看驱动程序。
unit SharingMemory;
interface
uses
nt_status, ntoskrnl, native, winioctl, fcall, macros;
function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall;
implementation
uses
seh;
var
g_pSharedMemory: PVOID;
g_pMdl: PVOID;
g_pUserAddress: PVOID;
g_fTimerStarted: boolean;
g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;
{更新系统时间到共享内存}
procedure UpdateTime; stdcall;
var
SysTime:LARGE_INTEGER;
begin
KeQuerySystemTime(@SysTime);
ExSystemTimeToLocalTime(@SysTime, g_pSharedMemory);
end;
procedure TimerRoutine(pDeviceObject:PDEVICE_OBJECT; pContext:PVOID); stdcall;
begin
UpdateTime;
end;
{清理过程--释放资源}
procedure Cleanup(pDeviceObject:PDEVICE_OBJECT); stdcall;
begin
if g_fTimerStarted then
begin
IoStopTimer(pDeviceObject);
DbgPrint('SharingMemory: Timer stopped'#13#10);
end;
if (g_pUserAddress <> nil) and (g_pMdl <> nil) then
begin
MmUnmapLockedPages(g_pUserAddress, g_pMdl);
DbgPrint('SharingMemory: Memory at address %08X unmapped'#13#10,
g_pUserAddress);
g_pUserAddress := nil;
end;
if g_pMdl <> nil then
begin
IoFreeMdl(g_pMdl);
DbgPrint('SharingMemory: MDL at address %08X freed'#13#10,
g_pMdl);
g_pMdl := nil;
end;
if g_pSharedMemory <> nil then
begin
ExFreePool(g_pSharedMemory);
DbgPrint('SharingMemory: Memory at address %08X released'#13#10,
g_pSharedMemory);
g_pSharedMemory := nil;
end;
end;
function DispatchCleanup(pDeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
begin
DbgPrint(#13#10'SharingMemory: Entering DispatchCleanup'#13#10);
Cleanup(pDeviceObject);
p_Irp^.IoStatus.Status := STATUS_SUCCESS;
p_Irp^.IoStatus.Information := 0;
IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
DbgPrint('SharingMemory: Leaving DispatchCleanup'#13#10);
result := STATUS_SUCCESS;
end;
function DispatchCreateClose(p_DeviceObject:PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
begin
p_Irp^.IoStatus.Status := STATUS_SUCCESS;
p_Irp^.IoStatus.Information := 0;
IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
result := STATUS_SUCCESS;
end;
function DispatchControl(p_DeviceObject: PDEVICE_OBJECT; p_Irp:PIRP): NTSTATUS; stdcall;
label
SafePlace;
var
dwContext:DWORD;
psl:PIO_STACK_LOCATION;
IOCTL_GIVE_ME_YOUR_MEMORY: DWORD;
pSystemBuffer: PVOID;
begin
DbgPrint(#13#10'SharingMemory: Entering DispatchControl'#13#10);
IOCTL_GIVE_ME_YOUR_MEMORY := CTL_CODE(FILE_DEVICE_UNKNOWN,
$800, METHOD_BUFFERED,
FILE_READ_ACCESS);
p_Irp^.IoStatus.Status := STATUS_UNSUCCESSFUL;
p_Irp^.IoStatus.Information := 0;
psl := IoGetCurrentIrpStackLocation(p_Irp); {取IRP的stack location的指针}
if psl^.Parameters.DeviceIoControl.IoControlCode = IOCTL_GIVE_ME_YOUR_MEMORY then
begin
{是我们控制码就开始处理}
if psl^.Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PVOID) then
begin
g_pSharedMemory := ExAllocatePool(NonPagedPool, PAGE_SIZE);
if g_pSharedMemory <> nil then
begin
DbgPrint('SharingMemory: %X bytes of nonpaged memory allocated at address %08X'#13#10,
PAGE_SIZE, g_pSharedMemory);
g_pMdl := IoAllocateMdl(g_pSharedMemory, PAGE_SIZE,
false, false, nil);
if g_pMdl <> nil then
begin
DbgPrint('SharingMemory: MDL allocated at address %08X'#13#10,
g_pMdl);
MmBuildMdlForNonPagedPool(g_pMdl);
{安装SEH}
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;
g_pUserAddress := MmMapLockedPagesSpecifyCache(g_pMdl,
UserMode, MmCached, nil, 0, NormalPagePriority);
if g_pUserAddress <> nil then
begin
DbgPrint('SharingMemory: Memory mapped into user space at address %08X'#13#10,
g_pUserAddress);
pSystemBuffer := p_Irp^.AssociatedIrp.SystemBuffer;
PVOID(pSystemBuffer^) := g_pUserAddress;
UpdateTime;
if IoInitializeTimer(p_DeviceObject, @TimerRoutine,
@dwContext) = STATUS_SUCCESS then
begin
IoStartTimer(p_DeviceObject);
g_fTimerStarted := true;
DbgPrint('SharingMemory: Timer started');
p_Irp^.IoStatus.Information := sizeof(PVOID);
p_Irp^.IoStatus.Status := STATUS_SUCCESS;
end;
end;
SafePlace: {发生异常安全退出的地方}
asm
pop fs:[0]
add esp, 4
end;
end;
end;
end else
begin
p_Irp^.IoStatus.Status := STATUS_BUFFER_TOO_SMALL;
end;
end else
begin
p_Irp^.IoStatus.Status := STATUS_INVALID_DEVICE_REQUEST;
end;
if p_Irp^.IoStatus.Status <> STATUS_SUCCESS then
begin
DbgPrint('SharingMemory: Something went wrong:'#13#10);
Cleanup(p_DeviceObject);
end;
IofCompleteRequest(p_Irp, IO_NO_INCREMENT);
DbgPrint('SharingMemory: Leaving DispatchControl'#13#10);
result := p_Irp^.IoStatus.Status;
end;
procedure DriverUnload(p_DriverObject:PDRIVER_OBJECT); stdcall;
begin
IoDeleteSymbolicLink(@g_usSymbolicLinkName);
IoDeleteDevice(p_DriverObject^.DeviceObject);
end;
{驱动程序进入点}
function _DriverEntry(pDriverObject:PDRIVER_OBJECT; pusRegistryPath:PUNICODE_STRING): NTSTATUS;
var
status: NTSTATUS;
pDeviceObject: TDeviceObject;
begin
status := STATUS_DEVICE_CONFIGURATION_ERROR;
g_pSharedMemory := nil;
g_pMdl := nil;
g_pUserAddress := nil;
g_fTimerStarted := false;
RtlInitUnicodeString(g_usDeviceName, '\Device\SharingMemory');
RtlInitUnicodeString(g_usSymbolicLinkName, '\DosDevices\SharingMemory');
if IoCreateDevice(pDriverObject, 0, @g_usDeviceName,
FILE_DEVICE_UNKNOWN, 0, true,
pDeviceObject) = STATUS_SUCCESS then
begin
if IoCreateSymbolicLink(@g_usSymbolicLinkName,
@g_usDeviceName) = STATUS_SUCCESS then
begin
pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @DispatchCreateClose;
pDriverObject^.MajorFunction[IRP_MJ_CLEANUP] := @DispatchCleanup;
pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @DispatchCreateClose;
pDriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL] := @DispatchControl;
pDriverObject^.DriverUnload := @DriverUnload;
status := STATUS_SUCCESS;
end else
begin
IoDeleteDevice(@pDeviceObject);
end;
end;
result := status;
end;
end.
pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @DispatchCreateClose;
pDriverObject^.MajorFunction[IRP_MJ_CLEANUP] := @DispatchCleanup;
pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @DispatchCreateClose;
pDriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL] := @DispatchControl;
pDriverObject^.DriverUnload := @DriverUnload;
g_pSharedMemory := ExAllocatePool(NonPagedPool, PAGE_SIZE);
if g_pSharedMemory <> nil then
begin
PMDL = ^TMDL;
TMDL=packed record
Next: PMDL;
Size: CSHORT;
MdlFlags: CSHORT;
Process: PEPROCESS;
MappedSystemVa: PVOID;
StartVa: PVOID;
ByteCount: ULONG;
ByteOffset: ULONG;
end; g_pMdl := IoAllocateMdl(g_pSharedMemory, PAGE_SIZE,
false, false, nil);
MmBuildMdlForNonPagedPool(g_pMdl);
g_pUserAddress := MmMapLockedPagesSpecifyCache(g_pMdl,
UserMode, MmCached, nil, 0, NormalPagePriority);
if g_pUserAddress <> nil then
begin
DbgPrint('SharingMemory: Memory mapped into user space at address %08X'#13#10,
g_pUserAddress);
pSystemBuffer := p_Irp^.AssociatedIrp.SystemBuffer;
PVOID(pSystemBuffer^) := g_pUserAddress;
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: