/*
文件名:KeInsertQueueApc.c
应用层有相应的公开的APC函数,如:QueueUserAPC。
但是内核中却没有公开的函数,在微软的网站上搜索下,只搜索到一篇文章:
http://www.microsoft.com/msj/0799/nerd/nerd0799.aspx
很早的了,上个世纪的。而且还有隐含的声明。
APC作为一个操作系统的基本的机制,岂能没有?除非你把应用层的也删除了等原因。
其实这些APC函数在内核中已经导出了,且在很早的版本都有了。
所以可以放心使用这些函数。
内核驱动开发的功能和性能在于开发人员的认识和胆量。
胆量从何而来,在于认识的熟练程度。
顺便说一下:
内核的DPC函数倒是公开了,如:
KeInitializeDpc
KeInsertQueueDpc
KeRemoveQueueDpc
本文的一些数据来自WRK和上面的链接。
本文只是一个简单的示例:
在内核中调用应用程序事先准备好的函数。
更多的功能请看网上:如杀进程,注入DLL等。
made by correy
made at 2014.09.11
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/
#include "ntddk.h"
#define FILE_DEVICE_UNKNOWN 0x00000022
#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN
#define IOCTL_NOTIFY_REGISTER_APC CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
typedef
VOID
(*PKNORMAL_ROUTINE) (
IN PVOID NormalContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
typedef
VOID
(*PKKERNEL_ROUTINE) (
IN struct _KAPC *Apc,
IN OUT PKNORMAL_ROUTINE *NormalRoutine,
IN OUT PVOID *NormalContext,
IN OUT PVOID *SystemArgument1,
IN OUT PVOID *SystemArgument2
);
typedef
VOID
(*PKRUNDOWN_ROUTINE) (
IN struct _KAPC *Apc
);
typedef enum _KAPC_ENVIRONMENT {
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment,
InsertApcEnvironment
} KAPC_ENVIRONMENT;
NTKERNELAPI
VOID
KeInitializeApc (
__out PRKAPC Apc,
__in PRKTHREAD Thread,
__in KAPC_ENVIRONMENT Environment,
__in PKKERNEL_ROUTINE KernelRoutine,
__in_opt PKRUNDOWN_ROUTINE RundownRoutine,
__in_opt PKNORMAL_ROUTINE NormalRoutine,
__in_opt KPROCESSOR_MODE ProcessorMode,
__in_opt PVOID NormalContext
);
PLIST_ENTRY
KeFlushQueueApc (
__inout PKTHREAD Thread,
__in KPROCESSOR_MODE ProcessorMode
);
NTKERNELAPI
BOOLEAN
KeInsertQueueApc (
__inout PRKAPC Apc,
__in_opt PVOID SystemArgument1,
__in_opt PVOID SystemArgument2,
__in KPRIORITY Increment
);
BOOLEAN
KeRemoveQueueApc (
__inout PKAPC Apc
);
void KnotifyUnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS KnotifyDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS KnotifyDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
NTSTATUS ntStatus;
UNICODE_STRING uszDriverString;
UNICODE_STRING uszDeviceString;
UNICODE_STRING uszNotifyEventString;
PDEVICE_OBJECT pDeviceObject;
__debugbreak();
RtlInitUnicodeString(&uszDriverString, L"\\Device\\test");// Point uszDriverString at the driver name
ntStatus = IoCreateDevice(DriverObject, 0, &uszDriverString, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);// Create and initialize device object
if(ntStatus != STATUS_SUCCESS)
return ntStatus;
RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\test");// Point uszDeviceString at the device name
ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);// Create symbolic link to the user-visible name
if(ntStatus != STATUS_SUCCESS)
{
IoDeleteDevice(pDeviceObject);// Delete device object if not successful
return ntStatus;
}
// Load structure to point to IRP handlers...
DriverObject->DriverUnload = KnotifyUnloadDriver;
DriverObject->MajorFunction[IRP_MJ_CREATE] = KnotifyDispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KnotifyDispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KnotifyDispatchIoctl;
return ntStatus;// Return success
}
NTSTATUS KnotifyDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
void KMApcCallback(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
/*
0: kd> k
ChildEBP RetAddr
b1a6fcfc 8050099b KNotify!KMApcCallback [d:\temp\sources\msj\column\0799\kernel\knotify.c @ 164]
b1a6fd4c 80542853 nt!KiDeliverApc+0x1af
b1a6fd4c 7c92e514 nt!KiServiceExit+0x59
0012fef8 7c92d21a ntdll!KiFastSystemCallRet
0012fefc 7c8023f1 ntdll!ZwDelayExecution+0xc
0012ff54 0040110b kernel32!SleepEx+0x61
0012ff78 00401228 ConsoleApplication1!main+0xab [e:\code\consoleapplication1\consoleapplication1.cpp @ 51]
0012ffc0 7c816037 ConsoleApplication1!__tmainCRTStartup+0xfe [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 241]
0012fff0 00000000 kernel32!BaseProcessStart+0x23
*/
{
ExFreePool(Apc);
return;
}
NTSTATUS KnotifyDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_NOTIFY_REGISTER_APC:
{
PKAPC Apc;
ULONG *UserRoutine = (ULONG *)Irp->AssociatedIrp.SystemBuffer;
Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
KeInitializeApc(Apc,
KeGetCurrentThread(),
OriginalApcEnvironment,
(PKKERNEL_ROUTINE)&KMApcCallback, // kernel-mode routine
0, // rundown routine
(PKNORMAL_ROUTINE)*UserRoutine, // user-mode routine
UserMode, (PVOID)(ULONG)1);
KeInsertQueueApc(Apc, (PVOID)(ULONG)2, (PVOID)(ULONG)3, 0);
ntStatus = STATUS_SUCCESS;
break;
}
default:
break;
}
Irp->IoStatus.Status = ntStatus;
// Set # of bytes to copy back to user-mode...
if(ntStatus == STATUS_SUCCESS)
Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
else
Irp->IoStatus.Information = 0;
if(ntStatus != STATUS_PENDING)
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
void KnotifyUnloadDriver(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING uszDeviceString;
IoDeleteDevice(DriverObject->DeviceObject);
RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\test");
IoDeleteSymbolicLink(&uszDeviceString);
}
----------------------------------------------------------------------------------------------------------------------------------------------
#include "stdafx.h"
#include <Windows.h>
#define FILE_DEVICE_UNKNOWN 0x00000022
#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN
#define IOCTL_NOTIFY_REGISTER_APC CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
void ApcCallback(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
/*
0: kd> k
ChildEBP RetAddr
0012fc1c 7c92e457 ConsoleApplication1!ApcCallback [e:\code\consoleapplication1\consoleapplication1.cpp @ 20]
0012ff54 0040110b ntdll!KiUserApcDispatcher+0x7
0012ff78 00401228 ConsoleApplication1!main+0xab [e:\code\consoleapplication1\consoleapplication1.cpp @ 51]
0012ffc0 7c816037 ConsoleApplication1!__tmainCRTStartup+0xfe [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 241]
0012fff0 00000000 kernel32!BaseProcessStart+0x23
*/
{
wchar_t Message[80];
wsprintf(Message,L"APC Callback!\n P1 == %lx\n P2 == %lx\n P3 == %lx", NormalContext, SystemArgument1, SystemArgument2);
MessageBox(NULL, Message, L"Unotify", MB_OK);
}
int __cdecl main ()
{
__debugbreak();
HANDLE hDevice = CreateFile(L"\\\\.\\test", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if(hDevice == INVALID_HANDLE_VALUE)
{
MessageBox(0,L"请加载驱动!",0,0);
return 0;
}
DWORD dwBytesReturned;
DWORD pfnApc = (DWORD)&ApcCallback;
BOOL bReturnCode = DeviceIoControl(hDevice, IOCTL_NOTIFY_REGISTER_APC, &pfnApc, sizeof(DWORD), 0, 0, &dwBytesReturned, 0);
if(bReturnCode == FALSE)
{
MessageBox(0,L"DeviceIoControl失败!",0,0);
return 0;
}
MessageBox(NULL,L"APC Dispatched!",L"Unotify",MB_OK);//先显示这个,再显示ApcCallback的消息框。不过这也可以想办法改变的。
SleepEx(INFINITE, TRUE);//这一行是所有实现的关键。
return 0;
}
没有评论:
发表评论