VOID GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer) { PGRAPHICS_SCREEN_BUFFER Buff = (PGRAPHICS_SCREEN_BUFFER)Buffer; /* * IMPORTANT !! Reinitialize the type so that we don't enter a recursive * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy. */ Buffer->Header.Type = SCREEN_BUFFER; /* * Uninitialize the graphics screen buffer * in the reverse way we initialized it. */ NtUnmapViewOfSection(Buff->ClientProcess, Buff->ClientBitMap); NtUnmapViewOfSection(NtCurrentProcess(), Buff->BitMap); NtClose(Buff->hSection); NtDuplicateObject(Buff->ClientProcess, Buff->ClientMutex, NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE); NtClose(Buff->Mutex); ConsoleFreeHeap(Buff->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy(Buffer); }
/* * @implemented */ BOOL NTAPI UnmapViewOfFile(LPCVOID lpBaseAddress) { NTSTATUS Status; /* Unmap the section */ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress); if (!NT_SUCCESS(Status)) { /* Check if the pages were protected */ if (Status == STATUS_INVALID_PAGE_PROTECTION) { /* Flush the region if it was a "secure memory cache" */ if (RtlFlushSecureMemoryCache((PVOID)lpBaseAddress, 0)) { /* Now try to unmap again */ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress); if (NT_SUCCESS(Status)) return TRUE; } } /* We failed */ BaseSetLastNTError(Status); return FALSE; } /* Otherwise, return sucess */ return TRUE; }
VOID WepCloseServerObjects( VOID ) { if (WeServerSharedSection) { NtClose(WeServerSharedSection); WeServerSharedSection = NULL; } if (WeServerSharedData) { NtUnmapViewOfSection(NtCurrentProcess(), WeServerSharedData); WeServerSharedData = NULL; } if (WeServerSharedSectionLock) { NtClose(WeServerSharedSectionLock); WeServerSharedSectionLock = NULL; } if (WeServerSharedSectionEvent) { NtClose(WeServerSharedSectionEvent); WeServerSharedSectionEvent = NULL; } }
/* * @implemented */ BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) { NTSTATUS Status; PIMAGE_NT_HEADERS NtHeaders; if (LDR_IS_DATAFILE(hLibModule)) { // FIXME: This SEH should go inside RtlImageNtHeader instead _SEH2_TRY { /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */ NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { NtHeaders = NULL; } _SEH2_END if (NtHeaders) { /* Unmap view */ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); /* Unload alternate resource module */ LdrUnloadAlternateResourceModule(hLibModule); } else Status = STATUS_INVALID_IMAGE_FORMAT; } else {
NTSTATUS PhLoadMappedImage( _In_opt_ PWSTR FileName, _In_opt_ HANDLE FileHandle, _In_ BOOLEAN ReadOnly, _Out_ PPH_MAPPED_IMAGE MappedImage ) { NTSTATUS status; status = PhMapViewOfEntireFile( FileName, FileHandle, ReadOnly, &MappedImage->ViewBase, &MappedImage->Size ); if (NT_SUCCESS(status)) { status = PhInitializeMappedImage( MappedImage, MappedImage->ViewBase, MappedImage->Size ); if (!NT_SUCCESS(status)) { NtUnmapViewOfSection(NtCurrentProcess(), MappedImage->ViewBase); } } return status; }
static int OnUnmapViewClick(HWND hDlg) { TFileTestData * pData = GetDialogData(hDlg); NTSTATUS Status; // Get the base address where it is mapped if(SaveDialog2(hDlg) == ERROR_SUCCESS) { // Unmap the view from the base address Status = NtUnmapViewOfSection(NtCurrentProcess(), pData->pvSectionMappedView); // Clear the base address, so the next click on "MapView" will succeed Hex2DlgTextPtr(hDlg, IDC_BASE_ADDRESS, NULL); pData->pvSectionMappedView = NULL; // Clear the view size, so the next click on "MapView" will succeed Hex2DlgTextPtr(hDlg, IDC_VIEW_SIZE, 0); pData->cbSectViewSize = 0; // Show the result SetResultInfo(hDlg, Status, pData->hSection); UpdateDialog(hDlg, pData); } return TRUE; }
NTSTATUS PhUnloadMappedImage( _Inout_ PPH_MAPPED_IMAGE MappedImage ) { return NtUnmapViewOfSection( NtCurrentProcess(), MappedImage->ViewBase ); }
NTSTATUS PhUnloadMappedArchive( _Inout_ PPH_MAPPED_ARCHIVE MappedArchive ) { return NtUnmapViewOfSection( NtCurrentProcess(), MappedArchive->ViewBase ); }
// UnmapPhysicalMemory // Maps a view of a section. // VOID UnmapPhysicalMemory( DWORD Address ) { NTSTATUS status; status = NtUnmapViewOfSection( (HANDLE) -1, (PVOID) Address ); if( !NT_SUCCESS(status)) { // PrintError("Unable to unmap view", status ); } }
/*********************************************************************** * exit_thread */ void exit_thread( int status ) { static void *prev_teb; shmlocal_t *shmlocal; sigset_t sigset; TEB *teb; if (status) /* send the exit code to the server (0 is already the default) */ { SERVER_START_REQ( terminate_thread ) { req->handle = wine_server_obj_handle( GetCurrentThread() ); req->exit_code = status; wine_server_call( req ); } SERVER_END_REQ; } if (interlocked_xchg_add( &nb_threads, 0 ) <= 1) { LdrShutdownProcess(); exit( status ); } LdrShutdownThread(); RtlFreeThreadActivationContextStack(); shmlocal = interlocked_xchg_ptr( &NtCurrentTeb()->Reserved5[2], NULL ); if (shmlocal) NtUnmapViewOfSection( NtCurrentProcess(), shmlocal ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } sigemptyset( &sigset ); sigaddset( &sigset, SIGQUIT ); pthread_sigmask( SIG_BLOCK, &sigset, NULL ); if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); pthread_exit( UIntToPtr(status) ); }
static void devmem_unmap(DWORD addr) { NTSTATUS r; r = NtUnmapViewOfSection((HANDLE) -1, (PVOID)addr); if(!NT_SUCCESS(r)) { logerr(0, "NtUnmapViewOfSection failed"); errno = unix_err(RtlNtStatusToDosError(r)); } }
/* * FUNCTION: Closes the current cabinet * RETURNS: * Status of operation */ static ULONG CloseCabinet(VOID) { if (FileBuffer) { NtUnmapViewOfSection(NtCurrentProcess(), FileBuffer); NtClose(FileSectionHandle); NtClose(FileHandle); FileBuffer = NULL; } return 0; }
/* * @implemented */ BOOL WINAPI Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) { PTH32SNAPSHOT Snapshot; LARGE_INTEGER SOffset; SIZE_T ViewSize; NTSTATUS Status; CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W)); SOffset.QuadPart = 0; ViewSize = 0; Snapshot = NULL; Status = NtMapViewOfSection(hSnapshot, NtCurrentProcess(), (PVOID*)&Snapshot, 0, 0, &SOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); if(NT_SUCCESS(Status)) { BOOL Ret; if(Snapshot->ProcessListCount > 0) { LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset); Snapshot->ProcessListIndex = 1; RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W)); Ret = TRUE; } else { SetLastError(ERROR_NO_MORE_FILES); Ret = FALSE; } NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); return Ret; } BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ BOOL WINAPI Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl) { PTH32SNAPSHOT Snapshot; LARGE_INTEGER SOffset; SIZE_T ViewSize; NTSTATUS Status; CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32)); SOffset.QuadPart = 0; ViewSize = 0; Snapshot = NULL; Status = NtMapViewOfSection(hSnapshot, NtCurrentProcess(), (PVOID*)&Snapshot, 0, 0, &SOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); if(NT_SUCCESS(Status)) { BOOL Ret; if(Snapshot->HeapListCount > 0 && Snapshot->HeapListIndex < Snapshot->HeapListCount) { LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset); RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32)); Ret = TRUE; } else { SetLastError(ERROR_NO_MORE_FILES); Ret = FALSE; } NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); return Ret; } BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ BOOL NTAPI UnmapViewOfFile(LPCVOID lpBaseAddress) { NTSTATUS Status; /* Unmap the section */ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)lpBaseAddress); if (!NT_SUCCESS(Status)) { /* We failed */ BaseSetLastNTError(Status); return FALSE; } /* Otherwise, return sucess */ return TRUE; }
/*********************************************************************** * UnmapViewOfFile (KERNEL32.@) * * Unmaps a mapped view of a file. * * PARAMS * addr [I] Address where mapped view begins. * * RETURNS * Success: TRUE. * Failure: FALSE. * */ BOOL WINAPI UnmapViewOfFile( LPCVOID addr ) { NTSTATUS status; if (GetVersion() & 0x80000000) { MEMORY_BASIC_INFORMATION info; if (!VirtualQuery( addr, &info, sizeof(info) ) || info.AllocationBase != addr) { SetLastError( ERROR_INVALID_ADDRESS ); return FALSE; } } status = NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; }
BOOL APIENTRY UnmapViewOfFile( LPCVOID lpBaseAddress ) /*++ Routine Description: A previously mapped view of a file may be unmapped from the callers address space using UnmapViewOfFile. Arguments: lpBaseAddress - Supplies the base address of a previously mapped view of a file that is to be unmapped. This value must be identical to the value returned by a previous call to MapViewOfFile. Return Value: TRUE - The operation was successful. All dirty pages within the specified range are stored in the on-disk representation of the mapped file. FALSE - The operation failed. Extended error status is available using GetLastError. --*/ { NTSTATUS Status; Status = NtUnmapViewOfSection(NtCurrentProcess(),(PVOID)lpBaseAddress); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); return FALSE; } return TRUE; }
VOID PhShowMemoryEditorDialog( _In_ HANDLE ProcessId, _In_ PVOID BaseAddress, _In_ SIZE_T RegionSize, _In_ ULONG SelectOffset, _In_ ULONG SelectLength, _In_opt_ PPH_STRING Title, _In_ ULONG Flags ) { PMEMORY_EDITOR_CONTEXT context; MEMORY_EDITOR_CONTEXT lookupContext; PPH_AVL_LINKS links; lookupContext.ProcessId = ProcessId; lookupContext.BaseAddress = BaseAddress; lookupContext.RegionSize = RegionSize; links = PhFindElementAvlTree(&PhMemoryEditorSet, &lookupContext.Links); if (!links) { context = PhAllocate(sizeof(MEMORY_EDITOR_CONTEXT)); memset(context, 0, sizeof(MEMORY_EDITOR_CONTEXT)); context->ProcessId = ProcessId; context->BaseAddress = BaseAddress; context->RegionSize = RegionSize; context->SelectOffset = SelectOffset; PhSwapReference(&context->Title, Title); context->Flags = Flags; context->WindowHandle = CreateDialogParam( PhInstanceHandle, MAKEINTRESOURCE(IDD_MEMEDIT), NULL, PhpMemoryEditorDlgProc, (LPARAM)context ); if (!context->LoadCompleted) { DestroyWindow(context->WindowHandle); return; } if (SelectOffset != -1) PostMessage(context->WindowHandle, WM_PH_SELECT_OFFSET, SelectOffset, SelectLength); PhRegisterDialog(context->WindowHandle); PhAddElementAvlTree(&PhMemoryEditorSet, &context->Links); ShowWindow(context->WindowHandle, SW_SHOW); } else { context = CONTAINING_RECORD(links, MEMORY_EDITOR_CONTEXT, Links); if (IsIconic(context->WindowHandle)) ShowWindow(context->WindowHandle, SW_RESTORE); else SetForegroundWindow(context->WindowHandle); if (SelectOffset != -1) PostMessage(context->WindowHandle, WM_PH_SELECT_OFFSET, SelectOffset, SelectLength); // Just in case. if ((Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); } }
/* * FUNCTION: Extracts a file from the cabinet * ARGUMENTS: * Search = Pointer to PCAB_SEARCH structure used to locate the file * RETURNS * Status of operation */ ULONG CabinetExtractFile(PCAB_SEARCH Search) { ULONG Size; // remaining file bytes to decompress ULONG CurrentOffset; // current uncompressed offset within the folder PUCHAR CurrentBuffer; // current pointer to compressed data in the block LONG RemainingBlock; // remaining comp data in the block HANDLE DestFile; HANDLE DestFileSection; PVOID DestFileBuffer; // mapped view of dest file PVOID CurrentDestBuffer; // pointer to the current position in the dest view PCFDATA CFData; // current data block ULONG Status; FILETIME FileTime; WCHAR DestName[MAX_PATH]; NTSTATUS NtStatus; UNICODE_STRING UnicodeString; ANSI_STRING AnsiString; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; FILE_BASIC_INFORMATION FileBasic; PCFFOLDER CurrentFolder; LARGE_INTEGER MaxDestFileSize; LONG InputLength, OutputLength; char Junk[512]; if (wcscmp(Search->Cabinet, CabinetName) != 0) { /* the file is not in the current cabinet */ DPRINT("File is not in this cabinet (%S != %S)\n", Search->Cabinet, CabinetName); return CAB_STATUS_NOFILE; } /* look up the folder that the file specifies */ if (Search->File->FolderIndex == 0xFFFD || Search->File->FolderIndex == 0xFFFF) { /* folder is continued from previous cabinet, that shouldn't happen here */ return CAB_STATUS_NOFILE; } else if (Search->File->FolderIndex == 0xFFFE) { /* folder is the last in this cabinet and continues into next */ CurrentFolder = &CabinetFolders[PCABHeader->FolderCount - 1]; } else { /* folder is completely contained within this cabinet */ CurrentFolder = &CabinetFolders[Search->File->FolderIndex]; } switch (CurrentFolder->CompressionType & CAB_COMP_MASK) { case CAB_COMP_NONE: CabinetSelectCodec(CAB_CODEC_RAW); break; case CAB_COMP_MSZIP: CabinetSelectCodec(CAB_CODEC_MSZIP); break; default: return CAB_STATUS_UNSUPPCOMP; } DPRINT("Extracting file at uncompressed offset (0x%X) Size (%d bytes)\n", (UINT)Search->File->FileOffset, (UINT)Search->File->FileSize); RtlInitAnsiString(&AnsiString, Search->File->FileName); wcscpy(DestName, DestPath); UnicodeString.MaximumLength = sizeof(DestName) - wcslen(DestName) * sizeof(WCHAR); UnicodeString.Buffer = DestName + wcslen(DestName); UnicodeString.Length = 0; RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); /* Create destination file, fail if it already exists */ RtlInitUnicodeString(&UnicodeString, DestName); InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); NtStatus = NtCreateFile(&DestFile, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus); /* If file exists, ask to overwrite file */ if (OverwriteHandler == NULL || OverwriteHandler(Search->File, DestName)) { /* Create destination file, overwrite if it already exists */ NtStatus = NtCreateFile(&DestFile, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE, FILE_SYNCHRONOUS_IO_ALERT, NULL, 0); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus); return CAB_STATUS_CANNOT_CREATE; } } else { DPRINT("File (%S) exists\n", DestName); return CAB_STATUS_FILE_EXISTS; } } MaxDestFileSize.QuadPart = Search->File->FileSize; NtStatus = NtCreateSection(&DestFileSection, SECTION_ALL_ACCESS, 0, &MaxDestFileSize, PAGE_READWRITE, SEC_COMMIT, DestFile); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtCreateSection failed: %x\n", NtStatus); Status = CAB_STATUS_NOMEMORY; goto CloseDestFile; } DestFileBuffer = 0; DestFileSize = 0; NtStatus = NtMapViewOfSection(DestFileSection, NtCurrentProcess(), &DestFileBuffer, 0, 0, 0, &DestFileSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtMapViewOfSection failed: %x\n", NtStatus); Status = CAB_STATUS_NOMEMORY; goto CloseDestFileSection; } CurrentDestBuffer = DestFileBuffer; if (!ConvertDosDateTimeToFileTime(Search->File->FileDate, Search->File->FileTime, &FileTime)) { DPRINT("DosDateTimeToFileTime() failed\n"); Status = CAB_STATUS_CANNOT_WRITE; goto UnmapDestFile; } NtStatus = NtQueryInformationFile(DestFile, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus); } else { memcpy(&FileBasic.LastAccessTime, &FileTime, sizeof(FILETIME)); NtStatus = NtSetInformationFile(DestFile, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(NtStatus)) { DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus); } } SetAttributesOnFile(Search->File, DestFile); /* Call extract event handler */ if (ExtractHandler != NULL) { ExtractHandler(Search->File, DestName); } /* find the starting block of the file start with the first data block of the folder */ CFData = (PCFDATA)(CabinetFolders[Search->File->FolderIndex].DataOffset + FileBuffer); CurrentOffset = 0; while (CurrentOffset + CFData->UncompSize <= Search->File->FileOffset) { /* walk the data blocks until we reach the one containing the start of the file */ CurrentOffset += CFData->UncompSize; CFData = (PCFDATA)((char *)(CFData + 1) + DataReserved + CFData->CompSize); } /* now decompress and discard any data in the block before the start of the file */ /* start of comp data */ CurrentBuffer = ((unsigned char *)(CFData + 1)) + DataReserved; RemainingBlock = CFData->CompSize; InputLength = RemainingBlock; while (CurrentOffset < Search->File->FileOffset) { /* compute remaining uncomp bytes to start of file, bounded by sizeof junk */ OutputLength = Search->File->FileOffset - CurrentOffset; if (OutputLength > (LONG)sizeof(Junk)) OutputLength = sizeof (Junk); /* negate to signal NOT end of block */ OutputLength = -OutputLength; CodecUncompress(Junk, CurrentBuffer, &InputLength, &OutputLength); /* add the uncomp bytes extracted to current folder offset */ CurrentOffset += OutputLength; /* add comp bytes consumed to CurrentBuffer */ CurrentBuffer += InputLength; /* subtract bytes consumed from bytes remaining in block */ RemainingBlock -= InputLength; /* neg for resume decompression of the same block */ InputLength = -RemainingBlock; } /* now CurrentBuffer points to the first comp byte of the file, so we can begin decompressing */ /* Size = remaining uncomp bytes of the file to decompress */ Size = Search->File->FileSize; while (Size > 0) { OutputLength = Size; DPRINT("Decompressing block at %x with RemainingBlock = %d, Size = %d\n", CurrentBuffer, RemainingBlock, Size); Status = CodecUncompress(CurrentDestBuffer, CurrentBuffer, &InputLength, &OutputLength); if (Status != CS_SUCCESS) { DPRINT("Cannot uncompress block\n"); if (Status == CS_NOMEMORY) Status = CAB_STATUS_NOMEMORY; Status = CAB_STATUS_INVALID_CAB; goto UnmapDestFile; } /* advance dest buffer by bytes produced */ CurrentDestBuffer = (PVOID)((ULONG_PTR)CurrentDestBuffer + OutputLength); /* advance src buffer by bytes consumed */ CurrentBuffer += InputLength; /* reduce remaining file bytes by bytes produced */ Size -= OutputLength; /* reduce remaining block size by bytes consumed */ RemainingBlock -= InputLength; if (RemainingBlock == 0) { /* used up this block, move on to the next */ DPRINT("Out of block data\n"); CFData = (PCFDATA)CurrentBuffer; RemainingBlock = CFData->CompSize; CurrentBuffer = (unsigned char *)(CFData + 1) + DataReserved; InputLength = RemainingBlock; } } Status = CAB_STATUS_SUCCESS; UnmapDestFile: NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer); CloseDestFileSection: NtClose(DestFileSection); CloseDestFile: NtClose(DestFile); return Status; }
NTSTATUS SetupCopyFile( PWCHAR SourceFileName, PWCHAR DestinationFileName) { OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandleSource; HANDLE FileHandleDest; static IO_STATUS_BLOCK IoStatusBlock; FILE_STANDARD_INFORMATION FileStandard; FILE_BASIC_INFORMATION FileBasic; ULONG RegionSize; UNICODE_STRING FileName; NTSTATUS Status; PVOID SourceFileMap = 0; HANDLE SourceFileSection; SIZE_T SourceSectionSize = 0; LARGE_INTEGER ByteOffset; #ifdef __REACTOS__ RtlInitUnicodeString(&FileName, SourceFileName); InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&FileHandleSource, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ, FILE_SEQUENTIAL_ONLY); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName); goto done; } #else FileHandleSource = CreateFileW(SourceFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (FileHandleSource == INVALID_HANDLE_VALUE) { Status = STATUS_UNSUCCESSFUL; goto done; } #endif Status = NtQueryInformationFile(FileHandleSource, &IoStatusBlock, &FileStandard, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed: %x\n", Status); goto closesrc; } Status = NtQueryInformationFile(FileHandleSource, &IoStatusBlock,&FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed: %x\n", Status); goto closesrc; } Status = NtCreateSection(&SourceFileSection, SECTION_MAP_READ, NULL, NULL, PAGE_READONLY, SEC_COMMIT, FileHandleSource); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName); goto closesrc; } Status = NtMapViewOfSection(SourceFileSection, NtCurrentProcess(), &SourceFileMap, 0, 0, NULL, &SourceSectionSize, ViewUnmap, 0, PAGE_READONLY ); if (!NT_SUCCESS(Status)) { DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName); goto closesrcsec; } RtlInitUnicodeString(&FileName, DestinationFileName); InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile(&FileHandleDest, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NO_INTERMEDIATE_BUFFERING | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateFile failed: %x\n", Status); goto unmapsrcsec; } RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart); IoStatusBlock.Status = 0; ByteOffset.QuadPart = 0; Status = NtWriteFile(FileHandleDest, NULL, NULL, NULL, &IoStatusBlock, SourceFileMap, RegionSize, &ByteOffset, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize); goto closedest; } /* Copy file date/time from source file */ Status = NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed: %x\n", Status); goto closedest; } /* shorten the file back to it's real size after completing the write */ Status = NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileStandard.EndOfFile, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed: %x\n", Status); } closedest: NtClose(FileHandleDest); unmapsrcsec: NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap); closesrcsec: NtClose(SourceFileSection); closesrc: NtClose(FileHandleSource); done: return Status; }
BOOL GetSetThreadContext_Injection() { TCHAR lpApplicationName[] = _T("C:\\Windows\\System32\\svchost.exe"); TCHAR lpApplicationName2[] = _T("C:\\masm32\\examples\\dialogs_later\\basic\\basicdlg.exe"); BOOL bResult; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; SecureZeroMemory(&StartupInfo, sizeof(STARTUPINFO)); SecureZeroMemory(&ProcessInfo, sizeof(PPROCESS_INFORMATION)); // Create the hollowed process in suspended mode bResult = CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo); if (bResult == NULL){ print_last_error(_T("CreateProcess")); return FALSE; } // Allocate space for context structure PCONTEXT pContext; LPVOID pTargetImageBase = NULL; pContext = PCONTEXT(VirtualAlloc(NULL, sizeof(LPVOID), MEM_COMMIT, PAGE_READWRITE)); if (pContext == NULL) { print_last_error(_T("VirtualAlloc")); return FALSE; } // Get the thread context of target pContext->ContextFlags = CONTEXT_FULL; bResult = GetThreadContext(ProcessInfo.hThread, pContext); if (bResult == NULL) { print_last_error(_T("GetThreadContext")); return FALSE; } // Read the image base address of target ReadProcessMemory(ProcessInfo.hProcess, LPCVOID(pContext->Ebx + 8), pTargetImageBase, 4, NULL); // Opening source image HANDLE hFile = CreateFile(lpApplicationName2, GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL); if (hFile == INVALID_HANDLE_VALUE) { print_last_error(_T("CreateFile")); return FALSE; } // Reading the file DWORD dwSize = GetFileSize(hFile, 0); DWORD dwBytesRead; PBYTE pBuffer = new BYTE[dwSize]; ReadFile(hFile, pBuffer, dwSize, &dwBytesRead, 0); PIMAGE_SECTION_HEADER pImageSectionHeader; PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuffer; if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) { PIMAGE_NT_HEADERS32 pNTHeaders = PIMAGE_NT_HEADERS(DWORD(pBuffer) + pDosHeader->e_lfanew); if (pNTHeaders->Signature == IMAGE_NT_SIGNATURE) { if (DWORD(pTargetImageBase) == pNTHeaders->OptionalHeader.ImageBase) { pNtUnmapViewOfSection NtUnmapViewOfSection; NtUnmapViewOfSection = (pNtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection")); NtUnmapViewOfSection(ProcessInfo.hProcess, pTargetImageBase); } LPVOID pImageBase; pImageBase = VirtualAllocEx(ProcessInfo.hProcess, LPVOID(pNTHeaders->OptionalHeader.ImageBase), pNTHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (pImageBase == NULL) { print_last_error(_T("VirtualAllocEx")); return FALSE; } WriteProcessMemory(ProcessInfo.hProcess, pImageBase, pBuffer, pNTHeaders->OptionalHeader.SizeOfHeaders, NULL); for (int Count = 0; Count < pNTHeaders->FileHeader.NumberOfSections; Count++) { pImageSectionHeader = PIMAGE_SECTION_HEADER(DWORD(pBuffer) + pDosHeader->e_lfanew + 248 + (Count * 40)); WriteProcessMemory(ProcessInfo.hProcess, LPVOID(DWORD(pImageBase) + pImageSectionHeader->VirtualAddress), LPVOID(DWORD(pBuffer) + pImageSectionHeader->PointerToRawData), pImageSectionHeader->SizeOfRawData, NULL); } WriteProcessMemory(ProcessInfo.hProcess, LPVOID(pContext->Ebx + 8), LPVOID(&pNTHeaders->OptionalHeader.ImageBase), 4, NULL); pContext->Eax = DWORD(pImageBase) + pNTHeaders->OptionalHeader.AddressOfEntryPoint; SetThreadContext(ProcessInfo.hThread, LPCONTEXT(pContext)); ResumeThread(ProcessInfo.hThread); } } return TRUE; }
BOOLEAN ZMain( IN PVOID DllHandle, ULONG Reason, IN PCONTEXT Context OPTIONAL) { static char szDumpFile[13]; NTSTATUS Status; DllHandle, Context; // avoid compiler warnings // if process is attaching, initialize the dll // if (Reason == DLL_PROCESS_ATTACH) { GdiSetBatchLimit (1); ApfInitDll(); } else if (Reason == DLL_THREAD_ATTACH) { GdiSetBatchLimit (1); } else if (Reason == DLL_PROCESS_DETACH) { // // Get semaphore // Status = NtWaitForSingleObject(hDataSem,FALSE,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: Could not wait for Dsemaphore in ZMain, %lx\n", Status)); } #endif // Number of processes accessing this dll is contained in // ApfData[I_CALIBRATE].cCalls. Decrement this number, and // if this number is then zero, dump the data. ApfData[I_CALIBRATE].cCalls--; if (ApfData[I_CALIBRATE].cCalls == 0) { strcpy (szDumpFile, MODULE_NAME); strcat (szDumpFile, ".end"); ApfDumpData ((LPSTR)szDumpFile); // // Unmap and close sections, and close semaphores // Status = NtUnmapViewOfSection(MyProcess,(PVOID)ApfControl); Status = NtClose(ApfDataSectionHandle); // This instance is now "uninitialized" // fInitDone = FALSE; } // // Release semaphore // Status = NtReleaseSemaphore(hDataSem,1,NULL); #ifdef ERRORDBG if (!NT_SUCCESS(Status)) { KdPrint (("WAP: DSemaphore Not Released in ZMain!! %lx\n", Status)); } #endif } return(TRUE); } /* ZMain () */
VOID GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, BOOL Defaults) { NTSTATUS Status; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL, hClientSection = NULL; LARGE_INTEGER SectionSize; ULONG ViewSize = 0; SIZE_T Length = 0; PCONSOLE_PROPS pSharedInfo = NULL; PGUI_CONSOLE_INFO GuiInfo = NULL; DPRINT("GuiConsoleShowConsoleProperties entered\n"); if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* * Create a memory section to share with the applet, and map it. */ /* Holds data for console.dll + console info + terminal-specific info */ SectionSize.QuadPart = sizeof(CONSOLE_PROPS) + sizeof(GUI_CONSOLE_INFO); Status = NtCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status); goto Quit; } Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pSharedInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status); goto Quit; } /* * Setup the shared console properties structure. */ /* Header */ pSharedInfo->hConsoleWindow = GuiData->hWindow; pSharedInfo->ShowDefaultParams = Defaults; /* * We fill-in the fields only if we display * our properties, not the default ones. */ if (!Defaults) { /* Console information */ pSharedInfo->ci.HistoryBufferSize = Console->HistoryBufferSize; pSharedInfo->ci.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; pSharedInfo->ci.HistoryNoDup = Console->HistoryNoDup; pSharedInfo->ci.QuickEdit = Console->QuickEdit; pSharedInfo->ci.InsertMode = Console->InsertMode; /////////////pSharedInfo->ci.InputBufferSize = 0; pSharedInfo->ci.ScreenBufferSize = ActiveBuffer->ScreenBufferSize; pSharedInfo->ci.ConsoleSize = ActiveBuffer->ViewSize; pSharedInfo->ci.CursorBlinkOn; pSharedInfo->ci.ForceCursorOff; pSharedInfo->ci.CursorSize = ActiveBuffer->CursorInfo.dwSize; if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) { PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer; pSharedInfo->ci.ScreenAttrib = Buffer->ScreenDefaultAttrib; pSharedInfo->ci.PopupAttrib = Buffer->PopupDefaultAttrib; } else // if (GetType(ActiveBuffer) == GRAPHICS_BUFFER) { // PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)ActiveBuffer; DPRINT1("GuiConsoleShowConsoleProperties - Graphics buffer\n"); // FIXME: Gather defaults from the registry ? pSharedInfo->ci.ScreenAttrib = DEFAULT_SCREEN_ATTRIB; pSharedInfo->ci.PopupAttrib = DEFAULT_POPUP_ATTRIB ; } pSharedInfo->ci.CodePage; /* GUI Information */ pSharedInfo->TerminalInfo.Size = sizeof(GUI_CONSOLE_INFO); GuiInfo = pSharedInfo->TerminalInfo.TermInfo = (PGUI_CONSOLE_INFO)(pSharedInfo + 1); wcsncpy(GuiInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE); GuiInfo->FaceName[LF_FACESIZE - 1] = UNICODE_NULL; GuiInfo->FontFamily = GuiData->GuiInfo.FontFamily; GuiInfo->FontSize = GuiData->GuiInfo.FontSize; GuiInfo->FontWeight = GuiData->GuiInfo.FontWeight; GuiInfo->FullScreen = GuiData->GuiInfo.FullScreen; GuiInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; GuiInfo->WindowOrigin = GuiData->GuiInfo.WindowOrigin; /* Offsetize */ pSharedInfo->TerminalInfo.TermInfo = (PVOID)((ULONG_PTR)GuiInfo - (ULONG_PTR)pSharedInfo); /* Palette */ memcpy(pSharedInfo->ci.Colors, Console->Colors, sizeof(Console->Colors)); /* Title of the console, original one corresponding to the one set by the console leader */ Length = min(sizeof(pSharedInfo->ci.ConsoleTitle) / sizeof(pSharedInfo->ci.ConsoleTitle[0]) - 1, Console->OriginalTitle.Length / sizeof(WCHAR)); wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); } else { Length = 0; // FIXME: Load the default parameters from the registry. } /* Null-terminate the title */ pSharedInfo->ci.ConsoleTitle[Length] = L'\0'; /* Unmap the view */ NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for the client */ Status = NtDuplicateObject(NtCurrentProcess(), hSection, ProcessData->Process->ProcessHandle, &hClientSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to duplicate section handle for client, Status = 0x%08lx\n", Status); goto Quit; } /* Start the properties dialog */ if (ProcessData->PropRoutine) { _SEH2_TRY { HANDLE Thread = NULL; _SEH2_TRY { Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, ProcessData->PropRoutine, (PVOID)hClientSection, 0, NULL); if (NULL == Thread) { DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError()); } else { DPRINT("ProcessData->PropRoutine remote thread creation succeeded, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process); /// WaitForSingleObject(Thread, INFINITE); } } _SEH2_FINALLY { CloseHandle(Thread); } _SEH2_END; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); DPRINT1("GuiConsoleShowConsoleProperties - Caught an exception, Status = 0x%08lx\n", Status); } _SEH2_END; }
VOID PropertiesUpdate( IN PCONSOLE_INFORMATION Console, IN HANDLE hClientSection ) /*++ Updates the console state from information sent by the properties dialog box. --*/ { HANDLE hSection; ULONG ulViewSize; NTSTATUS Status; PCONSOLE_STATE_INFO pStateInfo; PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; PSCREEN_INFORMATION ScreenInfo; ULONG FontIndex; WINDOWPLACEMENT wp; COORD NewSize; /* * Map the shared memory block handle into our address space. */ ProcessHandleRecord = CONTAINING_RECORD(Console->ProcessHandleList.Blink, CONSOLE_PROCESS_HANDLE, ListLink); Status = NtDuplicateObject(ProcessHandleRecord->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { KdPrint(("CONSRV: error %x mapping client handle\n", Status)); return; } /* * Get a pointer to the shared memory block. */ pStateInfo = NULL; ulViewSize = 0; Status = NtMapViewOfSection(hSection, NtCurrentProcess(), &pStateInfo, 0, 0, NULL, &ulViewSize, ViewUnmap, 0, PAGE_READONLY); if (!NT_SUCCESS(Status)) { KdPrint(("CONSRV: error %x mapping view of file\n", Status)); NtClose(hSection); return; } /* * Verify the size of the shared memory block. */ if (ulViewSize < sizeof(CONSOLE_STATE_INFO)) { KdPrint(("CONSRV: sizeof(hSection) < sizeof(CONSOLE_STATE_INFO)\n")); NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo); NtClose(hSection); return; } /* * Update the console state from the supplied values. */ ScreenInfo = Console->CurrentScreenBuffer; if (!(Console->Flags & CONSOLE_VDM_REGISTERED) && (pStateInfo->ScreenBufferSize.X != ScreenInfo->ScreenBufferSize.X || pStateInfo->ScreenBufferSize.Y != ScreenInfo->ScreenBufferSize.Y)) { ResizeScreenBuffer(ScreenInfo, pStateInfo->ScreenBufferSize, TRUE); } FontIndex = FindCreateFont(pStateInfo->FontFamily, pStateInfo->FaceName, pStateInfo->FontSize, pStateInfo->FontWeight); SetScreenBufferFont(ScreenInfo, FontIndex); SetCursorInformation(ScreenInfo, pStateInfo->CursorSize, ScreenInfo->BufferInfo.TextInfo.CursorVisible); NewSize.X = min(pStateInfo->WindowSize.X, ScreenInfo->MaximumWindowSize.X); NewSize.Y = min(pStateInfo->WindowSize.Y, ScreenInfo->MaximumWindowSize.Y); if (NewSize.X != CONSOLE_WINDOW_SIZE_X(ScreenInfo) || NewSize.Y != CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) { wp.length = sizeof(wp); GetWindowPlacement(Console->hWnd, &wp); wp.rcNormalPosition.right += (NewSize.X - CONSOLE_WINDOW_SIZE_X(ScreenInfo)) * SCR_FONTSIZE(ScreenInfo).X; wp.rcNormalPosition.bottom += (NewSize.Y - CONSOLE_WINDOW_SIZE_Y(ScreenInfo)) * SCR_FONTSIZE(ScreenInfo).Y; SetWindowPlacement(Console->hWnd, &wp); } #ifdef i386 if (FullScreenInitialized) { if (pStateInfo->FullScreen == FALSE) { if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) { ConvertToWindowed(Console); ASSERT(!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)); Console->FullScreenFlags = 0; ChangeDispSettings(Console, Console->hWnd, 0); } } else { if (Console->FullScreenFlags == 0) { ConvertToFullScreen(Console); Console->FullScreenFlags |= CONSOLE_FULLSCREEN; ChangeDispSettings(Console, Console->hWnd, CDS_FULLSCREEN); } } } #endif if (pStateInfo->QuickEdit) { Console->Flags |= CONSOLE_QUICK_EDIT_MODE; } else { Console->Flags &= ~CONSOLE_QUICK_EDIT_MODE; } if (pStateInfo->AutoPosition) { Console->Flags |= CONSOLE_AUTO_POSITION; } else { Console->Flags &= ~CONSOLE_AUTO_POSITION; SetWindowPos(Console->hWnd, NULL, pStateInfo->WindowPosX, pStateInfo->WindowPosY, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } if (Console->InsertMode != pStateInfo->InsertMode) { SetCursorMode(ScreenInfo, FALSE); Console->InsertMode = pStateInfo->InsertMode; } RtlCopyMemory(Console->ColorTable, pStateInfo->ColorTable, sizeof(Console->ColorTable)); SetScreenColors(ScreenInfo, pStateInfo->ScreenAttributes, pStateInfo->PopupAttributes, TRUE); Console->CommandHistorySize = pStateInfo->HistoryBufferSize; Console->MaxCommandHistories = pStateInfo->NumberOfHistoryBuffers; if (pStateInfo->HistoryNoDup) { Console->Flags |= CONSOLE_HISTORY_NODUP; } else { Console->Flags &= ~CONSOLE_HISTORY_NODUP; } NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo); NtClose(hSection); return; }
BOOL MapNewExecutableRegionInProcess( IN HANDLE TargetProcessHandle, IN HANDLE TargetThreadHandle, IN LPVOID NewExecutableRawImage) { PROCESS_BASIC_INFORMATION BasicInformation; PIMAGE_SECTION_HEADER SectionHeader; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NtHeader; PMINI_PEB ProcessPeb; NTSTATUS (NTAPI *NtUnmapViewOfSection)(HANDLE, LPVOID) = NULL; NTSTATUS (NTAPI *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG) = NULL; NTSTATUS Status; CONTEXT ThreadContext; LPVOID OldEntryPoint = NULL; LPVOID TargetImageBase = NULL; ULONG SectionIndex = 0; ULONG SizeOfBasicInformation; BOOL Success = FALSE; // // Error checking? Bah. // DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage; NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)NewExecutableRawImage + DosHeader->e_lfanew); do { // // Get the old entry point address by inspecting eax of the current // thread (which should be BaseProcessStart). Eax holds the address // of the entry point for the executable when the process is created // suspended. // ZeroMemory( &ThreadContext, sizeof(ThreadContext)); ThreadContext.ContextFlags = CONTEXT_INTEGER; if (!GetThreadContext( TargetThreadHandle, &ThreadContext)) { break; } OldEntryPoint = (LPVOID) NtHeader->OptionalHeader.ImageBase; // // Unmap the old executable region in the child process to avoid // conflicts // NtUnmapViewOfSection = (NTSTATUS (NTAPI *)(HANDLE, LPVOID))GetProcAddress( GetModuleHandle( TEXT("NTDLL")), "NtUnmapViewOfSection"); NtUnmapViewOfSection(TargetProcessHandle, OldEntryPoint); // // Change the entry point address to the new executable's entry point // ThreadContext.Eax = NtHeader->OptionalHeader.AddressOfEntryPoint + NtHeader->OptionalHeader.ImageBase; if (!SetThreadContext( TargetThreadHandle, &ThreadContext)) break; // // Allocate storage for the new executable in the child process // if (!(TargetImageBase = VirtualAllocEx( TargetProcessHandle, (LPVOID)NtHeader->OptionalHeader.ImageBase, NtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE))) break; // // Update the executable's image base address in the PEB... // NtQueryInformationProcess = (NTSTATUS (NTAPI *)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG))GetProcAddress( GetModuleHandle( TEXT("NTDLL")), "NtQueryInformationProcess"); if (NtQueryInformationProcess( TargetProcessHandle, ProcessBasicInformation, &BasicInformation, sizeof(BasicInformation), &SizeOfBasicInformation) != ERROR_SUCCESS) break; ProcessPeb = BasicInformation.PebBaseAddress; if (!WriteProcessMemory( TargetProcessHandle, (LPVOID)&ProcessPeb->ImageBaseAddress, (LPVOID)&NtHeader->OptionalHeader.ImageBase, sizeof(LPVOID), NULL)) break; // // Copy the image headers and all of the section contents // if (!WriteProcessMemory( TargetProcessHandle, TargetImageBase, NewExecutableRawImage, NtHeader->OptionalHeader.SizeOfHeaders, NULL)) break; Success = TRUE; for (SectionIndex = 0, SectionHeader = IMAGE_FIRST_SECTION(NtHeader); SectionIndex < NtHeader->FileHeader.NumberOfSections; SectionIndex++) { // // Skip uninitialized data // if ((!SectionHeader[SectionIndex].SizeOfRawData) || (SectionHeader[SectionIndex].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) continue; if (!WriteProcessMemory( TargetProcessHandle, (LPVOID)((PCHAR)TargetImageBase + SectionHeader[SectionIndex].VirtualAddress), (LPVOID)((PCHAR)NewExecutableRawImage + SectionHeader[SectionIndex].PointerToRawData), SectionHeader[SectionIndex].SizeOfRawData, NULL)) { Success = FALSE; break; } } } while (0); return Success; }
NTSTATUS LeGlobalData::Initialize() { BOOL IsLoader; PLEPEB LePeb; PLDR_MODULE Ntdll; PPEB_BASE Peb; NTSTATUS Status; NLSTABLEINFO NlsTableInfo; UNICODE_STRING SystemDirectory, NlsFileName, OemNlsFileName, LangFileName; PKEY_VALUE_PARTIAL_INFORMATION IndexValue; IsLoader = IsLeLoader(); Wow64 = Ps::IsWow64Process(); Ntdll = GetNtdllLdrModule(); LOOP_ONCE { LePeb = OpenOrCreateLePeb(); if (LePeb == nullptr) { ULONG_PTR DefaultACPLength, DefaultLCIDLength, DefaultOEMCPLength; WCHAR DefaultACP[0x20], DefaultOEMCP[0x20], DefaultLCID[0x20]; PVOID ReloadedNtdll; PUNICODE_STRING FullDllName; LePeb = GetLePeb(); InitDefaultLeb(&LePeb->Leb); FullDllName = &FindLdrModuleByHandle(&__ImageBase)->FullDllName; CopyMemory(LePeb->LeDllFullPath, FullDllName->Buffer, FullDllName->Length + sizeof(WCHAR)); Status = LoadPeImage(Ntdll->FullDllName.Buffer, &ReloadedNtdll, nullptr, LOAD_PE_IGNORE_RELOC); if (NT_SUCCESS(Status)) { PVOID LdrLoadDllAddress; LdrLoadDllAddress = LookupExportTable(ReloadedNtdll, NTDLL_LdrLoadDll); LePeb->LdrLoadDllAddress = PtrAdd(LdrLoadDllAddress, PtrOffset(Ntdll->DllBase, ReloadedNtdll)); CopyMemory(LePeb->LdrLoadDllBackup, LdrLoadDllAddress, LDR_LOAD_DLL_BACKUP_SIZE); LePeb->LdrLoadDllBackupSize = LDR_LOAD_DLL_BACKUP_SIZE; UnloadPeImage(ReloadedNtdll); } DefaultACPLength = (swprintf(DefaultACP, L"%d", LePeb->Leb.AnsiCodePage) + 1) * sizeof(WCHAR); DefaultOEMCPLength = (swprintf(DefaultOEMCP, L"%d", LePeb->Leb.OemCodePage) + 1) * sizeof(WCHAR); DefaultLCIDLength = (swprintf(DefaultLCID, L"%d", LePeb->Leb.LocaleID) + 1) * sizeof(WCHAR); REGISTRY_REDIRECTION_ENTRY64 *Entry, Entries[] = { { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_ACP), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_ACP), REG_SZ, DefaultACP, DefaultACPLength }, }, { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_OEMCP), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_OEMCP), REG_SZ, DefaultOEMCP, DefaultOEMCPLength }, }, { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_LANGUAGE), USTR64(REGKEY_DEFAULT_LANGUAGE), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_LANGUAGE), USTR64(REGKEY_DEFAULT_LANGUAGE), REG_SZ, DefaultLCID, DefaultLCIDLength }, }, }; Status = this->InitRegistryRedirection(Entries, countof(Entries), nullptr); } else { *GetLePeb() = *LePeb; Status = this->InitRegistryRedirection(LePeb->Leb.RegistryReplacement, LePeb->Leb.NumberOfRegistryRedirectionEntries, &LePeb->Leb); NtClose(LePeb->Section); CloseLePeb(LePeb); } if (IsLoader) break; Status = this->TextMetricCache.Initialize(); FAIL_RETURN(Status); PVOID NlsBaseAddress; LCID DefaultLocaleID; LARGE_INTEGER DefaultCasingTableSize; Status = NtInitializeNlsFiles(&NlsBaseAddress, &DefaultLocaleID, &DefaultCasingTableSize); FAIL_RETURN(Status); this->GetLePeb()->OriginalLocaleID = DefaultLocaleID; NtUnmapViewOfSection(CurrentProcess, NlsBaseAddress); WriteLog(L"init leb %s", GetLePeb()->LeDllFullPath); SystemDirectory = Ntdll->FullDllName; SystemDirectory.Length -= Ntdll->BaseDllName.Length; Status = RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &SystemDirectory, &this->SystemDirectory); FAIL_RETURN(Status); RtlInitEmptyString(&NlsFileName, nullptr, 0); RtlInitEmptyString(&OemNlsFileName, nullptr, 0); RtlInitEmptyString(&LangFileName, nullptr, 0); SCOPE_EXIT { RtlFreeUnicodeString(&NlsFileName); RtlFreeUnicodeString(&OemNlsFileName); RtlFreeUnicodeString(&LangFileName); } SCOPE_EXIT_END; Status = GetNlsFile(&NlsFileName, GetLeb()->AnsiCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetNlsFile(&OemNlsFileName, GetLeb()->OemCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetLangFile(&LangFileName, GetLeb()->LocaleID, REGPATH_LANGUAGE); FAIL_RETURN(Status); NtFileMemory AnsiFile, OemFile, LangFile; Status = ReadFileInSystemDirectory(AnsiFile, &NlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(OemFile, &OemNlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(LangFile, &LangFileName); FAIL_RETURN(Status); AnsiCodePageOffset = 0; OemCodePageOffset = ROUND_UP(AnsiFile.GetSize32(), 16); UnicodeCaseTableOffset = OemCodePageOffset + ROUND_UP(OemFile.GetSize32(), 16); Status = AllocVirtualMemory(&CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READWRITE, MEM_COMMIT | MEM_TOP_DOWN); FAIL_RETURN(Status); CopyMemory(PtrAdd(CodePageMapView, AnsiCodePageOffset), AnsiFile.GetBuffer(), AnsiFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, OemCodePageOffset), OemFile.GetBuffer(), OemFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, UnicodeCaseTableOffset), LangFile.GetBuffer(), LangFile.GetSize32()); ProtectVirtualMemory(CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READONLY); RtlInitNlsTables( (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset), &NlsTableInfo ); RtlResetRtlTranslations(&NlsTableInfo); WriteLog(L"reset nls"); Peb = CurrentPeb(); Peb->AnsiCodePageData = (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset); Peb->OemCodePageData = (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset); Peb->UnicodeCaseTableData = (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset); // LdrInitShimEngineDynamic(&__ImageBase); LdrRegisterDllNotification(0, [] (ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context) { return ((PLeGlobalData)Context)->DllNotification(NotificationReason, NotificationData); }, this, &DllNotificationCookie ); } Status = InstallHookPort(); WriteLog(L"inst hp: %08X", Status); FAIL_RETURN(Status); HookNtdllRoutines(Ntdll->DllBase); WriteLog(L"hook ntdll"); if (IsLoader) return Status; PLDR_MODULE Kernel32Ldr; Kernel32Ldr = GetKernel32Ldr(); if (Kernel32Ldr != nullptr) { Kernel32Ldr->EntryPoint = DelayInitDllEntry; // HookKernel32Routines(Kernel32Ldr->DllBase); } WriteLog(L"init %p", Status); return Status; }
NTSTATUS GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer, IN OUT PCONSOLE Console, IN PGRAPHICS_BUFFER_INFO GraphicsInfo) { NTSTATUS Status = STATUS_SUCCESS; PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL; LARGE_INTEGER SectionSize; ULONG ViewSize = 0; HANDLE ProcessHandle; if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL) return STATUS_INVALID_PARAMETER; *Buffer = NULL; Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer, Console, sizeof(GRAPHICS_SCREEN_BUFFER)); if (!NT_SUCCESS(Status)) return Status; NewBuffer->Header.Type = GRAPHICS_BUFFER; NewBuffer->Vtbl = &GraphicsVtbl; /* * Remember the handle to the process so that we can close or unmap * correctly the allocated resources when the client releases the * screen buffer. */ ProcessHandle = CsrGetClientThread()->Process->ProcessHandle; NewBuffer->ClientProcess = ProcessHandle; /* Get infos from the graphics buffer information structure */ NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength; NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength); if (NewBuffer->BitMapInfo == NULL) { CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); return STATUS_INSUFFICIENT_RESOURCES; } /* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */ if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0) GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight; /* We do not use anything else than uncompressed bitmaps */ if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB) { DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression); GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB; } RtlCopyMemory(NewBuffer->BitMapInfo, GraphicsInfo->Info.lpBitMapInfo, GraphicsInfo->Info.dwBitMapInfoLength); NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage; /* Set the screen buffer size. Fight against overflows. */ if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF && -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF ) { /* Be careful about the sign of biHeight */ NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ; NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight; NewBuffer->OldViewSize = NewBuffer->ViewSize = NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize; } else { Status = STATUS_INSUFFICIENT_RESOURCES; ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a mutex to synchronize bitmap memory access * between ourselves and the client. */ Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateMutant() failed: %lu\n", Status); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Duplicate the Mutex for the client. We must keep a trace of it * so that we can close it when the client releases the screen buffer. */ Status = NtDuplicateObject(NtCurrentProcess(), NewBuffer->Mutex, ProcessHandle, &NewBuffer->ClientMutex, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("NtDuplicateObject() failed: %lu\n", Status); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a memory section for the bitmap area, to share with the client. */ SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage; Status = NtCreateSection(&NewBuffer->hSection, SECTION_ALL_ACCESS, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status); NtClose(NewBuffer->ClientMutex); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a view for our needs. */ ViewSize = 0; NewBuffer->BitMap = NULL; Status = NtMapViewOfSection(NewBuffer->hSection, NtCurrentProcess(), (PVOID*)&NewBuffer->BitMap, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status); NtClose(NewBuffer->hSection); NtClose(NewBuffer->ClientMutex); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } /* * Create a view for the client. We must keep a trace of it so that * we can unmap it when the client releases the screen buffer. */ ViewSize = 0; NewBuffer->ClientBitMap = NULL; Status = NtMapViewOfSection(NewBuffer->hSection, ProcessHandle, (PVOID*)&NewBuffer->ClientBitMap, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status); NtUnmapViewOfSection(NtCurrentProcess(), NewBuffer->BitMap); NtClose(NewBuffer->hSection); NtClose(NewBuffer->ClientMutex); NtClose(NewBuffer->Mutex); ConsoleFreeHeap(NewBuffer->BitMapInfo); CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer); goto Quit; } NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0; NewBuffer->VirtualY = 0; NewBuffer->CursorBlinkOn = FALSE; NewBuffer->ForceCursorOff = TRUE; NewBuffer->CursorInfo.bVisible = FALSE; NewBuffer->CursorInfo.dwSize = 0; NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0; NewBuffer->Mode = 0; *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer; Status = STATUS_SUCCESS; Quit: return Status; }
INT_PTR CALLBACK PhpMemoryEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_EDITOR_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_EDITOR_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; if (context->Title) { SetWindowText(hwndDlg, context->Title->Buffer); } else { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"%s (%u) (0x%Ix - 0x%Ix)", processItem->ProcessName->Buffer, HandleToUlong(context->ProcessId), context->BaseAddress, (ULONG_PTR)context->BaseAddress + context->RegionSize)->Buffer); PhDereferenceObject(processItem); } } PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB { PhShowError(NULL, L"Unable to edit the memory region because it is too large."); return TRUE; } if (!NT_SUCCESS(status = PhOpenProcess( &context->ProcessHandle, PROCESS_VM_READ, context->ProcessId ))) { PhShowStatus(NULL, L"Unable to open the process", status, 0); return TRUE; } context->Buffer = PhAllocatePage(context->RegionSize, NULL); if (!context->Buffer) { PhShowError(NULL, L"Unable to allocate memory for the buffer."); return TRUE; } if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(PhMainWndHandle, L"Unable to read memory", status, 0); return TRUE; } PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), 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_BYTESPERROW), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GOTO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_WRITE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REREAD), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 290; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } context->HexEditHandle = GetDlgItem(hwndDlg, IDC_MEMORY); PhAddLayoutItem(&context->LayoutManager, context->HexEditHandle, NULL, PH_ANCHOR_ALL); HexEdit_SetBuffer(context->HexEditHandle, context->Buffer, (ULONG)context->RegionSize); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemEditPosition"); windowRectangle.Size = PhGetScalableIntegerPairSetting(L"MemEditSize", TRUE).Pair; PhAdjustRectangleToWorkingArea(NULL, &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"MemEditPosition", windowRectangle.Position); PhSetScalableIntegerPairSetting2(L"MemEditSize", windowRectangle.Size); } { PWSTR bytesPerRowStrings[7]; ULONG i; ULONG bytesPerRow; for (i = 0; i < sizeof(bytesPerRowStrings) / sizeof(PWSTR); i++) bytesPerRowStrings[i] = PhaFormatString(L"%u bytes per row", 1 << (2 + i))->Buffer; PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_BYTESPERROW), bytesPerRowStrings, sizeof(bytesPerRowStrings) / sizeof(PWSTR)); bytesPerRow = PhGetIntegerSetting(L"MemEditBytesPerRow"); if (bytesPerRow >= 4) { HexEdit_SetBytesPerRow(context->HexEditHandle, bytesPerRow); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_BYTESPERROW), PhaFormatString(L"%u bytes per row", bytesPerRow)->Buffer, FALSE); } } context->LoadCompleted = TRUE; } break; case WM_DESTROY: { if (context->LoadCompleted) { PhSaveWindowPlacementToSetting(L"MemEditPosition", L"MemEditSize", hwndDlg); PhRemoveElementAvlTree(&PhMemoryEditorSet, &context->Links); PhUnregisterDialog(hwndDlg); } RemoveProp(hwndDlg, PhMakeContextAtom()); PhDeleteLayoutManager(&context->LayoutManager); if (context->Buffer) PhFreePage(context->Buffer); if (context->ProcessHandle) NtClose(context->ProcessHandle); PhClearReference(&context->Title); if ((context->Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && context->ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), context->BaseAddress); PhFree(context); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_PROCESS_ITEM processItem; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); if (!context->Title && (processItem = PhReferenceProcessItem(context->ProcessId))) { PhSetFileDialogFileName(fileDialog, PhaFormatString(L"%s_0x%Ix-0x%Ix.bin", processItem->ProcessName->Buffer, context->BaseAddress, context->RegionSize)->Buffer); PhDereferenceObject(processItem); } else { PhSetFileDialogFileName(fileDialog, L"Memory.bin"); } if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { status = PhWriteFileStream(fileStream, context->Buffer, (ULONG)context->RegionSize); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_GOTO: { PPH_STRING selectedChoice = NULL; while (PhaChoiceDialog( hwndDlg, L"Go to Offset", L"Enter an offset:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemEditGotoChoices" )) { ULONG64 offset; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &offset)) { if (offset >= context->RegionSize) { PhShowError(hwndDlg, L"The offset is too large."); continue; } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); HexEdit_SetSel(context->HexEditHandle, (LONG)offset, (LONG)offset); break; } } } break; case IDC_WRITE: { NTSTATUS status; if (!context->WriteAccess) { HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ | PROCESS_VM_WRITE, context->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } if (context->ProcessHandle) NtClose(context->ProcessHandle); context->ProcessHandle = processHandle; context->WriteAccess = TRUE; } if (!NT_SUCCESS(status = PhWriteVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to write memory", status, 0); } } break; case IDC_REREAD: { NTSTATUS status; if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to read memory", status, 0); } InvalidateRect(context->HexEditHandle, NULL, TRUE); } break; case IDC_BYTESPERROW: if (HIWORD(wParam) == CBN_SELCHANGE) { PPH_STRING bytesPerRowString = PhaGetDlgItemText(hwndDlg, IDC_BYTESPERROW); PH_STRINGREF firstPart; PH_STRINGREF secondPart; ULONG64 bytesPerRow64; if (PhSplitStringRefAtChar(&bytesPerRowString->sr, ' ', &firstPart, &secondPart)) { if (PhStringToInteger64(&firstPart, 10, &bytesPerRow64)) { PhSetIntegerSetting(L"MemEditBytesPerRow", (ULONG)bytesPerRow64); HexEdit_SetBytesPerRow(context->HexEditHandle, (ULONG)bytesPerRow64); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SELECT_OFFSET: { HexEdit_SetEditMode(context->HexEditHandle, EDIT_ASCII); HexEdit_SetSel(context->HexEditHandle, (ULONG)wParam, (ULONG)wParam + (ULONG)lParam); } break; } return FALSE; }
/*********************************************************************** * UnmapViewOfFile (KERNEL32.@) * * Unmaps a mapped view of a file. * * PARAMS * addr [I] Address where mapped view begins. * * RETURNS * Success: TRUE. * Failure: FALSE. * */ BOOL WINAPI UnmapViewOfFile( LPCVOID addr ) { NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; }
static NTSTATUS TH32CreateSnapshotSectionInitialize(DWORD dwFlags, DWORD th32ProcessID, PRTL_DEBUG_INFORMATION HeapDebug, PRTL_DEBUG_INFORMATION ModuleDebug, PVOID ProcThrdInfo, HANDLE *SectionHandle) { PSYSTEM_PROCESS_INFORMATION ProcessInfo; LPHEAPLIST32 HeapListEntry; LPMODULEENTRY32W ModuleListEntry; LPPROCESSENTRY32W ProcessListEntry; LPTHREADENTRY32 ThreadListEntry; OBJECT_ATTRIBUTES ObjectAttributes; LARGE_INTEGER SSize, SOffset; HANDLE hSection; PTH32SNAPSHOT Snapshot; ULONG_PTR DataOffset; SIZE_T ViewSize; ULONG i, nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0; ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT); PRTL_PROCESS_HEAPS hi = NULL; PRTL_PROCESS_MODULES mi = NULL; NTSTATUS Status = STATUS_SUCCESS; /* * Determine the required size for the heap snapshot */ if(dwFlags & TH32CS_SNAPHEAPLIST) { hi = (PRTL_PROCESS_HEAPS)HeapDebug->Heaps; nHeaps = hi->NumberOfHeaps; RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32); } /* * Determine the required size for the module snapshot */ if(dwFlags & TH32CS_SNAPMODULE) { mi = (PRTL_PROCESS_MODULES)ModuleDebug->Modules; nModules = mi->NumberOfModules; RequiredSnapshotSize += nModules * sizeof(MODULEENTRY32W); } /* * Determine the required size for the processes and threads snapshot */ if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD)) { ULONG ProcOffset = 0; ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; do { ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); nProcesses++; nThreads += ProcessInfo->NumberOfThreads; ProcOffset = ProcessInfo->NextEntryOffset; } while(ProcOffset != 0); if(dwFlags & TH32CS_SNAPPROCESS) { RequiredSnapshotSize += nProcesses * sizeof(PROCESSENTRY32W); } if(dwFlags & TH32CS_SNAPTHREAD) { RequiredSnapshotSize += nThreads * sizeof(THREADENTRY32); } } /* * Create and map the section */ SSize.QuadPart = RequiredSnapshotSize; InitializeObjectAttributes(&ObjectAttributes, NULL, ((dwFlags & TH32CS_INHERIT) ? OBJ_INHERIT : 0), NULL, NULL); Status = NtCreateSection(&hSection, SECTION_ALL_ACCESS, &ObjectAttributes, &SSize, PAGE_READWRITE, SEC_COMMIT, NULL); if(!NT_SUCCESS(Status)) { return Status; } SOffset.QuadPart = 0; ViewSize = 0; Snapshot = NULL; Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&Snapshot, 0, 0, &SOffset, &ViewSize, ViewShare, 0, PAGE_READWRITE); if(!NT_SUCCESS(Status)) { NtClose(hSection); return Status; } RtlZeroMemory(Snapshot, sizeof(TH32SNAPSHOT)); DataOffset = 0; /* * Initialize the section data and fill it with all the data we collected */ /* initialize the heap list */ if(dwFlags & TH32CS_SNAPHEAPLIST) { Snapshot->HeapListCount = nHeaps; Snapshot->HeapListOffset = DataOffset; HeapListEntry = (LPHEAPLIST32)OffsetToPtr(Snapshot, DataOffset); for(i = 0; i < nHeaps; i++) { HeapListEntry->dwSize = sizeof(HEAPLIST32); HeapListEntry->th32ProcessID = th32ProcessID; HeapListEntry->th32HeapID = (ULONG_PTR)hi->Heaps[i].BaseAddress; HeapListEntry->dwFlags = hi->Heaps[i].Flags; HeapListEntry++; } DataOffset += hi->NumberOfHeaps * sizeof(HEAPLIST32); } /* initialize the module list */ if(dwFlags & TH32CS_SNAPMODULE) { Snapshot->ModuleListCount = nModules; Snapshot->ModuleListOffset = DataOffset; ModuleListEntry = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, DataOffset); for(i = 0; i < nModules; i++) { ModuleListEntry->dwSize = sizeof(MODULEENTRY32W); ModuleListEntry->th32ModuleID = 1; /* no longer used, always set to one! */ ModuleListEntry->th32ProcessID = th32ProcessID; ModuleListEntry->GlblcntUsage = mi->Modules[i].LoadCount; ModuleListEntry->ProccntUsage = mi->Modules[i].LoadCount; ModuleListEntry->modBaseAddr = (BYTE*)mi->Modules[i].ImageBase; ModuleListEntry->modBaseSize = mi->Modules[i].ImageSize; ModuleListEntry->hModule = (HMODULE)mi->Modules[i].ImageBase; MultiByteToWideChar(CP_ACP, 0, &mi->Modules[i].FullPathName[mi->Modules[i].OffsetToFileName], -1, ModuleListEntry->szModule, sizeof(ModuleListEntry->szModule) / sizeof(ModuleListEntry->szModule[0])); MultiByteToWideChar(CP_ACP, 0, mi->Modules[i].FullPathName, -1, ModuleListEntry->szExePath, sizeof(ModuleListEntry->szExePath) / sizeof(ModuleListEntry->szExePath[0])); ModuleListEntry++; } DataOffset += mi->NumberOfModules * sizeof(MODULEENTRY32W); } /* initialize the process list */ if(dwFlags & TH32CS_SNAPPROCESS) { ULONG ProcOffset = 0; Snapshot->ProcessListCount = nProcesses; Snapshot->ProcessListOffset = DataOffset; ProcessListEntry = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, DataOffset); ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; do { ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W); ProcessListEntry->cntUsage = 0; /* no longer used */ ProcessListEntry->th32ProcessID = (ULONG_PTR)ProcessInfo->UniqueProcessId; ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */ ProcessListEntry->th32ModuleID = 0; /* no longer used */ ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads; ProcessListEntry->th32ParentProcessID = (ULONG_PTR)ProcessInfo->InheritedFromUniqueProcessId; ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority; ProcessListEntry->dwFlags = 0; /* no longer used */ if(ProcessInfo->ImageName.Buffer != NULL) { lstrcpynW(ProcessListEntry->szExeFile, ProcessInfo->ImageName.Buffer, min(ProcessInfo->ImageName.Length / sizeof(WCHAR), sizeof(ProcessListEntry->szExeFile) / sizeof(ProcessListEntry->szExeFile[0]))); } else { lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]"); } ProcessListEntry++; ProcOffset = ProcessInfo->NextEntryOffset; } while(ProcOffset != 0); DataOffset += nProcesses * sizeof(PROCESSENTRY32W); } /* initialize the thread list */ if(dwFlags & TH32CS_SNAPTHREAD) { ULONG ProcOffset = 0; Snapshot->ThreadListCount = nThreads; Snapshot->ThreadListOffset = DataOffset; ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset); ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; do { PSYSTEM_THREAD_INFORMATION ThreadInfo; ULONG n; ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1); for(n = 0; n < ProcessInfo->NumberOfThreads; n++) { ThreadListEntry->dwSize = sizeof(THREADENTRY32); ThreadListEntry->cntUsage = 0; /* no longer used */ ThreadListEntry->th32ThreadID = (ULONG_PTR)ThreadInfo->ClientId.UniqueThread; ThreadListEntry->th32OwnerProcessID = (ULONG_PTR)ThreadInfo->ClientId.UniqueProcess; ThreadListEntry->tpBasePri = ThreadInfo->BasePriority; ThreadListEntry->tpDeltaPri = 0; /* no longer used */ ThreadListEntry->dwFlags = 0; /* no longer used */ ThreadInfo++; ThreadListEntry++; } ProcOffset = ProcessInfo->NextEntryOffset; } while(ProcOffset != 0); } /* * We're done, unmap the view and return the section handle */ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); if(NT_SUCCESS(Status)) { *SectionHandle = hSection; } else { NtClose(hSection); } return Status; }