www.pudn.com > Irp-Files.rar > driver.c
#include#include "ioctl.h" #include "wintypes.h" //--------------------------------------------------------------------------- #ifdef _DEBUG #define DbgPrint(_string) {DbgPrint _string;} #else #define DbgPrint(_string) #endif //--------------------------------------------------------------------------- NTSTATUS IoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { DbgPrint(("IoCompletionRoutine!\n")); *Irp->UserIosb = Irp->IoStatus; if (Irp->UserEvent) KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, 0); if (Irp->MdlAddress) { IoFreeMdl(Irp->MdlAddress); Irp->MdlAddress = NULL; } IoFreeIrp(Irp); return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS IrpFileCreate( IN PUNICODE_STRING FileName, IN ACCESS_MASK DesiredAccess, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT RealDevice, OUT PVOID *Object ) { NTSTATUS status; KEVENT event; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION irpSp; IO_SECURITY_CONTEXT securityContext; ACCESS_STATE accessState; OBJECT_ATTRIBUTES objectAttributes; PFILE_OBJECT fileObject; AUX_ACCESS_DATA auxData; RtlZeroMemory(&auxData, sizeof(AUX_ACCESS_DATA)); KeInitializeEvent(&event, SynchronizationEvent, FALSE); irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; InitializeObjectAttributes(&objectAttributes, NULL, OBJ_CASE_INSENSITIVE, 0, NULL); status = ObCreateObject(KernelMode, *IoFileObjectType, &objectAttributes, KernelMode, NULL, sizeof(FILE_OBJECT), 0, 0, (PVOID *)&fileObject); if (!NT_SUCCESS(status)) { IoFreeIrp(irp); return status; } RtlZeroMemory(fileObject, sizeof(FILE_OBJECT)); fileObject->Type = IO_TYPE_FILE; fileObject->Size = sizeof(FILE_OBJECT); fileObject->DeviceObject = RealDevice; // fileObject->RelatedFileObject = NULL; fileObject->Flags = FO_SYNCHRONOUS_IO; fileObject->FileName.MaximumLength = FileName->MaximumLength; fileObject->FileName.Buffer = ExAllocatePool(NonPagedPool, FileName->MaximumLength); if (fileObject->FileName.Buffer == NULL) { IoFreeIrp(irp); ObDereferenceObject(fileObject); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyUnicodeString(&fileObject->FileName, FileName); KeInitializeEvent(&fileObject->Lock, SynchronizationEvent, FALSE); KeInitializeEvent(&fileObject->Event, NotificationEvent, FALSE); irp->MdlAddress = NULL; irp->Flags |= IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API; irp->RequestorMode = KernelMode; irp->UserIosb = &ioStatus; irp->UserEvent = &event; irp->PendingReturned = FALSE; irp->Cancel = FALSE; irp->CancelRoutine = NULL; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.AuxiliaryBuffer = NULL; irp->Tail.Overlay.OriginalFileObject = fileObject; status = SeCreateAccessState( &accessState, &auxData, DesiredAccess, IoGetFileObjectGenericMapping()); if (!NT_SUCCESS(status)) { IoFreeIrp(irp); ExFreePool(fileObject->FileName.Buffer); ObDereferenceObject(fileObject); return status; } securityContext.SecurityQos = NULL; securityContext.AccessState = &accessState; securityContext.DesiredAccess = DesiredAccess; securityContext.FullCreateOptions = 0; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CREATE; irpSp->DeviceObject = DeviceObject; irpSp->FileObject = fileObject; irpSp->Parameters.Create.SecurityContext = &securityContext; irpSp->Parameters.Create.Options = (CreateDisposition << 24) | CreateOptions; irpSp->Parameters.Create.FileAttributes = (USHORT)FileAttributes; irpSp->Parameters.Create.ShareAccess = (USHORT)ShareAccess; irpSp->Parameters.Create.EaLength = 0; IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(DeviceObject, irp); if (status == STATUS_PENDING) KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); status = ioStatus.Status; if (!NT_SUCCESS(status)) { ExFreePool(fileObject->FileName.Buffer); fileObject->FileName.Length = 0; fileObject->DeviceObject = NULL; ObDereferenceObject(fileObject); } else { InterlockedIncrement(&fileObject->DeviceObject->ReferenceCount); if (fileObject->Vpb) { InterlockedIncrement(&fileObject->Vpb->ReferenceCount); } *Object = fileObject; DbgPrint(("Open file success! object = %x\n", fileObject)); } return status; } NTSTATUS IrpFileClose( IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject ) { NTSTATUS status; KEVENT event; PIRP irp; PVPB vpb; IO_STATUS_BLOCK ioStatusBlock; PIO_STACK_LOCATION irpSp; KeInitializeEvent(&event, SynchronizationEvent, FALSE); irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; irp->Tail.Overlay.OriginalFileObject = FileObject; irp->Tail.Overlay.Thread = PsGetCurrentThread(); irp->RequestorMode = KernelMode; irp->UserEvent = &event; irp->UserIosb = &irp->IoStatus; irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL; irp->Flags = IRP_SYNCHRONOUS_API | IRP_CLOSE_OPERATION; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CLEANUP; irpSp->FileObject = FileObject; status = IoCallDriver(DeviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject( &event, UserRequest, KernelMode, FALSE, NULL); } IoReuseIrp(irp , STATUS_SUCCESS); KeClearEvent(&event); irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_CLOSE; irpSp->FileObject = FileObject; irp->UserIosb = &ioStatusBlock; irp->UserEvent = &event; irp->Tail.Overlay.OriginalFileObject = FileObject; irp->Tail.Overlay.Thread = PsGetCurrentThread(); irp->AssociatedIrp.SystemBuffer = (PVOID)NULL; irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; vpb = FileObject->Vpb; if (vpb && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) { InterlockedDecrement(&vpb->ReferenceCount); FileObject->Flags |= FO_FILE_OPEN_CANCELLED; } status = IoCallDriver(DeviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL); } IoFreeIrp(irp); return status; } NTSTATUS IrpFileRead( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN ULONG Length, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatusBlock ) { NTSTATUS status; KEVENT event; PIRP irp; PIO_STACK_LOCATION irpSp; PDEVICE_OBJECT deviceObject; if (ByteOffset == NULL) { if (!(FileObject->Flags & FO_SYNCHRONOUS_IO)) return STATUS_INVALID_PARAMETER; ByteOffset = &FileObject->CurrentByteOffset; } if (FileObject->Vpb == 0 || FileObject->Vpb->RealDevice == NULL) return STATUS_UNSUCCESSFUL; deviceObject = FileObject->Vpb->DeviceObject; irp = IoAllocateIrp(deviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; irp->MdlAddress = IoAllocateMdl(Buffer, Length, FALSE, TRUE, NULL); if (irp->MdlAddress == NULL) { IoFreeIrp(irp); return STATUS_INSUFFICIENT_RESOURCES;; } MmBuildMdlForNonPagedPool(irp->MdlAddress); irp->Flags = IRP_READ_OPERATION; irp->RequestorMode = KernelMode; irp->UserIosb = IoStatusBlock; irp->UserEvent = &event; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.OriginalFileObject = FileObject; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_READ; irpSp->MinorFunction = IRP_MN_NORMAL; irpSp->DeviceObject = deviceObject; irpSp->FileObject = FileObject; irpSp->Parameters.Read.Length = Length; irpSp->Parameters.Read.ByteOffset = *ByteOffset; KeInitializeEvent(&event, SynchronizationEvent, FALSE); IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) status = KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); return status; } NTSTATUS IrpFileWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN ULONG Length, IN PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatusBlock ) { NTSTATUS status; KEVENT event; PIRP irp; PIO_STACK_LOCATION irpSp; PDEVICE_OBJECT deviceObject; if (ByteOffset == NULL) { if (!(FileObject->Flags & FO_SYNCHRONOUS_IO)) return STATUS_INVALID_PARAMETER; ByteOffset = &FileObject->CurrentByteOffset; } if (FileObject->Vpb == 0 || FileObject->Vpb->RealDevice == NULL) return STATUS_UNSUCCESSFUL; deviceObject = FileObject->Vpb->DeviceObject; irp = IoAllocateIrp(deviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; irp->MdlAddress = IoAllocateMdl(Buffer, Length, FALSE, TRUE, NULL); if (irp->MdlAddress == NULL) { IoFreeIrp(irp); return STATUS_INSUFFICIENT_RESOURCES;; } MmBuildMdlForNonPagedPool(irp->MdlAddress); irp->Flags = IRP_WRITE_OPERATION; irp->RequestorMode = KernelMode; irp->UserIosb = IoStatusBlock; irp->UserEvent = &event; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.OriginalFileObject = FileObject; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_WRITE; irpSp->MinorFunction = IRP_MN_NORMAL; irpSp->DeviceObject = deviceObject; irpSp->FileObject = FileObject; irpSp->Parameters.Write.Length = Length; irpSp->Parameters.Write.ByteOffset = *ByteOffset; KeInitializeEvent(&event, SynchronizationEvent, FALSE); IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) status = KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); return status; } NTSTATUS IrpFileQuery( IN PFILE_OBJECT FileObject, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass ) { NTSTATUS status; KEVENT event; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION irpSp; PDEVICE_OBJECT deviceObject; if (FileObject->Vpb == 0 || FileObject->Vpb->RealDevice == NULL) return STATUS_UNSUCCESSFUL; deviceObject = FileObject->Vpb->DeviceObject; KeInitializeEvent(&event, SynchronizationEvent, FALSE); irp = IoAllocateIrp(deviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; irp->Flags = IRP_BUFFERED_IO; irp->AssociatedIrp.SystemBuffer = FileInformation; irp->RequestorMode = KernelMode; irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL; irp->UserEvent = &event; irp->UserIosb = &ioStatus; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.OriginalFileObject = FileObject; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_QUERY_INFORMATION; irpSp->DeviceObject = deviceObject; irpSp->FileObject = FileObject; irpSp->Parameters.QueryFile.Length = Length; irpSp->Parameters.QueryFile.FileInformationClass = FileInformationClass; IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); return ioStatus.Status; } NTSTATUS IrpDirectoryQuery( IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, OUT PVOID Buffer, IN ULONG Length ) { NTSTATUS status; KEVENT event; PIRP irp; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION irpSp; PDEVICE_OBJECT deviceObject; PQUERY_DIRECTORY queryDirectory; if (FileObject->Vpb == 0 || FileObject->Vpb->RealDevice == NULL) return STATUS_UNSUCCESSFUL; deviceObject = FileObject->Vpb->DeviceObject; KeInitializeEvent(&event, SynchronizationEvent, FALSE); irp = IoAllocateIrp(deviceObject->StackSize, FALSE); if (irp == NULL) return STATUS_INSUFFICIENT_RESOURCES; irp->Flags = IRP_INPUT_OPERATION | IRP_BUFFERED_IO; irp->RequestorMode = KernelMode; irp->UserEvent = &event; irp->UserIosb = &ioStatus; irp->UserBuffer = Buffer; irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); irp->Tail.Overlay.OriginalFileObject = FileObject; irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL; //irp->Pointer = FileObject; irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY; irpSp->DeviceObject = deviceObject; irpSp->FileObject = FileObject; queryDirectory = (PQUERY_DIRECTORY)&irpSp->Parameters; queryDirectory->Length = Length; queryDirectory->FileName = NULL; queryDirectory->FileInformationClass = FileInformationClass; queryDirectory->FileIndex = 0; IoSetCompletionRoutine(irp, IoCompletionRoutine, NULL, TRUE, TRUE, TRUE); status = IoCallDriver(deviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); status = ioStatus.Status; } return status; } BOOLEAN GetDriveObject( IN ULONG DriveNumber, OUT PDEVICE_OBJECT *DeviceObject, OUT PDEVICE_OBJECT *ReadDevice ) { WCHAR driveName[] = L"\\DosDevices\\A:\\"; UNICODE_STRING deviceName; HANDLE deviceHandle; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatus; PFILE_OBJECT fileObject; NTSTATUS status; if (DriveNumber >= 'A' && DriveNumber <= 'Z') { driveName[12] = (CHAR)DriveNumber; } else if (DriveNumber >= 'a' && DriveNumber <= 'z') { driveName[12] = (CHAR)DriveNumber - 'a' + 'A'; } else { return FALSE; } RtlInitUnicodeString(&deviceName, driveName); InitializeObjectAttributes( &objectAttributes, &deviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); status = IoCreateFile( &deviceHandle, SYNCHRONIZE | FILE_ANY_ACCESS, &objectAttributes, &ioStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, NULL, 0x100); if (!NT_SUCCESS(status)) { DbgPrint(("Could not open drive %c: %x\n", DriveNumber, status)); return FALSE; } status = ObReferenceObjectByHandle( deviceHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, &fileObject, NULL); if (!NT_SUCCESS(status)) { DbgPrint(("Could not get fileobject from handle: %c\n", DriveNumber)); ZwClose(deviceHandle); return FALSE; } if (fileObject->Vpb == 0 || fileObject->Vpb->RealDevice == NULL) { ObDereferenceObject(fileObject); ZwClose(deviceHandle); return FALSE; } *DeviceObject = fileObject->Vpb->DeviceObject; *ReadDevice = fileObject->Vpb->RealDevice; ObDereferenceObject(fileObject); ZwClose(deviceHandle); return TRUE; } NTSTATUS fnCreateFile( IN PFILE_REQUEST_CREATE FileRequestCreate, IN ULONG InputBufferLength, OUT PIO_STATUS_BLOCK IoStatusBlock ) { PDEVICE_OBJECT deviceObject; PDEVICE_OBJECT realDevice; PFILE_OBJECT fileObject; NTSTATUS status; HANDLE newHandle; ANSI_STRING fname; UNICODE_STRING fileName; if (InputBufferLength <= sizeof(FILE_REQUEST_CREATE)) return STATUS_INVALID_PARAMETER; if ((FileRequestCreate->ShareAccess & ~FILE_SHARE_VALID_FLAGS) || (FileRequestCreate->CreateDisposition > FILE_MAXIMUM_DISPOSITION)) return STATUS_INVALID_PARAMETER; fname.Length = (USHORT)InputBufferLength - sizeof(FILE_REQUEST_CREATE); fname.Buffer = FileRequestCreate->FileName; fname.MaximumLength = fname.Length; if (fname.Buffer[fname.Length - 1] == '\0') fname.Length--; if (fname.Length < 3) return STATUS_INVALID_PARAMETER; DbgPrint(("Open %s %d\n", fname.Buffer, fname.Length)); FileRequestCreate->FileHandle = NULL; if (fname.Buffer[1] != ':') return STATUS_INVALID_PARAMETER; if (!GetDriveObject(fname.Buffer[0], &deviceObject, &realDevice)) { return STATUS_UNSUCCESSFUL; } fname.Buffer += 2; fname.MaximumLength -= 2; fname.Length -= 2; if (!NT_SUCCESS(RtlAnsiStringToUnicodeString( &fileName, &fname, TRUE))) { return STATUS_INSUFFICIENT_RESOURCES; } __try { DbgPrint(("deviceObject = %x\n", deviceObject)); status = IrpFileCreate( &fileName, FileRequestCreate->DesiredAccess, FILE_ATTRIBUTE_NORMAL, FileRequestCreate->ShareAccess, FileRequestCreate->CreateDisposition, 0, deviceObject, realDevice, &fileObject); } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); DbgPrint(("IrpCreate exception! error=%x\n", status)); RtlFreeUnicodeString(&fileName); return status; } RtlFreeUnicodeString(&fileName); if (!NT_SUCCESS(status)) { DbgPrint(("Irp open file failed\n")); return status; } status = ObOpenObjectByPointer( fileObject, 0, NULL, FileRequestCreate->DesiredAccess, *IoFileObjectType, KernelMode, &newHandle); ObDereferenceObject(fileObject); if (!NT_SUCCESS(status)) { DbgPrint(("ObOpenObjectByPointer failed\n")); return status; } FileRequestCreate->FileHandle = newHandle; IoStatusBlock->Information = sizeof(HANDLE); return status; } NTSTATUS fnReadFile( IN PFILE_REQUEST_READ FileRequestRead, IN ULONG InputBufferLength, OUT PIO_STATUS_BLOCK IoStatusBlock ) { NTSTATUS status; PFILE_OBJECT fileObject; IO_STATUS_BLOCK ioStatus; if (InputBufferLength < sizeof(FILE_REQUEST_READ)) return STATUS_INVALID_PARAMETER; if (InputBufferLength < sizeof(FILE_REQUEST_READ) + FileRequestRead->Length) return STATUS_INVALID_PARAMETER; DbgPrint(("read file\n")); status = ObReferenceObjectByHandle( FileRequestRead->FileHandle, GENERIC_READ, *IoFileObjectType, KernelMode, &fileObject, NULL); if (!NT_SUCCESS(status)) return status; __try { status = IrpFileRead( fileObject, NULL, FileRequestRead->Length, FileRequestRead->Buffer, &ioStatus); status = ioStatus.Status; FileRequestRead->ReadLength = sizeof(FILE_REQUEST_READ) + ioStatus.Information; } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); DbgPrint(("IrpRead exception! error=%x\n", status)); } ObDereferenceObject(fileObject); return status; } NTSTATUS fnDeleteFile( IN HANDLE FileHandle ) { NTSTATUS status; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; FILE_DISPOSITION_INFORMATION fdi; status = ObReferenceObjectByHandle( FileHandle, 0, *IoFileObjectType, KernelMode, &fileObject, NULL); if (!NT_SUCCESS(status)) { return status; } deviceObject = IoGetRelatedDeviceObject(fileObject); //fnCloseFile(deviceObject, fileObject); fdi.DeleteFile = TRUE; status = IoSetInformation( fileObject, FileDispositionInformation, sizeof(FILE_DISPOSITION_INFORMATION), &fdi); ObDereferenceObject(fileObject); return status; } NTSTATUS QueryHandleInfo( IN PQUERY_HANDLE_INFO QueryHandleInfo, OUT PVOID OutputBuffer, IN ULONG OutputBufferLength ) { NTSTATUS status; HANDLE processHandle, objectHandle; PEPROCESS process; PVOID object; OBJECT_ATTRIBUTES objectAttributes; CLIENT_ID clientID; POBJECT_NAME_INFORMATION objectName; ANSI_STRING objectNameA; ULONG returnLength; __try { if (QueryHandleInfo->Pid < 8) { PsLookupProcessByProcessId( (HANDLE)QueryHandleInfo->Pid, &process); KeAttachProcess(process); status = ObReferenceObjectByHandle( (HANDLE)QueryHandleInfo->Handle, GENERIC_READ, NULL, KernelMode, &object, NULL); KeDetachProcess(); if (!NT_SUCCESS(status)) { return status; } } else { InitializeObjectAttributes( &objectAttributes, NULL, 0, NULL, NULL); clientID.UniqueProcess = (HANDLE)QueryHandleInfo->Pid; clientID.UniqueThread = 0; status = ZwOpenProcess( &processHandle, PROCESS_DUP_HANDLE, &objectAttributes, &clientID); if (!NT_SUCCESS(status)) { return status; } status = ZwDuplicateObject( processHandle, (HANDLE)QueryHandleInfo->Handle, NtCurrentProcess(), &objectHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); ZwClose(processHandle); if (!NT_SUCCESS(status)) { return status; } status = ObReferenceObjectByHandle( objectHandle, GENERIC_READ, NULL, KernelMode, &object, NULL); ZwClose(objectHandle); if (!NT_SUCCESS(status)) { return status; } } if (object != (PVOID)QueryHandleInfo->Object) { ObDereferenceObject(object); return STATUS_OBJECT_TYPE_MISMATCH; } if (*(PULONG)object == 0x700005) { DbgPrint(("0x700005, link?\n")); return STATUS_SUCCESS; } objectName = ExAllocatePool(NonPagedPool, 0x400); if (objectName == NULL) { ObDereferenceObject(object); return STATUS_INSUFFICIENT_RESOURCES; } status = ObQueryNameString( object, objectName, 0x400, &returnLength); ObDereferenceObject(object); if (!NT_SUCCESS(status)) { ExFreePool(objectName); return status; } status = RtlUnicodeStringToAnsiString( &objectNameA, &objectName->Name, TRUE); ExFreePool(objectName); if (!NT_SUCCESS(status)) { return status; } if (objectNameA.Length >= OutputBufferLength) { RtlFreeAnsiString(&objectNameA); return STATUS_BUFFER_TOO_SMALL; } strcpy(OutputBuffer, objectNameA.Buffer); RtlFreeAnsiString(&objectNameA); return STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { return STATUS_ACCESS_VIOLATION; } } VOID PsExitSpecialApc( IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2 ) { NTSTATUS status; NTSTATUS ExitStatus; PKTHREAD KThread; CHAR ch; ExitStatus = (NTSTATUS)((LONG_PTR)Apc->NormalContext); ExFreePool(Apc); status = PsTerminateSystemThread(ExitStatus); if (status == STATUS_INVALID_PARAMETER) { KThread = KeGetCurrentThread(); if (*NtBuildNumber == 2195) { ch = *((PCHAR)KThread + 0x1fc); *((PCHAR)KThread + 0x1fc) = '\0'; //NtTerminateThread((HANDLE)-1, ExitStatus); *((PCHAR)KThread + 0x1fc) = ch; } } } NTSTATUS KillThread( IN PVOID ThreadId, IN NTSTATUS ExitStatus ) { NTSTATUS status; PETHREAD Thread; PKAPC ExitApc; status = PsLookupThreadByThreadId(ThreadId, &Thread); if (!NT_SUCCESS(status)) return STATUS_UNSUCCESSFUL; status = ObReferenceObjectByPointer( Thread, 0x1f03ff, *PsThreadType, KernelMode); if (!NT_SUCCESS(status)) return STATUS_UNSUCCESSFUL; if (Thread == PsGetCurrentThread()) { ObDereferenceObject(Thread); PsTerminateSystemThread(ExitStatus); } else { ExitApc = ExAllocatePool(NonPagedPool, sizeof(KAPC)); if (!ExitApc) return STATUS_INSUFFICIENT_RESOURCES; KeInitializeApc( ExitApc, Thread, OriginalApcEnvironment, PsExitSpecialApc, NULL, 0, KernelMode, ULongToPtr(ExitStatus)); if (!KeInsertQueueApc(ExitApc, ExitApc, NULL, 2)) { ExFreePool(ExitApc); return STATUS_UNSUCCESSFUL; } } return STATUS_SUCCESS; } #define PROCESS_PAGE_DIR_BASE 0xC0300000 #define PROCESS_PAGE_TABLE_BASE 0xC0000000 typedef unsigned long* PPTE; /************************************************************************** * GetPteAddress - Returns a pointer to the page table entry corresponding * to a given memory address. * * Parameters: * PVOID VirtualAddress - Address you wish to acquire a pointer to the * page table entry for. * * Return - Pointer to the page table entry for VirtualAddress or an error * code. * * Error Codes: * ERROR_PTE_NOT_PRESENT - The page table for the given virtual * address is not present in memory. * ERROR_PAGE_NOT_PRESENT - The page containing the data for the * given virtual address is not present in * memory. **************************************************************************/ PPTE GetPteAddress( PVOID VirtualAddress ) { PPTE pPTE = 0; __asm { cli //disable interrupts pushad mov esi, PROCESS_PAGE_DIR_BASE mov edx, VirtualAddress mov eax, edx shr eax, 22 lea eax, [esi + eax*4] //pointer to page directory entry test [eax], 0x80 //is it a large page? jnz Is_Large_Page //it's a large page mov esi, PROCESS_PAGE_TABLE_BASE shr edx, 12 lea eax, [esi + edx*4] //pointer to page table entry (PTE) mov pPTE, eax jmp Done //NOTE: There is not a page table for large pages because //the phys frames are contained in the page directory. Is_Large_Page: mov pPTE, eax Done: popad sti //reenable interrupts }//end asm return pPTE; }//end GetPteAddress /************************************************************************** * GetPhysicalFrameAddress - Gets the base physical address in memory where * the page is mapped. This corresponds to the * bits 12 - 32 in the page table entry. * * Parameters - * PPTE pPte - Pointer to the PTE that you wish to retrieve the * physical address from. * * Return - The physical address of the page. **************************************************************************/ ULONG GetPhysicalFrameAddress( PPTE pPte ) { ULONG Frame = 0; __asm { cli pushad mov eax, pPte mov ecx, [eax] shr ecx, 12 //physical page frame consists of the //upper 20 bits mov Frame, ecx popad sti }//end asm return Frame; }//end GetPhysicalFrameAddress #define HIGHEST_USER_ADDRESS 0x80000000 #define ERROR_PAGE_NOT_IN_LIST 0 typedef struct _HIDDEN_CODE_LIST { PVOID ExecuteView; PVOID ReadWriteView; ULONG PageNumber; PVOID LoadExecutePage; PEPROCESS PageOwner; } HIDDEN_CODE_LIST, *PHIDDEN_CODE_LIST; ULONG OldInt0EHandler = 0; VOID EnableWriteProtect( BOOLEAN Enable ) { if (!Enable) { __asm { mov eax, cr0; and eax, 0xFFFEFFFF; // CR0 16 BIT = 0 mov cr0, eax; } } else { __asm { mov eax, cr0; or eax, 0x10000 mov cr0, eax; } } } void __declspec(naked) NewInt0EHandler(void) { __asm { pushad // mov edx, dword ptr [esp + 0x20] //PageFault.ErrorCode // test edx, 0x04 //if the processor was in user mode, then // jnz PassDown //pass it down mov eax, cr2 cmp eax, HIGHEST_USER_ADDRESS jae PassDown push eax // call FindPageInHookedList mov ebp, eax cmp ebp, ERROR_PAGE_NOT_IN_LIST jz PassDown mov eax, cr2 mov esi, PROCESS_PAGE_DIR_BASE mov ebx, eax shr ebx, 22 lea ebx, [esi + ebx * 4] //ebx = pPTE for large page test [ebx], 0x80 //check if its a large page jnz IsLargePage mov esi, PROCESS_PAGE_TABLE_BASE mov ebx, eax shr ebx, 12 lea ebx, [esi + ebx * 4] //ebx = pPTE IsLargePage: cmp [esp + 0x24], eax //Is due to an attepmted execute? jne LoadDTLB cli or dword ptr [ebx], 0x01 mov eax, [ebx] and eax, 0xFFFFF000 push eax call [ebp].LoadExecutePage //Eax返回新的执行页 mov eax, [ebp].ExecuteView mov edi, [ebx] and edi, 0x00000FFF //preserve the lower 12 bits of the faulting page's PTE and eax, 0xFFFFF000 //isolate the physical address in the "fake" page's PTE or eax, edi mov edx, [ebx] //保存原来的PTE mov [ebx], eax //替换物理帧 mov eax, cr2 //页失败地址 mov eax, dword ptr [eax] //载入ITLB mov [ebx], edx //还原PTE and dword ptr [ebx], 0xFFFFFFFE sti jmp ReturnWithoutPassdown LoadDTLB: cli or dword ptr [ebx], 0x01 mov eax, dword ptr [eax] //载入DTLB and dword ptr [ebx], 0xFFFFFFFE sti ReturnWithoutPassDown: popad add esp, 4 iretd PassDown: popad jmp OldInt0EHandler } } /* void HookMemoryPage( PVOID ExecutePage, PVOID ReadWritePage, ULONG PageNumber ) { HOOKED_LIST_ENTRY HookedPage = {0}; HookedPage.ExecuteView = ExecutePage; HookedPage.ReadWriteView = pReadWritePage; HookedPage.PageNumber = PageNumber; HookedPage.PageOwner = PsGetCurrentProcess(); __asm cli //disable interrupts if (g_OldInt0EHandler == NULL) { HookInt(&g_OldInt0EHandler, (unsigned long)NewInt0EHandler, 0x0E); } HookedPage.pExecutePte = GetPteAddress(pExecutePage); HookedPage.pReadWritePte = GetPteAddress(pReadWritePage); //Insert the hooked page into the list PushPageIntoHookedList(HookedPage); //Enable the global page feature EnableGlobalPageFeature(HookedPage.pExecutePte); //Mark the page non present MarkPageNotPresent(HookedPage.pExecutePte); //Go ahead and flush the TLBs. We want to guarantee that all //subsequent accesses to this hooked page are filtered //through our new page fault handler. __asm invlpg ExecutePage __asm sti //reenable interrupts }//*/ typedef struct tagIDTR { WORD IDTLimit; WORD LowIDTbase; WORD HiIDTbase; } IDTR, *PIDTR; typedef struct tagIDTENTRY { WORD OffsetLow; WORD selector; WORD unused_lo : 13; WORD DPL : 2; WORD P : 1; WORD OffsetHigh; } IDTENTRY, *PIDTENTRY; VOID EnableInt0EHook( BOOLEAN Enable ) { IDTR idtr; PIDTENTRY OIdt; PIDTENTRY NIdt; if (Enable) { __asm sidt idtr OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase); NIdt = &(OIdt[0x0e]); __asm cli OldInt0EHandler = MAKELONG(OIdt[0x0e].OffsetLow,OIdt[0x0e].OffsetHigh); NIdt->OffsetLow = LOWORD(NewInt0EHandler); NIdt->OffsetHigh = HIWORD(NewInt0EHandler); __asm lidt idtr __asm sti } else if (OldInt0EHandler) { __asm sidt idtr OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase); NIdt = &(OIdt[0x0e]); __asm cli NIdt->OffsetLow = LOWORD(OldInt0EHandler); NIdt->OffsetHigh = HIWORD(OldInt0EHandler); OldInt0EHandler = 0; __asm lidt idtr __asm sti } } NTSTATUS DispatchRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION irp_stack; NTSTATUS status; irp_stack = IoGetCurrentIrpStackLocation(Irp); status = STATUS_INVALID_DEVICE_REQUEST; switch (irp_stack->MajorFunction) { case IRP_MJ_CREATE: case IRP_MJ_CLOSE: case IRP_MJ_CLEANUP: status = STATUS_SUCCESS; break; } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } NTSTATUS ControlRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION IrpStack; ULONG IoControlCode; PVOID InputBuffer, OutputBuffer; ULONG InputBufferLength, OutputBufferLength; NTSTATUS status; IrpStack = IoGetCurrentIrpStackLocation(Irp); IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; InputBuffer = Irp->AssociatedIrp.SystemBuffer; OutputBuffer = Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (IoControlCode) { case IOCTL_FILE_CREATE: status = fnCreateFile( InputBuffer, InputBufferLength, &Irp->IoStatus); break; case IOCTL_FILE_DELETE: if (InputBufferLength < sizeof(PVOID)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = fnDeleteFile(*(HANDLE *)InputBuffer); break; case IOCTL_FILE_READ: status = fnReadFile( InputBuffer, InputBufferLength, &Irp->IoStatus); break; case IOCTL_HANDLE_INFO: if (InputBufferLength < sizeof(QUERY_HANDLE_INFO) || OutputBufferLength <= 1) { status = STATUS_BUFFER_TOO_SMALL; break; } status = QueryHandleInfo( (PQUERY_HANDLE_INFO)InputBuffer, OutputBuffer, OutputBufferLength); break; case IOCTL_TEST_FUNCTION: DbgPrint(("IOCTL_TEST_FUNCTION\n")); if (InputBufferLength != sizeof(ULONG)) { status = STATUS_INVALID_PARAMETER; break; } *(PULONG)InputBuffer = 0x12345678; Irp->IoStatus.Information = 4; status = STATUS_SUCCESS; break; default: Irp->IoStatus.Information = 0; status = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } VOID DriverUnload( IN PDRIVER_OBJECT DriverObject ) { UNICODE_STRING DeviceLink; DbgPrint(("Unloading driver (%p)\n", DriverObject)); RtlInitUnicodeString(&DeviceLink, L"\\DosDevices\\drvTest"); IoDeleteSymbolicLink(&DeviceLink); IoDeleteDevice(DriverObject->DeviceObject); } NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { UNICODE_STRING DeviceName; UNICODE_STRING DeviceLink; PDEVICE_OBJECT DeviceObject; ULONG i; NTSTATUS status; DbgPrint(("My driver entry!\n")); RtlInitUnicodeString(&DeviceName, L"\\Device\\drvTest"); RtlInitUnicodeString(&DeviceLink, L"\\DosDevices\\drvTest"); status = IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) return status; status = IoCreateSymbolicLink(&DeviceLink, &DeviceName); if (!NT_SUCCESS(status)) { IoDeleteDevice(DeviceObject); return status; } for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) DriverObject->MajorFunction[i] = DispatchRoutine; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlRoutine; DriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; } //---------------------------------------------------------------------------