//---------------------------------------------------------------------- // // RegmonMapServiceTable // // If we are running on Whistler then we have // to double map the system service table to get around the // fact that the system service table is write-protected on systems // with > 128MB memory. Since there's no harm in always double mapping, // we always do it, regardless of whether or not we are on Whistler. // //---------------------------------------------------------------------- PVOID * RegmonMapServiceTable( SERVICE_HOOK_DESCRIPTOR **HookDescriptors ) { // // Allocate an array to store original function addresses in. This // makes us play well with other hookers. // *HookDescriptors = (SERVICE_HOOK_DESCRIPTOR *) ExAllocatePool( NonPagedPool, KeServiceDescriptorTable->Limit * sizeof(SERVICE_HOOK_DESCRIPTOR)); if( !*HookDescriptors ) { return NULL; } memset( *HookDescriptors, 0, KeServiceDescriptorTable->Limit * sizeof(SERVICE_HOOK_DESCRIPTOR)); // // Build an MDL that describes the system service table function // pointers array. // KdPrint(("Reglib: KeServiceDescriptorTable: %I64x Pointers: %I64x Limit: %d\n", KeServiceDescriptorTable, KeServiceDescriptorTable->ServicePointers, KeServiceDescriptorTable->Limit )); KeServiceTableMdl = MmCreateMdl( NULL, KeServiceDescriptorTable->ServicePointers, KeServiceDescriptorTable->Limit * sizeof(PVOID)); if( !KeServiceTableMdl ) { return NULL; } // // Fill in the physical pages and then double-map the description. Note // that MmMapLockedPages is obsolete as of Win2K and has been replaced // with MmMapLockedPagesSpecifyCache. However, we use the same driver // on all NT platforms, so we use it anyway. // MmBuildMdlForNonPagedPool( KeServiceTableMdl ); KeServiceTableMdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; #if defined(_M_IA64) return MmMapLockedPagesSpecifyCache( KeServiceTableMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority ); #else return MmMapLockedPages( KeServiceTableMdl, KernelMode ); #endif }
NTSTATUS initMDL() { // map memory into our domain g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4); if(!g_pmdlSystemCall) return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(g_pmdlSystemCall); // change MDL permissions g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); MDLinit = TRUE; return STATUS_SUCCESS; }
/** * 设置钩子函数 * */ NTSTATUS sstHook_OpenProcess() { if(m_MDL == NULL) { m_MDL = MmCreateMdl(NULL,KeServiceDescriptorTable->ServiceTableBase,KeServiceDescriptorTable->NumberOfService*4); if(!m_MDL) return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(m_MDL); m_MDL->MdlFlags = m_MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; m_Mapped = (PVOID *)MmMapLockedPages(m_MDL, KernelMode); HOOK_SYSCALL(ZwOpenProcess,MyNtOpenProcess,pOriNtOpenProcess); g_openProcessId = (ULONG)SYSTEMSERVICE(ZwOpenProcess); return STATUS_SUCCESS; } UpdateService(SYSCALL_INDEX(ZwOpenProcess),(PVOID)MyNtOpenProcess); return STATUS_SUCCESS; }
//---------------------------------------------------------------------- // // RegmonMapMem // // Double maps memory for writing. // //---------------------------------------------------------------------- PVOID RegmonMapMem( PVOID Pointer, ULONG Length, PMDL *MapMdl ) { *MapMdl = MmCreateMdl( NULL, Pointer, Length ); if( !(*MapMdl)) { return NULL; } MmBuildMdlForNonPagedPool( *MapMdl ); (*MapMdl)->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; #if defined(_M_IA64) return MmMapLockedPagesSpecifyCache( *MapMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority ); #else return MmMapLockedPages( *MapMdl, KernelMode ); #endif }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath) { DriverObject->DriverUnload = OnUnload; DbgPrint("Driver cargado"); ZwOpenProcessIni =(TypZwOpenProc)(SYSTEMSERVICE(ZwOpenProcess)); //Creamos la MDL para deshabilitar la protección de memoria g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4); if(!g_pmdlSystemCall) return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(g_pmdlSystemCall); g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); DbgPrint("Hookeando..."); HOOK_SYSCALL( ZwOpenProcess, NewZwOpenProcess, ZwOpenProcessIni ); return STATUS_SUCCESS; }
NTSTATUS AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; LARGE_INTEGER cacheSizeBytes; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; UNICODE_STRING uniServiceName; __Enter { // // First this is to load the library // RtlInitUnicodeString( &uniServiceName, AFS_REDIR_LIBRARY_SERVICE_ENTRY); ntStatus = AFSLoadLibrary( 0, &uniServiceName); if( !NT_SUCCESS( ntStatus)) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n", ntStatus); try_return( ntStatus); } // // Save off the cache file information // pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize; pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount; pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength; cacheSizeBytes = RedirInitInfo->ExtentCount; cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize; AFSDumpFileLocation.Length = 0; AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR)); AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, AFSDumpFileLocation.MaximumLength, AFS_GENERIC_MEMORY_23_TAG); if( AFSDumpFileLocation.Buffer == NULL) { AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( AFSDumpFileLocation.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); AFSDumpFileLocation.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)], (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset), RedirInitInfo->DumpFileLocationLength); AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength; // // Be sure the shutdown flag is not set // ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN); // // Set up the Throttles. // // Max IO is 10% of the cache, or the value in the registry, // with a minimum of 5Mb (and a maximum of 50% cache size) // if( AFSMaxDirectIo) { // // collect what the user // pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo; pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204)) { pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204; } // // For small cache configurations ... // if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2) { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } // // Maximum Dirty is 50% of the cache, or the value in the // registry. No minimum, maximum of 90% of cache size. // if (AFSMaxDirtyFile) { pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile; pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2; } cacheSizeBytes.QuadPart *= 9; cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10; if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart) { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart; } // // Store off any flags for the file system // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES); } if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 && RedirInitInfo->MemoryCacheLength.QuadPart != 0) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; #ifdef AMD64 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.QuadPart, RedirInitInfo->MemoryCacheLength.QuadPart); #else pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.LowPart, RedirInitInfo->MemoryCacheLength.LowPart); #endif if( pDevExt->Specific.RDR.CacheMdl != NULL) { __try { MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl, KernelMode, IoModifyAccess); pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl, NormalPagePriority); } __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) ) { IoFreeMdl( pDevExt->Specific.RDR.CacheMdl); pDevExt->Specific.RDR.CacheMdl = NULL; } if( pDevExt->Specific.RDR.CacheMdl != NULL) { pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength; ntStatus = STATUS_SUCCESS; } } }
NTSTATUS MiCcPrepareReadInfo ( IN PMI_READ_INFO MiReadInfo ) /*++ Routine Description: This routine constructs MDLs that describe the pages in the argument read-list. The caller will then issue the I/O on return. Arguments: MiReadInfo - Supplies a pointer to the read-list. Return Value: Various NTSTATUS codes. Environment: Kernel mode, PASSIVE_LEVEL. --*/ { UINT64 PteOffset; NTSTATUS Status; PMMPTE ProtoPte; PMMPTE LastProto; PMMPTE *ProtoPteArray; PCONTROL_AREA ControlArea; PSUBSECTION Subsection; PMMINPAGE_SUPPORT InPageSupport; PMDL Mdl; PMDL IoMdl; PMDL ApiMdl; ULONG i; PFN_NUMBER NumberOfPages; ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES (MiReadInfo->FileOffset.LowPart, MiReadInfo->LengthInBytes); // // Translate the section object into the relevant control area. // ControlArea = (PCONTROL_AREA)MiReadInfo->FileObject->SectionObjectPointer->DataSectionObject; // // If the section is backed by a ROM, then there's no need to prefetch // anything as it would waste RAM. // if (ControlArea->u.Flags.Rom == 1) { return STATUS_NOT_SUPPORTED; } // // Initialize the internal Mi readlist. // MiReadInfo->ControlArea = ControlArea; // // Allocate and initialize an inpage support block for this run. // InPageSupport = MiGetInPageSupportBlock (MM_NOIRQL, &Status); if (InPageSupport == NULL) { ASSERT (!NT_SUCCESS (Status)); return Status; } MiReadInfo->InPageSupport = InPageSupport; // // Allocate and initialize an MDL to return to our caller. The actual // frame numbers are filled in when all the pages are reference counted. // ApiMdl = MmCreateMdl (NULL, NULL, NumberOfPages << PAGE_SHIFT); if (ApiMdl == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } ApiMdl->MdlFlags |= MDL_PAGES_LOCKED; MiReadInfo->ApiMdl = ApiMdl; // // Allocate and initialize an MDL to use for the actual transfer (if any). // IoMdl = MmCreateMdl (NULL, NULL, NumberOfPages << PAGE_SHIFT); if (IoMdl == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } MiReadInfo->IoMdl = IoMdl; Mdl = IoMdl; // // Make sure the section is really prefetchable - physical and // pagefile-backed sections are not. // if ((ControlArea->u.Flags.PhysicalMemory) || (ControlArea->u.Flags.Image == 1) || (ControlArea->FilePointer == NULL)) { return STATUS_INVALID_PARAMETER_1; } // // Start the read at the proper file offset. // InPageSupport->ReadOffset = MiReadInfo->FileOffset; ASSERT (BYTE_OFFSET (InPageSupport->ReadOffset.LowPart) == 0); InPageSupport->FilePointer = MiReadInfo->FileObject; // // Stash a pointer to the start of the prototype PTE array (the values // in the array are not contiguous as they may cross subsections) // in the inpage block so we can walk it quickly later when the pages // are put into transition. // ProtoPteArray = (PMMPTE *)(Mdl + 1); InPageSupport->BasePte = (PMMPTE) ProtoPteArray; // // Data (but not image) reads use the whole page and the filesystems // zero fill any remainder beyond valid data length so we don't // bother to handle this here. It is important to specify the // entire page where possible so the filesystem won't post this // which will hurt perf. LWFIX: must use CcZero to make this true. // ASSERT (((ULONG_PTR)Mdl & (sizeof(QUAD) - 1)) == 0); InPageSupport->u1.e1.PrefetchMdlHighBits = ((ULONG_PTR)Mdl >> 3); // // Initialize the prototype PTE pointers. // ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0); if (ControlArea->u.Flags.Rom == 0) { Subsection = (PSUBSECTION)(ControlArea + 1); } else { Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1); } #if DBG if (MiCcDebug & MI_CC_FORCE_PREFETCH) { MiRemoveUserPages (); } #endif // // Calculate the first prototype PTE address. // PteOffset = (UINT64)(MiReadInfo->FileOffset.QuadPart >> PAGE_SHIFT); // // Make sure the PTEs are not in the extended part of the segment. // while (TRUE) { // // A memory barrier is needed to read the subsection chains // in order to ensure the writes to the actual individual // subsection data structure fields are visible in correct // order. This avoids the need to acquire any stronger // synchronization (ie: PFN lock), thus yielding better // performance and pageability. // KeMemoryBarrier (); if (PteOffset < (UINT64) Subsection->PtesInSubsection) { break; } PteOffset -= Subsection->PtesInSubsection; Subsection = Subsection->NextSubsection; } Status = MiAddViewsForSectionWithPfn ((PMSUBSECTION) Subsection, Subsection->PtesInSubsection); if (!NT_SUCCESS (Status)) { return Status; } MiReadInfo->FirstReferencedSubsection = Subsection; MiReadInfo->LastReferencedSubsection = Subsection; ProtoPte = &Subsection->SubsectionBase[PteOffset]; LastProto = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; for (i = 0; i < NumberOfPages; i += 1) { // // Calculate which PTE maps the given logical block offset. // // Always look forwards (as an optimization) in the subsection chain. // // A quick check is made first to avoid recalculations and loops where // possible. // if (ProtoPte >= LastProto) { // // Handle extended subsections. Increment the view count for // every subsection spanned by this request, creating prototype // PTEs if needed. // ASSERT (i != 0); Subsection = Subsection->NextSubsection; Status = MiAddViewsForSectionWithPfn ((PMSUBSECTION) Subsection, Subsection->PtesInSubsection); if (!NT_SUCCESS (Status)) { return Status; } MiReadInfo->LastReferencedSubsection = Subsection; ProtoPte = Subsection->SubsectionBase; LastProto = &Subsection->SubsectionBase[Subsection->PtesInSubsection]; } *ProtoPteArray = ProtoPte; ProtoPteArray += 1; ProtoPte += 1; } return STATUS_SUCCESS; }
NTSTATUS AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; LARGE_INTEGER cacheSizeBytes; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; UNICODE_STRING uniServiceName; __Enter { // // First this is to load the library // RtlInitUnicodeString( &uniServiceName, AFS_REDIR_LIBRARY_SERVICE_ENTRY); ntStatus = AFSLoadLibrary( 0, &uniServiceName); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n", ntStatus)); try_return( ntStatus); } // // Save off the cache file information // pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize; pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount; pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength; cacheSizeBytes = RedirInitInfo->ExtentCount; cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize; AFSDumpFileLocation.Length = 0; AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR)); AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, AFSDumpFileLocation.MaximumLength, AFS_GENERIC_MEMORY_23_TAG); if( AFSDumpFileLocation.Buffer == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n")); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( AFSDumpFileLocation.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); AFSDumpFileLocation.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)], (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset), RedirInitInfo->DumpFileLocationLength); AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength; // // Be sure the shutdown flag is not set // ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN); // // Set up the Throttles. // // Max IO is 10% of the cache, or the value in the registry, // with a minimum of 5Mb (and a maximum of 50% cache size) // if( AFSMaxDirectIo) { // // collect what the user // pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo; pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204)) { pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204; } // // For small cache configurations ... // if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2) { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } // // Maximum Dirty is 50% of the cache, or the value in the // registry. No minimum, maximum of 90% of cache size. // if (AFSMaxDirtyFile) { pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile; pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2; } cacheSizeBytes.QuadPart *= 9; cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10; if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart) { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart; } // // Store off any flags for the file system // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES); } if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES); } // // Global Reparse Point Policy // pDevExt->Specific.RDR.ReparsePointPolicy = RedirInitInfo->GlobalReparsePointPolicy; // // Are we performing direct to service IO? // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_PERFORM_SERVICE_IO)) { // // Send IO requests directly to service // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO); } else { if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 && RedirInitInfo->MemoryCacheLength.QuadPart != 0) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; #ifdef AMD64 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.QuadPart, RedirInitInfo->MemoryCacheLength.QuadPart); #else pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.LowPart, RedirInitInfo->MemoryCacheLength.LowPart); #endif if( pDevExt->Specific.RDR.CacheMdl != NULL) { __try { MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl, KernelMode, IoModifyAccess); pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl, NormalPagePriority); } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDumpTraceFilesFnc(); IoFreeMdl( pDevExt->Specific.RDR.CacheMdl); pDevExt->Specific.RDR.CacheMdl = NULL; } if( pDevExt->Specific.RDR.CacheMdl != NULL) { pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength; ntStatus = STATUS_SUCCESS; } } } if( !NT_SUCCESS( ntStatus) && RedirInitInfo->CacheFileNameLength == 0) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector Unable to initialize cache file %08lX\n", ntStatus)); try_return( ntStatus); } if( pDevExt->Specific.RDR.CacheMdl == NULL) { if( RedirInitInfo->CacheFileNameLength == 0) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector CacheMdl == NULL\n")); try_return( ntStatus = STATUS_INVALID_PARAMETER); } // // Go open the cache file // pDevExt->Specific.RDR.CacheFile.Length = 0; pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR)); pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, pDevExt->Specific.RDR.CacheFile.MaximumLength, AFS_GENERIC_MEMORY_24_TAG); if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n")); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)], RedirInitInfo->CacheFileName, RedirInitInfo->CacheFileNameLength); pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength; InitializeObjectAttributes( &stObjectAttribs, &pDevExt->Specific.RDR.CacheFile, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector ZwOpenFile failure %08lX\n", ntStatus)); try_return( ntStatus); } // // Map to the fileobject // ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle, SYNCHRONIZE, NULL, KernelMode, (void **)&pDevExt->Specific.RDR.CacheFileObject, NULL); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n", ntStatus)); try_return( ntStatus); } } }
/* * DriverEntry initializes the driver and is the first routine called by the * system after the driver is loaded. DriverEntry specifies the other entry * points in the function driver, such as EvtDevice and DriverUnload. * * @param DriverObject - represents the instance of the function driver that is loaded * into memory. DriverEntry must initialize members of DriverObject before it * returns to the caller. DriverObject is allocated by the system before the * driver is loaded, and it is released by the system after the system unloads * the function driver from memory. * @param RegistryPath - represents the driver specific path in the Registry. * The function driver can use the path to store driver related data between * reboots. The path does not store hardware instance specific data. * * @return STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise */ NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath ) { // Local variables NTSTATUS status; PDEVICE_EXTENSION devExt; PDEVICE_OBJECT devObj; UNICODE_STRING devName; UNICODE_STRING linkName; int counter; DbgPrint("%s - version %s", NAME, VERSION); DbgPrint("Built %s %s\n", __DATE__, __TIME__); // Set the basic dispatch routines for all IRPs handled for (counter = 0; counter < IRP_MJ_MAXIMUM_FUNCTION; counter++) { pDriverObject->MajorFunction[counter] = OutboundDispatchPassDown; } // Set a specific dispatch routine for read requests pDriverObject->MajorFunction[IRP_MJ_READ] = OutboundDispatchRead; // Hook the keyboard stack status = OutboundHookKeyboard(pDriverObject); if (!NT_SUCCESS(status)) DbgPrint("Error hooking the keyboard.\n"); else DbgPrint("Successfully hooked the keyboard.\n"); // Save old system call locations OldZwWriteFile = (ZWWRITEFILE)(SYSTEMSERVICE(ZwWriteFile)); OldZwCreateFile = (ZWCREATEFILE)(SYSTEMSERVICE(ZwCreateFile)); //***Begin HideProcessHookMDL SSDT hook code*** // Map the memory into our domain so we can change the permissions on the MDL. g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices * 4); if(!g_pmdlSystemCall) { DbgPrint("Failed mapping memory..."); return STATUS_UNSUCCESSFUL; } MmBuildMdlForNonPagedPool(g_pmdlSystemCall); // Change the flags of the MDL g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); //TODO: use MmMapLockedPagesSpecifyCache instead, MmMapLockedPages is obselete according to OACR // Hook the system call _asm{cli} HOOK_SYSCALL(ZwWriteFile, NewZwWriteFile, OldZwWriteFile); HOOK_SYSCALL(ZwCreateFile, NewZwCreateFile, OldZwCreateFile); _asm{sti} //***End HideProcessHookMDL SSDT hook code*** // Set the driver unload routine pDriverObject->DriverUnload = Unload; return STATUS_SUCCESS; } // DriverEntry