// Creats Post breakpoint object, adds it to the list and enables it _Use_decl_annotations_ void SbpCreateAndEnablePostBreakpoint( void* address, const PatchInformation& info, const CapturedParameters& parameters, EptData* ept_data) { auto duplicated_info = SbppFindDuplicatedPostPatchInfo(address, PsGetCurrentThreadId()); if (duplicated_info) { duplicated_info->parameters = parameters; return; } auto info_for_post = SbppCreatePostBreakpoint( address, info, PsGetCurrentThreadId(), parameters); auto ptr = info_for_post.get(); SbppAddBreakpointToList(std::move(info_for_post)); SbppEnablePageShadowingForExec(*ptr, ept_data); }
void TlsRemoveCurrentThread(THREAD_LOCAL_STORAGE* InTls) { /* Description: Removes the caller from the local storage. If the caller is already removed, the method will do nothing. Parameters: - InTls The storage from which the caller should be removed. */ #ifndef DRIVER ULONG CurrentId = (ULONG)GetCurrentThreadId(); #else ULONG CurrentId = (ULONG)PsGetCurrentThreadId(); #endif ULONG Index; RtlAcquireLock(&InTls->ThreadSafe); for(Index = 0; Index < MAX_THREAD_COUNT; Index++) { if(InTls->IdList[Index] == CurrentId) { InTls->IdList[Index] = 0; RtlZeroMemory(&InTls->Entries[Index], sizeof(THREAD_RUNTIME_INFO)); } } RtlReleaseLock(&InTls->ThreadSafe); }
VOID ThreadStart(PVOID lpStartContext) { PKEVENT pEvent = (PKEVENT)lpStartContext; DbgPrint("Hello! I am kernel thread. My ID is %u. Regards..", (ULONG)PsGetCurrentThreadId()); KeSetEvent(pEvent, 0, 0); PsTerminateSystemThread(STATUS_SUCCESS); }
VOID __stdcall Filter(ULONG ServiceId, ULONG TableBase, ULONG Argc, ULONG StackAddr) { ULONG pid = (ULONG)PsGetCurrentProcessId(); if (pid == g_nPid) { ULONG i; PXBoxData pData=(PXBoxData)ExAllocateFromNPagedLookasideList(&g_nPageList); if(!pData) return; if (StackAddr < MmUserProbeAddress) pData->bFromUser = 1; else pData->bFromUser = 0; if (TableBase == (ULONG)KeServiceDescriptorTable.ServiceTableBase) pData->bFromSSDT = 1; else pData->bFromSSDT = 0; if (Argc > 16) Argc = 16; pData->argc = (UCHAR)Argc; for (i = 0; i < Argc; ++i) pData->args[i] = ((PULONG)StackAddr)[i]; pData->pid = (ULONG)pid; pData->tid = (ULONG)PsGetCurrentThreadId(); pData->sid = ServiceId; KeQuerySystemTime(&pData->time); ExInterlockedInsertTailList(&g_linkListHead, &pData->ListEntry, &g_lock); KeReleaseSemaphore( &g_keySemaphore, 0, 1, FALSE ); } }
NTSTATUS IoCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Context); PAGED_CODE(); KdPrint(("SYS(%d:%d):IoCompletionRoutine!\n", PsGetCurrentProcessId(), PsGetCurrentThreadId())); *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; }
void AFSProcessNotify( IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create) { // // If this is a create notification then update our tree, otherwise remove the // entry // if( Create) { AFSProcessCreate( ParentId, ProcessId, PsGetCurrentProcessId(), PsGetCurrentThreadId()); } else { AFSProcessDestroy( ProcessId); } return; }
VOID NDISLWF_ReceiveNetBufferListsHandler ( NDIS_HANDLE FilterModuleContext, PNET_BUFFER_LIST NetBufferLists, NDIS_PORT_NUMBER PortNumber, ULONG NumberOfNetBufferLists, ULONG ReceiveFlags ) { PNDISLWF_CONTEXT FilterContext = (PNDISLWF_CONTEXT)FilterModuleContext; // process the NBL chain to determine if should be allowed or rejected if ( ProcessNblChain ( NetBufferLists ) ) { DPF(("%s!%s [%x.%x] NBL=%p BLOCKED\n", __MODULE__, __FUNCTION__, PsGetCurrentProcessId(), PsGetCurrentThreadId(), NetBufferLists )); // Step #1 : Return the NBL chain to the caller instead of indicating it up to // the driver above (NdisFReturnNetBufferLists()) // ensure that the ReceiveFlags are properly translated to ReturnFlags NdisFReturnNetBufferLists(FilterContext->FilterHandle, NetBufferLists, ReceiveFlags & NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL); } else { // Step #2 : Indicate the NBL chain to the driver above (NdisFIndicateReceiveNetBufferLists()) NdisFIndicateReceiveNetBufferLists(FilterContext->FilterHandle, NetBufferLists, PortNumber, NumberOfNetBufferLists, ReceiveFlags); } } // NDISLWF_ReceiveNetBufferListsHandler()
void WmipWaitForCollectionEnabled( PBGUIDENTRY GuidEntry ) { PAGED_CODE(); WmipAssert((GuidEntry->Flags & GE_FLAG_COLLECTION_IN_PROGRESS) == GE_FLAG_COLLECTION_IN_PROGRESS); // // Collection Enable/Disable is in progress so // we cannot return just yet. Right now there could be a // disable request being processed and if we didn't wait, we // might get back to this caller before that disable request // got around to realizing that it needs to send and enable // request (needed by this thread's caller). So we'd have a // situation where a thread though that collection was enabled // but in reality it wasn't yet enabled. if ((GuidEntry->Flags & GE_FLAG_WAIT_ENABLED) == 0) { KeInitializeEvent(GuidEntry->CollectInProgress, NotificationEvent, FALSE); GuidEntry->Flags |= GE_FLAG_WAIT_ENABLED; WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: %p.%p for %p %x created event\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), GuidEntry, GuidEntry->Flags)); } WmipLeaveSMCritSection(); WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: %p.%p waiting for %p %x on event\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), GuidEntry, GuidEntry->Flags)); KeWaitForSingleObject(GuidEntry->CollectInProgress, Executive, KernelMode, FALSE, NULL); WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: %p.%p done %p %x waiting on event\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), GuidEntry, GuidEntry->Flags)); WmipEnterSMCritSection(); }
BOOL TlsAddCurrentThread(THREAD_LOCAL_STORAGE* InTls) { /* Description: Tries to reserve a THREAD_RUNTIME_INFO entry for the calling thread. On success it may call TlsGetCurrentValue() to query a pointer to its private entry. This is a replacement for the Windows Thread Local Storage which seems to cause trouble when using it in Explorer.EXE for example. No parameter validation (for performance reasons). This method will raise an assertion if the thread was already added to the storage! Parameters: - InTls The thread local storage to allocate from. Returns: TRUE on success, FALSE otherwise. */ #ifndef DRIVER ULONG CurrentId = (ULONG)GetCurrentThreadId(); #else ULONG CurrentId = (ULONG)PsGetCurrentThreadId(); #endif LONG Index = -1; LONG i; RtlAcquireLock(&InTls->ThreadSafe); // select Index AND check whether thread is already registered. for(i = 0; i < MAX_THREAD_COUNT; i++) { if((InTls->IdList[i] == 0) && (Index == -1)) Index = i; ASSERT(InTls->IdList[i] != CurrentId); } if(Index == -1) { RtlReleaseLock(&InTls->ThreadSafe); return FALSE; } InTls->IdList[Index] = CurrentId; RtlZeroMemory(&InTls->Entries[Index], sizeof(THREAD_RUNTIME_INFO)); RtlReleaseLock(&InTls->ThreadSafe); return TRUE; }
// Enumerate all big pages and calls a callback routine when it matched with // a criteria specified by filters parameters. It stops to enumerate when the // callback returned false. template <typename TableType> static void WinXpEnumBigPages( __in EnumBigPagesCallbackType Callback, __in_opt void* Context, __in_opt ULONG KeyFilter, __in_opt SIZE_T MinSizeFilter, __in TableType* BigPageTable, __in SIZE_T NumberOfBigPageTable) { DBG_PRINT("[%5Iu:%5Iu] Initialize : PoolBigPageTable = %p\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), BigPageTable); DBG_PRINT("[%5Iu:%5Iu] Initialize : PoolBigPageTableSize = %p\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), NumberOfBigPageTable); for (SIZE_T i = 0; i < NumberOfBigPageTable; ++i) { auto entry = &BigPageTable[i]; auto startAddr = reinterpret_cast<ULONG_PTR>(entry->Va); // Ignore unused entries if (!startAddr || (startAddr & 1)) { continue; } // Get the size in bytes const auto sizeInBytes = entry->Size * Multiplier<TableType>::value; // Filter if it is needed if ((KeyFilter && entry->Key != KeyFilter) || (sizeInBytes < MinSizeFilter)) { continue; } // Call a callback function if (!Callback(startAddr, sizeInBytes, entry->Key, Context)) { break; } } }
VCOS_STATUS_T vcos_platform_init(void) { VCOS_STATUS_T st; uint32_t flags = 0; st = _vcos_named_semaphore_init(); if (!vcos_verify(st == VCOS_SUCCESS)) goto end; flags |= VCOS_INIT_NAMED_SEM; st = vcos_once(¤t_thread_key_once, current_thread_key_init); if (!vcos_verify(st == VCOS_SUCCESS)) goto end; /* Initialise a VCOS wrapper for the thread which called vcos_init. */ st = vcos_semaphore_create(&vcos_thread_main.suspend, NULL, 0); if (!vcos_verify(st == VCOS_SUCCESS)) goto end; flags |= VCOS_INIT_MAIN_SEM; #ifdef WIN32_KERN vcos_thread_main.thread = PsGetCurrentThreadId(); // TODO Implement thread context for kernel mode #else int pst; vcos_thread_main.thread = GetCurrentThread(); // For windows zero return value is failure pst = TlsSetValue(_vcos_thread_current_key, &vcos_thread_main); if (!vcos_verify(pst != 0)) { st = VCOS_EINVAL; goto end; } #endif st = vcos_msgq_init(); if (!vcos_verify(st == VCOS_SUCCESS)) goto end; flags |= VCOS_INIT_MSGQ; vcos_logging_init(); end: if (st != VCOS_SUCCESS) vcos_term(flags); return st; }
EXTERN_C ULONG_PTR Win8HandleKeDelayExecutionThread( __in ULONG_PTR* AddressOfReturnAddress) { PAGED_CODE(); const auto pg_SelfEncryptWaitAndDecrypt = g_Symbols.KiScbQueueScanWorker + WIN8_OFFSET_TO_Pg_SelfEncryptWaitAndDecrypt; auto returnAddr = *AddressOfReturnAddress; // Check if the thread is going to return to Pg_SelfEncryptWaitAndDecrypt if (returnAddr == pg_SelfEncryptWaitAndDecrypt) { DBG_PRINT("[%5Iu:%5Iu] PatchGuard ???????????????? :" " KeDelayExecutionThread is returning to" " Pg_SelfEncryptWaitAndDecrypt (%016llX).\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), returnAddr); //DBG_BREAK(); return 1; } // Check if the thread is going to return to FsRtlMdlReadCompleteDevEx if (*reinterpret_cast<ULONG64*>(returnAddr) == WIN8_KeDelayExecutionThread_RETURN_CODE_PATTERN) { DBG_PRINT("[%5Iu:%5Iu] PatchGuard ???????????????? :" " KeDelayExecutionThread is returning to" " FsRtlMdlReadCompleteDevEx (%016llX).\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), returnAddr); //DBG_BREAK(); return 2; } // It is not a PatchGuard return 0; }
/*! * \see http://blogs.msdn.com/b/michael_howard/archive/2005/01/14/353379.aspx */ NTSTATUS NTAPI KsecGatherEntropyData( PKSEC_ENTROPY_DATA EntropyData) { MD4_CTX Md4Context; PTEB Teb; PPEB Peb; PWSTR String; SIZE_T ReturnLength; NTSTATUS Status; /* Query some generic values */ EntropyData->CurrentProcessId = PsGetCurrentProcessId(); EntropyData->CurrentThreadId = PsGetCurrentThreadId(); KeQueryTickCount(&EntropyData->TickCount); KeQuerySystemTime(&EntropyData->SystemTime); EntropyData->PerformanceCounter = KeQueryPerformanceCounter( &EntropyData->PerformanceFrequency); /* Check if we have a TEB/PEB for the process environment */ Teb = PsGetCurrentThread()->Tcb.Teb; if (Teb != NULL) { Peb = Teb->ProcessEnvironmentBlock; /* Initialize the MD4 context */ MD4Init(&Md4Context); _SEH2_TRY { /* Get the end of the environment */ String = Peb->ProcessParameters->Environment; while (*String) { String += wcslen(String) + 1; } /* Update the MD4 context from the environment data */ MD4Update(&Md4Context, (PUCHAR)Peb->ProcessParameters->Environment, (ULONG)((PUCHAR)String - (PUCHAR)Peb->ProcessParameters->Environment)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Simply ignore the exception */ } _SEH2_END; /* Finalize and copy the MD4 hash */ MD4Final(&Md4Context); RtlCopyMemory(&EntropyData->EnvironmentHash, Md4Context.digest, 16); }
void WmipReleaseCollectionEnabled( PBGUIDENTRY GuidEntry ) { PAGED_CODE(); if (GuidEntry->Flags & GE_FLAG_WAIT_ENABLED) { WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: %p.%p enable releasning %p.%p %x event %p\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), GuidEntry, GuidEntry->Flags)); KeSetEvent(GuidEntry->CollectInProgress, 0, FALSE); WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: %p.%p enable did release %p %x event %p\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), GuidEntry, GuidEntry->Flags)); GuidEntry->Flags &= ~GE_FLAG_WAIT_ENABLED; } }
NDIS_STATUS NDISLWF_RestartHandler ( NDIS_HANDLE FilterModuleContext, PNDIS_FILTER_RESTART_PARAMETERS RestartParameters ) { PNDISLWF_CONTEXT FilterContext = (PNDISLWF_CONTEXT)FilterModuleContext; DPF(("%s!%s [%x.%x] (Context=%p RestartParameters=%p)\n", __MODULE__, __FUNCTION__, PsGetCurrentProcessId(), PsGetCurrentThreadId(), FilterContext, RestartParameters )); return NDIS_STATUS_SUCCESS; } //NDISLWF_RestartHandler()
VOID NDISLWF_StatusHandler ( NDIS_HANDLE FilterModuleContext, PNDIS_STATUS_INDICATION StatusIndication ) { PNDISLWF_CONTEXT FilterContext = (PNDISLWF_CONTEXT)FilterModuleContext; DPF(("%s!%s [%x.%x] (Context=%p StatusIndication=%p)\n", __MODULE__, __FUNCTION__, PsGetCurrentProcessId(), PsGetCurrentThreadId(), FilterModuleContext, StatusIndication )); NdisFIndicateStatus(FilterContext->FilterHandle, StatusIndication); } //NDISLWF_StatusHandler()
EXTERN_C static bool WinXpCollectPatchGuardContexts( __in ULONG_PTR StartAddress, __in SIZE_T SizeInBytes, __in ULONG Key, __inout_opt void* Context) { // Ignore this if the address is not in the NonPaged pool if (StartAddress < *g_WinXSymbols.MmNonPagedPoolStart) { return true; } if (!Context) { return false; } auto storage = static_cast<PatchGuardContexts*>(Context); PatchGuardContextInfo result = {}; for (SIZE_T searchedBytes = 0; searchedBytes < SizeInBytes; /**/) { // Search a context const auto remainingBytes = SizeInBytes - searchedBytes; const auto searchPosition = StartAddress + searchedBytes; const auto checkedBytes = WinXpSearchPatchGuardContext( searchPosition, remainingBytes, result); searchedBytes += checkedBytes; // Check if a context was found if (result.PgContext) { // save it to the storage storage->PgContexts[storage->NumberOfPgContexts] = result; storage->NumberOfPgContexts++; DBG_PRINT("[%5Iu:%5Iu] PatchGuard %016llX : XorKey %016llX\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), result.PgContext, result.XorKey); break; } } // Tell WinXpEnumBigPages to stop enumerating pages when the storage is full return (storage->NumberOfPgContexts < storage->MAX_SUPPORTED_NUMBER_OF_PG_CONTEXTS); }
BOOL TlsGetCurrentValue( THREAD_LOCAL_STORAGE* InTls, THREAD_RUNTIME_INFO** OutValue) { /* Description: Queries the THREAD_RUNTIME_INFO for the calling thread. The caller shall previously be added to the storage by using TlsAddCurrentThread(). Parameters: - InTls The storage where the caller is registered. - OutValue Is filled with a pointer to the caller's private storage entry. Returns: FALSE if the caller was not registered in the storage, TRUE otherwise. */ #ifndef DRIVER ULONG CurrentId = (ULONG)GetCurrentThreadId(); #else ULONG CurrentId = (ULONG)PsGetCurrentThreadId(); #endif LONG Index; for(Index = 0; Index < MAX_THREAD_COUNT; Index++) { if(InTls->IdList[Index] == CurrentId) { *OutValue = &InTls->Entries[Index]; return TRUE; } } return FALSE; }
VOID NTAPI DbgLogEvent(PSLIST_HEADER pslh, LOG_EVENT_TYPE nEventType, LPARAM lParam) { PLOGENTRY pLogEntry; /* Log a maximum of 100 events */ if (QueryDepthSList(pslh) >= 1000) return; /* Allocate a logentry */ pLogEntry = EngAllocMem(0, sizeof(LOGENTRY), 'golG'); if (!pLogEntry) return; /* Set type */ pLogEntry->nEventType = nEventType; pLogEntry->ulUnique = InterlockedIncrement((LONG*)&gulLogUnique); pLogEntry->dwProcessId = HandleToUlong(PsGetCurrentProcessId()); pLogEntry->dwThreadId = HandleToUlong(PsGetCurrentThreadId()); pLogEntry->lParam = lParam; /* Capture a backtrace */ DbgCaptureStackBackTace(pLogEntry->apvBackTrace, 20); switch (nEventType) { case EVENT_ALLOCATE: case EVENT_CREATE_HANDLE: case EVENT_REFERENCE: case EVENT_DEREFERENCE: case EVENT_LOCK: case EVENT_UNLOCK: case EVENT_DELETE: case EVENT_FREE: case EVENT_SET_OWNER: default: break; } /* Push it on the list */ InterlockedPushEntrySList(pslh, &pLogEntry->sleLink); }
// runs in kernel mode as KAPC.KernelRoutine VOID KernelApcKernelRoutine ( PKAPC Apc, PKNORMAL_ROUTINE *NormalRoutine, PVOID *NormalContext, PVOID *SystemArgument1, PVOID *SystemArgument2 ) { UNREFERENCED_PARAMETER(NormalContext); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); DPF(("%s!%s CID=%x.%x Irql=%u Apc=%p NormalRoutine=%p\n", __MODULE__, __FUNCTION__, PsGetCurrentProcessId(), PsGetCurrentThreadId(), KeGetCurrentIrql(), Apc, *NormalRoutine )); ExFreePool ( Apc ); }
// A thread runs as long as info.buffer_flush_thread_should_be_alive is true and // flushes a log buffer to a log file every kLogpLogFlushIntervalMsec msec. _Use_decl_annotations_ static VOID LogpBufferFlushThreadRoutine( void *start_context) { PAGED_CODE(); auto status = STATUS_SUCCESS; auto info = reinterpret_cast<LogBufferInfo *>(start_context); info->buffer_flush_thread_started = true; HYPERPLATFORM_LOG_DEBUG("Log thread started (TID= %p).", PsGetCurrentThreadId()); while (info->buffer_flush_thread_should_be_alive) { NT_ASSERT(LogpIsLogFileActivated(*info)); if (info->log_buffer_head[0]) { NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); NT_ASSERT(!KeAreAllApcsDisabled()); status = LogpFlushLogBuffer(info); // Do not flush the file for overall performance. Even a case of // bug check, we should be able to recover logs by looking at both // log buffers. } LogpSleep(kLogpLogFlushIntervalMsec); } PsTerminateSystemThread(status); }
void SendRegistryOperationToUserland (ULONG _opType, PUNICODE_STRING _pTarget ) { PRECORD_LIST recordList = SpyNewRecord(); if (!recordList) return; //Set the operation type. recordList->LogRecord.Data.RecordType = _opType; //Fill the basic stuff (PID-TID). recordList->LogRecord.Data.ProcessId = (FILE_ID)PsGetCurrentProcessId(); recordList->LogRecord.Data.ThreadId = (FILE_ID)PsGetCurrentThreadId(); //Fill the SystemTypeStuff. KeQuerySystemTime(&recordList->LogRecord.Data.OriginatingTime); KeQuerySystemTime(&recordList->LogRecord.Data.CompletionTime); ////Set the name to "" UNICODE_STRING emptySTR; RtlInitUnicodeString(&emptySTR, L""); DbgPrint("SendRegistryOperationToUserland : %wZ", _pTarget); SpySetRecordNameAndEcpData(&recordList->LogRecord, _pTarget, NULL); ////Send to the userland! SpyLog(recordList); }
// Gets called by AsmKeWaitForSingleObject, and returns one of following codes: // 1. returning to FsRtlMdlReadCompleteDevEx (PatchGuard) // 0. returning to anywhere else (Not PatchGuard) // AsmKeWaitForSingleObject returns the thread till ExpWorkerThead if the // returned code is 1 rather than manipulating them. This is because the // PatchGuard context may be encrypted on the fly and cannot be manipulated at // that moment. EXTERN_C ULONG_PTR Win8HandleKeWaitForSingleObject( __in ULONG_PTR* AddressOfReturnAddress) { auto returnAddr = *AddressOfReturnAddress; // Check if the thread is going to return to FsRtlMdlReadCompleteDevEx if (*reinterpret_cast<ULONG_PTR*>(returnAddr) == WIN8_KeWaitForSingleObject_RETURN_CODE_PATTERN) { DBG_PRINT("[%5Iu:%5Iu] PatchGuard ???????????????? :" " KeWaitForSingleObject is returning to" " FsRtlMdlReadCompleteDevEx (%016llX).\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), returnAddr); //DBG_BREAK(); return 1; } // It is not a PatchGuard return 0; }
void rnd_reseed_now() { seed_data seed; KeQuerySystemTime(&seed.seed20); seed.seed1 = PsGetCurrentProcess(); seed.seed2 = PsGetCurrentProcessId(); seed.seed3 = KeGetCurrentThread(); seed.seed4 = PsGetCurrentThreadId(); seed.seed5 = KeGetCurrentProcessorNumber(); seed.seed6 = KeQueryInterruptTime(); seed.seed10 = KeQueryPerformanceCounter(NULL); seed.seed11 = __rdtsc(); seed.seed12 = ExGetPreviousMode(); seed.seed14 = IoGetTopLevelIrp(); seed.seed15 = MmQuerySystemSize(); seed.seed24 = KeGetCurrentIrql(); if (KeGetCurrentIrql() == PASSIVE_LEVEL) { seed.seed7 = KeQueryPriorityThread(seed.seed3); seed.seed17 = ExUuidCreate(&seed.seed18); seed.seed19 = RtlRandom(&seed.seed8); } if (KeGetCurrentIrql() <= APC_LEVEL) { seed.seed13 = IoGetInitialStack(); seed.seed16 = PsGetProcessExitTime(); IoGetStackLimits(&seed.seed22, &seed.seed23); } KeQueryTickCount(&seed.seed21); rnd_add_buff(&seed, sizeof(seed)); /* Prevent leaks */ zeroauto(&seed, sizeof(seed)); }
// Gets called from AsmPg_IndependentContextWorkItemRoutine EXTERN_C void Win8HandlePg_IndependentContextWorkItemRoutine( __in Pg_IndependentContextWorkItemContext* Context) { DBG_PRINT("[%5Iu:%5Iu] PatchGuard %016llX :" " Pg_IndependentContextWorkItemRoutine was called.\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), Context->PgContext); if (Win8pIsMonitoringModeEnabled()) { // Now, we have got a decrypted PatchGuard context that is about to // execute Pg_IndependentContextWorkItemRoutine auto pgContext = reinterpret_cast<PgContext_8_1*>(Context->PgContext); Win8pPatchPgContext(pgContext); } else { // You can replace the routine with a harmless empty function instead of // modifying the PatchGuard context. Context->FsUninitializeSmallMcb = [](void*) {}; } }
// Concatenates meta information such as the current time and a process ID to // user given log message. EXTERN_C static NTSTATUS LogpMakePrefix(_In_ ULONG Level, _In_ const char *FunctionName, _In_ const char *LogMessage, _Out_ char *LogBuffer, _In_ size_t LogBufferLength) { char const *levelString = nullptr; switch (Level) { case LOGP_LEVEL_DEBUG: levelString = "DBG"; break; case LOGP_LEVEL_INFO: levelString = "INF"; break; case LOGP_LEVEL_WARN: levelString = "WRN"; break; case LOGP_LEVEL_ERROR: levelString = "ERR"; break; default: return STATUS_INVALID_PARAMETER; } auto status = STATUS_SUCCESS; char timeBuffer[20] = {}; if ((g_LogpDebugFlag & LOG_OPT_DISABLE_TIME) == 0) { // Want the current time. TIME_FIELDS timeFields; LARGE_INTEGER systemTime, localTime; KeQuerySystemTime(&systemTime); ExSystemTimeToLocalTime(&systemTime, &localTime); RtlTimeToTimeFields(&localTime, &timeFields); status = RtlStringCchPrintfA(timeBuffer, RTL_NUMBER_OF(timeBuffer), "%02u:%02u:%02u.%03u\t", timeFields.Hour, timeFields.Minute, timeFields.Second, timeFields.Milliseconds); if (!NT_SUCCESS(status)) { return status; } } char functionNameBuffer[50] = {}; if ((g_LogpDebugFlag & LOG_OPT_DISABLE_FUNCTION_NAME) == 0) { // Want the function name const auto baseFunctionName = LogpFindBaseFunctionName(FunctionName); status = RtlStringCchPrintfA(functionNameBuffer, RTL_NUMBER_OF(functionNameBuffer), "%-40s\t", baseFunctionName); if (!NT_SUCCESS(status)) { return status; } } // // It uses PsGetProcessId(PsGetCurrentProcess()) instead of // PsGetCurrentThreadProcessId() because the later sometimes returns // unwanted value, for example: // PID == 4 but its image name != ntoskrnl.exe // The author is guessing that it is related to attaching processes but // not quite sure. The former way works as expected. // status = RtlStringCchPrintfA( LogBuffer, LogBufferLength, "%s%s\t%5lu\t%5lu\t%-15s\t%s%s\r\n", timeBuffer, levelString, reinterpret_cast<ULONG_PTR>(PsGetProcessId(PsGetCurrentProcess())), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), PsGetProcessImageFileName(PsGetCurrentProcess()), functionNameBuffer, LogMessage); return status; }
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; }
NTSTATUS ioctlDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpSp; NTSTATUS NtStatus = STATUS_SUCCESS; int ret = 0; union { struct nm_ifreq ifr; struct nmreq nmr; } arg; size_t argsize = 0; PVOID data; struct sockopt *sopt; int space, len = 0; (void)DeviceObject; // XXX irpSp = IoGetCurrentIrpStackLocation(Irp); argsize = irpSp->Parameters.DeviceIoControl.InputBufferLength; data = Irp->AssociatedIrp.SystemBuffer; switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { case NIOCGINFO: DbgPrint("Netmap.sys: NIOCGINFO"); argsize = sizeof(arg.nmr); break; case NIOCREGIF: DbgPrint("Netmap.sys: NIOCREGIF"); argsize = sizeof(arg.nmr); #if 0 struct nmreq* test = (struct nmreq*) Irp->AssociatedIrp.SystemBuffer; DbgPrint("IFNAMSIZ: %i , sizeof(nmreq): %i\n", IFNAMSIZ, sizeof(struct nmreq)); DbgPrint("nr_version: %i , nr_ringid: %i\n", test->nr_version, test->nr_ringid); DbgPrint("nr_cmd: %i , nr_name: %s\n", test->nr_cmd, test->nr_name); DbgPrint("nr_tx_rings: %i , nr_tx_slots: %i\n", test->nr_tx_rings, test->nr_tx_slots); DbgPrint("nr_offset: %i , nr_flags: %s\n", test->nr_offset, test->nr_flags); #endif break; case NIOCTXSYNC: //DbgPrint("Netmap.sys: NIOCTXSYNC"); break; case NIOCRXSYNC: //DbgPrint("Netmap.sys: NIOCRXSYNC"); break; case NIOCCONFIG: DbgPrint("Netmap.sys: NIOCCONFIG"); argsize = sizeof(arg.ifr); break; case NETMAP_MMAP: DbgPrint("Netmap.sys: NETMAP_MMAP"); NtStatus = windows_netmap_mmap(Irp); Irp->IoStatus.Status = NtStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return NtStatus; case NETMAP_GETSOCKOPT: case NETMAP_SETSOCKOPT: DbgPrint("Netmap.sys: NETMAP_SET/GET-SOCKOPT (Common code)"); if (argsize < sizeof(struct sockopt)) { NtStatus = STATUS_BAD_DATA; Irp->IoStatus.Status = NtStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return NtStatus; } sopt = Irp->AssociatedIrp.SystemBuffer; len = sopt->sopt_valsize; if (irpSp->Parameters.DeviceIoControl.IoControlCode == NETMAP_SETSOCKOPT) { DbgPrint("Netmap.sys: NETMAP_SETSOCKOPT"); NtStatus = do_netmap_set_ctl(NULL, sopt->sopt_name, sopt + 1, len); Irp->IoStatus.Information = 0; } else { DbgPrint("Netmap.sys: NETMAP_GETSOCKOPT"); NtStatus = do_netmap_get_ctl(NULL, sopt->sopt_name, sopt + 1, &len); sopt->sopt_valsize = len; // XXX should we use OutputBufferLength ? space = irpSp->Parameters.DeviceIoControl.InputBufferLength; if (len + sizeof(struct sockopt) <= space) { Irp->IoStatus.Information = len + sizeof(struct sockopt); } else { Irp->IoStatus.Information = space; } } Irp->IoStatus.Status = NtStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return NtStatus; case NETMAP_POLL: { //DbgPrint("%i: Requested call to POLL \n", PsGetCurrentThreadId()); POLL_REQUEST_DATA *pollData = data; LARGE_INTEGER tout; tout.QuadPart = -(int)(pollData->timeout) * 1000 * 10; struct netmap_priv_d *priv = irpSp->FileObject->FsContext; if (priv == NULL) { NtStatus = STATUS_DEVICE_DATA_ERROR; goto done; } irpSp->FileObject->FsContext2 = NULL; pollData->revents = netmap_poll(priv, pollData->events, irpSp); while ((irpSp->FileObject->FsContext2 != NULL) && (pollData->revents == 0)) { NTSTATUS waitResult = KeWaitForSingleObject(&((win_SELINFO*)irpSp->FileObject->FsContext2)->queue, UserRequest, KernelMode, FALSE, &tout); if (waitResult == STATUS_TIMEOUT) { DbgPrint("%i: Timeout on 0x%p \n", PsGetCurrentThreadId(), irpSp->FileObject->FsContext2); pollData->revents = STATUS_TIMEOUT; NtStatus = STATUS_TIMEOUT; break; } pollData->revents = netmap_poll(priv, pollData->events, irpSp); } irpSp->FileObject->FsContext2 = NULL; copy_to_user((void*)data, &arg, sizeof(POLL_REQUEST_DATA), Irp); } Irp->IoStatus.Status = NtStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return NtStatus; default: //bail out if unknown request issued DbgPrint("Netmap.sys: wrong request issued! (%i)", irpSp->Parameters.DeviceIoControl.IoControlCode); NtStatus = STATUS_INVALID_DEVICE_REQUEST; IoCompleteRequest(Irp, IO_NO_INCREMENT); return NtStatus; } if (argsize) { if (!data) { NtStatus = STATUS_DATA_ERROR; } else { bzero(&arg, argsize); if (!NT_SUCCESS(copy_from_user(&arg, (void *)data, argsize, Irp))) { NtStatus = STATUS_DATA_ERROR; } } } if (NT_SUCCESS(NtStatus)) { struct netmap_priv_d *priv = irpSp->FileObject->FsContext; if (priv == NULL) { NtStatus = STATUS_DEVICE_DATA_ERROR; goto done; } ret = netmap_ioctl(priv, irpSp->Parameters.DeviceIoControl.IoControlCode, (caddr_t)&arg, NULL); if (NT_SUCCESS(ret)) { if (data && !NT_SUCCESS(copy_to_user((void*)data, &arg, argsize, Irp))) { DbgPrint("Netmap.sys: ioctl failure/cannot copy data to user"); NtStatus = STATUS_DATA_ERROR; } } else { DbgPrint("Netmap.sys: ioctl failure (%i)", ret); NtStatus = STATUS_BAD_DATA; } } done: Irp->IoStatus.Status = NtStatus; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return NtStatus; }
/** ----------------------------------------------------------------------- \brief debug message output routine \param IN Level Debug Level (DBG_ERR, DBG_INFO, etc..) IN Format Debug Message Format \return NONE \code \endcode -------------------------------------------------------------------------*/ VOID DrvDebugPrint(IN DWORD Level, IN const char* Function,IN const char* Format, IN ...) { CHAR ProcName[NT_PROCNAMELEN]={0}; ULONG i=0; va_list vaList; va_start(vaList, Format); // check mask for debug area and debug level // if (Level <= g_DebugLevel) { // find a free buffer // for (i = 0; i < NUMBER_DEBUG_BUFFERS; ++i) { if (InterlockedCompareExchange((LONG*)&g_DebugBufferBusy[i], 1, 0) == 0) { __try { if (TRUE != NT_SUCCESS( RtlStringCbVPrintfA( g_DebugBuffer[i], sizeof(g_DebugBuffer[i]), Format, vaList ))) { return; } } __except(EXCEPTION_EXECUTE_HANDLER) { return; } get_process_name(PsGetCurrentProcess(), ProcName); if (DPFLTR_ERROR_LEVEL == Level) { DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, DRIVERNAME"(IRQL %2.2d): %-16s(%04u:%04u) : [ERR ] %s(), %s\n", KeGetCurrentIrql(), ProcName, PsGetCurrentProcessId(), PsGetCurrentThreadId(), Function, g_DebugBuffer[i] ); } else if (DPFLTR_WARNING_LEVEL == Level) { DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL | DPFLTR_MASK, DRIVERNAME"(IRQL %2.2d): %-16s(%04u:%04u) : [WARN] %s(), %s\n", KeGetCurrentIrql(), ProcName, PsGetCurrentProcessId(), PsGetCurrentThreadId(), Function, g_DebugBuffer[i] ); } //else if (DPFLTR_TRACE_LEVEL == Level) //{ // DbgPrintEx( // DPFLTR_IHVDRIVER_ID, // DPFLTR_TRACE_LEVEL | DPFLTR_MASK, // DRIVERNAME"(IRQL %2.2d): [TRCE] %s(), %s\n", // KeGetCurrentIrql(), // Function, // g_DebugBuffer[i] // ); //} else { DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL | DPFLTR_MASK, DRIVERNAME"(IRQL %2.2d): %-16s(%04u:%04u) : [INFO] %s(), %s\n", KeGetCurrentIrql(), ProcName, PsGetCurrentProcessId(), PsGetCurrentThreadId(), Function, g_DebugBuffer[i] ); } InterlockedExchange((LONG*)&g_DebugBufferBusy[i], 0); break; } } }
EXTERN_C NTSTATUS WinXDisablePatchGuard( __in const WinXSymbols& Symbols) { // Based on the size of FsRtlMdlReadCompleteDevEx on each platform static const SIZE_T MIN_SIZE_FILTER_XP = 0x2000; static const SIZE_T MIN_SIZE_FILTER = 0x4000; g_WinXSymbols = Symbols; auto exclusivity = std::experimental::unique_resource( ExclGainExclusivity(), ExclReleaseExclusivity); if (!exclusivity) { return STATUS_UNSUCCESSFUL; } // Collects all PatchGuard contexts PatchGuardContexts contexts = {}; if (Symbols.PoolBigPageTableXp) { // For XP WinXpEnumBigPages(WinXpCollectPatchGuardContexts, &contexts, 0, MIN_SIZE_FILTER_XP, *g_WinXSymbols.PoolBigPageTableXp, *g_WinXSymbols.PoolBigPageTableSize); } else { // For 7 and Vista WinXpEnumBigPages(WinXpCollectPatchGuardContexts, &contexts, 0, MIN_SIZE_FILTER, *g_WinXSymbols.PoolBigPageTable, *g_WinXSymbols.PoolBigPageTableSize); } //DBG_BREAK(); DBG_PRINT("[%5Iu:%5Iu] Initialize : %Iu contexts found.\n", reinterpret_cast<ULONG_PTR>(PsGetCurrentProcessId()), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), contexts.NumberOfPgContexts); auto status = STATUS_SUCCESS; if (!contexts.NumberOfPgContexts || contexts.NumberOfPgContexts == contexts.MAX_SUPPORTED_NUMBER_OF_PG_CONTEXTS) { // If a lot of PatchGuard contexts were found, it is likely an error status = STATUS_UNSUCCESSFUL; } else { // Install patches for all contexts for (SIZE_T i = 0; i < contexts.NumberOfPgContexts; ++i) { WinXpInstallPatchOnPatchGuardContext(contexts.PgContexts[i]); } } return status; }