BOOLEAN NTAPI RtlDebugDestroyHeap(HANDLE HeapPtr) { SIZE_T Size = 0; PHEAP Heap = (PHEAP)HeapPtr; if (Heap == RtlGetCurrentPeb()->ProcessHeap) { DPRINT1("HEAP: It's forbidden delete process heap!"); return FALSE; } if (Heap->Signature != HEAP_SIGNATURE) { DPRINT1("HEAP: Invalid heap %p signature 0x%x\n", Heap, Heap->Signature); return FALSE; } if (!RtlpValidateHeap(Heap, FALSE)) return FALSE; /* Make heap invalid by zeroing its signature */ Heap->Signature = 0; /* Free validate headers copy if it was existing */ if (Heap->HeaderValidateCopy) { ZwFreeVirtualMemory(NtCurrentProcess(), &Heap->HeaderValidateCopy, &Size, MEM_RELEASE); } return TRUE; }
/* Usermode only! */ VOID NTAPI RtlpAddHeapToProcessList(PHEAP Heap) { PPEB Peb; /* Get PEB */ Peb = RtlGetCurrentPeb(); /* Acquire the lock */ RtlEnterCriticalSection(&RtlpProcessHeapsListLock); //_SEH2_TRY { /* Check if max number of heaps reached */ if (Peb->NumberOfHeaps == Peb->MaximumNumberOfHeaps) { // TODO: Handle this case ASSERT(FALSE); } /* Add the heap to the process heaps */ Peb->ProcessHeaps[Peb->NumberOfHeaps] = Heap; Peb->NumberOfHeaps++; Heap->ProcessHeapsListIndex = (USHORT)Peb->NumberOfHeaps; // } _SEH2_FINALLY { /* Release the lock */ RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); // } _SEH2_END }
/* * SfuQueryEnvironmentVariableOffset * * Purpose: * * Return offset to the given environment variable. * */ LPWSTR SfuQueryEnvironmentVariableOffset( PUNICODE_STRING Value ) { UNICODE_STRING str1; PWCHAR EnvironmentBlock, ptr; EnvironmentBlock = RtlGetCurrentPeb()->ProcessParameters->Environment; ptr = EnvironmentBlock; do { if (*ptr == 0) return 0; RtlSecureZeroMemory(&str1, sizeof(str1)); RtlInitUnicodeString(&str1, ptr); if (RtlPrefixUnicodeString(Value, &str1, TRUE)) break; ptr += _strlen(ptr) + 1; } while (1); return (ptr + Value->Length / sizeof(WCHAR)); }
/* Usermode only! */ VOID NTAPI RtlpRemoveHeapFromProcessList(PHEAP Heap) { PPEB Peb; PHEAP *Current, *Next; ULONG Count; /* Get PEB */ Peb = RtlGetCurrentPeb(); /* Acquire the lock */ RtlEnterCriticalSection(&RtlpProcessHeapsListLock); /* Check if we don't need anything to do */ if ((Heap->ProcessHeapsListIndex == 0) || (Heap->ProcessHeapsListIndex > Peb->NumberOfHeaps) || (Peb->NumberOfHeaps == 0)) { /* Release the lock */ RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); return; } /* The process actually has more than one heap. Use classic, lernt from university times algorithm for removing an entry from a static array */ Current = (PHEAP *)&Peb->ProcessHeaps[Heap->ProcessHeapsListIndex - 1]; Next = Current + 1; /* How many items we need to shift to the left */ Count = Peb->NumberOfHeaps - (Heap->ProcessHeapsListIndex - 1); /* Move them all in a loop */ while (--Count) { /* Copy it and advance next pointer */ *Current = *Next; /* Update its index */ (*Current)->ProcessHeapsListIndex -= 1; /* Advance pointers */ Current++; Next++; } /* Decrease total number of heaps */ Peb->NumberOfHeaps--; /* Zero last unused item */ Peb->ProcessHeaps[Peb->NumberOfHeaps] = NULL; Heap->ProcessHeapsListIndex = 0; /* Release the lock */ RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); }
BOOL kull_m_process_peb(PKULL_M_MEMORY_HANDLE memory, PPEB pPeb, BOOL isWOW) { BOOL status = FALSE; PROCESS_BASIC_INFORMATION processInformations; HANDLE hProcess = (memory->type == KULL_M_MEMORY_TYPE_PROCESS) ? memory->pHandleProcess->hProcess : GetCurrentProcess(); KULL_M_MEMORY_HANDLE hBuffer = {KULL_M_MEMORY_TYPE_OWN, NULL}; KULL_M_MEMORY_ADDRESS aBuffer = {pPeb, &hBuffer}; KULL_M_MEMORY_ADDRESS aProcess= {NULL, memory}; PROCESSINFOCLASS info; ULONG szPeb, szBuffer, szInfos; LPVOID buffer; #ifdef _M_X64 if(isWOW) { info = ProcessWow64Information; szBuffer = sizeof(processInformations.PebBaseAddress); buffer = &processInformations.PebBaseAddress; szPeb = sizeof(PEB_F32); } else { #endif info = ProcessBasicInformation; szBuffer = sizeof(processInformations); buffer = &processInformations; szPeb = sizeof(PEB); #ifdef _M_X64 } #endif switch(memory->type) { #ifndef MIMIKATZ_W2000_SUPPORT case KULL_M_MEMORY_TYPE_OWN: if(!isWOW) { *pPeb = *RtlGetCurrentPeb(); status = TRUE; break; } #endif case KULL_M_MEMORY_TYPE_PROCESS: if(NT_SUCCESS(NtQueryInformationProcess(hProcess, info, buffer, szBuffer, &szInfos)) && (szInfos == szBuffer) && processInformations.PebBaseAddress) { aProcess.address = processInformations.PebBaseAddress; status = kull_m_memory_copy(&aBuffer, &aProcess, szPeb); } break; } return status; }
VOID NTAPI RtlInitializeHeapManager(VOID) { PPEB Peb; /* Get PEB */ Peb = RtlGetCurrentPeb(); /* Initialize heap-related fields of PEB */ Peb->NumberOfHeaps = 0; /* Initialize the process heaps list protecting lock */ RtlInitializeCriticalSection(&RtlpProcessHeapsListLock); }
VOID NTAPI RtlpSetHeapParameters(IN PRTL_HEAP_PARAMETERS Parameters) { PPEB Peb; /* Get PEB */ Peb = RtlGetCurrentPeb(); /* Apply defaults for non-set parameters */ if (!Parameters->SegmentCommit) Parameters->SegmentCommit = Peb->HeapSegmentCommit; if (!Parameters->SegmentReserve) Parameters->SegmentReserve = Peb->HeapSegmentReserve; if (!Parameters->DeCommitFreeBlockThreshold) Parameters->DeCommitFreeBlockThreshold = Peb->HeapDeCommitFreeBlockThreshold; if (!Parameters->DeCommitTotalFreeThreshold) Parameters->DeCommitTotalFreeThreshold = Peb->HeapDeCommitTotalFreeThreshold; }
NTSYSAPI NTSTATUS STDAPIVCALLTYPE RtlSetThreadIsCritical( IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN CheckFlag ) { PPEB Peb; ULONG Enable; NTSTATUS Status; if ( ARGUMENT_PRESENT(OldValue) ) { *OldValue = FALSE; } Peb = RtlGetCurrentPeb(); if ( CheckFlag && ! (Peb->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS) ) { return STATUS_UNSUCCESSFUL; } if ( ARGUMENT_PRESENT(OldValue) ) { NtQueryInformationThread(NtCurrentThread(), ThreadBreakOnTermination, &Enable, sizeof(Enable), NULL); *OldValue = (BOOLEAN) Enable; } Enable = NewValue; Status = NtSetInformationThread(NtCurrentThread(), ThreadBreakOnTermination, &Enable, sizeof(Enable)); return Status; }
/* * SfuBuildBotPath * * Purpose: * * Return full path to bot in both variants. * */ BOOL SfuBuildBotPath( _Inout_ PZA_BOT_PATH Context ) { BOOL cond = FALSE, bResult = FALSE; OBJECT_ATTRIBUTES obja; UNICODE_STRING ustr1, ustr2; WCHAR szRegBuffer[MAX_PATH + 1]; HANDLE ProcessHeap; HANDLE hKey = NULL; NTSTATUS status; KEY_VALUE_PARTIAL_INFORMATION *pki = NULL; LPWSTR lpEnv; ULONG memIO = 0; LPWSTR lpLocalBotName, lpPFilesBotName; PVOID Wow64Information = NULL; GUID sfGUID; if (Context == NULL) return bResult; ProcessHeap = RtlGetCurrentPeb()->ProcessHeap; RtlSecureZeroMemory(&ustr1, sizeof(ustr1)); do { if (!SfInitMD5()) break; RtlSecureZeroMemory(&sfGUID, sizeof(sfGUID)); SfuCalcVolumeMD5((BYTE*)&sfGUID); status = NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information, &Wow64Information, sizeof(PVOID), NULL); if (!NT_SUCCESS(status)) break; //query current user registry string if (!NT_SUCCESS(RtlFormatCurrentUserKeyPath(&ustr1))) break; lpLocalBotName = Context->szBotPathLocal; lpPFilesBotName = Context->szBotPathPFiles; RtlSecureZeroMemory(&szRegBuffer, sizeof(szRegBuffer)); wsprintf(szRegBuffer, T_SHELL_FOLDERS_KEY, ustr1.Buffer); RtlFreeUnicodeString(&ustr1); //open User Shell Folders key to query Local AppData value RtlSecureZeroMemory(&ustr2, sizeof(ustr2)); RtlInitUnicodeString(&ustr2, szRegBuffer); InitializeObjectAttributes(&obja, &ustr2, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtOpenKey(&hKey, KEY_READ, &obja); if (!NT_SUCCESS(status)) break; //query value size RtlInitUnicodeString(&ustr2, T_LOCAL_APPDATA_VALUE); NtQueryValueKey(hKey, &ustr2, KeyValuePartialInformation, NULL, 0, &memIO); if (memIO == 0) break; pki = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, memIO); if (pki == NULL) break; //query value status = NtQueryValueKey(hKey, &ustr2, KeyValuePartialInformation, pki, memIO, &memIO); if (!NT_SUCCESS(status)) break; RtlInitUnicodeString(&ustr2, (WCHAR*)pki->Data); memIO = 0; //expand environment variable inside value RtlSecureZeroMemory(&szRegBuffer, sizeof(szRegBuffer)); ustr1.Buffer = szRegBuffer; ustr1.Length = 0; ustr1.MaximumLength = sizeof(szRegBuffer); status = RtlExpandEnvironmentStrings_U(NULL, &ustr2, &ustr1, &memIO); if (!NT_SUCCESS(status)) { ustr1.Buffer = NULL; break; } //build result string _strcpy(lpLocalBotName, T_GLOBAL_LINK); _strcat(lpLocalBotName, szRegBuffer); wsprintf(_strend(lpLocalBotName), T_SIREFEF_DIRECTORY, sfGUID.Data1, sfGUID.Data2, sfGUID.Data3, sfGUID.Data4[0], sfGUID.Data4[1], sfGUID.Data4[2], sfGUID.Data4[3], sfGUID.Data4[4], sfGUID.Data4[5], sfGUID.Data4[6], sfGUID.Data4[7]); ustr1.Buffer = NULL; _strcpy(lpPFilesBotName, T_GLOBAL_LINK); if (Wow64Information == NULL) { lpEnv = L"ProgramFiles="; } else { lpEnv = L"ProgramFiles(x86)="; } RtlInitUnicodeString(&ustr2, lpEnv); lpEnv = SfuQueryEnvironmentVariableOffset(&ustr2); if (lpEnv) { _strcat(lpPFilesBotName, lpEnv); wsprintf(_strend(lpPFilesBotName), T_SIREFEF_DIRECTORY, sfGUID.Data1, sfGUID.Data2, sfGUID.Data3, sfGUID.Data4[0], sfGUID.Data4[1], sfGUID.Data4[2], sfGUID.Data4[3], sfGUID.Data4[4], sfGUID.Data4[5], sfGUID.Data4[6], sfGUID.Data4[7]); } bResult = TRUE; } while (cond); if (hKey != NULL) { NtClose(hKey); } if (ustr1.Buffer != NULL) { RtlFreeUnicodeString(&ustr1); } if (pki != NULL) { RtlFreeHeap(ProcessHeap, 0, pki); } return bResult; }
/* * @implemented */ NTSTATUS NTAPI RtlQueryEnvironmentVariable_U(PWSTR Environment, PUNICODE_STRING Name, PUNICODE_STRING Value) { NTSTATUS Status; PWSTR wcs; UNICODE_STRING var; PWSTR val; BOOLEAN SysEnvUsed = FALSE; DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n", Environment, Name, Value); if (Environment == NULL) { PPEB Peb = RtlGetCurrentPeb(); if (Peb) { Environment = Peb->ProcessParameters->Environment; SysEnvUsed = TRUE; } } if (Environment == NULL) { return(STATUS_VARIABLE_NOT_FOUND); } Value->Length = 0; if (SysEnvUsed) RtlAcquirePebLock(); wcs = Environment; DPRINT("Starting search at :%p\n", wcs); while (*wcs) { var.Buffer = wcs++; wcs = wcschr(wcs, L'='); if (wcs == NULL) { wcs = var.Buffer + wcslen(var.Buffer); DPRINT("Search at :%S\n", wcs); } if (*wcs) { var.Length = var.MaximumLength = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR); val = ++wcs; wcs += wcslen(wcs); DPRINT("Search at :%S\n", wcs); if (RtlEqualUnicodeString(&var, Name, TRUE)) { Value->Length = (USHORT)(wcs - val) * sizeof(WCHAR); if (Value->Length <= Value->MaximumLength) { memcpy(Value->Buffer, val, min(Value->Length + sizeof(WCHAR), Value->MaximumLength)); DPRINT("Value %S\n", val); DPRINT("Return STATUS_SUCCESS\n"); Status = STATUS_SUCCESS; } else { DPRINT("Return STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; } if (SysEnvUsed) RtlReleasePebLock(); return(Status); } } wcs++; } if (SysEnvUsed) RtlReleasePebLock(); DPRINT("Return STATUS_VARIABLE_NOT_FOUND: %wZ\n", Name); return(STATUS_VARIABLE_NOT_FOUND); }