NTSTATUS CreateDllSection(IN IN PUNICODE_STRING pDllName, OUT PHANDLE pSection, OUT PPVOID pBaseAddress) { HANDLE hFile; OBJECT_ATTRIBUTES oa = {sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE}; IO_STATUS_BLOCK iosb; SIZE_T size=0; NTSTATUS status; PAGED_CODE(); ASSERT(pSection&&pBaseAddress); *pBaseAddress = NULL; status = ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(status)) { oa.ObjectName = 0; status = ZwCreateSection(pSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, SEC_IMAGE, hFile); if (NT_SUCCESS(status)) { status = ZwMapViewOfSection(*pSection, ZwCurrentProcess(), pBaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE); if (!NT_SUCCESS(status)) { ZwClose(*pSection); } } ZwClose(hFile); } return status; }
/// <summary> /// Allocate/Free process memory /// </summary> /// <param name="pAllocFree">Request params.</param> /// <param name="pResult">Allocated region info.</param> /// <returns>Status code</returns> NTSTATUS BBAllocateFreeMemory( IN PALLOCATE_FREE_MEMORY pAllocFree, OUT PALLOCATE_FREE_MEMORY_RESULT pResult ) { NTSTATUS status = STATUS_SUCCESS; PEPROCESS pProcess = NULL; ASSERT( pResult != NULL ); if (pResult == NULL) return STATUS_INVALID_PARAMETER; status = PsLookupProcessByProcessId( (HANDLE)pAllocFree->pid, &pProcess ); if (NT_SUCCESS( status )) { KAPC_STATE apc; PVOID base = (PVOID)pAllocFree->base; ULONG_PTR size = pAllocFree->size; KeStackAttachProcess( pProcess, &apc ); if (pAllocFree->allocate) { if (pAllocFree->physical != FALSE) { status = BBAllocateFreePhysical( pProcess, pAllocFree, pResult ); } else { status = ZwAllocateVirtualMemory( ZwCurrentProcess(), &base, 0, &size, pAllocFree->type, pAllocFree->protection ); pResult->address = (ULONGLONG)base; pResult->size = size; } } else { MI_VAD_TYPE vadType = VadNone; BBGetVadType( pProcess, pAllocFree->base, &vadType ); if (vadType == VadDevicePhysicalMemory) status = BBAllocateFreePhysical( pProcess, pAllocFree, pResult ); else status = ZwFreeVirtualMemory( ZwCurrentProcess(), &base, &size, pAllocFree->type ); } KeUnstackDetachProcess( &apc ); } else DPRINT( "BlackBone: %s: PsLookupProcessByProcessId failed with status 0x%X\n", __FUNCTION__, status ); if (pProcess) ObDereferenceObject( pProcess ); return status; }
inline NTSTATUS AdjustPrivilege(bool is_enable, ULONG privilege) { TOKEN_PRIVILEGES new_privs = {}; HANDLE h_process_token = {}; auto status = ZwOpenProcessTokenEx(ZwCurrentProcess(), TOKEN_ALL_ACCESS, OBJ_KERNEL_HANDLE, &h_process_token); if (!NT_SUCCESS(status)) { return status; } DEFER(ZwClose(h_process_token)); new_privs.PrivilegeCount = 1; new_privs.Privileges[0].Luid = RtlConvertUlongToLuid(privilege); if (is_enable) { new_privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; } else { new_privs.Privileges[0].Attributes = 0; } return ZwAdjustPrivilegesToken(h_process_token, false, &new_privs, sizeof(new_privs), nullptr, nullptr); }
/// <summary> /// Create new thread in the target process /// Must be running in target process context /// </summary> /// <param name="pBaseAddress">Thread start address</param> /// <param name="pParam">Thread argument</param> /// <param name="flags">Thread creation flags</param> /// <param name="wait">If set to TRUE - wait for thread completion</param> /// <param name="pExitStatus">Thread exit status</param> /// <returns>Status code</returns> NTSTATUS BBExecuteInNewThread( IN PVOID pBaseAddress, IN PVOID pParam, IN ULONG flags, IN BOOLEAN wait, OUT PNTSTATUS pExitStatus ) { HANDLE hThread = NULL; OBJECT_ATTRIBUTES ob = { 0 }; InitializeObjectAttributes( &ob, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); NTSTATUS status = ZwCreateThreadEx( &hThread, THREAD_QUERY_LIMITED_INFORMATION, &ob, ZwCurrentProcess(), pBaseAddress, pParam, flags, 0, 0x1000, 0x100000, NULL ); // Wait for completion if (NT_SUCCESS( status ) && wait != FALSE) { // Force 60 sec timeout LARGE_INTEGER timeout = { 0 }; timeout.QuadPart = -(60ll * 10 * 1000 * 1000); status = ZwWaitForSingleObject( hThread, TRUE, &timeout ); if (NT_SUCCESS( status )) { THREAD_BASIC_INFORMATION info = { 0 }; ULONG bytes = 0; status = ZwQueryInformationThread( hThread, ThreadBasicInformation, &info, sizeof( info ), &bytes ); if (NT_SUCCESS( status ) && pExitStatus) { *pExitStatus = info.ExitStatus; } else if (!NT_SUCCESS( status )) { DPRINT( "BlackBone: %s: ZwQueryInformationThread failed with status 0x%X\n", __FUNCTION__, status ); } } else DPRINT( "BlackBone: %s: ZwWaitForSingleObject failed with status 0x%X\n", __FUNCTION__, status ); } else DPRINT( "BlackBone: %s: ZwCreateThreadEx failed with status 0x%X\n", __FUNCTION__, status ); if (hThread) ZwClose( hThread ); return status; }
/// <summary> /// Enumerate committed, accessible, non-guarded memory regions /// </summary> /// <param name="pList">Region list</param> /// <param name="start">Region start</param> /// <param name="end">Region end</param> /// <param name="mapSections">If set to FALSE, section objects will be excluded from list</param> /// <returns>Status code</returns> NTSTATUS BBBuildProcessRegionListForRange( IN PLIST_ENTRY pList, IN ULONG_PTR start, IN ULONG_PTR end, IN BOOLEAN mapSections ) { NTSTATUS status = STATUS_SUCCESS; MEMORY_BASIC_INFORMATION mbi = { 0 }; SIZE_T length = 0; ULONG_PTR memptr = 0; PMAP_ENTRY pEntry = NULL; for (memptr = start; memptr < end; memptr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize) { status = ZwQueryVirtualMemory( ZwCurrentProcess(), (PVOID)memptr, MemoryBasicInformationEx, &mbi, sizeof( mbi ), &length ); if (!NT_SUCCESS( status )) { DPRINT( "BlackBone: %s: ZwQueryVirtualMemory for address 0x%p returned status 0x%X\n", __FUNCTION__, memptr, status ); // STATUS_INVALID_PARAMETER is a normal status for last secured VAD under Win7 return status == STATUS_INVALID_PARAMETER ? STATUS_SUCCESS : status; } // Skip non-committed, no-access and guard pages else if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && !(mbi.Protect & PAGE_GUARD)) { // Ignore shared memory if required if (mbi.Type != MEM_PRIVATE && !mapSections) continue; pEntry = ExAllocatePoolWithTag( PagedPool, sizeof( MAP_ENTRY ), BB_POOL_TAG ); if (pEntry == NULL) { DPRINT( "BlackBone: %s: Failed to allocate memory for Remap descriptor\n", __FUNCTION__ ); BBCleanupPageList( FALSE, pList ); return STATUS_NO_MEMORY; } pEntry->originalPtr = (ULONG_PTR)mbi.BaseAddress; pEntry->size = mbi.RegionSize; pEntry->newPtr = 0; pEntry->pMdl = NULL; pEntry->locked = FALSE; pEntry->shared = mbi.Type != MEM_PRIVATE; InsertTailList( pList, &pEntry->link ); } } //if (NT_SUCCESS( status )) //status = BBConsolidateRegionList( pList ); return status; }
void test(PUCHAR arg1) { PUCHAR shellcodeAddress = 0; SIZE_T RegionSize = sizeof(new_code); NTSTATUS status; DWORD ContinueAddress; KAPC_STATE kapc; PMDL p_mdl; PDWORD MappedImTable; if (KeGetCurrentIrql() == PASSIVE_LEVEL) { status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &shellcodeAddress, 0, &RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(status)) { return; } shellcodeAddress += 8; ContinueAddress = *(PDWORD)(arg1 + 0xB8); RtlCopyMemory((PVOID)(new_code + 4), &shellcodeAddress, 4); RtlCopyMemory((PVOID)(new_code + 8), &ContinueAddress, 4); RtlCopyMemory((PVOID)(shellcodeAddress-8), new_code, sizeof(new_code)); //KdPrint(("%08X\n", shellcodeAddress - 8)); if (ContinueAddress > 0x7fff0000) { //KdPrint(("in kernel address:%08X!\n", ContinueAddress)); } else { *(PDWORD)(arg1 + 0xB8) = shellcodeAddress - 8; //KdPrint(("in user address:%08X!\n", ContinueAddress)); } } }
NTSTATUS CWdfDevice::CreateUserModeHandle(HANDLE RequestorProcess, PHANDLE ObjectHandle) { IO_STATUS_BLOCK IoStatusBlock; PCUNICODE_STRING UniName = m_CachedName; OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes(&ObjectAttributes, const_cast<PUNICODE_STRING>(UniName), OBJ_KERNEL_HANDLE, nullptr, nullptr); HANDLE KernelHandle; auto status = ZwOpenFile(&KernelHandle, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, 0, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS); if (!NT_SUCCESS(status)) { return status; } status = ZwDuplicateObject(ZwCurrentProcess(), KernelHandle, RequestorProcess, ObjectHandle, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! ZwDuplicateObject failed. %!STATUS!", status); ZwClose(KernelHandle); } return status; }
NtMaxPrivilege_() : _h_process_token(), _previous_state() { auto status = ZwOpenProcessTokenEx(ZwCurrentProcess(), TOKEN_ALL_ACCESS, OBJ_KERNEL_HANDLE, &_h_process_token); Assert(NT_SUCCESS(status) && _h_process_token); _previous_state = MakeBuffer(4096); auto previous_state = Cast<PTOKEN_PRIVILEGES>(_previous_state); status = ZwAdjustPrivilegesToken(_h_process_token, true, nullptr, _previous_state.capacity(), previous_state, Unused<PULONG>()); Assert(NT_SUCCESS(status)); for (ULONG priv_num = SE_MIN_WELL_KNOWN_PRIVILEGE; priv_num <= SE_MAX_WELL_KNOWN_PRIVILEGE; ++priv_num) { TOKEN_PRIVILEGES new_priv = {}; new_priv.PrivilegeCount = 1; new_priv.Privileges[0].Luid = RtlConvertUlongToLuid(priv_num); new_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; status = ZwAdjustPrivilegesToken(_h_process_token, false, &new_priv, sizeof(new_priv), nullptr, nullptr); Assert(NT_SUCCESS(status)); } }
void ShareLockKImp::UninitializeShareLock() { switch(m_LockType) { case LockTypeMutex: RtlZeroMemory(&m_LockObject.m_Mutex.m_Mutex, sizeof(KMUTEX)); break; case LockTypeEvent: RtlZeroMemory(&m_LockObject.m_Event.m_Event, sizeof(KEVENT)); break; case LockTypeSemaphore: RtlZeroMemory(&m_LockObject.m_Semaphore.m_Semaphore, sizeof(KSEMAPHORE)); break; case LockTypeSpinlock: break; case LockTypeNamedSpinlock: { if (m_LockObject.m_NamedSpinlock.m_hMapView) { ZwUnmapViewOfSection(ZwCurrentProcess(), m_LockObject.m_NamedSpinlock.m_hMapView); m_LockObject.m_NamedSpinlock.m_hMapView = NULL; } if (m_LockObject.m_NamedSpinlock.m_hMapFile) { ZwClose(m_LockObject.m_NamedSpinlock.m_hMapFile); m_LockObject.m_NamedSpinlock.m_hMapFile = NULL; } m_LockObject.m_NamedSpinlock.m_lpHeader = NULL; } break; default: break; } m_LockType = LockTypeNone; }
ProcessInformation GetProcessInfo() { PEPROCESS pep; ULONG ret,retlen; NTSTATUS rc,status; ProcessInformation process; PFILE_OBJECT fileObject = NULL; PUNICODE_STRING temp_unicode; PVOID unicode; ULONG ppid = 0; PCHAR toto; PAGED_CODE(); // On recupere le PID process.pid = (LONG)PsGetCurrentProcessId(); PsLookupProcessByProcessId ((HANDLE)process.pid,&pep); toto = (PCHAR) pep; process.ppid = *((ULONG*)(toto+0x140)); // On recupere les 16 premiers bits du nom du process process.name = PsGetProcessImageFileName(pep); // On recupere le path complet du process rc = ZwQueryInformationProcess(ZwCurrentProcess(), ProcessImageFileName, NULL, 0, &ret); if(rc == STATUS_INFO_LENGTH_MISMATCH) { retlen = ret - sizeof(UNICODE_STRING); unicode = ExAllocatePool(NonPagedPool, ret); process.pathname = (PUNICODE_STRING) ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)); // if(process.pathname->MaximumLength < retlen) // { // RtlInitUnicodeString(process.pathname, L"Echec" ); // return process; // } if(unicode != NULL) { RtlInitUnicodeString(process.pathname,0); rc = ZwQueryInformationProcess(ZwCurrentProcess(), ProcessImageFileName, unicode, ret, &ret); if( rc == STATUS_SUCCESS) { temp_unicode = (PUNICODE_STRING) unicode; // process.pathname = (PUNICODE_STRING) ExAllocatePool(NonPagedPool, temp_unicode->Length); RtlCopyUnicodeString(process.pathname, temp_unicode ); // RtlInitUnicodeString(process.pathname, unicode ); } else RtlInitUnicodeString(process.pathname, L"Echec" ); ExFreePool(unicode); } } return process; }
static VOID TestPhysicalMemorySection(VOID) { NTSTATUS Status; UNICODE_STRING SectionName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory"); OBJECT_ATTRIBUTES ObjectAttributes; HANDLE SectionHandle; PVOID SectionObject; PUCHAR MyPage; PHYSICAL_ADDRESS MyPagePhysical; PUCHAR ZeroPageContents; PHYSICAL_ADDRESS ZeroPagePhysical; PVOID Mapping; PUCHAR MappingBytes; SIZE_T ViewSize; SIZE_T EqualBytes; MyPage = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, 'MPmK'); if (skip(MyPage != NULL, "Out of memory\n")) return; MyPagePhysical = MmGetPhysicalAddress(MyPage); RtlFillMemory(MyPage + 0 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0x23); RtlFillMemory(MyPage + 1 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0x67); RtlFillMemory(MyPage + 2 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0xab); RtlFillMemory(MyPage + 3 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0xef); ZeroPageContents = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'ZPmK'); if (skip(ZeroPageContents != NULL, "Out of memory\n")) { ExFreePoolWithTag(MyPage, 'MPmK'); return; } ZeroPagePhysical.QuadPart = 0; Mapping = MmMapIoSpace(ZeroPagePhysical, PAGE_SIZE, MmCached); if (skip(Mapping != NULL, "Failed to map zero page\n")) { ExFreePoolWithTag(ZeroPageContents, 'ZPmK'); ExFreePoolWithTag(MyPage, 'MPmK'); return; } RtlCopyMemory(ZeroPageContents, Mapping, PAGE_SIZE); MmUnmapIoSpace(Mapping, PAGE_SIZE); InitializeObjectAttributes(&ObjectAttributes, &SectionName, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No section\n")) { /* Map zero page and compare */ Mapping = NULL; ViewSize = PAGE_SIZE; Status = ZwMapViewOfSection(SectionHandle, ZwCurrentProcess(), &Mapping, 0, 0, &ZeroPagePhysical, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No view\n")) { ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping); EqualBytes = RtlCompareMemory(Mapping, ZeroPageContents, PAGE_SIZE); ok_eq_size(EqualBytes, PAGE_SIZE); Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping); ok_eq_hex(Status, STATUS_SUCCESS); } /* Map the zero page non-cached */ Mapping = NULL; ViewSize = PAGE_SIZE; Status = ZwMapViewOfSection(SectionHandle, ZwCurrentProcess(), &Mapping, 0, 0, &ZeroPagePhysical, &ViewSize, ViewUnmap, 0, PAGE_READWRITE | PAGE_NOCACHE); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No view\n")) { ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping); EqualBytes = RtlCompareMemory(Mapping, ZeroPageContents, PAGE_SIZE); ok_eq_size(EqualBytes, PAGE_SIZE); Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping); ok_eq_hex(Status, STATUS_SUCCESS); } /* Map our NP page, compare, and check that modifications are reflected */ Mapping = NULL; ViewSize = PAGE_SIZE; Status = ZwMapViewOfSection(SectionHandle, ZwCurrentProcess(), &Mapping, 0, 0, &MyPagePhysical, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No view\n")) { ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping); EqualBytes = RtlCompareMemory(Mapping, MyPage, PAGE_SIZE); ok_eq_size(EqualBytes, PAGE_SIZE); MappingBytes = Mapping; ok(MappingBytes[5] == 0x23, "Mapping[5] = 0x%x\n", MappingBytes[5]); ok(MyPage[5] == 0x23, "MyPage[5] = 0x%x\n", MyPage[5]); MyPage[5] = 0x44; ok(MappingBytes[5] == 0x44, "Mapping[5] = 0x%x\n", MappingBytes[5]); ok(MyPage[5] == 0x44, "MyPage[5] = 0x%x\n", MyPage[5]); MappingBytes[5] = 0x88; ok(MappingBytes[5] == 0x88, "Mapping[5] = 0x%x\n", MappingBytes[5]); ok(MyPage[5] == 0x88, "MyPage[5] = 0x%x\n", MyPage[5]); Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping); ok_eq_hex(Status, STATUS_SUCCESS); } Status = ZwClose(SectionHandle); ok_eq_hex(Status, STATUS_SUCCESS); } /* Try flag 0x80000000, which ROS calls SEC_PHYSICALMEMORY */ InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, NULL, PAGE_READWRITE, 0x80000000, NULL); ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6); if (NT_SUCCESS(Status)) ZwClose(SectionHandle); /* Assertion failure: AllocationAttributes & SEC_IMAGE | SEC_RESERVE | SEC_COMMIT */ if (!KmtIsCheckedBuild) { InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS, &ObjectAttributes, NULL, PAGE_READWRITE, 0x80000000, NULL, NULL); ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6); if (NT_SUCCESS(Status)) ObDereferenceObject(SectionObject); } InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS, &ObjectAttributes, NULL, PAGE_READWRITE, SEC_RESERVE | 0x80000000, NULL, NULL); ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6); if (NT_SUCCESS(Status)) ObDereferenceObject(SectionObject); ExFreePoolWithTag(ZeroPageContents, 'ZPmK'); ExFreePoolWithTag(MyPage, 'MPmK'); }
HANDLE GetCurrentProcessHandle() { return ZwCurrentProcess(); }
VOID tgwinkEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) { WDFMEMORY mem; NTSTATUS status; WDFDEVICE dev; PDEVICE_CONTEXT context; void *uBase = NULL; LARGE_INTEGER offset; size_t size; dev = WdfIoQueueGetDevice(Queue); context = DeviceGetContext(dev); switch (IoControlCode) { case IOCTL_TGWINK_SAY_HELLO: if (OutputBufferLength != 4) { WdfRequestComplete(Request, STATUS_BAD_DATA); break; } status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, status); break; } *((DWORD32 *)(WdfMemoryGetBuffer(mem, NULL))) = 0x5a5aa5a5; WdfRequestComplete(Request, STATUS_SUCCESS); break; case IOCTL_TGWINK_MAP_BAR_0: if (sizeof(void *) > OutputBufferLength) { KdPrint("tgwinkEvtIoDeviceControl needs a larger buffer (%d > %d)!\n", sizeof(void *), OutputBufferLength); WdfRequestComplete(Request, STATUS_BUFFER_TOO_SMALL); break; } offset = context->bar[0].phyAddr; size = context->bar[0].length; status = ZwMapViewOfSection(context->hMemory, ZwCurrentProcess(), &uBase, 0, 0, &offset, &size, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not map view of section, status "); switch (status) { case STATUS_CONFLICTING_ADDRESSES: KdPrint("STATUS_CONFLICTING_ADDRESSES\n"); break; case STATUS_INVALID_PAGE_PROTECTION: KdPrint("STATUS_INVALID_PAGE_PROTECTION\n"); break; case STATUS_SECTION_PROTECTION: KdPrint("STATUS_SECTION_PROTECTION\n"); break; default: KdPrint("0x % x\n", status); break; } WdfRequestComplete(Request, status); break; } status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, status); break; } *((void **)(WdfMemoryGetBuffer(mem, NULL))) = uBase; WdfRequestComplete(Request, STATUS_SUCCESS); break; case IOCTL_TGWINK_READ_PHYS: { PVOID buf; ULONG_PTR page, ofs, vtgt = 0; SIZE_T vsz = 0; if (InputBufferLength != sizeof(PVOID)) { KdPrint("tgwinkEvtIoDeviceControl requires a %d-byte buffer for this ioctl (got %d)\n", sizeof(PVOID), OutputBufferLength); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); break; } status = WdfRequestRetrieveInputBuffer(Request, sizeof(PVOID), &buf, NULL); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } ofs = *((ULONG_PTR *)buf); page = ofs & ~0xfff; vsz = OutputBufferLength + (page ^ ofs); buf = NULL; status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } status = ZwMapViewOfSection(context->hMemory, (HANDLE)-1, (PVOID *)&vtgt, 0, 0, (PLARGE_INTEGER)&page, &vsz, ViewUnmap, 0, PAGE_READONLY); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not map view of physical memory section, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } ofs -= page; status = WdfMemoryCopyFromBuffer(mem, 0, (PVOID)(vtgt + ofs), OutputBufferLength); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to copy data from memory to buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)vtgt); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to unmap view of physical memory section, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, OutputBufferLength); } break; case IOCTL_TGWINK_PEND_INTR: { WdfWaitLockAcquire(context->nnLock, NULL); if (context->notifyNext) { PINTERRUPT_CONTEXT pCtx = InterruptGetContext(context->hIrq); status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to retrieve output memory, status 0x%x\n", status); WdfRequestComplete(Request, status); } status = WdfMemoryCopyFromBuffer(mem, 0, &pCtx->serial, 8); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to copy interrupt number to buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); } WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 8); context->notifyNext = 0; KdPrint("tgwinkEvtIoDeviceControl satisfied interrupt notification request synchronously.\n"); //WdfInterruptEnable(context->hIrq); } else { KdPrint("tgwinkEvtIoDeviceControl forwarding PEND_INTR request to notification queue\n"); WdfRequestForwardToIoQueue(Request, context->NotificationQueue); } WdfWaitLockRelease(context->nnLock); } break; default: WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); } }
static VOID TestDuplicate( _In_ HANDLE Handle) { NTSTATUS Status; HANDLE NewHandle; struct { ACCESS_MASK DesiredAccess; ULONG RequestedAttributes; ULONG Options; ACCESS_MASK GrantedAccess; ULONG ExpectedAttributes; } Tests[] = { { DIRECTORY_ALL_ACCESS, 0, 0, DIRECTORY_ALL_ACCESS, 0 }, { DIRECTORY_ALL_ACCESS, OBJ_KERNEL_HANDLE, 0, DIRECTORY_ALL_ACCESS, 0 }, { DIRECTORY_QUERY, 0, 0, DIRECTORY_QUERY, 0 }, { DIRECTORY_QUERY, OBJ_INHERIT, 0, DIRECTORY_QUERY, OBJ_INHERIT }, { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ACCESS, DIRECTORY_ALL_ACCESS, OBJ_INHERIT }, /* 5 */ { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ATTRIBUTES, DIRECTORY_QUERY, 0 }, { DIRECTORY_QUERY, OBJ_INHERIT, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES, DIRECTORY_ALL_ACCESS, 0 }, }; ULONG i; for (i = 0; i < RTL_NUMBER_OF(Tests); i++) { trace("Test %lu\n", i); Status = ZwDuplicateObject(ZwCurrentProcess(), Handle, ZwCurrentProcess(), &NewHandle, Tests[i].DesiredAccess, Tests[i].RequestedAttributes, Tests[i].Options); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n")) { ok(IsUserHandle(NewHandle), "New handle = %p\n", NewHandle); CheckObject(NewHandle, 3UL, 2UL, Tests[i].ExpectedAttributes, Tests[i].GrantedAccess); CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS); Status = ObCloseHandle(NewHandle, UserMode); ok_eq_hex(Status, STATUS_SUCCESS); CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); } } /* If TargetProcess is the System process, we do get a kernel handle */ Status = ZwDuplicateObject(ZwCurrentProcess(), Handle, SystemProcessHandle, &NewHandle, DIRECTORY_ALL_ACCESS, OBJ_KERNEL_HANDLE, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "DuplicateHandle failed\n")) { ok(IsKernelHandle(NewHandle), "New handle = %p\n", NewHandle); CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS); CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS); Status = ObCloseHandle(NewHandle, UserMode); ok_eq_hex(Status, STATUS_INVALID_HANDLE); CheckObject(NewHandle, 3UL, 2UL, 0, DIRECTORY_ALL_ACCESS); CheckObject(Handle, 3UL, 2UL, 0UL, DIRECTORY_ALL_ACCESS); if (IsKernelHandle(NewHandle)) { Status = ObCloseHandle(NewHandle, KernelMode); ok_eq_hex(Status, STATUS_SUCCESS); CheckObject(Handle, 2UL, 1UL, 0UL, DIRECTORY_ALL_ACCESS); } } }
BOOL ShareMemKImp::InitializeShareMem(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSize, LPCWSTR lpName, DWORD dwDesiredAccess, ShareMemClassInit* lpInitialization, void* lpUserContext) { UninitializeShareMem(); DWORD size; size = dwMaximumSize + sizeof(ShareMemHeader); if (size < dwMaximumSize) return FALSE; UNICODE_STRING us; RtlInitUnicodeString(&us, lpName); OBJECT_ATTRIBUTES attr; InitializeObjectAttributes(&attr, &us, OBJ_OPENIF, NULL, NULL); LARGE_INTEGER li; li.QuadPart = size; NTSTATUS status; status = ZwCreateSection(&m_hMapSect, READ_CONTROL|WRITE_DAC|dwDesiredAccess, &attr, &li, flProtect, SEC_COMMIT, hFile); BOOLEAN init; init = status != STATUS_SUCCESS ? FALSE : TRUE; if (m_hMapSect) { SIZE_T v_size; v_size = 0; status = ZwMapViewOfSection(m_hMapSect, ZwCurrentProcess(), &m_hMapView, 0, size, NULL, &v_size, ViewUnmap, 0, PAGE_READWRITE); if (m_hMapView) { m_hMapSize = dwMaximumSize; ShareMemHeader* smh; smh = (ShareMemHeader*)m_hMapView; if (init) { LARGE_INTEGER tick; KeQueryTickCount(&tick); RtlStringCchPrintfW(smh->m_LockName, sizeof(smh->m_LockName), L"K-%08x-%08x-%08x", PsGetCurrentProcessId(), PsGetCurrentThreadId(), tick.LowPart); if (lpInitialization) smh->m_bResult = lpInitialization(this, lpUserContext); else smh->m_bResult = TRUE; smh->m_bInitialized = TRUE; } else while(1) if (smh->m_bInitialized) break; return smh->m_bResult; } } return FALSE; }
/* * @implemented */ VOID NTAPI RtlAssert(IN PVOID FailedAssertion, IN PVOID FileName, IN ULONG LineNumber, IN PCHAR Message OPTIONAL) { CHAR Action[2]; CONTEXT Context; /* Capture caller's context for the debugger */ RtlCaptureContext(&Context); /* Enter prompt loop */ for (;;) { /* Print the assertion */ DbgPrint("\n*** Assertion failed: %s%s\n" "*** Source File: %s, line %lu\n\n", Message != NULL ? Message : "", (PSTR)FailedAssertion, (PSTR)FileName, LineNumber); /* Prompt for action */ DbgPrompt("Break repeatedly, break Once, Ignore," " terminate Process or terminate Thread (boipt)? ", Action, sizeof(Action)); switch (Action[0]) { /* Break repeatedly */ case 'B': case 'b': /* Do a breakpoint, then prompt again */ DbgPrint("Execute '.cxr %p' to dump context\n", &Context); DbgBreakPoint(); break; /* Ignore */ case 'I': case 'i': /* Return to caller */ return; /* Break once */ case 'O': case 'o': /* Do a breakpoint and return */ DbgPrint("Execute '.cxr %p' to dump context\n", &Context); DbgBreakPoint(); return; /* Terminate process*/ case 'P': case 'p': /* Terminate us */ ZwTerminateProcess(ZwCurrentProcess(), STATUS_UNSUCCESSFUL); break; /* Terminate thread */ case 'T': case 't': /* Terminate us */ ZwTerminateThread(ZwCurrentThread(), STATUS_UNSUCCESSFUL); break; /* Unrecognized */ default: /* Prompt again */ break; } } /* Shouldn't get here */ DbgBreakPoint(); ZwTerminateProcess(ZwCurrentProcess(), STATUS_UNSUCCESSFUL); }
/// <summary> /// Process section object pages /// Function will attempt to trigger copy-on-write for underlying pages to convert them into private /// If copy-on-write fails, region will be then mapped as read-only /// </summary> /// <param name="pEntry">Region data</param> /// <returns>Status code</returns> NTSTATUS BBHandleSharedRegion( IN PMAP_ENTRY pEntry ) { NTSTATUS status = STATUS_SUCCESS; MEMORY_BASIC_INFORMATION mbi = { 0 }; SIZE_T length = 0; ULONG_PTR memptr = 0; // Iterate underlying memory regions for (memptr = pEntry->originalPtr; memptr < pEntry->originalPtr + pEntry->size; memptr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize) { PVOID pBase = NULL; SIZE_T size = 0; MEMORY_WORKING_SET_EX_INFORMATION wsInfo = { 0 }; ULONG oldProt = 0; BOOLEAN writable = FALSE; status = ZwQueryVirtualMemory( ZwCurrentProcess(), (PVOID)memptr, MemoryBasicInformation, &mbi, sizeof( mbi ), &length ); if (!NT_SUCCESS( status )) { DPRINT( "BlackBone: %s: ZwQueryVirtualMemory for address 0x%p failed\n", __FUNCTION__, memptr ); return status; } writable = (mbi.Protect & (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE)); pBase = mbi.BaseAddress; size = (SIZE_T)mbi.RegionSize; // Make readonly pages writable if (writable || NT_SUCCESS( ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &size, PAGE_EXECUTE_READWRITE, &oldProt ) )) { BOOLEAN failed = FALSE; // Touch pages to trigger copy-on-write and create private copies // This is crucial to prevent changes on section pages __try { ProbeForWrite( mbi.BaseAddress, mbi.RegionSize, PAGE_SIZE ); } __except (EXCEPTION_EXECUTE_HANDLER) { DPRINT( "BlackBone: %s: Exception while touching address 0x%p\n", __FUNCTION__, mbi.BaseAddress ); failed = TRUE; } // Restore protection if (writable == FALSE) ZwProtectVirtualMemory( ZwCurrentProcess(), &pBase, &size, oldProt, &oldProt ); if (failed) return STATUS_SHARING_VIOLATION; // If region was writable, it's safe to map shared pages if (writable) continue; // // Ensure pages were made private // for (ULONG_PTR pPage = (ULONG_PTR)mbi.BaseAddress; pPage < (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; pPage += PAGE_SIZE) { RtlZeroMemory( &wsInfo, sizeof( wsInfo ) ); wsInfo.VirtualAddress = (PVOID)pPage; // Check page 'shared' flag if (NT_SUCCESS( ZwQueryVirtualMemory( ZwCurrentProcess(), NULL, MemoryWorkingSetExInformation, &wsInfo, sizeof( wsInfo ), &length ) ) && wsInfo.VirtualAttributes.Shared) { DPRINT( "BlackBone: %s: Page at address 0x%p is still shared!", __FUNCTION__, pPage ); return STATUS_SHARING_VIOLATION; } } } else {