📄 pgpwipedeletent.c
字号:
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
//
//----------------------------------------------------------------------
#if (_WIN32_WINNT >= 0x0500)
VOID PGPWDNTWorkItem( IN PDEVICE_OBJECT DeviceObject, PVOID Context )
#else // _WIN32_WINNT < 0x5000
VOID PGPWDNTWorkItem( PVOID Context )
#endif // _WIN32_WINNT >= 0x5000
{
PPGPWDNT_COMPLETE_CONTEXT pwntcc;
pwntcc=(PPGPWDNT_COMPLETE_CONTEXT)Context;
num_scheds++;
// Do the APC call back to the user callback
SendAPC(tc_callback, tc_thread, (ULONG)pwntcc->FileName, 0, 0);
KeWaitForSingleObject(&apc_sem,Executive, KernelMode, FALSE, NULL);
// Free the filename
ExFreePool(pwntcc->FileName);
num_scheds--;
// Complete the IRP
pwntcc->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pwntcc->Irp,IO_NO_INCREMENT);
#if (_WIN32_WINNT >= 0x0500)
// free the work item
IoFreeWorkItem(pwntcc->WorkItem);
#endif // _WIN32_WINNT >= 0x5000
// Free the context memory
ExFreePool(pwntcc);
}
//----------------------------------------------------------------------
// 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 send it back
// to the user callback
//
//----------------------------------------------------------------------
NTSTATUS PGPWDNTHookDone( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
IN PVOID Context )
{
PPGPWDNT_COMPLETE_CONTEXT pwntcc;
pwntcc=(PPGPWDNT_COMPLETE_CONTEXT)Context;
if( NT_SUCCESS(Irp->IoStatus.Status))
{
#if (_WIN32_WINNT >= 0x0500)
pwntcc->WorkItem = IoAllocateWorkItem(DeviceObject);
if (pwntcc->WorkItem == NULL)
return STATUS_SUCCESS;
IoQueueWorkItem(pwntcc->WorkItem, PGPWDNTWorkItem,
CriticalWorkQueue, Context);
#else // _WIN32_WINNT < 0x5000
ExInitializeWorkItem(&(pwntcc->WorkItem),PGPWDNTWorkItem,Context);
ExQueueWorkItem(&(pwntcc->WorkItem),CriticalWorkQueue);
#endif // _WIN32_WINNT >= 0x5000
// 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(pwntcc->FileName);
ExFreePool(pwntcc);
return Irp->IoStatus.Status;
}
}
//----------------------------------------------------------------------
//
// pgpWipeDeleteDispatch
//
// This routine is the main hook routine where we figure out what
// calls are being sent to the file system.
//
//----------------------------------------------------------------------
NTSTATUS
pgpWipeDeleteDispatch (
PDEVICE_OBJECT HookDevice,
IN PIRP Irp )
{
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PDEVEXTENSION pdeve;
PPGPWDNT_COMPLETE_CONTEXT completeContext;
char *FileName;
PVOID Token;
// Point at the device extension, which contains information on which
// file system this IRP is headed for
pdeve = HookDevice->DeviceExtension;
// Determine what function we're dealing with
switch( currentIrpStack->MajorFunction )
{
case IRP_MJ_CLEANUP:
{
// Do stuff only if WOD is turned on
if((tc_flags&WDFLAG_WIPEFILES)!=0)
{
// If the file will be deleted, see if we have to PGPWDNT it
if(currentIrpStack->FileObject->DeletePending &&
(SystemProcess != PsGetCurrentProcess())&&
(tc_flags!=WDFLAG_NOOP)&&
(tc_callback!=0))
{
Token=PsReferencePrimaryToken(PsGetCurrentProcess());
if(Token)
{
if(PGPWDNTCheckFileForPGPWDNT(HookDevice,Irp,&FileName))
{
// Tell the OS not to delete the file
PGPWDNTSetDispositionFile( pdeve->pdevoNext,
currentIrpStack->FileObject, FALSE );
// Set up the completion context
completeContext =
ExAllocatePool( NonPagedPool, sizeof( PGPWDNT_COMPLETE_CONTEXT));
completeContext->Irp = Irp;
completeContext->Token = Token;
completeContext->DeviceObject = HookDevice;
completeContext->FileName = FileName;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine( Irp, PGPWDNTHookDone,
(PVOID) completeContext, TRUE, TRUE, TRUE );
IoMarkIrpPending( Irp );
IoCallDriver( pdeve->pdevoNext, Irp );
// Now stall the IRP
return STATUS_PENDING;
}
}
}
}
// default behavior
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver( pdeve->pdevoNext, Irp );
}
#if (_WIN32_WINNT >= 0x0500)
case IRP_MJ_POWER:
// must use special calls to pass down power IRPs
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(pdeve->pdevoNext, Irp);
#endif // _WIN32_WINNT >= 0x5000
default:
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver( pdeve->pdevoNext, Irp );
}
}
//----------------------------------------------------------------------
// D R I V E R - E N T R Y A N D H O O K R O U T I N E S
//----------------------------------------------------------------------
//----------------------------------------------------------------------
//
// HookDrive
//
// Hook the drive specified by determining which device object to
// attach to. The algorithm used here is similar to the one used
// internally by NT to determine which device object a file system request
// is directed at.
//
//----------------------------------------------------------------------
BOOLEAN
HookDrive(
IN USHORT Drive,
IN PDRIVER_OBJECT DriverObject,
IN PDRVEXTENSION DriverExtension,
IN HANDLE VolumeHandle )
{
PDEVICE_OBJECT fileSysDevice;
PDEVICE_OBJECT hookDevice;
NTSTATUS ntStatus;
PFILE_OBJECT fileObject;
IO_STATUS_BLOCK ioStatus;
PDEVEXTENSION pdeve;
UCHAR fsAttribInformation[256];
//
// Got the file handle, so now look-up the file-object it refers to
//
ntStatus = ObReferenceObjectByHandle( VolumeHandle, FILE_READ_DATA,
NULL, KernelMode, &fileObject, NULL );
if( !NT_SUCCESS( ntStatus ))
{
PGPdbgPrint(("PGPutil: Could not get fileobject from handle: %c\n",
'A'+Drive ));
return FALSE;
}
//
// Next, find out what device is associated with the file object by
// getting its related device object
//
fileSysDevice = IoGetRelatedDeviceObject( fileObject );
if ( ! fileSysDevice )
{
PGPdbgPrint(("PGPutil: Could not get related device object: %c\n",
'A'+Drive ));
ObDereferenceObject( fileObject );
return FALSE;
}
//
// The file system's device hasn't been hooked already, so make a
// hooking device object that will be attached to it.
//
ntStatus = IoCreateDevice( DriverObject,
sizeof(DEVEXTENSION),
NULL,
fileSysDevice->DeviceType,
0,
FALSE,
&hookDevice );
if ( !NT_SUCCESS(ntStatus) )
{
PGPdbgPrint(("PGPutil: failed to create associated device: %c\n",
'A'+Drive ));
ObDereferenceObject( fileObject );
return FALSE;
}
//
// Clear the device's init flag as per NT DDK KB article on creating device
// objects from a dispatch routine
//
hookDevice->Flags &= ~DO_DEVICE_INITIALIZING;
//
// Setup the device extensions. The drive letter and file system object
// are stored in the extension.
//
pdeve = hookDevice->DeviceExtension;
pdeve->ulDeviceType = WIPE_DELETE_DEV;
pdeve->pdrve = DriverExtension;
pdeve->ulSkipCount = 0; // not used by this device
pdeve->ucLogicalDrive = 'A'+Drive;
pdeve->pdevoNext = fileSysDevice;
pdeve->bIsNTFS = FALSE;
pdeve->bIsAnsi = FALSE;
//
// Determine which file system this is. If this fails, assume its NOT NTFS
//
ntStatus = ZwQueryVolumeInformationFile(
VolumeHandle, &ioStatus, fsAttribInformation,
sizeof(fsAttribInformation), FileFsAttributeInformation );
if( !NT_SUCCESS( ntStatus ))
{
PGPdbgPrint(("PGPutil: Could not get volume attributes: %x\n", ntStatus));
}
else if( RtlCompareMemory(
((PFILE_FS_ATTRIBUTE_INFORMATION)fsAttribInformation)->FileSystemName,
L"NTFS", 8 ) == 8)
{
pdeve->bIsNTFS = TRUE;
PGPdbgVerbosePrint((" => Its an NTFS volume\n"));
}
//
// Finally, attach to the device. The second we're successfully attached,
// we may start receiving IRPs targetted at the device we've hooked.
//
if ( IoAttachDeviceToDeviceStack( hookDevice, fileSysDevice ) == NULL )
{
//
// Couldn't attach for some reason
//
PGPdbgPrint(("PGPutil: Connect with Filesystem failed: %c (%x) =>%x\n",
'A'+Drive, fileSysDevice, ntStatus ));
//
// Derefence the object and get out
//
ObDereferenceObject( fileObject );
return FALSE;
}
//
// Note which device this is
//
LDriveDevices[Drive] = hookDevice;
//
// Dereference the object
//
ObDereferenceObject( fileObject );
return TRUE;
}
//----------------------------------------------------------------------
//
// Installable driver initialization. Here we just set ourselves up.
// This function is called from the drivers DriverEntry routine.
//
//----------------------------------------------------------------------
NTSTATUS
pgpWipeDeleteInit (
IN PDRIVER_OBJECT DriverObject,
IN PDRVEXTENSION DriverExtension)
{
NTSTATUS ntStatus;
WCHAR volumeBuffer[] = L"\\DosDevices\\X:\\";
UNICODE_STRING volumeBufferUnicodeString;
USHORT drive;
HANDLE volumeHandle;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatus;
BOOLEAN errorMode;
FILE_FS_DEVICE_INFORMATION fsDeviceInformation;
PGPdbgVerbosePrint (("PGPutil: entering pgpWipeDeleteInit\n"));
// Some setup work to initialize the driver
KeInitializeSemaphore(&apc_sem,0,1);
num_scheds=0;
//
// If not NT 4.0 Final Release, shorten the Fast I/O table so that PGPWDNT
// will work on the Betas and Release Candidates
//
if( *NtBuildNumber < NT4FINAL )
{
FastIOHook.SizeOfFastIoDispatch =
(ULONG) &FastIOHook.FastIoQueryNetworkOpenInfo -
(ULONG) &FastIOHook;
}
//
// Set up the Fast I/O dispatch table
//
DriverObject->FastIoDispatch = &FastIOHook;
//
// Disable hard errors so that we don't pop-up when touching removable media
//
errorMode = IoSetThreadHardErrorMode( FALSE );
//
// Need to check each drive to see if its a local hard disk
//
RtlInitUnicodeString (&volumeBufferUnicodeString,
volumeBuffer );
for(drive = 2; drive < 26; drive++ )
{
LDriveDevices[drive] = NULL;
volumeBufferUnicodeString.Buffer[12] = drive+'A';
InitializeObjectAttributes( &objectAttributes,
&volumeBufferUnicodeString,
OBJ_CASE_INSENSITIVE, NULL, NULL );
ntStatus = ZwCreateFile( &volumeHandle, FILE_ANY_ACCESS,
&objectAttributes, &ioStatus, NULL, 0,
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -