pid_t fork(void) { NTSTATUS nErrCode; CONTEXT ctxThreadContext; HANDLE hProcess; HANDLE hThread; INITIAL_TEB itInitialTeb; CLIENT_ID ciClientId; MEMORY_BASIC_INFORMATION mbiStackInfo; THREAD_BASIC_INFORMATION tbiThreadInfo; struct __tagcsrmsg{ PORT_MESSAGE PortMessage; struct CSRSS_MESSAGE CsrssMessage; PROCESS_INFORMATION ProcessInformation; CLIENT_ID Debugger; ULONG CreationFlags; ULONG VdmInfo[2]; } csrmsg; /* STEP 1: Duplicate current process */ nErrCode = NtCreateProcess ( &hProcess, PROCESS_ALL_ACCESS, NULL, NtCurrentProcess(), TRUE, 0, 0, 0 ); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtCreateProcess() failed with status 0x%08X\n", nErrCode); goto fail; } /* STEP 2: Duplicate current thread */ /* 2.1: duplicate registers */ ctxThreadContext.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_FLOATING_POINT; /* get the current thread's registers */ nErrCode = NtGetContextThread(NtCurrentThread(), &ctxThreadContext); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtGetContextThread() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } /* redirect the child process to the child_branch label (see 4.3 below) */ ctxThreadContext.Eip = (ULONG)&&child_branch; /* 2.2: duplicate stack */ /* get stack base and size */ nErrCode = NtQueryVirtualMemory ( NtCurrentProcess(), (PVOID)ctxThreadContext.Esp, MemoryBasicInformation, &mbiStackInfo, sizeof(mbiStackInfo), 0 ); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtQueryVirtualMemory() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } itInitialTeb.StackCommit = 0; itInitialTeb.StackReserve = 0; itInitialTeb.StackBase = (PVOID)((ULONG)(mbiStackInfo.BaseAddress) + mbiStackInfo.RegionSize); itInitialTeb.StackLimit = mbiStackInfo.BaseAddress; itInitialTeb.StackAllocate = mbiStackInfo.AllocationBase; /* 2.3: create duplicate thread */ nErrCode = NtCreateThread ( &hThread, THREAD_ALL_ACCESS, NULL, hProcess, (CLIENT_ID *)&ciClientId, &ctxThreadContext, &itInitialTeb, TRUE ); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtCreateThread() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } /* 2.4: duplicate the TEB */ /* store the client id in the child thread's stack (see 4.3b) */ nErrCode = NtWriteVirtualMemory ( hProcess, &ciClientId, &ciClientId, sizeof(ciClientId), 0 ); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } /* get the child thread's TEB base */ nErrCode = NtQueryInformationThread ( hThread, ThreadBasicInformation, &tbiThreadInfo, sizeof(tbiThreadInfo), 0 ); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtQueryInformationThread() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } /* copy the TEB */ nErrCode = NtWriteVirtualMemory ( hProcess, tbiThreadInfo.TebBaseAddress, NtCurrentTeb(), sizeof(TEB), 0 ); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } /* STEP 3: Call Win32 subsystem */ memset(&csrmsg, 0, sizeof(csrmsg)); csrmsg.ProcessInformation.hProcess = hProcess; csrmsg.ProcessInformation.hThread = hThread; csrmsg.ProcessInformation.dwProcessId = (DWORD)ciClientId.UniqueProcess; csrmsg.ProcessInformation.dwThreadId = (DWORD)ciClientId.UniqueThread; nErrCode = CsrClientCallServer(&csrmsg, 0, 0x10000, 0x24); /* failure */ if(!NT_SUCCESS(nErrCode)) { ERR("CsrClientCallServer() failed with status 0x%08X\n", nErrCode); goto cleanup_and_fail; } /* STEP 4: Finalization */ /* 4.1: resume thread */ nErrCode = NtResumeThread(hThread, 0); /* 4.2: close superfluous handles */ NtClose(hProcess); NtClose(hThread); /* 4.3: (parent) return the child process id */ return ((pid_t)(ciClientId.UniqueProcess)); /* 4.3b: (child) cleanup and return 0 */ child_branch: /* restore the thread and process id in the TEB */ memcpy(&NtCurrentTeb()->Cid, &ciClientId, sizeof(ciClientId)); /* return 0 */ return (0); cleanup_and_fail: NtTerminateProcess(hProcess, nErrCode); fail: errno = __status_to_errno(nErrCode); return (-1); }
LONG WINAPI BasepCheckForReadOnlyResource(IN PVOID Ptr) { PVOID Data; ULONG Size, OldProtect; SIZE_T Size2; MEMORY_BASIC_INFORMATION mbi; NTSTATUS Status; LONG Ret = EXCEPTION_CONTINUE_SEARCH; /* Check if it was an attempt to write to a read-only image section! */ Status = NtQueryVirtualMemory(NtCurrentProcess(), Ptr, MemoryBasicInformation, &mbi, sizeof(mbi), NULL); if (NT_SUCCESS(Status) && mbi.Protect == PAGE_READONLY && mbi.Type == MEM_IMAGE) { /* Attempt to treat it as a resource section. We need to use SEH here because we don't know if it's actually a resource mapping */ _SEH2_TRY { Data = RtlImageDirectoryEntryToData(mbi.AllocationBase, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &Size); if (Data != NULL && (ULONG_PTR)Ptr >= (ULONG_PTR)Data && (ULONG_PTR)Ptr < (ULONG_PTR)Data + Size) { /* The user tried to write into the resources. Make the page writable... */ Size2 = 1; Status = NtProtectVirtualMemory(NtCurrentProcess(), &Ptr, &Size2, PAGE_READWRITE, &OldProtect); if (NT_SUCCESS(Status)) { Ret = EXCEPTION_CONTINUE_EXECUTION; } } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { } _SEH2_END; }
UINT_PTR SectionRelayBuffer::RegisterSection(UINT_PTR section) { UINT_PTR i; UINT_PTR base=(UINT_PTR)(section)>>31; for (i=0;i<section_count;i++) if (record[i].section_register==base) break; if (i<section_count) { record[i].section_referenced++; return record[i].section_relay_buffer; } UINT_PTR addr=(base<<31)+0x40000000; UINT_PTR size=0x1000,len; LPVOID allocate; MEMORY_BASIC_INFORMATION info; allocate=(LPVOID)addr; for (;;) { allocate=(LPVOID)addr; NtQueryVirtualMemory(NtCurrentProcess(),allocate, MemoryBasicInformation,&info,sizeof(info),&len); if ((info.State&MEM_FREE)) if ((UINT_PTR)info.BaseAddress+info.RegionSize-addr>=0x1000) break; addr=(UINT_PTR)info.BaseAddress-0x1000; } NtAllocateVirtualMemory(NtCurrentProcess(),&allocate, 0,&size,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); addr=(UINT_PTR)allocate; record[section_count].section_register=section>>31; record[section_count].section_relay_buffer=addr; record[section_count].section_referenced=1; section_count++; return addr; }
BOOL PsGetImageFileNameEx(HANDLE ProcessHandle, LPVOID ModuleBase, LPWSTR FileName, SIZE_T Length, PSIZE_T ReturnLength) { NTSTATUS status = STATUS_UNSUCCESSFUL; PNT_UNICODE_STRING unicodeString; SIZE_T bufferSize; LPVOID buffer; SIZE_T retLength; bufferSize = 0x100; do { buffer = AllocMem(bufferSize); if (!buffer) { break; } status = NtQueryVirtualMemory(ProcessHandle, ModuleBase, NT_MEMORY_INFORMATION_CLASS::MemoryMappedFilenameInformation, buffer, bufferSize, &retLength); if (status == STATUS_BUFFER_OVERFLOW) { DeallocMem(buffer); bufferSize = retLength; } else { break; } } while (TRUE); if (buffer) { unicodeString = (PNT_UNICODE_STRING)buffer; wcscpy_s(FileName, Length, unicodeString->Buffer); *ReturnLength = unicodeString->MaximumLength; DeallocMem(buffer); return STATUS_UNSUCCESSFUL; } return status; }
/*********************************************************************** * VirtualQueryEx (KERNEL32.@) * * Provides info about a range of pages in virtual address space of a * specified process. * * PARAMS * process [I] Handle to process. * addr [I] Address of region. * info [O] Address of info buffer. * len [I] Size of buffer. * * RETURNS * Number of bytes returned in information buffer. */ SIZE_T WINAPI VirtualQueryEx( HANDLE process, LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len ) { SIZE_T ret; NTSTATUS status; if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret ))) { SetLastError( RtlNtStatusToDosError(status) ); ret = 0; } return ret; }
static NTSTATUS NTAPI TerminatorM2( _In_ HANDLE ProcessId ) { NTSTATUS status; HANDLE processHandle; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION, ProcessId ))) { PVOID baseAddress; MEMORY_BASIC_INFORMATION basicInfo; ULONG oldProtect; baseAddress = (PVOID)0; while (NT_SUCCESS(NtQueryVirtualMemory( processHandle, baseAddress, MemoryBasicInformation, &basicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL ))) { SIZE_T regionSize; regionSize = basicInfo.RegionSize; NtProtectVirtualMemory( processHandle, &basicInfo.BaseAddress, ®ionSize, PAGE_NOACCESS, &oldProtect ); baseAddress = PTR_ADD_OFFSET(baseAddress, basicInfo.RegionSize); } NtClose(processHandle); } return status; }
NTSTATUS WINAPI SafeNtQueryVirtualMemory( HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID Buffer, ULONG Length, PULONG ResultLength ) { NTSTATUS rc; /*if (CheckOldFunction(&OldNtQueryVirtualMemory)) rc=OldNtQueryVirtualMemory(ProcessHandle,BaseAddress,MemoryInformationClass,Buffer,Length,ResultLength); else*/ rc=NtQueryVirtualMemory(ProcessHandle,BaseAddress,MemoryInformationClass,Buffer,Length,ResultLength); return rc; }
NTSTATUS validatePePointer(PVOID pImageBase, PVOID pArbitraryPtr, ULONGLONG accessLength, BOOLEAN isNewImage){ UNREFERENCED_PARAMETER(accessLength); MEMORY_BASIC_VLM_INFORMATION vlmImageInfo; ULONGLONG returnLen = 0; NTSTATUS status = 0; static ULONGLONG peSize = 0; if (!peSize || isNewImage){ status = NtQueryVirtualMemory(INVALID_HANDLE_VALUE, pImageBase, MemoryBasicVlmInformation, &vlmImageInfo, sizeof(MEMORY_BASIC_VLM_INFORMATION), &returnLen); if (status) return status; peSize = vlmImageInfo.SizeOfImage; } ///The viability of this pointer validation is based on three assumptions: ///1. Each mapped section of the image is at least readable (R) without guard (+G). ///2. There don't exist any free pages between two sections of the same image. if ((pImageBase < ALIGN_DOWN_POINTER(pArbitraryPtr, PVOID)) && (((PUCHAR)ALIGN_UP_POINTER(pArbitraryPtr, PVOID) + accessLength) < ((PUCHAR)pImageBase + peSize))) return STATUS_SUCCESS; return STATUS_INVALID_ADDRESS; }
/****************************************************************************** * RtlCreateEnvironment [NTDLL.@] */ NTSTATUS WINAPI RtlCreateEnvironment(BOOLEAN inherit, PWSTR* env) { NTSTATUS nts; TRACE("(%u,%p)!\n", inherit, env); if (inherit) { MEMORY_BASIC_INFORMATION mbi; RtlAcquirePebLock(); nts = NtQueryVirtualMemory(NtCurrentProcess(), NtCurrentTeb()->Peb->ProcessParameters->Environment, 0, &mbi, sizeof(mbi), NULL); if (nts == STATUS_SUCCESS) { *env = NULL; nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)env, 0, &mbi.RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (nts == STATUS_SUCCESS) memcpy(*env, NtCurrentTeb()->Peb->ProcessParameters->Environment, mbi.RegionSize); else *env = NULL; } RtlReleasePebLock(); } else { SIZE_T size = 1; PVOID addr = NULL; nts = NtAllocateVirtualMemory(NtCurrentProcess(), &addr, 0, &size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (nts == STATUS_SUCCESS) *env = addr; } return nts; }
INT_PTR CALLBACK PhpMemoryResultsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_RESULTS_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_RESULTS_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhRegisterDialog(hwndDlg); { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"Results - %s (%u)", processItem->ProcessName->Buffer, HandleToUlong(processItem->ProcessId))->Buffer); PhDereferenceObject(processItem); } } lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(lvHandle, FALSE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 120, L"Address"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"Length"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Result"); PhLoadListViewColumnsFromSetting(L"MemResultsListViewColumns", lvHandle); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_COPY), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 250; rect.bottom = 180; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } ListView_SetItemCount(lvHandle, context->Results->Count); SetDlgItemText(hwndDlg, IDC_INTRO, PhaFormatString(L"%s results.", PhaFormatUInt64(context->Results->Count, TRUE)->Buffer)->Buffer); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemResultsPosition"); windowRectangle.Size = PhGetIntegerPairSetting(L"MemResultsSize"); PhAdjustRectangleToWorkingArea(hwndDlg, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemResultsPosition", windowRectangle.Position); PhSetIntegerPairSetting(L"MemResultsSize", windowRectangle.Size); } } break; case WM_DESTROY: { PhSaveWindowPlacementToSetting(L"MemResultsPosition", L"MemResultsSize", hwndDlg); PhSaveListViewColumnsToSetting(L"MemResultsListViewColumns", GetDlgItem(hwndDlg, IDC_LIST)); PhDeleteLayoutManager(&context->LayoutManager); PhUnregisterDialog(hwndDlg); RemoveProp(hwndDlg, PhMakeContextAtom()); PhDereferenceMemoryResults((PPH_MEMORY_RESULT *)context->Results->Items, context->Results->Count); PhDereferenceObject(context->Results); PhFree(context); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_COPY: { HWND lvHandle; PPH_STRING string; ULONG selectedCount; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); selectedCount = ListView_GetSelectedCount(lvHandle); if (selectedCount == 0) { // User didn't select anything, so copy all items. string = PhpGetStringForSelectedResults(lvHandle, context->Results, TRUE); PhSetStateAllListViewItems(lvHandle, LVIS_SELECTED, LVIS_SELECTED); } else { string = PhpGetStringForSelectedResults(lvHandle, context->Results, FALSE); } PhSetClipboardString(hwndDlg, &string->sr); PhDereferenceObject(string); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)lvHandle, TRUE); } break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Text files (*.txt)", L"*.txt" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, L"Search Results.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; PPH_STRING string; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PhWriteStringAsUtf8FileStream(fileStream, &PhUnicodeByteOrderMark); PhWritePhTextHeader(fileStream); string = PhpGetStringForSelectedResults(GetDlgItem(hwndDlg, IDC_LIST), context->Results, TRUE); PhWriteStringAsUtf8FileStreamEx(fileStream, string->Buffer, string->Length); PhDereferenceObject(string); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_FILTER: { PPH_EMENU menu; RECT buttonRect; POINT point; PPH_EMENU_ITEM selectedItem; ULONG filterType = 0; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_MEMFILTER), 0); GetClientRect(GetDlgItem(hwndDlg, IDC_FILTER), &buttonRect); point.x = 0; point.y = buttonRect.bottom; ClientToScreen(GetDlgItem(hwndDlg, IDC_FILTER), &point); selectedItem = PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y); if (selectedItem) { switch (selectedItem->Id) { case ID_FILTER_CONTAINS: filterType = FILTER_CONTAINS; break; case ID_FILTER_CONTAINS_CASEINSENSITIVE: filterType = FILTER_CONTAINS_IGNORECASE; break; case ID_FILTER_REGEX: filterType = FILTER_REGEX; break; case ID_FILTER_REGEX_CASEINSENSITIVE: filterType = FILTER_REGEX_IGNORECASE; break; } } if (filterType != 0) FilterResults(hwndDlg, context, filterType); PhDestroyEMenu(menu); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; HWND lvHandle; lvHandle = GetDlgItem(hwndDlg, IDC_LIST); PhHandleListViewNotifyForCopy(lParam, lvHandle); switch (header->code) { case LVN_GETDISPINFO: { NMLVDISPINFO *dispInfo = (NMLVDISPINFO *)header; if (dispInfo->item.mask & LVIF_TEXT) { PPH_MEMORY_RESULT result = context->Results->Items[dispInfo->item.iItem]; switch (dispInfo->item.iSubItem) { case 0: { WCHAR addressString[PH_PTR_STR_LEN_1]; PhPrintPointer(addressString, result->Address); wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, addressString, _TRUNCATE ); } break; case 1: { WCHAR lengthString[PH_INT32_STR_LEN_1]; PhPrintUInt32(lengthString, (ULONG)result->Length); wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, lengthString, _TRUNCATE ); } break; case 2: wcsncpy_s( dispInfo->item.pszText, dispInfo->item.cchTextMax, result->Display.Buffer, _TRUNCATE ); break; } } } break; case NM_DBLCLK: { if (header->hwndFrom == lvHandle) { INT index; if ((index = ListView_GetNextItem( lvHandle, -1, LVNI_SELECTED )) != -1) { NTSTATUS status; PPH_MEMORY_RESULT result = context->Results->Items[index]; HANDLE processHandle; MEMORY_BASIC_INFORMATION basicInfo; PPH_SHOWMEMORYEDITOR showMemoryEditor; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, context->ProcessId ))) { if (NT_SUCCESS(status = NtQueryVirtualMemory( processHandle, result->Address, MemoryBasicInformation, &basicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL ))) { showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = context->ProcessId; showMemoryEditor->BaseAddress = basicInfo.BaseAddress; showMemoryEditor->RegionSize = basicInfo.RegionSize; showMemoryEditor->SelectOffset = (ULONG)((ULONG_PTR)result->Address - (ULONG_PTR)basicInfo.BaseAddress); showMemoryEditor->SelectLength = (ULONG)result->Length; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } NtClose(processHandle); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to edit memory", status, 0); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; } return FALSE; }
static void tstQueryVirtualMemory(void) { RTTestISub("NtQueryVirtualMemory"); uintptr_t cbAdvance = 0; uintptr_t uPtrWhere = 0; for (;;) { SIZE_T cbActual = 0; MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 }; NTSTATUS rcNt = NtQueryVirtualMemory(g_hProcess, (void const *)uPtrWhere, MemoryBasicInformation, &MemInfo, sizeof(MemInfo), &cbActual); if (!NT_SUCCESS(rcNt)) { RTTestIPrintf(RTTESTLVL_ALWAYS, "%p: rcNt=%#x\n", uPtrWhere, rcNt); break; } /* stringify the memory state. */ char szMemType[1024]; char szMemState[1024]; char szMemProt[1024]; char szAllocProt[1024]; if ( MemInfo.AllocationBase != NULL && MemInfo.AllocationBase == MemInfo.BaseAddress && MemInfo.Protect != MemInfo.AllocationProtect) RTTestIPrintf(RTTESTLVL_ALWAYS, "\n"); RTTestIPrintf(RTTESTLVL_ALWAYS, "%p-%p %-8s %-8s %-12s", MemInfo.BaseAddress, (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize - 1, stringifyMemType(MemInfo.Type, szMemType, sizeof(szMemType)), stringifyMemState(MemInfo.State, szMemState, sizeof(szMemState)), stringifyMemProt(MemInfo.Protect, szMemProt, sizeof(szMemProt)) ); if ((uintptr_t)MemInfo.AllocationBase != 0) { if (MemInfo.AllocationBase != MemInfo.BaseAddress) RTTestIPrintf(RTTESTLVL_ALWAYS, " %p", MemInfo.AllocationBase); else RTTestIPrintf(RTTESTLVL_ALWAYS, " %s", stringifyMemProt(MemInfo.AllocationProtect, szAllocProt, sizeof(szAllocProt))); } RTTestIPrintf(RTTESTLVL_ALWAYS, "\n"); if ((uintptr_t)MemInfo.BaseAddress != uPtrWhere) RTTestIPrintf(RTTESTLVL_ALWAYS, " !Warning! Queried %p got BaseAddress=%p!\n", uPtrWhere, MemInfo.BaseAddress); /* Image or mapped, then try get a file name. */ if (MemInfo.Type == MEM_IMAGE || MemInfo.Type == MEM_MAPPED) { union { MEMORY_SECTION_NAME Core; WCHAR awcPadding[UNICODE_STRING_MAX_CHARS + (sizeof(UNICODE_STRING_MAX_CHARS) + 1) / sizeof(WCHAR)]; } uBuf; RT_ZERO(uBuf); uBuf.Core.SectionFileName.Length = UNICODE_STRING_MAX_CHARS * 2; uBuf.Core.SectionFileName.MaximumLength = UNICODE_STRING_MAX_CHARS * 2; uBuf.Core.SectionFileName.Buffer = &uBuf.Core.NameBuffer[0]; cbActual = 0; rcNt = NtQueryVirtualMemory(g_hProcess, (void const *)uPtrWhere, MemorySectionName, &uBuf, sizeof(uBuf), &cbActual); if (NT_SUCCESS(rcNt)) RTTestIPrintf(RTTESTLVL_ALWAYS, " %.*ls\n", uBuf.Core.SectionFileName.Length / 2, uBuf.Core.SectionFileName.Buffer); else { RTTestIPrintf(RTTESTLVL_ALWAYS, "%p: MemorySectionName - rcNt=%#x\n", uPtrWhere, rcNt); RTTESTI_CHECK(rcNt == STATUS_FILE_INVALID && MemInfo.Type == MEM_MAPPED); } } /* Advance. */ cbAdvance = MemInfo.RegionSize; //cbAdvance = 0; if (uPtrWhere + cbAdvance <= uPtrWhere) break; uPtrWhere += MemInfo.RegionSize; } }
/****************************************************************************** * RtlSetEnvironmentVariable [NTDLL.@] */ NTSTATUS WINAPI RtlSetEnvironmentVariable(PWSTR* penv, PUNICODE_STRING name, PUNICODE_STRING value) { INT len, old_size; LPWSTR p, env; NTSTATUS nts = STATUS_VARIABLE_NOT_FOUND; MEMORY_BASIC_INFORMATION mbi; TRACE("(%p, %s, %s)\n", penv, debugstr_us(name), debugstr_us(value)); if (!name || !name->Buffer || !name->Length) return STATUS_INVALID_PARAMETER_1; len = name->Length / sizeof(WCHAR); /* variable names can't contain a '=' except as a first character */ for (p = name->Buffer + 1; p < name->Buffer + len; p++) if (*p == '=') return STATUS_INVALID_PARAMETER; if (!penv) { RtlAcquirePebLock(); env = NtCurrentTeb()->Peb->ProcessParameters->Environment; } else env = *penv; /* compute current size of environment */ for (p = env; *p; p += strlenW(p) + 1); old_size = p + 1 - env; /* Find a place to insert the string */ for (p = env; *p; p += strlenW(p) + 1) { if (!strncmpiW(name->Buffer, p, len) && (p[len] == '=')) break; } if (!value && !*p) goto done; /* Value to remove doesn't exist */ /* Realloc the buffer */ len = value ? len + value->Length / sizeof(WCHAR) + 2 : 0; if (*p) len -= strlenW(p) + 1; /* The name already exists */ if (len < 0) { LPWSTR next = p + strlenW(p) + 1; /* We know there is a next one */ memmove(next + len, next, (old_size - (next - env)) * sizeof(WCHAR)); } nts = NtQueryVirtualMemory(NtCurrentProcess(), env, 0, &mbi, sizeof(mbi), NULL); if (nts != STATUS_SUCCESS) goto done; if ((old_size + len) * sizeof(WCHAR) > mbi.RegionSize) { LPWSTR new_env; SIZE_T new_size = (old_size + len) * sizeof(WCHAR); new_env = NULL; nts = NtAllocateVirtualMemory(NtCurrentProcess(), (void**)&new_env, 0, &new_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (nts != STATUS_SUCCESS) goto done; memmove(new_env, env, (p - env) * sizeof(WCHAR)); assert(len > 0); memmove(new_env + (p - env) + len, p, (old_size - (p - env)) * sizeof(WCHAR)); p = new_env + (p - env); RtlDestroyEnvironment(env); if (!penv) NtCurrentTeb()->Peb->ProcessParameters->Environment = new_env; else *penv = new_env; } else { if (len > 0) memmove(p + len, p, (old_size - (p - env)) * sizeof(WCHAR)); } /* Set the new string */ if (value) { memcpy( p, name->Buffer, name->Length ); p += name->Length / sizeof(WCHAR); *p++ = '='; memcpy( p, value->Buffer, value->Length ); p[value->Length / sizeof(WCHAR)] = 0; } done: if (!penv) RtlReleasePebLock(); return nts; }
/* * @implemented */ NTSTATUS NTAPI RtlSetEnvironmentVariable(PWSTR *Environment, PUNICODE_STRING Name, PUNICODE_STRING Value) { MEMORY_BASIC_INFORMATION mbi; UNICODE_STRING var; size_t hole_len, new_len, env_len = 0; WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0; PWSTR head = NULL; SIZE_T size = 0, new_size; LONG f = 1; NTSTATUS Status = STATUS_SUCCESS; DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n", Environment, Name, Value); /* Variable name must not be empty */ if (Name->Length < sizeof(WCHAR)) return STATUS_INVALID_PARAMETER; /* Variable names can't contain a '=' except as a first character. */ for (wcs = Name->Buffer + 1; wcs < Name->Buffer + (Name->Length / sizeof(WCHAR)); wcs++) { if (*wcs == L'=') return STATUS_INVALID_PARAMETER; } if (Environment) { env = *Environment; } else { RtlAcquirePebLock(); env = NtCurrentPeb()->ProcessParameters->Environment; } if (env) { /* get environment length */ wcs = env_end = env; do { env_end += wcslen(env_end) + 1; } while (*env_end); env_end++; env_len = env_end - env; DPRINT("environment length %lu characters\n", env_len); /* find where to insert */ while (*wcs) { var.Buffer = wcs++; wcs = wcschr(wcs, L'='); if (wcs == NULL) { wcs = var.Buffer + wcslen(var.Buffer); } if (*wcs) { var.Length = (USHORT)(wcs - var.Buffer) * sizeof(WCHAR); var.MaximumLength = var.Length; val = ++wcs; wcs += wcslen(wcs); f = RtlCompareUnicodeString(&var, Name, TRUE); if (f >= 0) { if (f) /* Insert before found */ { hole = tail = var.Buffer; } else /* Exact match */ { head = var.Buffer; tail = ++wcs; hole = val; } goto found; } } wcs++; } hole = tail = wcs; /* Append to environment */ } found: if (Value != NULL && Value->Buffer != NULL) { hole_len = tail - hole; /* calculate new environment size */ new_size = Value->Length + sizeof(WCHAR); /* adding new variable */ if (f) new_size += Name->Length + sizeof(WCHAR); new_len = new_size / sizeof(WCHAR); if (hole_len < new_len) { /* enlarge environment size */ /* check the size of available memory */ new_size += (env_len - hole_len) * sizeof(WCHAR); new_size = ROUND_UP(new_size, PAGE_SIZE); mbi.RegionSize = 0; DPRINT("new_size %lu\n", new_size); if (env) { Status = NtQueryVirtualMemory(NtCurrentProcess(), env, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(Status)) { if (Environment == NULL) { RtlReleasePebLock(); } return(Status); } } if (new_size > mbi.RegionSize) { /* reallocate memory area */ Status = NtAllocateVirtualMemory(NtCurrentProcess(), (PVOID)&new_env, 0, &new_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { if (Environment == NULL) { RtlReleasePebLock(); } return(Status); } if (env) { memmove(new_env, env, (hole - env) * sizeof(WCHAR)); hole = new_env + (hole - env); } else { /* absolutely new environment */ tail = hole = new_env; *hole = 0; env_end = hole + 1; } } } /* move tail */ memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR)); if (new_env) { /* we reallocated environment, let's free the old one */ if (Environment) *Environment = new_env; else NtCurrentPeb()->ProcessParameters->Environment = new_env; if (env) { size = 0; NtFreeVirtualMemory(NtCurrentProcess(), (PVOID)&env, &size, MEM_RELEASE); } } /* and now copy given stuff */ if (f) { /* copy variable name and '=' character */ memmove(hole, Name->Buffer, Name->Length); hole += Name->Length / sizeof(WCHAR); *hole++ = L'='; } /* copy value */ memmove(hole, Value->Buffer, Value->Length); hole += Value->Length / sizeof(WCHAR); *hole = 0; } else { /* remove the environment variable */ if (f == 0) { memmove(head, tail, (env_end - tail) * sizeof(WCHAR)); } } if (Environment == NULL) { RtlReleasePebLock(); } return(Status); }
/* * @implemented */ NTSTATUS NTAPI RtlCreateEnvironment( BOOLEAN Inherit, PWSTR *OutEnvironment) { MEMORY_BASIC_INFORMATION MemInfo; PVOID CurrentEnvironment, NewEnvironment = NULL; NTSTATUS Status = STATUS_SUCCESS; SIZE_T RegionSize = PAGE_SIZE; /* Check if we should inherit the current environment */ if (Inherit) { /* In this case we need to lock the PEB */ RtlAcquirePebLock(); /* Get a pointer to the current Environment and check if it's not NULL */ CurrentEnvironment = NtCurrentPeb()->ProcessParameters->Environment; if (CurrentEnvironment != NULL) { /* Query the size of the current environment allocation */ Status = NtQueryVirtualMemory(NtCurrentProcess(), CurrentEnvironment, MemoryBasicInformation, &MemInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(Status)) { RtlReleasePebLock(); *OutEnvironment = NULL; return Status; } /* Allocate a new region of the same size */ RegionSize = MemInfo.RegionSize; Status = NtAllocateVirtualMemory(NtCurrentProcess(), &NewEnvironment, 0, &RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { RtlReleasePebLock(); *OutEnvironment = NULL; return Status; } /* Copy the current environment */ RtlCopyMemory(NewEnvironment, CurrentEnvironment, MemInfo.RegionSize); } /* We are done with the PEB, release the lock */ RtlReleasePebLock (); } /* Check if we still need an environment */ if (NewEnvironment == NULL) { /* Allocate a new environment */ Status = NtAllocateVirtualMemory(NtCurrentProcess(), &NewEnvironment, 0, &RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (NT_SUCCESS(Status)) { RtlZeroMemory(NewEnvironment, RegionSize); } } *OutEnvironment = NewEnvironment; return Status; }
VOID CaptureVaSpace( IN HANDLE Process ) { NTSTATUS Status; PVOID BaseAddress; PVAINFO VaInfo; PMODINFO Mod; BaseAddress = NULL; LastAllocationBase = NULL; InitializeListHead(&VaList); VaInfo = LocalAlloc(LMEM_ZEROINIT,sizeof(*VaInfo)); while ( (ULONG)BaseAddress < STOP_AT ) { Status = NtQueryVirtualMemory( Process, BaseAddress, MemoryBasicInformation, &VaInfo->BasicInfo, sizeof(VaInfo->BasicInfo), NULL ); if ( !NT_SUCCESS(Status) ) { LocalFree(VaInfo); return; } else { switch (VaInfo->BasicInfo.State ) { case MEM_COMMIT : if ( VaInfo->BasicInfo.Type == MEM_IMAGE ) { TotalModInfo.CommitVector[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize; Mod = LocateModInfo(BaseAddress); if ( Mod ) { Mod->CommitVector[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize; } } else { if ( VaInfo->BasicInfo.Type == MEM_MAPPED ) { MappedCommit[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize; } else { PrivateCommit[ProtectionToIndex(VaInfo->BasicInfo.Protect)] += VaInfo->BasicInfo.RegionSize; } } break; case MEM_RESERVE : if ( VaInfo->BasicInfo.Type == MEM_IMAGE ) { ImageReservedBytes += VaInfo->BasicInfo.RegionSize; } else { ReservedBytes += VaInfo->BasicInfo.RegionSize; } break; case MEM_FREE : if ( VaInfo->BasicInfo.Type == MEM_IMAGE ) { ImageFreeBytes += VaInfo->BasicInfo.RegionSize; } else { FreeBytes += VaInfo->BasicInfo.RegionSize; } break; } BaseAddress = (PVOID)((ULONG)BaseAddress + VaInfo->BasicInfo.RegionSize); } } }
_CRTAPI1 main() { LONG i, j; PULONG p4, p3, p2, p1, oldp1, vp1; ULONG Size1, Size2, Size3; NTSTATUS status, alstatus; HANDLE CurrentProcessHandle; HANDLE GiantSection; HANDLE Section2, Section4; MEMORY_BASIC_INFORMATION MemInfo; ULONG OldProtect; STRING Name3; HANDLE Section1; OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES Object1Attributes; ULONG ViewSize; LARGE_INTEGER Offset; LARGE_INTEGER SectionSize; UNICODE_STRING Unicode; CurrentProcessHandle = NtCurrentProcess(); DbgPrint(" Memory Management Tests - AllocVm, FreeVm, ProtectVm, QueryVm\n"); p1 = (PULONG)0x20020000; Size1 = 0xbc0000; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", alstatus, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 1 **************\n"); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 2 **************\n"); DbgPrint("FAILURE query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } if ((MemInfo.RegionSize != Size1) || (MemInfo.BaseAddress != p1) || (MemInfo.Protect != PAGE_READWRITE) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_COMMIT)) { DbgPrint("******** FAILED TEST 3 **************\n"); DbgPrint("FAILURE query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } p2 = (PULONG)NULL; Size2 = 0x100000; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 3, &Size2, MEM_TOP_DOWN | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %lC start %lx size %lx\n", status, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 3a.1 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } // // Touch every other page. // vp1 = p2 + 3000; while (vp1 < (PULONG)((PCHAR)p2 + Size2)) { *vp1 = 938; vp1 += 3000; } // // Decommit pages. // Size3 = Size2 - 5044; vp1 = p2 + 3000; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, &Size3, MEM_DECOMMIT); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3a.4 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } // // Split the memory block using MEM_RELEASE. // vp1 = p2 + 5000; Size3 = Size2 - 50000; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&vp1, &Size3, MEM_RELEASE); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3a.b **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } vp1 = p2 + 3000; Size3 = 41; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&vp1, &Size3, MEM_RELEASE); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3a.5 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } // // free every page, ignore the status. // vp1 = p2; Size3 = 30; while (vp1 < (PULONG)((PCHAR)p2 + Size2)) { status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&vp1, &Size3, MEM_RELEASE); vp1 += 128; } p2 = (PULONG)NULL; Size2 = 0x10000; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 3, &Size2, MEM_TOP_DOWN | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 3.1 **************\n"); } else { if (p2 != (PVOID)0x1fff0000) { DbgPrint("******** FAILED TEST 3.2 **************\n"); DbgPrint("p2 = %lx\n",p2); } status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, &Size2, MEM_RELEASE); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 3.3 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } } if (NT_SUCCESS(alstatus)) { status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, MEM_RELEASE); } if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 4 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } p1 = (PULONG)NULL; Size1 = 16 * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_RESERVE, PAGE_READWRITE | PAGE_GUARD); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 5 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 6 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx alloc_protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type); } if ((MemInfo.RegionSize != Size1) || (MemInfo.BaseAddress != p1) || (MemInfo.AllocationProtect != (PAGE_READWRITE | PAGE_GUARD)) || (MemInfo.Protect != 0) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_RESERVE)) { DbgPrint("******** FAILED TEST 7 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx alloc_protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type); } Size2 = 8192; oldp1 = p1; p1 = p1 + 14336; // 64k -8k /4 status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 8 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); } status = NtQueryVirtualMemory (CurrentProcessHandle, oldp1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 9 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, oldp1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } if ((MemInfo.RegionSize != 56*1024) || (MemInfo.BaseAddress != oldp1) || (MemInfo.AllocationProtect != (PAGE_READWRITE | PAGE_GUARD)) || (MemInfo.Protect != 0) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_RESERVE)) { DbgPrint("******** FAILED TEST 10 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, oldp1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx alloc_protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 11 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } if ((MemInfo.RegionSize != Size2) || (MemInfo.BaseAddress != p1) || (MemInfo.Protect != PAGE_EXECUTE_READWRITE) || (MemInfo.Type != MEM_PRIVATE) || (MemInfo.State != MEM_COMMIT) || (MemInfo.AllocationBase != oldp1)) { DbgPrint("******** FAILED TEST 12 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, oldp1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } Size1 = Size2; status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_READONLY | PAGE_NOCACHE, &OldProtect); if ((!NT_SUCCESS(status)) || (OldProtect != PAGE_EXECUTE_READWRITE)) { DbgPrint("******** FAILED TEST 13 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); } status = NtQueryVirtualMemory (CurrentProcessHandle, p1, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if ((!NT_SUCCESS(status)) || MemInfo.Protect != (PAGE_NOCACHE | PAGE_READONLY)) { DbgPrint("******** FAILED TEST 14 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } i = *p1; status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_NOACCESS | PAGE_NOCACHE, &OldProtect); if (status != STATUS_INVALID_PAGE_PROTECTION) { DbgPrint("******** FAILED TEST 15 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect, i); } status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_READONLY, &OldProtect); if ((!NT_SUCCESS(status)) || (OldProtect != (PAGE_NOCACHE | PAGE_READONLY))) { DbgPrint("******** FAILED TEST 16 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); } status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1, PAGE_READWRITE, &OldProtect); if ((!NT_SUCCESS(status)) || (OldProtect != (PAGE_READONLY))) { DbgPrint("******** FAILED TEST 17 **************\n"); DbgPrint("protected VM status %X, base %lx, size %lx, old protect %lx\n", status, p1, Size1, OldProtect); } for (i = 1; i < 12; i++) { p2 = (PULONG)NULL; Size2 = i * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 18 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p2, Size2); } if (i==4) { p3 = p2; } if (i == 8) { Size3 = 12000; status = NtFreeVirtualMemory (CurrentProcessHandle,(PVOID *)&p3, &Size3, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 19 **************\n"); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } } } p3 = p1 + 8 * 1024; status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 20 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p3, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } p3 = p1 - 8 * 1024; status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 21 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p3, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } Size3 = 16 * 4096; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, &Size3, MEM_RELEASE); if (status != STATUS_UNABLE_TO_FREE_VM) { DbgPrint("******** FAILED TEST 22 **************\n"); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } Size3 = 1 * 4096; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, &Size3, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 23 **************\n"); DbgPrint("free vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } p3 = (PULONG)NULL; Size3 = 300 * 4096; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, 0, &Size3, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 24 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p3, Size3); } p1 = p3; p2 = ((PULONG)((PUCHAR)p3 + Size3)); p4 = p1; j = 0; while (p3 < p2) { j += 1; if (j % 8 == 0) { if (*p4 != (ULONG)p4) { DbgPrint("bad value in xcell %lx value is %lx\n",p4, *p4); } p4 += 1; *p4 = (ULONG)p4; p4 = p4 + 1026; } *p3 = (ULONG)p3; p3 += 1027; } DbgPrint("checking values\n"); status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 25 **************\n"); DbgPrint("query vm status %X address %lx Base %lx size %lx\n", status, p3, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 1cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 2cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 3cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 4cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in 5cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } p3 = p1; while (p3 < p2) { if (*p3 != (ULONG)p3) { DbgPrint("bad value in cell %lx value is %lx\n",p3, *p3); } p3 += 1027; } // // Check physical frame mapping. // // // Check physical frame mapping. // RtlInitAnsiString (&Name3, "\\Device\\PhysicalMemory"); status = RtlAnsiStringToUnicodeString(&Unicode,&Name3,TRUE); if (!NT_SUCCESS(status)) { printf("string conversion failed status %lx\n", status); ExitProcess (status); } InitializeObjectAttributes( &ObjectAttributes, &Unicode, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtOpenSection ( &Section1, SECTION_MAP_READ | SECTION_MAP_WRITE, &ObjectAttributes ); RtlFreeUnicodeString(&Unicode); if (status != 0) { DbgPrint("******** FAILED TEST 26 **************\n"); DbgPrint("open physical section failed %lx\n", status); } p1 = NULL; Offset.LowPart = 0x810ff033; Offset.HighPart = 0; ViewSize = 300*4096; status = NtMapViewOfSection (Section1, NtCurrentProcess(), (PVOID *)&p1, 0, ViewSize, &Offset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 27 **************\n"); DbgPrint ("map physical section %X offset = %lx, base %lx\n",status, Offset.LowPart, p1); } p1 = NULL; Size1 = 8 * 1024 * 1024; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", alstatus, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 28 **************\n"); } RtlZeroMemory (p1, Size1); Size1 -= 20000; (PUCHAR)p1 += 5000; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size1 , MEM_DECOMMIT); if (!(NT_SUCCESS(status))) { DbgPrint(" free vm failed - status %lx\n",status); DbgPrint("******** FAILED TEST 29 **************\n"); NtTerminateProcess(NtCurrentProcess(),status); } Size1 -= 20000; (PUCHAR)p1 += 5000; alstatus = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(alstatus)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", alstatus, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 30 **************\n"); } RtlZeroMemory (p1, Size1); Size1 = 28 * 4096; p1 = NULL; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size1, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD); if (!NT_SUCCESS(status)) { DbgPrint("failed first created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); DbgPrint("******** FAILED TEST 31 **************\n"); } try { // // attempt to write the guard page. // *p1 = 973; DbgPrint("************ FAILURE TEST 31.3 guard page exception did not occur\n"); } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); if (status != STATUS_GUARD_PAGE_VIOLATION) { DbgPrint("******** FAILED TEST 32 ******\n"); } } p2 = NULL; Size2 = 200*1024*1024; //200MB status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_COMMIT, PAGE_READWRITE); if (NT_SUCCESS(status)) { status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, &Size2, MEM_RELEASE); } else { if ((status != STATUS_COMMITMENT_LIMIT) && (status != STATUS_PAGEFILE_QUOTA_EXCEEDED)) { DbgPrint("******** FAILED TEST 33 ************** %lx\n",status); } } // // Create a giant section (2gb) // InitializeObjectAttributes( &Object1Attributes, NULL, 0, NULL, NULL ); SectionSize.LowPart = 0x7f000000; SectionSize.HighPart = 0; status = NtCreateSection (&GiantSection, SECTION_MAP_READ | SECTION_MAP_WRITE, &Object1Attributes, &SectionSize, PAGE_READWRITE, SEC_RESERVE, NULL); if (!NT_SUCCESS(status)) { DbgPrint("failed create big section status %X\n", status); DbgPrint("******** FAILED TEST 41 **************\n"); } // // Attempt to map the section (this should fail). // p1 = NULL; ViewSize = 0; status = NtMapViewOfSection (GiantSection, CurrentProcessHandle, (PVOID *)&p1, 0L, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (status != STATUS_NO_MEMORY) { DbgPrint("failed map big section status %X\n", status); DbgPrint("******** FAILED TEST 42 **************\n"); } #ifdef i386 // // Test MEM_DOS_LIM support. // InitializeObjectAttributes( &Object1Attributes, NULL, OBJ_CASE_INSENSITIVE, NULL, NULL ); SectionSize.LowPart = 1575757, SectionSize.HighPart = 0; status = NtCreateSection (&Section4, SECTION_MAP_READ | SECTION_MAP_WRITE, &Object1Attributes, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 42 **************\n"); DbgPrint("t1 create section status %X section handle %lx\n", status, (ULONG)Section4); } p3 = (PVOID)0x9001000; ViewSize = 8000; status = NtMapViewOfSection (Section4, CurrentProcessHandle, (PVOID *)&p3, 0L, 0, 0, &ViewSize, ViewUnmap, MEM_DOS_LIM, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 43 **************\n"); DbgPrint("t1 map section status %X base %lx size %lx\n", status, (ULONG)p3, ViewSize); NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); } p2 = (PVOID)0x9003000; ViewSize = 8000; status = NtMapViewOfSection (Section4, CurrentProcessHandle, (PVOID *)&p2, 0L, 0, 0, &ViewSize, ViewUnmap, MEM_DOS_LIM, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 44 **************\n"); DbgPrint("t1 map section status %X base %lx size %lx\n", status, (ULONG)p3, ViewSize); NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); } status = NtQueryVirtualMemory (CurrentProcessHandle, p3, MemoryBasicInformation, &MemInfo, sizeof (MEMORY_BASIC_INFORMATION), NULL); if (!NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 44 **************\n"); DbgPrint("FAILURE query vm status %X address %lx Base %lx size %lx\n", status, p1, MemInfo.BaseAddress, MemInfo.RegionSize); DbgPrint(" state %lx protect %lx type %lx\n", MemInfo.State, MemInfo.Protect, MemInfo.Type); } *p3 = 98; if (*p3 != *p2) { DbgPrint("******** FAILED TEST 45 **************\n"); } Size2 = 8; p1 = (PVOID)((ULONG)p2 - 0x3000); status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (NT_SUCCESS(status)) { DbgPrint("******** FAILED TEST 46 **************\n"); DbgPrint("created vm status %X start %lx size %lx\n", status, (ULONG)p1, Size1); } #endif DbgPrint(" End of Memory Management Tests - CreateSection, MapView\n"); DbgPrint("creating too much virtual address space\n"); i = 0; do { p2 = NULL; Size2 = 8*1024*1024 + 9938; i += 1; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &Size2, MEM_RESERVE, PAGE_READWRITE); } while (NT_SUCCESS (status)); if (status != STATUS_NO_MEMORY) { DbgPrint("******** FAILED TEST 46 **************\n"); } DbgPrint("created vm done (successfully) status %X, number of allocs %ld\n", status, i); DbgPrint(" End of Memory Management Tests - AllocVm, FreeVm, ProtectVm, QueryVm\n"); { ULONG size, Size; PVOID BaseAddress; NTSTATUS Status; Size = 50*1024; size = Size - 1; BaseAddress = (PVOID)1; // we pass an address of 1, so mm will round it down to 0. if we // passed 0, it looks like a not present argument // N.B. We have to make two separate calls to allocatevm, because // we want a specific virtual address. If we don't first reserve // the address, the mm fails the commit call. Status = NtAllocateVirtualMemory( NtCurrentProcess(), &BaseAddress, 0L, &size, MEM_RESERVE, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { DbgPrint("NtReserveVirtualMemory failed !!!! Status = %lx\n", Status); } size = Size - 1; BaseAddress = (PVOID)1; Status = NtAllocateVirtualMemory( NtCurrentProcess(), &BaseAddress, 0L, &size, MEM_COMMIT, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { DbgPrint("NtCommitVirtualMemory failed !!!! Status = %lx\n", Status); } } ExitProcess (0); }
NTSTATUS CheckIsExplorer() { NTSTATUS Status; PLDR_MODULE Module; PWSTR FullPath, BackSlash; ULONG ReturnLength; ULONG_PTR Length; MEMORY_BASIC_INFORMATION MemoryBasic; PPROCESS_IMAGE_FILE_NAME ExeFileName; PMEMORY_MAPPED_FILENAME_INFORMATION NtdllFileName; MEMORY_MAPPED_FILENAME_INFORMATION LocalMapped; static WCHAR ExplorerName[] = L"explorer.exe"; Status = NtQueryVirtualMemory(CurrentProcess, NtClose, MemoryMappedFilenameInformation, &LocalMapped, sizeof(LocalMapped), &Length); if (Status != STATUS_INFO_LENGTH_MISMATCH && Status != STATUS_BUFFER_OVERFLOW) return Status; NtdllFileName = (PMEMORY_MAPPED_FILENAME_INFORMATION)AllocStack(Length); Status = NtQueryVirtualMemory(CurrentProcess, NtClose, MemoryMappedFilenameInformation, NtdllFileName, Length, &Length); FAIL_RETURN(Status); Status = NtQueryInformationProcess(CurrentProcess, ProcessImageFileName, nullptr, 0, &ReturnLength); if (Status != STATUS_INFO_LENGTH_MISMATCH) return Status; ExeFileName = (PPROCESS_IMAGE_FILE_NAME)AllocStack(ReturnLength); Status = NtQueryInformationProcess(CurrentProcess, ProcessImageFileName, ExeFileName, ReturnLength, &ReturnLength); FAIL_RETURN(Status); BackSlash = nullptr; Length = NtdllFileName->Name.Length / sizeof(WCHAR) - 1; for (; Length != 0; --Length) { if (NtdllFileName->Name.Buffer[Length] != '\\') continue; if (BackSlash != nullptr) { BackSlash = &NtdllFileName->Name.Buffer[Length]; break; } BackSlash = &NtdllFileName->Name.Buffer[Length]; } if (BackSlash == nullptr) return STATUS_NO_MATCH; ++BackSlash; if (PtrOffset(BackSlash, NtdllFileName->Name.Buffer) + sizeof(ExplorerName) > NtdllFileName->Name.MaximumLength) return STATUS_NO_MATCH; CopyStruct(BackSlash, ExplorerName, sizeof(ExplorerName)); NtdllFileName->Name.Length = PtrOffset(BackSlash + CONST_STRLEN(ExplorerName), NtdllFileName->Name.Buffer); Status = RtlEqualUnicodeString(&NtdllFileName->Name, &ExeFileName->ImageFileName, TRUE) ? STATUS_SUCCESS : STATUS_NO_MATCH; return Status; }
static NTSTATUS NTAPI TerminatorM1( _In_ HANDLE ProcessId ) { NTSTATUS status; HANDLE processHandle; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE, ProcessId ))) { PVOID pageOfGarbage; SIZE_T pageSize; PVOID baseAddress; MEMORY_BASIC_INFORMATION basicInfo; pageOfGarbage = NULL; pageSize = PAGE_SIZE; if (!NT_SUCCESS(NtAllocateVirtualMemory( NtCurrentProcess(), &pageOfGarbage, 0, &pageSize, MEM_COMMIT, PAGE_READONLY ))) { NtClose(processHandle); return STATUS_NO_MEMORY; } baseAddress = (PVOID)0; while (NT_SUCCESS(NtQueryVirtualMemory( processHandle, baseAddress, MemoryBasicInformation, &basicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL ))) { ULONG i; // Make sure we don't write to views of mapped files. That // could possibly corrupt files! if (basicInfo.Type == MEM_PRIVATE) { for (i = 0; i < basicInfo.RegionSize; i += PAGE_SIZE) { PhWriteVirtualMemory( processHandle, PTR_ADD_OFFSET(baseAddress, i), pageOfGarbage, PAGE_SIZE, NULL ); } } baseAddress = PTR_ADD_OFFSET(baseAddress, basicInfo.RegionSize); } // Size needs to be zero if we're freeing. pageSize = 0; NtFreeVirtualMemory( NtCurrentProcess(), &pageOfGarbage, &pageSize, MEM_RELEASE ); NtClose(processHandle); } return status; }