/// <summary> /// Hide memory from NtQueryVirtualMemory /// </summary> /// <param name="pProcess">Target process object</param> /// <param name="address">Target address</param> /// <returns>Status code</returns> NTSTATUS BBUnlinkVAD( IN PEPROCESS pProcess, IN ULONG_PTR address ) { NTSTATUS status = STATUS_SUCCESS; PMMVAD_SHORT pVadShort = NULL; status = BBFindVAD( pProcess, address, &pVadShort ); if (!NT_SUCCESS( status )) return status; // Erase image name if (pVadShort->u.VadFlags.VadType == VadImageMap) { PMMVAD pVadLong = (PMMVAD)pVadShort; if (pVadLong->Subsection && pVadLong->Subsection->ControlArea && pVadLong->Subsection->ControlArea->FilePointer.Object) { PFILE_OBJECT pFile = (PFILE_OBJECT)(pVadLong->Subsection->ControlArea->FilePointer.Value & ~0xF); pFile->FileName.Buffer[0] = L'\0'; pFile->FileName.Length = 0; } else return STATUS_INVALID_ADDRESS; } // Make NO_ACCESS else if (pVadShort->u.VadFlags.VadType == VadDevicePhysicalMemory) { pVadShort->u.VadFlags.Protection = MM_ZERO_ACCESS; } // Invalid VAD type else status = STATUS_INVALID_PARAMETER; return status; }
/// <summary> /// Change VAD protection flags /// </summary> /// <param name="pProcess">Target process object</param> /// <param name="address">Target address</param> /// <param name="prot">New protection flags</param> /// <returns>Status code</returns> NTSTATUS BBProtectVAD( IN PEPROCESS pProcess, IN ULONG_PTR address, IN ULONG prot ) { NTSTATUS status = STATUS_SUCCESS; PMMVAD_SHORT pVadShort = NULL; status = BBFindVAD( pProcess, address, &pVadShort ); if (NT_SUCCESS( status )) pVadShort->u.VadFlags.Protection = prot; return status; }
/// <summary> /// Get region VAD type /// </summary> /// <param name="pProcess">Target process object</param> /// <param name="address">Target address</param> /// <param name="pType">Resulting VAD type</param> /// <returns>Status code</returns> NTSTATUS BBGetVadType( IN PEPROCESS pProcess, IN ULONG_PTR address, OUT PMI_VAD_TYPE pType ) { NTSTATUS status = STATUS_SUCCESS; PMMVAD_SHORT pVad = NULL; status = BBFindVAD( pProcess, address, &pVad ); if (!NT_SUCCESS( status )) return status; *pType = pVad->u.VadFlags.VadType; return status; }
/// <summary> /// Allocate kernel memory and map into User space. Or free previously allocated memory /// </summary> /// <param name="pProcess">Target process object</param> /// <param name="pAllocFree">Request params.</param> /// <param name="pResult">Allocated region info.</param> /// <returns>Status code</returns> NTSTATUS BBAllocateFreePhysical( IN PEPROCESS pProcess, IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult ) { NTSTATUS status = STATUS_SUCCESS; PVOID pRegionBase = NULL; PMDL pMDL = NULL; ASSERT( pProcess != NULL && pResult != NULL ); if (pProcess == NULL || pResult == NULL) return STATUS_INVALID_PARAMETER; // MDL doesn't support regions this large if (pAllocFree->size > 0xFFFFFFFF) { DPRINT( "BlackBone: %s: Region size if too big: 0x%p\n", __FUNCTION__, pAllocFree->size ); return STATUS_INVALID_PARAMETER; } // Align on page boundaries pAllocFree->base = (ULONGLONG)PAGE_ALIGN( pAllocFree->base ); pAllocFree->size = ADDRESS_AND_SIZE_TO_SPAN_PAGES( pAllocFree->base, pAllocFree->size ) << PAGE_SHIFT; // Allocate if (pAllocFree->allocate != FALSE) { PMMVAD_SHORT pVad = NULL; if (pAllocFree->base != 0 && BBFindVAD( pProcess, pAllocFree->base, &pVad ) != STATUS_NOT_FOUND) return STATUS_ALREADY_COMMITTED; pRegionBase = ExAllocatePoolWithTag( NonPagedPool, pAllocFree->size, BB_POOL_TAG ); if (!pRegionBase) return STATUS_NO_MEMORY; // Cleanup buffer before mapping it into UserMode to prevent exposure of kernel data RtlZeroMemory( pRegionBase, pAllocFree->size ); pMDL = IoAllocateMdl( pRegionBase, (ULONG)pAllocFree->size, FALSE, FALSE, NULL ); if (pMDL == NULL) { ExFreePoolWithTag( pRegionBase, BB_POOL_TAG ); return STATUS_NO_MEMORY; } MmBuildMdlForNonPagedPool( pMDL ); // Map at original base __try { pResult->address = (ULONGLONG)MmMapLockedPagesSpecifyCache( pMDL, UserMode, MmCached, (PVOID)pAllocFree->base, FALSE, NormalPagePriority ); } __except (EXCEPTION_EXECUTE_HANDLER) { } // Map at any suitable if (pResult->address == 0 && pAllocFree->base != 0) { __try { pResult->address = (ULONGLONG)MmMapLockedPagesSpecifyCache( pMDL, UserMode, MmCached, NULL, FALSE, NormalPagePriority ); } __except (EXCEPTION_EXECUTE_HANDLER) { } }