📄 pgpwdnt.c
字号:
void MyRoutine(struct _KAPC *Apc,
PKNORMAL_ROUTINE norm_routine,
void *context,
void *SysArg1,
void *SysArg2)
{
ExFreePool(Apc);
return;
}
/* pointer to the APC we will create */
static struct _KAPC *apc;
/* KeInitializeApc() and KeInsertQueueApc() are the two functions needed to
send an APC; they're both exported but not prototyped in the DDK, so we
prototype them here. */
void KeInitializeApc(struct _KAPC *Apc, PKTHREAD thread,
unsigned char state_index,
PKKERNEL_ROUTINE ker_routine,
PKRUNDOWN_ROUTINE rd_routine,
PKNORMAL_ROUTINE nor_routine,
unsigned char mode,
void *context);
void KeInsertQueueApc(struct _KAPC *APC,
void *SysArg1,
void *SysArg2,
unsigned char arg4);
/* call this function when you need to send a user-mode APC to
the current thread. addr must be linear address of your user-mode
function to call:
void MyApcRoutine(ULONG arg1, ULONG arg2, ULONG arg3);
...
SendAddrToTheDriverUsingIoctl((ULONG)MyApcRoutine);
you should send it to the driver using your custom IOCTL.
arg1, arg2, arg3 are arbitrary ulong's which are passed to the function
residing at addr; this function should be prototyped as receiving three
parameters and returning void. */
void SendAPC(ULONG addr, PKTHREAD thread, ULONG arg1, ULONG arg2, ULONG arg3)
{
/* this is self-explanatory */
apc=ExAllocatePool(NonPagedPool, sizeof(struct _KAPC));
/* Initialize the user-mode APC */
KeInitializeApc(apc, thread, 0,
(PKKERNEL_ROUTINE)&MyRoutine, 0,
(PKNORMAL_ROUTINE)addr, 1, (PVOID)arg1);
/* Insert it to the queue of the target thread */
KeInsertQueueApc(apc, (PVOID)arg2, (PVOID)arg3, 0);
/* Mark the current thread as alertable to force it to deliver the APC on
the next return to the user-mode. NOTE: severely undocumented code here!
*/
*((unsigned char *)thread+0x4a)=1;
}
//----------------------------------------------------------------------
//
// PGPWDNTworkitem
//
// Called by the system, this is initiated in the completion callback.
// We use it to ensure we''re running at passive level when we do
// an PGPWDNT
//
//----------------------------------------------------------------------
VOID PGPWDNTWorkItem( PVOID Context )
{
BOOLEAN mutexGrabbed = FALSE;
// PMDL Mdl;
//
// Grab our mutex
//
if( PGPWDNTMutex ) {
KeWaitForSingleObject( PGPWDNTMutex, Executive, KernelMode,
FALSE, NULL );
mutexGrabbed = TRUE;
DbgPrint(("Got mutex\n"));
}
// Mdl = IoAllocateMdl((void *)((PPGPWDNT_COMPLETE_CONTEXT)Context)->FileName,
// 1024,0,FALSE,NULL);
// MmBuildMdlForNonPagedPool(Mdl);
// MmProbeAndLockPages(Mdl, KernelMode,IoReadAccess);
//
// Call the PGPWDNT routine
//
SendAPC(tc_callback, tc_thread,
(ULONG)((PPGPWDNT_COMPLETE_CONTEXT)Context)->FileName, 0, 0);
//
// Release Mutex
//
if( mutexGrabbed ) {
DbgPrint(("Releasing mutex\n"));
KeReleaseMutex( PGPWDNTMutex, FALSE );
}
//
// Complete the IRP
//
((PPGPWDNT_COMPLETE_CONTEXT) Context)->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( ((PPGPWDNT_COMPLETE_CONTEXT) Context)->Irp,
IO_NO_INCREMENT );
//
// Free memory
//
// ExFreePool( ((PPGPWDNT_COMPLETE_CONTEXT) Context)->FileName);
ExFreePool( Context );
}
//----------------------------------------------------------------------
// D I S P A T C H A N D H O O K E N T R Y P O I N T S
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//
// PGPWDNTHookDone
//
// Gets control on the way back from a delete operation. At this point
// the file cannot be opened by anything else, so we can move it into
// the recycle bin.
//
//----------------------------------------------------------------------
NTSTATUS PGPWDNTHookDone( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
IN PVOID Context )
{
if( NT_SUCCESS(Irp->IoStatus.Status)) {
ExInitializeWorkItem( &((PPGPWDNT_COMPLETE_CONTEXT) Context)->WorkItem,
PGPWDNTWorkItem, Context );
ExQueueWorkItem( &((PPGPWDNT_COMPLETE_CONTEXT) Context)->WorkItem,
CriticalWorkQueue );
//
// We have to complete the IRP later
//
return STATUS_MORE_PROCESSING_REQUIRED;
} else {
//
// Now we have to mark Irp as pending if necessary
//
if( Irp->PendingReturned ) {
IoMarkIrpPending( Irp );
}
//
// Free the completion context
//
ExFreePool( ((PPGPWDNT_COMPLETE_CONTEXT) Context)->FileName );
ExFreePool( Context );
return Irp->IoStatus.Status;
}
}
//----------------------------------------------------------------------
//
// PGPWDNTHookRoutine
//
// This routine is the main hook routine where we figure out what
// calls are being sent to the file system.
//
//----------------------------------------------------------------------
NTSTATUS PGPWDNTHookRoutine( PDEVICE_OBJECT HookDevice, IN PIRP Irp )
{
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PFILE_OBJECT fileObject;
PHOOK_EXTENSION hookExt;
PPGPWDNT_COMPLETE_CONTEXT completeContext;
//
// Extract the file object from the IRP
//
fileObject = currentIrpStack->FileObject;
//
// Point at the device extension, which contains information on which
// file system this IRP is headed for
//
hookExt = HookDevice->DeviceExtension;
//
// Copy parameters down to next level in the stack for the driver below us
//
*nextIrpStack = *currentIrpStack;
//
// Determine what function we're dealing with
//
switch( currentIrpStack->MajorFunction ) {
case IRP_MJ_CLEANUP:
//
// If the file will be deleted, see if we have to PGPWDNT it
//
completeContext = ExAllocatePool( NonPagedPool, sizeof( PGPWDNT_COMPLETE_CONTEXT));
if( fileObject->DeletePending && (SystemProcess != PsGetCurrentProcess()) &&
PGPWDNTCheckFileForPGPWDNT( HookDevice, Irp, completeContext )) {
//
// PGPWDNT the file
// Not yet!
// PGPWDNTSetDispositionFile( hookExt->FileSystem, currentIrpStack->FileObject,
// FALSE );
//
// Finish setting up the completion context
//
completeContext->DeviceObject = HookDevice;
completeContext->Irp = Irp;
completeContext->Token = PsReferencePrimaryToken(PsGetCurrentProcess());
if( !completeContext->Token ) {
//
// Couldn't reference the token(?)
//
DbgPrint(("PGPWDNT: Could not reference the process token.\n"));
ExFreePool( completeContext );
} else {
//
// Set the completion routine where we finish the job
//
DbgPrint(("PGPWDNT: going to move this to the recycle bin\n"));
IoSetCompletionRoutine( Irp, PGPWDNTHookDone, (PVOID) completeContext, TRUE, TRUE, TRUE );
IoMarkIrpPending( Irp );
IoCallDriver( hookExt->FileSystem, Irp );
//
// Return this because we're going to stall the IRP in the
// completion routine
//
return STATUS_PENDING;
}
} else {
ExFreePool( completeContext );
}
break;
default:
//
// Register a never-called completion routine just so that the IRP stack
// doesn't have a bogus completion routine in it.
//
IoSetCompletionRoutine( Irp, PGPWDNTHookDone, 0, FALSE, FALSE, FALSE );
break;
}
//
// Return the results of the call to the caller
//
return IoCallDriver( hookExt->FileSystem, Irp );
}
//----------------------------------------------------------------------
//
// PGPWDNTDeviceRoutine
//
// In this routine we handle requests to our own device. The only
// requests we care about handling explicitely are IOCTL commands that
// we will get from the GUI. We also expect to get Create and Close
// commands when the GUI opens and closes communications with us.
//
//----------------------------------------------------------------------
NTSTATUS PGPWDNTDeviceRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PIO_STACK_LOCATION irpStack;
PVOID inputBuffer;
PVOID outputBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
//
// Go ahead and set the request up as successful
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get the pointer to the input/output buffer and its length
//
inputBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBuffer = Irp->AssociatedIrp.SystemBuffer;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (irpStack->MajorFunction) {
case IRP_MJ_CREATE:
DbgPrint(("PGPWDNT: IRP_MJ_CREATE\n"));
break;
case IRP_MJ_CLOSE:
DbgPrint(("PGPWDNT: IRP_MJ_CLOSE\n"));
break;
}
//
// Complete the IRP
//
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------
//
// PGPWDNTDispatch
//
// Based on which device the Irp is destined for we call either the
// filesystem filter function, or our own device handling routine.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -