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); }
static NTSTATUS PhpDuplicateHandleFromProcessItem( _Out_ PHANDLE NewHandle, _In_ ACCESS_MASK DesiredAccess, _In_ HANDLE ProcessId, _In_ HANDLE Handle ) { NTSTATUS status; HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, ProcessId ))) return status; status = NtDuplicateObject( processHandle, Handle, NtCurrentProcess(), NewHandle, DesiredAccess, 0, 0 ); NtClose(processHandle); return status; }
ULONG BaseSrvCreateThread( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus ) { PBASE_CREATETHREAD_MSG a = (PBASE_CREATETHREAD_MSG)&m->u.ApiMessageData; HANDLE Thread; NTSTATUS Status; PCSR_PROCESS Process; PCSR_THREAD t; t = CSR_SERVER_QUERYCLIENTTHREAD(); Process = t->Process; if (Process->ClientId.UniqueProcess != a->ClientId.UniqueProcess) { if ( a->ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess ) { return STATUS_SUCCESS; } Status = CsrLockProcessByClientId( a->ClientId.UniqueProcess, &Process ); if (!NT_SUCCESS( Status )) { return( Status ); } } // // Get handles to the thread local to the // Windows server. // Status = NtDuplicateObject( t->Process->ProcessHandle, a->ThreadHandle, NtCurrentProcess(), &Thread, 0L, 0L, DUPLICATE_SAME_ACCESS ); if ( NT_SUCCESS(Status) ) { Status = CsrCreateThread( Process, Thread, &a->ClientId ); } if (Process != t->Process) { CsrUnlockProcess( Process ); } return( (ULONG)Status ); ReplyStatus; // get rid of unreferenced parameter warning message }
ULONG BaseSrvNlsPreserveSection( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus) { PBASE_NLS_PRESERVE_SECTION_MSG a = (PBASE_NLS_PRESERVE_SECTION_MSG)&m->u.ApiMessageData; HANDLE hSection = (HANDLE)0; /* section handle */ HANDLE hProcess = (HANDLE)0; /* process handle */ OBJECT_ATTRIBUTES ObjA; /* object attributes structure */ NTSTATUS rc = 0L; /* return code */ /* * Duplicate the section handle for the server. */ InitializeObjectAttributes(&ObjA, NULL, 0, NULL, NULL); rc = NtOpenProcess(&hProcess, PROCESS_DUP_HANDLE, &ObjA, &m->h.ClientId); if (!NT_SUCCESS(rc)) { KdPrint(("NLSAPI (BaseSrv): Could NOT Open Process - %lx.\n", rc)); return (rc); } /* * The hSection value will not be used for anything. However, * it must remain open so that the object remains permanent. */ rc = NtDuplicateObject(hProcess, a->hSection, NtCurrentProcess(), &hSection, 0L, 0L, DUPLICATE_SAME_ACCESS); /* * Return the return value from NtDuplicateObject. */ return (rc); ReplyStatus; // get rid of unreferenced parameter warning message }
/* * @implemented */ BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions) { NTSTATUS Status; HANDLE hTargetHandle; hSourceHandle = TranslateStdHandle(hSourceHandle); if ((IsConsoleHandle(hSourceHandle)) && ((hSourceHandle != NtCurrentProcess()) && (hSourceHandle != NtCurrentThread()))) { if ((hSourceProcessHandle != NtCurrentProcess()) && (hTargetProcessHandle != NtCurrentProcess())) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } hTargetHandle = DuplicateConsoleHandle(hSourceHandle, dwDesiredAccess, bInheritHandle, dwOptions); if (hTargetHandle != INVALID_HANDLE_VALUE) { if (lpTargetHandle) *lpTargetHandle = hTargetHandle; return TRUE; } return FALSE; } Status = NtDuplicateObject(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle ? OBJ_INHERIT : 0, dwOptions); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
NTSTATUS BaseSrvNlsConnect( PCSR_PROCESS Process, PVOID pConnectionInfo, PULONG pConnectionInfoLength) { /* * Duplicate the mutant handle. */ return ( NtDuplicateObject(NtCurrentProcess(), hNlsCacheMutant, Process->ProcessHandle, (PHANDLE)pConnectionInfo, SYNCHRONIZE, 0L, 0L ) ); }
/* * @implemented */ BOOL WINAPI DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions) { DWORD SourceProcessId, TargetProcessId; NTSTATUS Status; hSourceHandle = TranslateStdHandle(hSourceHandle); if (IsConsoleHandle(hSourceHandle)) { SourceProcessId = GetProcessId(hSourceProcessHandle); TargetProcessId = GetProcessId(hTargetProcessHandle); if (!SourceProcessId || !TargetProcessId || SourceProcessId != TargetProcessId || SourceProcessId != GetCurrentProcessId()) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } *lpTargetHandle = DuplicateConsoleHandle(hSourceHandle, dwDesiredAccess, bInheritHandle, dwOptions); return *lpTargetHandle != INVALID_HANDLE_VALUE; } Status = NtDuplicateObject(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle ? OBJ_INHERIT : 0, dwOptions); if (!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); return FALSE; } return TRUE; }
NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent) { NTSTATUS Status; /* Create the event */ Status = NtCreateEvent(ServerEvent, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); if (!NT_SUCCESS(Status)) return Status; /* Duplicate the event into the client process */ Status = NtDuplicateObject(NtCurrentProcess(), *ServerEvent, CsrGetClientThread()->Process->ProcessHandle, ClientEvent, 0, 0, DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) NtClose(*ServerEvent); return Status; }
IHFSERVICE DWORD IHFAPI IHF_ActiveDetachProcess(DWORD pid) { DWORD module, engine, dwWrite; HANDLE hProc, hThread, hCmd; IO_STATUS_BLOCK ios; //man->LockHookman(); ProcessRecord* pr = man->GetProcessRecord(pid); hCmd = man->GetCmdHandleByPID(pid); if (pr == 0 || hCmd == 0) return FALSE; //hProc = pr->process_handle; //This handle may be closed(thus invalid) during the detach process. NtDuplicateObject(NtCurrentProcess(), pr->process_handle, NtCurrentProcess(), &hProc, 0, 0, DUPLICATE_SAME_ACCESS); //Make a copy of the process handle. module = pr->module_register; if (module == 0) return FALSE; engine = pr->engine_register; engine &= ~0xFF; SendParam sp = {}; sp.type = 4; NtWriteFile(hCmd, 0,0,0, &ios, &sp, sizeof(SendParam),0,0); //cmdq->AddRequest(sp, pid); dwWrite = 0x1000; hThread = IthCreateThread(LdrUnloadDll, engine, hProc); if (hThread == 0 || hThread == INVALID_HANDLE_VALUE) return FALSE; NtWaitForSingleObject(hThread, 0, 0); NtClose(hThread); hThread = IthCreateThread(LdrUnloadDll, module, hProc); if (hThread == 0 || hThread == INVALID_HANDLE_VALUE) return FALSE; NtWaitForSingleObject(hThread, 0, 0); //man->UnlockHookman(); THREAD_BASIC_INFORMATION info; NtQueryInformationThread(hThread, ThreadBasicInformation, &info, sizeof(info), 0); NtClose(hThread); NtSetEvent(hPipeExist, 0); FreeThreadStart(hProc); NtClose(hProc); dwWrite = 0x1000; return info.ExitStatus; }
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; }
int wmain(int argc, WCHAR *argv[]) { /* Display welcome message */ printf("handle_monitor %s - Adam Kramer\n", VERSION_NUMBER); /* These variables hold configuration options, which can be altered by arguments passed */ BOOL bIncludeSigned = FALSE; BOOL bSuspendProcess = FALSE; BOOL bVerbose = FALSE; DWORD dNumberCycles = 10; DWORD dHandleChangeThreshold = 10; DWORD dIterationPause = 1000; /* Process arguments */ if (argc > 1) { for (int iNumberArgs = 1; iNumberArgs < argc; iNumberArgs++) { /* /signed - will include signed files in the alerts */ if (!wcscmp(argv[iNumberArgs], L"/signed")) { bIncludeSigned = TRUE; printf("Info: Will show signed files as well as unsigned\n"); } /* /suspect - will attempt to suspend suspicious processes */ else if (!wcscmp(argv[iNumberArgs], L"/suspend")) { bSuspendProcess = TRUE; printf("Info: Will attempt to suspend suspicious processes\n"); } /* /verbose - will display details of iterations and hidden results */ else if (!wcscmp(argv[iNumberArgs], L"/verbose")) { bVerbose = TRUE; printf("Info: Will display verbose status messages\n"); } /* /cycles - allows the user to set cycles completed before analysis */ else if (WCHAR* wSetCycles = wcsstr(argv[iNumberArgs], L"/cycles=")) { wSetCycles = wcschr(wSetCycles, '='); if (!(dNumberCycles = _wtol(++wSetCycles))) { printf("Error: Invalid /cycles parameter\n"); return 1; } printf("Info: Setting number of cycles to %d\n", dNumberCycles); } /* /threshold - allows the user to set the threshold for minimum number of new handles which are suspicious */ else if (WCHAR* wSetThreshold = wcsstr(argv[iNumberArgs], L"/threshold=")) { wSetThreshold = wcschr(wSetThreshold, '='); if (!(dHandleChangeThreshold = _wtol(++wSetThreshold))) { printf("Error: Invalid /threshold parameter\n"); return 1; } printf("Info: Setting handle threshold to %d\n", dHandleChangeThreshold); } /* /pause - allows the user to set a pause between cycles (reduce system load, increase window for finding something) */ else if (WCHAR* wSetPause = wcsstr(argv[iNumberArgs], L"/pause=")) { wSetPause = wcschr(wSetPause, '='); dIterationPause = _wtol(++wSetPause); printf("Info: Setting pause between cycles to %dms\n", dIterationPause); } } /* End of argument processing */ } else { /* No argument passed, accordingly display the usage instructions */ printf("Usage: handle_monitor.exe <optional parameters>\n\n"); printf("Optional parameters:\n"); printf("/cycles=X - Set number of cycles before a review [Default: 10]\n"); printf("/threshold=X - Set suspicion threshold for number of new handles [Default: 10]\n"); printf("/pause=X - Set pause in milliseconds between cycles [Default: 1000]\n"); printf("/signed - Include signed executables in review process\n"); printf("/suspend - Suspend processes identified as suspicious\n"); printf("/verbose - Display verbose progress messages\n\n"); printf("Info: No parameters specified, launching monitoring (Ctrl+C to stop)\n"); } /* Import functions manually from NTDLL */ _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryObject"); /* Master loop! - This runs forever until a user presses Ctrl+C */ for (;;) { /* Update user that process is starting (if /verbose mode activiated) */ if (bVerbose) printf("Verbose Info: Starting sequence\n"); /* Variables used for retrieving handles */ NTSTATUS status; ULONG handleInfoSize = 0x10000; HANDLE processHandle; ULONG i; PSYSTEM_HANDLE_INFORMATION handleInfo; /* Used in each handle iteration to identify the index in iProcessArray of the specific process */ int iCurrentProcess_ArrayIndex = -1; /* Handle array - PROCESS INDEX / HANDLE NUMBER / TEXT OF HANDLE This holds all handles which have been found per process */ auto cHandleArray = new WCHAR[MAX_PROCESSES][MAX_FILE_HANDLES][MAX_PATH](); signed int iProcessArray[MAX_PROCESSES][3] = { 0 }; /* Set process array to -1, which indicates nothing has been set */ for (int j = 0; j < (MAX_PROCESSES - 1); j++) iProcessArray[j][0] = -1; /* Loop dNumberCycles [default: 10] times before analysing result */ for (unsigned int iCycleCounter = 1; iCycleCounter <= dNumberCycles; iCycleCounter++) { handleInfoSize = 0x10000; handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { printf("NtQuerySystemInformation failed!\n"); return 1; } /* Loop for each handle on the system, processing it accordingly... */ for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; /* Open a handle to the process associated with the handle */ if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.ProcessId))) continue; /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, GENERIC_READ, 0, 0))) { CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* Query the object type */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject(dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL))) { free(objectTypeInfo); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* If it's not a file handle, go to next one (as we're only interested in file handles) */ if (wcscmp(objectTypeInfo->Name.Buffer, L"File")) { free(objectTypeInfo); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* Identify the filename from the handle we're looking at */ WCHAR* wHandleFileName = new WCHAR[MAX_PATH](); if (!GetFileNameFromHandle(dupHandle, wHandleFileName)) { free(objectTypeInfo); free(wHandleFileName); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* This is where we add our findings to the database */ iCurrentProcess_ArrayIndex = -1; /* Check whether we've already got an entry for the process we're looking at */ for (int j = 0; j < (MAX_PROCESSES - 1); j++) if (iProcessArray[j][PROCESS_ARRAY_INDEX] == handle.ProcessId) iCurrentProcess_ArrayIndex = j; /* If not, create a new entry for the process associated with the current handle */ if (iCurrentProcess_ArrayIndex == -1) for (int j = 0; j < (MAX_PROCESSES - 1); j++) if (iProcessArray[j][PROCESS_ARRAY_INDEX] == -1) { iProcessArray[j][PROCESS_ARRAY_INDEX] = handle.ProcessId; iCurrentProcess_ArrayIndex = j; break; } /* If there's more than MAX_PROCESSES, throw an error TODO: Tidy this up, identify number of running processes dynamically and set array size accordingly */ if (iCurrentProcess_ArrayIndex == -1) { printf("Error: Too many processes running!\n"); return 1; } /* Look through the handle array, to see whether the filename can be found */ WCHAR cCurrentHandleText[MAX_PATH]; for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) { /* If we hit NULL, there are no more to find, so add ours */ swprintf_s(cCurrentHandleText, MAX_PATH, L"%ls", wHandleFileName); if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){ wcscpy_s(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText); break; } /* If we find ours, then stop searching */ else if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText)) break; } /* If it's the first (or last) cycle, tally how many entries in the handle array for this particular process we have so far */ if (iCycleCounter == 1) for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){ iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_START_CYCLE] = (j - 1); break; } if (iCycleCounter == dNumberCycles) for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")) { iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_END_CYCLE] = (j - 1); break; } free(objectTypeInfo); free(wHandleFileName); CloseHandle(dupHandle); CloseHandle(processHandle); } free(handleInfo); /* If the iteration pause is not 0, sleep for the requested time [Default: 1000ms] */ if (dIterationPause) Sleep(dIterationPause); /* If /verbose active - inform user which cycle we are on */ if (bVerbose) if (iCycleCounter == 1) printf("Verbose Info: Completed cycle %d", iCycleCounter); else if (iCycleCounter == dNumberCycles) printf(" %d\n", iCycleCounter); else printf(" %d", iCycleCounter); } /* If /verbose active - inform user we are now starting a review */ if (bVerbose) printf("Verbose Info: Cycles completed, beginning review\n"); /* Check if any of them met threshold*/ for (int j = 0; j < (MAX_PROCESSES - 1); j++) { if (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] < iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]) continue; /* dHandleDelta is the difference between number of handles for a process from first cycle to the last one */ DWORD dHandleDelta = (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] - iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]); /* Check whether the delta is equal or above the threshold */ if (dHandleDelta >= dHandleChangeThreshold) { HANDLE pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, iProcessArray[j][PROCESS_ARRAY_INDEX]); TCHAR tProcessName[MAX_PATH]; GetModuleFileNameEx(pHandle, 0, tProcessName, MAX_PATH); CloseHandle(pHandle); /* If we don't want signed, yet it is signed, skip... */ if (!bIncludeSigned && (is_signed(tProcessName) == 0)) { if (bVerbose) wprintf(L"Verbose Info: Skipping alert on %s (%d) despite trigger, as it is signed (use /signed to alert on signed executables too)\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX]); continue; } /* Inform the user if we have a suspicious process */ wprintf(L"Alert! Process: %s (%d) has had a suspicious number of handles (%d) created in the last cycle\nNew handles created during this cycle:\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX], dHandleDelta); for (DWORD k = 1; k <= dHandleDelta; k++) wprintf(L"%s\n", cHandleArray[j][iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE] + k]); if (bSuspendProcess) { printf("Info: Attempting to suspend process %d\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); /* Attach debugger to process (freeze it!)*/ if (!DebugActiveProcess(iProcessArray[j][PROCESS_ARRAY_INDEX])) { printf("Info: Could not attach to process %d as a debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); } else { DebugSetProcessKillOnExit(FALSE); printf("Info: Successfully attached to process %d as debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); printf("Info: It will remain frozen until this process is terminated\n"); } } printf("------------------------------------------------------------------------------\n"); } } if (bVerbose) printf("Verbose Info: Review complete\n"); free(cHandleArray); } return 0; }
VOID GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, BOOL Defaults) { NTSTATUS Status; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL, hClientSection = NULL; PVOID ThreadParameter = NULL; // Is either hClientSection or the console window handle, // depending on whether we display the default settings or // the settings of a particular console. DPRINT("GuiConsoleShowConsoleProperties entered\n"); if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* * Be sure we effectively have a properties dialog routine (that launches * the console control panel applet). It resides in kernel32.dll (client). */ if (ProcessData->PropRoutine == NULL) goto Quit; /* * Create a memory section to be shared with the console control panel applet * in the case we are displaying the settings of a particular console. * In that case the ThreadParameter is the hClientSection handle. * In the case we display the default console parameters, we don't need to * create a memory section. We just need to open the applet, and in this case * the ThreadParameter is the parent window handle of the applet's window, * that is, the console window. */ if (!Defaults) { PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer; LARGE_INTEGER SectionSize; ULONG ViewSize = 0; PCONSOLE_STATE_INFO pSharedInfo = NULL; /* * Create a memory section to share with the applet, and map it. */ SectionSize.QuadPart = sizeof(CONSOLE_STATE_INFO); // Standard size SectionSize.QuadPart += Console->OriginalTitle.Length; // Add the length in bytes of the console title string 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. */ /* Store the real size of the structure */ pSharedInfo->cbSize = SectionSize.QuadPart; /* * When we setup the settings of a particular console, the parent window * of the applet's window is the console window, and it is given via the * hWnd member of the shared console info structure. */ pSharedInfo->hWnd = GuiData->hWindow; /* Console information */ pSharedInfo->HistoryBufferSize = Console->HistoryBufferSize; pSharedInfo->NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers; pSharedInfo->HistoryNoDup = Console->HistoryNoDup; pSharedInfo->QuickEdit = Console->QuickEdit; pSharedInfo->InsertMode = Console->InsertMode; /// pSharedInfo->InputBufferSize = 0; pSharedInfo->ScreenBufferSize = ActiveBuffer->ScreenBufferSize; pSharedInfo->WindowSize = ActiveBuffer->ViewSize; pSharedInfo->CursorSize = ActiveBuffer->CursorInfo.dwSize; if (GetType(ActiveBuffer) == TEXTMODE_BUFFER) { PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)ActiveBuffer; pSharedInfo->ScreenAttributes = Buffer->ScreenDefaultAttrib; pSharedInfo->PopupAttributes = 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->ScreenAttributes = DEFAULT_SCREEN_ATTRIB; pSharedInfo->PopupAttributes = DEFAULT_POPUP_ATTRIB ; } /// pSharedInfo->CodePage; /* GUI Information */ wcsncpy(pSharedInfo->FaceName, GuiData->GuiInfo.FaceName, LF_FACESIZE); pSharedInfo->FaceName[LF_FACESIZE - 1] = UNICODE_NULL; pSharedInfo->FontFamily = GuiData->GuiInfo.FontFamily; pSharedInfo->FontSize = GuiData->GuiInfo.FontSize; pSharedInfo->FontWeight = GuiData->GuiInfo.FontWeight; pSharedInfo->FullScreen = GuiData->GuiInfo.FullScreen; pSharedInfo->AutoPosition = GuiData->GuiInfo.AutoPosition; pSharedInfo->WindowPosition = GuiData->GuiInfo.WindowOrigin; /* Palette */ RtlCopyMemory(pSharedInfo->ColorTable, Console->Colors, sizeof(Console->Colors)); /* Copy the original title of the console and null-terminate it */ RtlCopyMemory(pSharedInfo->ConsoleTitle, Console->OriginalTitle.Buffer, Console->OriginalTitle.Length); pSharedInfo->ConsoleTitle[Console->OriginalTitle.Length / sizeof(WCHAR)] = UNICODE_NULL; /* Unmap the view */ NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); /* 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; } /* For the settings of a particular console, use the shared client section handle as the thread parameter */ ThreadParameter = (PVOID)hClientSection; } else { /* For the default settings, use the console window handle as the thread parameter */ ThreadParameter = (PVOID)GuiData->hWindow; } /* Start the console control panel applet */ _SEH2_TRY { HANDLE Thread = NULL; _SEH2_TRY { Thread = CreateRemoteThread(ProcessData->Process->ProcessHandle, NULL, 0, ProcessData->PropRoutine, ThreadParameter, 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); } } _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; Quit: /* We have finished, close the section handle if any */ if (hSection) NtClose(hSection); LeaveCriticalSection(&Console->Lock); return; }
VOID PropertiesDlgShow( IN PCONSOLE_INFORMATION Console ) /*++ Displays the properties dialog and updates the window state, if necessary. --*/ { HANDLE hSection = NULL; HANDLE hClientSection = NULL; HANDLE hThread; ULONG ulViewSize; LARGE_INTEGER li; NTSTATUS Status; PCONSOLE_STATE_INFO pStateInfo; PCONSOLE_PROCESS_HANDLE ProcessHandleRecord; PSCREEN_INFORMATION ScreenInfo; LPTHREAD_START_ROUTINE MyPropRoutine; /* * Create a shared memory block. */ li.QuadPart = sizeof(CONSOLE_STATE_INFO) + Console->OriginalTitleLength; Status = NtCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &li, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(Status)) { KdPrint(("CONSRV: error %x creating file mapping\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_READWRITE); if (!NT_SUCCESS(Status)) { KdPrint(("CONSRV: error %x mapping view of file\n", Status)); NtClose(hSection); return; } /* * Fill in the shared memory block with the current values. */ ScreenInfo = Console->CurrentScreenBuffer; pStateInfo->Length = li.LowPart; pStateInfo->ScreenBufferSize = ScreenInfo->ScreenBufferSize; pStateInfo->WindowSize.X = CONSOLE_WINDOW_SIZE_X(ScreenInfo); pStateInfo->WindowSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo); pStateInfo->WindowPosX = Console->WindowRect.left; pStateInfo->WindowPosY = Console->WindowRect.top; if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) { pStateInfo->FontSize = SCR_FONTSIZE(ScreenInfo); pStateInfo->FontFamily = SCR_FAMILY(ScreenInfo); pStateInfo->FontWeight = SCR_FONTWEIGHT(ScreenInfo); wcscpy(pStateInfo->FaceName, SCR_FACENAME(ScreenInfo)); pStateInfo->CursorSize = ScreenInfo->BufferInfo.TextInfo.CursorSize; } pStateInfo->FullScreen = Console->FullScreenFlags & CONSOLE_FULLSCREEN; pStateInfo->QuickEdit = Console->Flags & CONSOLE_QUICK_EDIT_MODE; pStateInfo->AutoPosition = Console->Flags & CONSOLE_AUTO_POSITION; pStateInfo->InsertMode = Console->InsertMode; pStateInfo->ScreenAttributes = ScreenInfo->Attributes; pStateInfo->PopupAttributes = ScreenInfo->PopupAttributes; pStateInfo->HistoryBufferSize = Console->CommandHistorySize; pStateInfo->NumberOfHistoryBuffers = Console->MaxCommandHistories; pStateInfo->HistoryNoDup = Console->Flags & CONSOLE_HISTORY_NODUP; RtlCopyMemory(pStateInfo->ColorTable, Console->ColorTable, sizeof(Console->ColorTable)); pStateInfo->hWnd = Console->hWnd; wcscpy(pStateInfo->ConsoleTitle, Console->OriginalTitle); NtUnmapViewOfSection(NtCurrentProcess(), pStateInfo); /* * Map the shared memory block handle into the client side process's * address space. */ ProcessHandleRecord = CONTAINING_RECORD(Console->ProcessHandleList.Blink, CONSOLE_PROCESS_HANDLE, ListLink); Status = NtDuplicateObject(NtCurrentProcess(), hSection, ProcessHandleRecord->ProcessHandle, &hClientSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { KdPrint(("CONSRV: error %x mapping handle to client\n", Status)); NtClose(hSection); return; } /* * Get a pointer to the client-side properties routine. */ if (ProcessHandleRecord->PropRoutine) { MyPropRoutine = ProcessHandleRecord->PropRoutine; } else { MyPropRoutine = PropRoutine; } /* * Call back into the client process to spawn the properties dialog. */ UnlockConsole(Console); hThread = InternalCreateCallbackThread(ProcessHandleRecord->ProcessHandle, (DWORD)MyPropRoutine, (DWORD)hClientSection); if (!hThread) { KdPrint(("CONSRV: CreateRemoteThread failed %d\n", GetLastError())); } LockConsole(Console); /* * Close any open handles and free allocated memory. */ if (hThread) NtClose(hThread); if (hSection) NtClose(hSection); return; }
NTSTATUS NTAPI SmpExecPgm(IN PSM_API_MSG SmApiMsg, IN PSMP_CLIENT_CONTEXT ClientContext, IN HANDLE SmApiPort) { HANDLE ProcessHandle; NTSTATUS Status; PSM_EXEC_PGM_MSG SmExecPgm; RTL_USER_PROCESS_INFORMATION ProcessInformation; OBJECT_ATTRIBUTES ObjectAttributes; /* Open the client process */ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); Status = NtOpenProcess(&ProcessHandle, PROCESS_DUP_HANDLE, &ObjectAttributes, &SmApiMsg->h.ClientId); if (!NT_SUCCESS(Status)) { /* Fail */ DPRINT1("SmExecPgm: NtOpenProcess Failed %lx\n", Status); return Status; } /* Copy the process information out of the message */ SmExecPgm = &SmApiMsg->u.ExecPgm; ProcessInformation = SmExecPgm->ProcessInformation; /* Duplicate the process handle */ Status = NtDuplicateObject(ProcessHandle, SmExecPgm->ProcessInformation.ProcessHandle, NtCurrentProcess(), &ProcessInformation.ProcessHandle, PROCESS_ALL_ACCESS, 0, 0); if (!NT_SUCCESS(Status)) { /* Close the handle and fail */ NtClose(ProcessHandle); DPRINT1("SmExecPgm: NtDuplicateObject (Process) Failed %lx\n", Status); return Status; } /* Duplicate the thread handle */ Status = NtDuplicateObject(ProcessHandle, SmExecPgm->ProcessInformation.ThreadHandle, NtCurrentProcess(), &ProcessInformation.ThreadHandle, THREAD_ALL_ACCESS, 0, 0); if (!NT_SUCCESS(Status)) { /* Close both handles and fail */ NtClose(ProcessInformation.ProcessHandle); NtClose(ProcessHandle); DPRINT1("SmExecPgm: NtDuplicateObject (Thread) Failed %lx\n", Status); return Status; } /* Close the process handle and call the internal client API */ NtClose(ProcessHandle); return SmpSbCreateSession(NULL, NULL, &ProcessInformation, 0, SmExecPgm->DebugFlag ? &SmApiMsg->h.ClientId : NULL); }
/* * Function for dealing with the undocumented message and structure used by * Windows' console.dll for setting console info. * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf * for more information. */ VOID GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, HANDLE hClientSection) { NTSTATUS Status = STATUS_SUCCESS; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL; ULONG ViewSize = 0; PCONSOLE_STATE_INFO pConInfo = NULL; if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); goto Quit; } /* Get a view of the shared section */ Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pConInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); goto Quit; } _SEH2_TRY { /* Check that the section is well-sized */ if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) || (pConInfo->cbSize < sizeof(CONSOLE_STATE_INFO)) ) { DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n"); Status = STATUS_INVALID_VIEW_SIZE; _SEH2_YIELD(goto Quit); } // TODO: Check that GuiData->hWindow == pConInfo->hWnd /* Retrieve terminal informations */ /* Console information */ #if 0 // FIXME: Things not set ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize; ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers; ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup; ConInfo.CodePage = pConInfo->CodePage; #endif /* * Apply the settings */ /* Set the console informations */ ConSrvApplyUserSettings(Console, pConInfo); /* Set the terminal informations */ /* Change the font */ InitFonts(GuiData, pConInfo->FaceName, pConInfo->FontFamily, pConInfo->FontSize, pConInfo->FontWeight); // HACK, needed because changing font may change the size of the window /**/TermResizeTerminal(Console);/**/ /* Move the window to the user's values */ GuiData->GuiInfo.AutoPosition = !!pConInfo->AutoPosition; GuiData->GuiInfo.WindowOrigin = pConInfo->WindowPosition; GuiConsoleMoveWindow(GuiData); InvalidateRect(GuiData->hWindow, NULL, TRUE); /* * Apply full-screen mode. */ if (!!pConInfo->FullScreen != GuiData->GuiInfo.FullScreen) { SwitchFullScreen(GuiData, !!pConInfo->FullScreen); } /* * The settings are saved in the registry by console.dll itself, if needed. */ // if (SaveSettings) // { // GuiConsoleWriteUserSettings(GuiInfo); // } Status = STATUS_SUCCESS; }
PyObject* psutil_get_open_files(long pid, HANDLE processHandle) { _NtQuerySystemInformation NtQuerySystemInformation = GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); _NtQueryObject NtQueryObject = GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; ULONG i; ULONG fileNameLength; PyObject *filesList = Py_BuildValue("[]"); PyObject *arg = NULL; PyObject *fileFromWchar = NULL; if (filesList == NULL) return NULL; handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); if (handleInfo == NULL) { Py_DECREF(filesList); PyErr_NoMemory(); return NULL; } /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) { handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); } /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { //printf("NtQuerySystemInformation failed!\n"); Py_DECREF(filesList); free(handleInfo); return NULL; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo = NULL; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; fileFromWchar = NULL; arg = NULL; /* Check if this handle belongs to the PID the user specified. */ if (handle.ProcessId != pid) continue; /* Skip handles with the following access codes as the next call to NtDuplicateObject() or NtQueryObject() might hang forever. */ if((handle.GrantedAccess == 0x0012019f) || (handle.GrantedAccess == 0x001a019f) || (handle.GrantedAccess == 0x00120189) || (handle.GrantedAccess == 0x00100000)) { continue; } /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject( processHandle, handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ))) { //printf("[%#x] Error!\n", handle.Handle); continue; } /* Query the object type. */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { //printf("[%#x] Error!\n", handle.Handle); free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { /* Reallocate the buffer and try again. */ objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { /* We have the type name, so just display that.*/ /* printf( "[%#x] %.*S: (could not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); */ free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } /* Cast our buffer into an UNICODE_STRING. */ objectName = *(PUNICODE_STRING)objectNameInfo; /* Print the information! */ if (objectName.Length) { /* The object has a name. Make sure it is a file otherwise ignore it */ fileNameLength = objectName.Length / 2; if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) { //printf("%.*S\n", objectName.Length / 2, objectName.Buffer); fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer, fileNameLength); if (fileFromWchar == NULL) goto error_py_fun; #if PY_MAJOR_VERSION >= 3 arg = Py_BuildValue("N", PyUnicode_AsUTF8String(fileFromWchar)); #else arg = Py_BuildValue("N", PyUnicode_FromObject(fileFromWchar)); #endif if (!arg) goto error_py_fun; Py_XDECREF(fileFromWchar); fileFromWchar = NULL; if (PyList_Append(filesList, arg)) goto error_py_fun; Py_XDECREF(arg); } /* printf( "[%#x] %.*S: %.*S\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer, objectName.Length / 2, objectName.Buffer ); */ } else { /* Print something else. */ /* printf( "[%#x] %.*S: (unnamed)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); */ ;; } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); CloseHandle(processHandle); return filesList; error_py_fun: Py_XDECREF(arg); Py_XDECREF(fileFromWchar); Py_DECREF(filesList); return NULL; }
NTSTATUS PhpGetBestObjectName( __in HANDLE ProcessHandle, __in HANDLE Handle, __in PPH_STRING ObjectName, __in PPH_STRING TypeName, __out PPH_STRING *BestObjectName ) { NTSTATUS status; PPH_STRING bestObjectName = NULL; PPH_GET_CLIENT_ID_NAME handleGetClientIdName; if (PhEqualString2(TypeName, L"EtwRegistration", TRUE)) { if (KphIsConnected()) { ETWREG_BASIC_INFORMATION basicInfo; status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectEtwRegBasicInformation, &basicInfo, sizeof(ETWREG_BASIC_INFORMATION), NULL ); if (NT_SUCCESS(status)) { static PH_STRINGREF publishersKeyName = PH_STRINGREF_INIT(L"Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\"); PPH_STRING guidString; PPH_STRING keyName; HANDLE keyHandle; PPH_STRING publisherName = NULL; guidString = PhFormatGuid(&basicInfo.Guid); // We should perform a lookup on the GUID to get the publisher name. keyName = PhConcatStringRef2(&publishersKeyName, &guidString->sr); if (NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName->sr, 0 ))) { publisherName = PhQueryRegistryString(keyHandle, NULL); if (publisherName && publisherName->Length == 0) { PhDereferenceObject(publisherName); publisherName = NULL; } NtClose(keyHandle); } PhDereferenceObject(keyName); if (publisherName) { bestObjectName = publisherName; PhDereferenceObject(guidString); } else { bestObjectName = guidString; } } } } else if (PhEqualString2(TypeName, L"File", TRUE)) { // Convert the file name to a DOS file name. bestObjectName = PhResolveDevicePrefix(ObjectName); if (!bestObjectName) { bestObjectName = ObjectName; PhReferenceObject(ObjectName); } } else if (PhEqualString2(TypeName, L"Key", TRUE)) { bestObjectName = PhFormatNativeKeyName(ObjectName); } else if (PhEqualString2(TypeName, L"Process", TRUE)) { CLIENT_ID clientId; clientId.UniqueThread = NULL; if (KphIsConnected()) { PROCESS_BASIC_INFORMATION basicInfo; status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectProcessBasicInformation, &basicInfo, sizeof(PROCESS_BASIC_INFORMATION), NULL ); if (!NT_SUCCESS(status)) goto CleanupExit; clientId.UniqueProcess = basicInfo.UniqueProcessId; } else { HANDLE dupHandle; PROCESS_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, ProcessQueryAccess, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetProcessBasicInformation(dupHandle, &basicInfo); NtClose(dupHandle); if (!NT_SUCCESS(status)) goto CleanupExit; clientId.UniqueProcess = basicInfo.UniqueProcessId; } handleGetClientIdName = PhHandleGetClientIdName; if (handleGetClientIdName) bestObjectName = handleGetClientIdName(&clientId); } else if (PhEqualString2(TypeName, L"Thread", TRUE)) { CLIENT_ID clientId; if (KphIsConnected()) { THREAD_BASIC_INFORMATION basicInfo; status = KphQueryInformationObject( ProcessHandle, Handle, KphObjectThreadBasicInformation, &basicInfo, sizeof(THREAD_BASIC_INFORMATION), NULL ); if (!NT_SUCCESS(status)) goto CleanupExit; clientId = basicInfo.ClientId; } else { HANDLE dupHandle; THREAD_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, ThreadQueryAccess, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetThreadBasicInformation(dupHandle, &basicInfo); NtClose(dupHandle); if (!NT_SUCCESS(status)) goto CleanupExit; clientId = basicInfo.ClientId; } handleGetClientIdName = PhHandleGetClientIdName; if (handleGetClientIdName) bestObjectName = handleGetClientIdName(&clientId); } else if (PhEqualString2(TypeName, L"TmEn", TRUE)) { HANDLE dupHandle; ENLISTMENT_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, ENLISTMENT_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetEnlistmentBasicInformation(dupHandle, &basicInfo); NtClose(dupHandle); if (NT_SUCCESS(status)) { bestObjectName = PhFormatGuid(&basicInfo.EnlistmentId); } } else if (PhEqualString2(TypeName, L"TmRm", TRUE)) { HANDLE dupHandle; GUID guid; PPH_STRING description; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, RESOURCEMANAGER_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetResourceManagerBasicInformation( dupHandle, &guid, &description ); NtClose(dupHandle); if (NT_SUCCESS(status)) { if (!PhIsNullOrEmptyString(description)) { bestObjectName = description; } else { bestObjectName = PhFormatGuid(&guid); if (description) PhDereferenceObject(description); } } } else if (PhEqualString2(TypeName, L"TmTm", TRUE)) { HANDLE dupHandle; PPH_STRING logFileName = NULL; TRANSACTIONMANAGER_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, TRANSACTIONMANAGER_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetTransactionManagerLogFileName( dupHandle, &logFileName ); if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(logFileName)) { bestObjectName = PhGetFileName(logFileName); PhDereferenceObject(logFileName); } else { if (logFileName) PhDereferenceObject(logFileName); status = PhGetTransactionManagerBasicInformation( dupHandle, &basicInfo ); if (NT_SUCCESS(status)) { bestObjectName = PhFormatGuid(&basicInfo.TmIdentity); } } NtClose(dupHandle); } else if (PhEqualString2(TypeName, L"TmTx", TRUE)) { HANDLE dupHandle; PPH_STRING description = NULL; TRANSACTION_BASIC_INFORMATION basicInfo; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, TRANSACTION_QUERY_INFORMATION, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetTransactionPropertiesInformation( dupHandle, NULL, NULL, &description ); if (NT_SUCCESS(status) && !PhIsNullOrEmptyString(description)) { bestObjectName = description; } else { if (description) PhDereferenceObject(description); status = PhGetTransactionBasicInformation( dupHandle, &basicInfo ); if (NT_SUCCESS(status)) { bestObjectName = PhFormatGuid(&basicInfo.TransactionId); } } NtClose(dupHandle); } else if (PhEqualString2(TypeName, L"Token", TRUE)) { HANDLE dupHandle; PTOKEN_USER tokenUser = NULL; TOKEN_STATISTICS statistics = { 0 }; status = NtDuplicateObject( ProcessHandle, Handle, NtCurrentProcess(), &dupHandle, TOKEN_QUERY, 0, 0 ); if (!NT_SUCCESS(status)) goto CleanupExit; status = PhGetTokenUser(dupHandle, &tokenUser); PhGetTokenStatistics(dupHandle, &statistics); if (NT_SUCCESS(status)) { PPH_STRING fullName; fullName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL); if (fullName) { PH_FORMAT format[3]; PhInitFormatSR(&format[0], fullName->sr); PhInitFormatS(&format[1], L": 0x"); PhInitFormatX(&format[2], statistics.AuthenticationId.LowPart); bestObjectName = PhFormat(format, 3, fullName->Length + 8 + 16); PhDereferenceObject(fullName); } PhFree(tokenUser); } NtClose(dupHandle); } CleanupExit: if (!bestObjectName) { bestObjectName = ObjectName; PhReferenceObject(ObjectName); } *BestObjectName = bestObjectName; return STATUS_SUCCESS; }
VOID GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, HANDLE hClientSection, BOOL SaveSettings) { NTSTATUS Status = STATUS_SUCCESS; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL; ULONG ViewSize = 0; PCONSOLE_PROPS pConInfo = NULL; PCONSOLE_INFO ConInfo = NULL; PTERMINAL_INFO TermInfo = NULL; PGUI_CONSOLE_INFO GuiInfo = NULL; if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); goto Quit; } /* Get a view of the shared section */ Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pConInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); goto Quit; } _SEH2_TRY { /* Check that the section is well-sized */ if ( (ViewSize < sizeof(CONSOLE_PROPS)) || (pConInfo->TerminalInfo.Size != sizeof(GUI_CONSOLE_INFO)) || (ViewSize < sizeof(CONSOLE_PROPS) + pConInfo->TerminalInfo.Size) ) { DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_PROPS) + sizeof(Terminal_specific_info)\n"); Status = STATUS_INVALID_VIEW_SIZE; _SEH2_YIELD(goto Quit); } // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow /* Retrieve terminal informations */ ConInfo = &pConInfo->ci; TermInfo = &pConInfo->TerminalInfo; GuiInfo = TermInfo->TermInfo = (PVOID)((ULONG_PTR)pConInfo + (ULONG_PTR)TermInfo->TermInfo); /* * If we don't set the default parameters, * apply them, otherwise just save them. */ if (pConInfo->ShowDefaultParams == FALSE) { /* Set the console informations */ ConSrvApplyUserSettings(Console, ConInfo); /* Set the terminal informations */ // memcpy(&GuiData->GuiInfo, GuiInfo, sizeof(GUI_CONSOLE_INFO)); /* Change the font */ InitFonts(GuiData, GuiInfo->FaceName, GuiInfo->FontFamily, GuiInfo->FontSize, GuiInfo->FontWeight); // HACK, needed because changing font may change the size of the window /**/TermResizeTerminal(Console);/**/ /* Move the window to the user's values */ GuiData->GuiInfo.AutoPosition = GuiInfo->AutoPosition; GuiData->GuiInfo.WindowOrigin = GuiInfo->WindowOrigin; GuiConsoleMoveWindow(GuiData); InvalidateRect(GuiData->hWindow, NULL, TRUE); /* * Apply full-screen mode. */ if (GuiInfo->FullScreen != GuiData->GuiInfo.FullScreen) { SwitchFullScreen(GuiData, GuiInfo->FullScreen); } } /* * Save settings if needed */ // FIXME: Do it in the console properties applet ?? if (SaveSettings) { DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess); ConSrvWriteUserSettings(ConInfo, ProcessId); GuiConsoleWriteUserSettings(GuiInfo, ConInfo->ConsoleTitle, ProcessId); } Status = STATUS_SUCCESS; }
static INT_PTR CALLBACK PhpFindObjectsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhFindObjectsListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_RESULTS); PhInitializeLayoutManager(&WindowLayoutManager, hwndDlg); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_REGEX), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, lvHandle, NULL, PH_ANCHOR_ALL); MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 150; MinimumSize.bottom = 100; MapDialogRect(hwndDlg, &MinimumSize); PhRegisterDialog(hwndDlg); PhLoadWindowPlacementFromSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSetListViewStyle(lvHandle, TRUE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Process"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Type"); PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Name"); PhAddListViewColumn(lvHandle, 3, 3, 3, LVCFMT_LEFT, 80, L"Handle"); PhSetExtendedListView(lvHandle); ExtendedListView_SetSortFast(lvHandle, TRUE); ExtendedListView_SetCompareFunction(lvHandle, 0, PhpObjectProcessCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 1, PhpObjectTypeCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 2, PhpObjectNameCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 3, PhpObjectHandleCompareFunction); PhLoadListViewColumnsFromSetting(L"FindObjListViewColumns", lvHandle); Button_SetCheck(GetDlgItem(hwndDlg, IDC_REGEX), PhGetIntegerSetting(L"FindObjRegex") ? BST_CHECKED : BST_UNCHECKED); } break; case WM_DESTROY: { PhSetIntegerSetting(L"FindObjRegex", Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED); PhSaveWindowPlacementToSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSaveListViewColumnsToSetting(L"FindObjListViewColumns", PhFindObjectsListViewHandle); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_FILTER), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_FILTER), 0, -1); } break; case WM_CLOSE: { ShowWindow(hwndDlg, SW_HIDE); // IMPORTANT // Set the result to 0 so the default dialog message // handler doesn't invoke IDCANCEL, which will send // WM_CLOSE, creating an infinite loop. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0); } return TRUE; case WM_SETCURSOR: { if (SearchThreadHandle) { SetCursor(LoadCursor(NULL, IDC_WAIT)); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); return TRUE; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDOK: { // Don't continue if the user requested cancellation. if (SearchStop) break; if (!SearchThreadHandle) { ULONG i; PhMoveReference(&SearchString, PhGetWindowText(GetDlgItem(hwndDlg, IDC_FILTER))); if (SearchRegexCompiledExpression) { pcre2_code_free(SearchRegexCompiledExpression); SearchRegexCompiledExpression = NULL; } if (SearchRegexMatchData) { pcre2_match_data_free(SearchRegexMatchData); SearchRegexMatchData = NULL; } if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED) { int errorCode; PCRE2_SIZE errorOffset; SearchRegexCompiledExpression = pcre2_compile( SearchString->Buffer, SearchString->Length / sizeof(WCHAR), PCRE2_CASELESS | PCRE2_DOTALL, &errorCode, &errorOffset, NULL ); if (!SearchRegexCompiledExpression) { PhShowError(hwndDlg, L"Unable to compile the regular expression: \"%s\" at position %zu.", PhGetStringOrDefault(PH_AUTO(PhPcre2GetErrorMessage(errorCode)), L"Unknown error"), errorOffset ); break; } SearchRegexMatchData = pcre2_match_data_create_from_pattern(SearchRegexCompiledExpression, NULL); } // Clean up previous results. ListView_DeleteAllItems(PhFindObjectsListViewHandle); if (SearchResults) { for (i = 0; i < SearchResults->Count; i++) { PPHP_OBJECT_SEARCH_RESULT searchResult = SearchResults->Items[i]; PhDereferenceObject(searchResult->TypeName); PhDereferenceObject(searchResult->Name); if (searchResult->ProcessName) PhDereferenceObject(searchResult->ProcessName); PhFree(searchResult); } PhDereferenceObject(SearchResults); } // Start the search. SearchResults = PhCreateList(128); SearchResultsAddIndex = 0; SearchThreadHandle = PhCreateThread(0, PhpFindObjectsThreadStart, NULL); if (!SearchThreadHandle) { PhClearReference(&SearchResults); break; } SetDlgItemText(hwndDlg, IDOK, L"Cancel"); SetCursor(LoadCursor(NULL, IDC_WAIT)); } else { SearchStop = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); } } break; case IDCANCEL: { SendMessage(hwndDlg, WM_CLOSE, 0, 0); } break; case ID_OBJECT_CLOSE: { PPHP_OBJECT_SEARCH_RESULT *results; ULONG numberOfResults; ULONG i; PhGetSelectedListViewItemParams( PhFindObjectsListViewHandle, &results, &numberOfResults ); if (numberOfResults != 0 && PhShowConfirmMessage( hwndDlg, L"close", numberOfResults == 1 ? L"the selected handle" : L"the selected handles", L"Closing handles may cause system instability and data corruption.", FALSE )) { for (i = 0; i < numberOfResults; i++) { NTSTATUS status; HANDLE processHandle; if (results[i]->ResultType != HandleSearchResult) continue; if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, results[i]->ProcessId ))) { if (NT_SUCCESS(status = NtDuplicateObject( processHandle, results[i]->Handle, NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE ))) { PhRemoveListViewItem(PhFindObjectsListViewHandle, PhFindListViewItemByParam(PhFindObjectsListViewHandle, 0, results[i])); } NtClose(processHandle); } if (!NT_SUCCESS(status)) { if (!PhShowContinueStatus(hwndDlg, PhaFormatString(L"Unable to close \"%s\"", results[i]->Name->Buffer)->Buffer, status, 0 )) break; } } } PhFree(results); } break; case ID_HANDLE_OBJECTPROPERTIES1: case ID_HANDLE_OBJECTPROPERTIES2: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { PH_HANDLE_ITEM_INFO info; info.ProcessId = result->ProcessId; info.Handle = result->Handle; info.TypeName = result->TypeName; info.BestObjectName = result->Name; if (LOWORD(wParam) == ID_HANDLE_OBJECTPROPERTIES1) PhShowHandleObjectProperties1(hwndDlg, &info); else PhShowHandleObjectProperties2(hwndDlg, &info); } } break; case ID_OBJECT_GOTOOWNINGPROCESS: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { PPH_PROCESS_NODE processNode; if (processNode = PhFindProcessNode(result->ProcessId)) { ProcessHacker_SelectTabPage(PhMainWndHandle, 0); ProcessHacker_SelectProcessNode(PhMainWndHandle, processNode); ProcessHacker_ToggleVisible(PhMainWndHandle, TRUE); } } } break; case ID_OBJECT_PROPERTIES: { PPHP_OBJECT_SEARCH_RESULT result = PhGetSelectedListViewItemParam(PhFindObjectsListViewHandle); if (result) { if (result->ResultType == HandleSearchResult) { PPH_HANDLE_ITEM handleItem; handleItem = PhCreateHandleItem(&result->Info); handleItem->BestObjectName = handleItem->ObjectName = result->Name; PhReferenceObjectEx(result->Name, 2); handleItem->TypeName = result->TypeName; PhReferenceObject(result->TypeName); PhShowHandleProperties( hwndDlg, result->ProcessId, handleItem ); PhDereferenceObject(handleItem); } else { // DLL or Mapped File. Just show file properties. PhShellProperties(hwndDlg, result->Name->Buffer); } } } break; case ID_OBJECT_COPY: { PhCopyListView(PhFindObjectsListViewHandle); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case NM_DBLCLK: { if (header->hwndFrom == PhFindObjectsListViewHandle) { SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_PROPERTIES, 0); } } break; case LVN_KEYDOWN: { if (header->hwndFrom == PhFindObjectsListViewHandle) { LPNMLVKEYDOWN keyDown = (LPNMLVKEYDOWN)header; switch (keyDown->wVKey) { case 'C': if (GetKeyState(VK_CONTROL) < 0) SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_COPY, 0); break; case 'A': if (GetKeyState(VK_CONTROL) < 0) PhSetStateAllListViewItems(PhFindObjectsListViewHandle, LVIS_SELECTED, LVIS_SELECTED); break; case VK_DELETE: SendMessage(hwndDlg, WM_COMMAND, ID_OBJECT_CLOSE, 0); break; } } } break; } } break; case WM_CONTEXTMENU: { if ((HWND)wParam == PhFindObjectsListViewHandle) { POINT point; PPHP_OBJECT_SEARCH_RESULT *results; ULONG numberOfResults; point.x = (SHORT)LOWORD(lParam); point.y = (SHORT)HIWORD(lParam); if (point.x == -1 && point.y == -1) PhGetListViewContextMenuPoint((HWND)wParam, &point); PhGetSelectedListViewItemParams(PhFindObjectsListViewHandle, &results, &numberOfResults); if (numberOfResults != 0) { PPH_EMENU menu; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_FINDOBJ), 0); PhSetFlagsEMenuItem(menu, ID_OBJECT_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT); PhpInitializeFindObjMenu(menu, results, numberOfResults); PhShowEMenu( menu, hwndDlg, PH_EMENU_SHOW_SEND_COMMAND | PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y ); PhDestroyEMenu(menu); } PhFree(results); } } break; case WM_SIZE: { PhLayoutManagerLayout(&WindowLayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SEARCH_UPDATE: { HWND lvHandle; ULONG i; lvHandle = GetDlgItem(hwndDlg, IDC_RESULTS); ExtendedListView_SetRedraw(lvHandle, FALSE); PhAcquireQueuedLockExclusive(&SearchResultsLock); for (i = SearchResultsAddIndex; i < SearchResults->Count; i++) { PPHP_OBJECT_SEARCH_RESULT searchResult = SearchResults->Items[i]; CLIENT_ID clientId; PPH_PROCESS_ITEM processItem; PPH_STRING clientIdName; INT lvItemIndex; clientId.UniqueProcess = searchResult->ProcessId; clientId.UniqueThread = NULL; processItem = PhReferenceProcessItem(clientId.UniqueProcess); clientIdName = PhGetClientIdNameEx(&clientId, processItem ? processItem->ProcessName : NULL); lvItemIndex = PhAddListViewItem( lvHandle, MAXINT, clientIdName->Buffer, searchResult ); PhDereferenceObject(clientIdName); if (processItem) { PhSetReference(&searchResult->ProcessName, processItem->ProcessName); PhDereferenceObject(processItem); } else { searchResult->ProcessName = NULL; } PhSetListViewSubItem(lvHandle, lvItemIndex, 1, searchResult->TypeName->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 2, searchResult->Name->Buffer); PhSetListViewSubItem(lvHandle, lvItemIndex, 3, searchResult->HandleString); } SearchResultsAddIndex = i; PhReleaseQueuedLockExclusive(&SearchResultsLock); ExtendedListView_SetRedraw(lvHandle, TRUE); } break; case WM_PH_SEARCH_FINISHED: { NTSTATUS handleSearchStatus = (NTSTATUS)wParam; // Add any un-added items. SendMessage(hwndDlg, WM_PH_SEARCH_UPDATE, 0, 0); NtWaitForSingleObject(SearchThreadHandle, FALSE, NULL); NtClose(SearchThreadHandle); SearchThreadHandle = NULL; SearchStop = FALSE; ExtendedListView_SortItems(GetDlgItem(hwndDlg, IDC_RESULTS)); SetDlgItemText(hwndDlg, IDOK, L"Find"); EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (handleSearchStatus == STATUS_INSUFFICIENT_RESOURCES) { PhShowWarning( hwndDlg, L"Unable to search for handles because the total number of handles on the system is too large. " L"Please check if there are any processes with an extremely large number of handles open." ); } } break; } return FALSE; }
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; }
PPH_LIST EnumerateAppDomainIpcBlockWow64( _In_ HANDLE ProcessHandle, _In_ AppDomainEnumerationIPCBlock_Wow64* AppDomainIpcBlock ) { LARGE_INTEGER timeout; SIZE_T appDomainInfoBlockLength; HANDLE legacyPrivateBlockMutexHandle = NULL; AppDomainEnumerationIPCBlock_Wow64 tempBlock; AppDomainInfo_Wow64* appDomainInfoBlock = NULL; PPH_LIST appDomainsList = PhCreateList(1); // If the mutex isn't filled in, the CLR is either starting up or shutting down if (!AppDomainIpcBlock->Mutex) { goto CleanupExit; } // Dup the valid mutex handle into this process. if (!NT_SUCCESS(NtDuplicateObject( ProcessHandle, UlongToHandle(AppDomainIpcBlock->Mutex), NtCurrentProcess(), &legacyPrivateBlockMutexHandle, GENERIC_ALL, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ))) { goto CleanupExit; } // Acquire the mutex, only waiting two seconds. // We can't actually gaurantee that the target put a mutex object in here. if (NtWaitForSingleObject( legacyPrivateBlockMutexHandle, FALSE, PhTimeoutFromMilliseconds(&timeout, 2000) ) == STATUS_WAIT_0) { // Make sure the mutex handle is still valid. If its not, then we lost a shutdown race. if (!AppDomainIpcBlock->Mutex) { goto CleanupExit; } } else { // Again, landing here is most probably a shutdown race. goto CleanupExit; } // Beware: If the target pid is not properly honoring the mutex, the data in the IPC block may still shift underneath us. // If we get here, then hMutex is held by this process. // Make a copy of the IPC block so that we can gaurantee that it's not changing on us. memcpy(&tempBlock, AppDomainIpcBlock, sizeof(AppDomainEnumerationIPCBlock_Wow64)); // It's possible the process will not have any appdomains. if ((tempBlock.ListOfAppDomains == 0) != (tempBlock.SizeInBytes == 0)) { goto CleanupExit; } // All the data in the IPC block is signed integers. They should never be negative, // so check that now. if ((tempBlock.TotalSlots < 0) || (tempBlock.NumOfUsedSlots < 0) || (tempBlock.LastFreedSlot < 0) || (tempBlock.SizeInBytes < 0) || (tempBlock.ProcessNameLengthInBytes < 0)) { goto CleanupExit; } // Allocate memory to read the remote process' memory into appDomainInfoBlockLength = tempBlock.SizeInBytes; // Check other invariants. if (appDomainInfoBlockLength != tempBlock.TotalSlots * sizeof(AppDomainInfo_Wow64)) { goto CleanupExit; } appDomainInfoBlock = (AppDomainInfo_Wow64*)PhAllocate(appDomainInfoBlockLength); memset(appDomainInfoBlock, 0, appDomainInfoBlockLength); if (!NT_SUCCESS(NtReadVirtualMemory( ProcessHandle, UlongToPtr(tempBlock.ListOfAppDomains), appDomainInfoBlock, appDomainInfoBlockLength, NULL ))) { PhFree(appDomainInfoBlock); goto CleanupExit; } // Collect all the AppDomain names into a list of strings. for (INT i = 0; i < tempBlock.NumOfUsedSlots; i++) { SIZE_T appDomainNameLength; PVOID appDomainName; if (!appDomainInfoBlock[i].AppDomainName) continue; // Should be positive, and at least have a null-terminator character. if (appDomainInfoBlock[i].NameLengthInBytes <= 1) continue; // Make sure buffer has right geometry. if (appDomainInfoBlock[i].NameLengthInBytes < 0) continue; // If it's not on a WCHAR boundary, then we may have a 1-byte buffer-overflow. appDomainNameLength = appDomainInfoBlock[i].NameLengthInBytes / sizeof(WCHAR); if ((appDomainNameLength * sizeof(WCHAR)) != appDomainInfoBlock[i].NameLengthInBytes) continue; // It should at least have 1 char for the null terminator. if (appDomainNameLength < 1) continue; // We know the string is a well-formed null-terminated string, // but beyond that, we can't verify that the data is actually truthful. appDomainName = PhAllocate(appDomainInfoBlock[i].NameLengthInBytes + 1); memset(appDomainName, 0, appDomainInfoBlock[i].NameLengthInBytes + 1); if (!NT_SUCCESS(NtReadVirtualMemory( ProcessHandle, UlongToPtr(appDomainInfoBlock[i].AppDomainName), appDomainName, appDomainInfoBlock[i].NameLengthInBytes, NULL ))) { PhFree(appDomainName); continue; } PhAddItemList(appDomainsList, appDomainName); } CleanupExit: if (appDomainInfoBlock) { PhFree(appDomainInfoBlock); } if (legacyPrivateBlockMutexHandle) { NtReleaseMutant(legacyPrivateBlockMutexHandle, NULL); NtClose(legacyPrivateBlockMutexHandle); } return appDomainsList; }
ULONG BaseSrvNlsCreateSortSection( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus) { PBASE_NLS_CREATE_SORT_SECTION_MSG a = (PBASE_NLS_CREATE_SORT_SECTION_MSG)&m->u.ApiMessageData; HANDLE hNewSec = (HANDLE)0; /* new section handle */ HANDLE hProcess = (HANDLE)0; /* process handle */ OBJECT_ATTRIBUTES ObjA; /* object attributes structure */ NTSTATUS rc = 0L; /* return code */ ULONG pSecurityDescriptor[MAX_PATH_LEN]; /* security descriptor buffer */ PSID pWorldSid; /* ptr to world SID */ /* * Set the handles to null. */ a->hNewSection = NULL; /* * Create the NEW Section for Read and Write access. * Add a ReadOnly security descriptor so that only the * initial creating process may write to the section. */ if (rc = CreateSecurityDescriptor(pSecurityDescriptor, &pWorldSid, GENERIC_READ)) { return (rc); } InitializeObjectAttributes(&ObjA, &(a->SectionName), OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, pSecurityDescriptor); rc = NtCreateSection(&hNewSec, SECTION_MAP_READ | SECTION_MAP_WRITE, &ObjA, &(a->SectionSize), PAGE_READWRITE, SEC_COMMIT, NULL); /* * Check for error from NtCreateSection. */ if (!NT_SUCCESS(rc)) { /* * If the name has already been created, ignore the error. */ if (rc != STATUS_OBJECT_NAME_COLLISION) { KdPrint(("NLSAPI (BaseSrv): Could NOT Create Section %wZ - %lx.\n", &(a->SectionName), rc)); return (rc); } } /* * Duplicate the new section handle for the client. * The client will map a view of the section and fill in the data. */ InitializeObjectAttributes(&ObjA, NULL, 0, NULL, NULL); rc = NtOpenProcess(&hProcess, PROCESS_DUP_HANDLE, &ObjA, &m->h.ClientId); if (!NT_SUCCESS(rc)) { KdPrint(("NLSAPI (BaseSrv): Could NOT Open Process - %lx.\n", rc)); return (rc); } rc = NtDuplicateObject(NtCurrentProcess(), hNewSec, hProcess, &(a->hNewSection), 0L, 0L, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Return the return value from NtDuplicateObject. */ return (rc); ReplyStatus; // get rid of unreferenced parameter warning message }
NTSTATUS ModifySelfSizeOfImage(LPWSTR ExeFullPath, LPWSTR CommandLine, ULONG SizeOfImage) { BOOL Result; ULONG Length; PVOID FakeCPInfoBuffer; WCHAR CmdFullPath[MAX_NTPATH]; PWCHAR CmdLineBuffer; NTSTATUS Status; PLDR_MODULE LdrModule; PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS NtHeader; PIMAGE_SECTION_HEADER SectionHeader; FAKE_CREATE_PROCESS_INFO *fcpi; PROCESS_INFORMATION ProcessInformation; CONTEXT Context; NtFileDisk file; UNICODE_STRING ExeNtPath, *ProcessCommandLine; UNREFERENCED_PARAMETER(CommandLine); LdrModule = Nt_FindLdrModuleByName(NULL); DosHeader = (PIMAGE_DOS_HEADER)&__ImageBase; NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew); fcpi = (FAKE_CREATE_PROCESS_INFO *)AllocStack(0x2000); fcpi->PeHeaderSize = (ULONG_PTR)(IMAGE_FIRST_SECTION(NtHeader) + NtHeader->FileHeader.NumberOfSections) - (ULONG_PTR)DosHeader; Status = file.Open(LdrModule->FullDllName.Buffer); if (!NT_SUCCESS(Status)) return Status; Status = file.Read(fcpi->PeHeader, fcpi->PeHeaderSize); if (!NT_SUCCESS(Status)) return Status; CmdLineBuffer = (PWCHAR)((ULONG_PTR)fcpi->PeHeader + fcpi->PeHeaderSize); fcpi->CommandLine.Buffer = CmdLineBuffer; fcpi->CommandLine.Length = (USHORT)(StrLengthW(ExeFullPath) * sizeof(WCHAR)); ProcessCommandLine = &Nt_CurrentPeb()->ProcessParameters->CommandLine; CopyMemory(CmdLineBuffer, ProcessCommandLine->Buffer, ProcessCommandLine->Length); *(PULONG_PTR)&CmdLineBuffer += ProcessCommandLine->Length; CmdLineBuffer[0] = 0; fcpi->CommandLine.Length = ProcessCommandLine->Length; fcpi->CommandLine.MaximumLength = fcpi->CommandLine.Length + sizeof(WCHAR); ++CmdLineBuffer; CmdLineBuffer = (PWCHAR)ROUND_UP((ULONG_PTR)CmdLineBuffer, 16); RtlDosPathNameToNtPathName_U(LdrModule->FullDllName.Buffer, &ExeNtPath, NULL, NULL); fcpi->ExeNtPath.Buffer = CmdLineBuffer; CopyMemory(CmdLineBuffer, ExeNtPath.Buffer, ExeNtPath.Length); *(PULONG_PTR)&CmdLineBuffer += ExeNtPath.Length; CmdLineBuffer[0] = 0; fcpi->ExeNtPath.Length = ExeNtPath.Length; fcpi->ExeNtPath.MaximumLength = fcpi->ExeNtPath.Length + sizeof(WCHAR); *CmdLineBuffer++ = 0; RtlFreeUnicodeString(&ExeNtPath); DosHeader = (PIMAGE_DOS_HEADER)fcpi->PeHeader; NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHeader + DosHeader->e_lfanew); SectionHeader = IMAGE_FIRST_SECTION(NtHeader); SectionHeader += NtHeader->FileHeader.NumberOfSections - 1; SizeOfImage -= LdrModule->SizeOfImage; SizeOfImage = ROUND_UP(SizeOfImage, MEMORY_PAGE_SIZE); SectionHeader->Misc.VirtualSize = ROUND_UP(SectionHeader->Misc.VirtualSize, MEMORY_PAGE_SIZE) + SizeOfImage; if (NtHeader->FileHeader.SizeOfOptionalHeader > FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, SizeOfImage) + RTL_FIELD_SIZE(IMAGE_OPTIONAL_HEADER, SizeOfImage)) NtHeader->OptionalHeader.SizeOfImage += SizeOfImage; Length = Nt_GetSystemDirectory(CmdFullPath, countof(CmdFullPath)); StrCopyW(CmdFullPath + Length, L"cmd.exe"); ProcessInformation.hProcess = NtCurrentProcess(); ProcessInformation.hThread = NtCurrentThread(); #if 1 Result = Nt_CreateProcess(NULL, CmdFullPath, NULL, CREATE_SUSPENDED, NULL, &ProcessInformation); if (!Result) return STATUS_UNSUCCESSFUL; #endif FakeCPInfoBuffer = NULL; LOOP_ONCE { ULONG_PTR Offset; Status = NtDuplicateObject( NtCurrentProcess(), NtCurrentProcess(), ProcessInformation.hProcess, &fcpi->ProcessHandle, 0, 0, DUPLICATE_SAME_ACCESS ); if (!NT_SUCCESS(Status)) break; /* Status = NtDuplicateObject( NtCurrentProcess(), file, ProcessInformation.hProcess, &fcpi->FileHandle, 0, 0, DUPLICATE_SAME_ACCESS ); if (!NT_SUCCESS(Status)) break; */ Status = Nt_AllocateMemory(ProcessInformation.hProcess, &FakeCPInfoBuffer, MEMORY_PAGE_SIZE); if (!NT_SUCCESS(Status)) break; fcpi->CreateProcessInternalW = CreateProcessInternalW; fcpi->NtTerminateProcess = NtTerminateProcess; fcpi->LdrShutdownProcess = LdrShutdownProcess; fcpi->NtCreateFile = NtCreateFile; fcpi->NtWriteFile = NtWriteFile; fcpi->NtClose = NtClose; fcpi->NtWaitForSingleObject = NtWaitForSingleObject; fcpi->InitialDirectory.Buffer = NULL; Offset = (ULONG_PTR)FakeCPInfoBuffer - (ULONG_PTR)fcpi; *(PULONG_PTR)&fcpi->CommandLine.Buffer += Offset; *(PULONG_PTR)&fcpi->ExeNtPath.Buffer += Offset; Status = Nt_WriteMemory( ProcessInformation.hProcess, FakeCPInfoBuffer, fcpi, (ULONG_PTR)CmdLineBuffer - (ULONG_PTR)fcpi, &Length ); if (!NT_SUCCESS(Status)) break; Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; Status = NtGetContextThread(ProcessInformation.hThread, &Context); if (!NT_SUCCESS(Status)) break; Context.Eip = (ULONG_PTR)FakeCPInfoBuffer + Length; Context.Eip = ROUND_UP(Context.Eip, 16); Context.Ecx = (ULONG_PTR)FakeCPInfoBuffer; Status = Nt_WriteMemory( ProcessInformation.hProcess, (PVOID)Context.Eip, ModifySizeOfImage, (ULONG_PTR)ModifySizeOfImageEnd - (ULONG_PTR)ModifySizeOfImage, &Length ); if (!NT_SUCCESS(Status)) break; #if 1 Status = NtSetContextThread(ProcessInformation.hThread, &Context); if (!NT_SUCCESS(Status)) break; Status = NtResumeThread(ProcessInformation.hThread, NULL); #else INLINE_ASM jmp Context.Eip; #endif } if (!NT_SUCCESS(Status)) { if (FakeCPInfoBuffer != NULL) Nt_FreeMemory(ProcessInformation.hProcess, FakeCPInfoBuffer); NtTerminateProcess(ProcessInformation.hProcess, 0); } NtClose(ProcessInformation.hProcess); NtClose(ProcessInformation.hThread); return Status; }
bool search::generate_pbo_list() { NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; ULONG pid; HANDLE processHandle; ULONG i; _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); if (!NtQuerySystemInformation || !NtDuplicateObject || !NtQueryObject) return false; pid = GetCurrentProcessId(); processHandle = GetCurrentProcess(); handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { LOG(ERROR) << "Error opening object for pbo search"; free(handleInfo); return false; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; /* Check if this handle belongs to the PID the user specified. */ if (handle.ProcessId != pid) continue; /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject( processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ))) { continue; } /* Query the object type. */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { CloseHandle(dupHandle); continue; } /* Query the object name (unless it has an access of 0x0012019f, on which NtQueryObject could hang. */ if (handle.GrantedAccess == 0x0012019f) { free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { /* Reallocate the buffer and try again. */ objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } /* Cast our buffer into an UNICODE_STRING. */ objectName = *(PUNICODE_STRING)objectNameInfo; /* Print the information! */ if (objectName.Length) { std::wstring tmp_type(objectTypeInfo->Name.Buffer); std::wstring tmp_name(objectName.Buffer); std::string object_type(tmp_type.begin(), tmp_type.end()); std::string object_name(tmp_name.begin(), tmp_name.end()); if (object_type == "File" && object_name.find(".pbo") != object_name.npos) { char buffer[MAX_PATH]; GetFinalPathNameByHandle(dupHandle, buffer, sizeof(buffer), VOLUME_NAME_DOS); LOG(DEBUG) << "Pbo: " << buffer; _active_pbo_list.push_back(std::string(buffer)); } } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); return true; }
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; }
int wmain(int argc, WCHAR *argv[]) { _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; ULONG pid = 0; HANDLE processHandle; ULONG i; if (argc < 2) { printf("Usage: handles filepath [pid]\n"); return 1; } if (argc > 2) { pid = _wtoi(argv[2]); } // convert C:\Windows\System32 to \Device\HarddiskVolume1\Windows\System32 const WCHAR* filePath = argv[1]; if (wcslen(filePath) < 2 || filePath[1] != L':') { printf("Can't process input path which is tool short or not contain local driver!\n"); return 1; } PWSTR pDosDriveName = new TCHAR[MAX_PATH]; TCHAR szDrive[3] = TEXT(" :"); szDrive[0] = filePath[0]; DWORD uiLen = QueryDosDeviceW(szDrive, pDosDriveName, MAX_PATH); if (0 == uiLen) { if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { printf("QueryDosDeviceW failed: %d\n", GetLastError()); return 1; } delete[]pDosDriveName; pDosDriveName = new TCHAR[uiLen + 1]; uiLen = QueryDosDevice(szDrive, pDosDriveName, uiLen + 1); if (0 == uiLen) { printf("QueryDosDeviceW failed: %d\n", GetLastError()); return 1; } } wcscat(pDosDriveName, &filePath[2]); handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { printf("NtQuerySystemInformation failed!\n"); return 1; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; // Jump of no file /*if (handle.ObjectTypeNumber != 31) { continue; }*/ /* Check if this handle belongs to the PID the user specified. */ if (pid != 0 && handle.ProcessId != pid) continue; if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.ProcessId))) { //printf("Could not open PID %d! (Don't try to open a system process.)\n", handle.ProcessId); continue; } /* Duplicate the handle so we can query it. */ DWORD re = NtDuplicateObject( processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ); if (ERROR_SUCCESS != re) { printf("[%#x] Error!\n", handle.Handle); continue; } /* Query the object type. */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { printf("[%#x] Error!\n", handle.Handle); CloseHandle(dupHandle); continue; } /* Query the object name (unless it has an access of 0x0012019f, on which NtQueryObject could hang. */ if (handle.GrantedAccess == 0x0012019f) { /* We have the type, so display that. */ printf( "[%#x] %.*S: (did not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(MyNtQueryObject( NtQueryObject, dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { /* Reallocate the buffer and try again. */ objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(MyNtQueryObject( NtQueryObject, dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { /* We have the type name, so just display that. */ printf( "[%#x] %.*S: (could not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } /* Cast our buffer into an UNICODE_STRING. */ objectName = *(PUNICODE_STRING)objectNameInfo; /* Print the information! */ if (objectName.Length) { /* The object has a name. */ printf( "[%#x] %.*S: %.*S\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer, objectName.Length / 2, objectName.Buffer ); if (wcscmp(objectName.Buffer, pDosDriveName) == 0) { printf("opend by process: %d", handle.ProcessId); break; } } else { /* Print something else. */ printf( "[%#x] %.*S: (unnamed)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); CloseHandle(processHandle); return 0; }
/* * Function for dealing with the undocumented message and structure used by * Windows' console.dll for setting console info. * See http://www.catch22.net/sites/default/source/files/setconsoleinfo.c * and http://www.scn.rain.com/~neighorn/PDF/MSBugPaper.pdf * for more information. */ VOID GuiApplyWindowsConsoleSettings(PGUI_CONSOLE_DATA GuiData, HANDLE hClientSection) { NTSTATUS Status = STATUS_SUCCESS; PCONSRV_CONSOLE Console = GuiData->Console; PCONSOLE_PROCESS_DATA ProcessData; HANDLE hSection = NULL; ULONG ViewSize = 0; PCONSOLE_STATE_INFO pConInfo = NULL; CONSOLE_INFO ConInfo; GUI_CONSOLE_INFO GuiInfo; #if 0 SIZE_T Length; #endif if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return; /* Get the console leader process, our client */ ProcessData = ConSrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, hClientSection, NtCurrentProcess(), &hSection, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping client handle, Status = 0x%08lx\n", Status); goto Quit; } /* Get a view of the shared section */ Status = NtMapViewOfSection(hSection, NtCurrentProcess(), (PVOID*)&pConInfo, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Error when mapping view of file, Status = 0x%08lx\n", Status); goto Quit; } _SEH2_TRY { /* Check that the section is well-sized */ if ( (ViewSize < sizeof(CONSOLE_STATE_INFO)) || (pConInfo->cbSize != sizeof(CONSOLE_STATE_INFO)) ) { DPRINT1("Error: section bad-sized: sizeof(Section) < sizeof(CONSOLE_STATE_INFO)\n"); Status = STATUS_INVALID_VIEW_SIZE; _SEH2_YIELD(goto Quit); } // TODO: Check that GuiData->hWindow == pConInfo->hConsoleWindow /* Retrieve terminal informations */ // Console information ConInfo.HistoryBufferSize = pConInfo->HistoryBufferSize; ConInfo.NumberOfHistoryBuffers = pConInfo->NumberOfHistoryBuffers; ConInfo.HistoryNoDup = !!pConInfo->HistoryNoDup; ConInfo.QuickEdit = !!pConInfo->QuickEdit; ConInfo.InsertMode = !!pConInfo->InsertMode; ConInfo.ScreenBufferSize = pConInfo->ScreenBufferSize; ConInfo.ConsoleSize = pConInfo->WindowSize; ConInfo.CursorSize = pConInfo->CursorSize; ConInfo.ScreenAttrib = pConInfo->ScreenColors; ConInfo.PopupAttrib = pConInfo->PopupColors; memcpy(&ConInfo.Colors, pConInfo->ColorTable, sizeof(ConInfo.Colors)); ConInfo.CodePage = pConInfo->CodePage; /**ConInfo.ConsoleTitle[MAX_PATH + 1] = pConInfo->ConsoleTitle; // FIXME: memcpy**/ #if 0 /* Title of the console, original one corresponding to the one set by the console leader */ Length = min(sizeof(pConInfo->ConsoleTitle) / sizeof(pConInfo->ConsoleTitle[0]) - 1, Console->OriginalTitle.Length / sizeof(WCHAR)); wcsncpy(pSharedInfo->ci.ConsoleTitle, Console->OriginalTitle.Buffer, Length); #endif // BOOLEAN ConInfo.CursorBlinkOn = pConInfo-> // BOOLEAN ConInfo.ForceCursorOff = pConInfo-> // Terminal information wcsncpy(GuiInfo.FaceName, pConInfo->FaceName, LF_FACESIZE); GuiInfo.FaceName[LF_FACESIZE - 1] = UNICODE_NULL; GuiInfo.FontFamily = pConInfo->FontFamily; GuiInfo.FontSize = pConInfo->FontSize; GuiInfo.FontWeight = pConInfo->FontWeight; GuiInfo.FullScreen = !!pConInfo->FullScreen; GuiInfo.AutoPosition = !!pConInfo->AutoPosition; GuiInfo.WindowOrigin = pConInfo->WindowPosition; // WORD GuiInfo.ShowWindow = pConInfo-> /* * If we don't set the default parameters, * apply them, otherwise just save them. */ #if 0 if (pConInfo->ShowDefaultParams == FALSE) #endif { /* Set the console informations */ ConSrvApplyUserSettings(Console, &ConInfo); /* Set the terminal informations */ // memcpy(&GuiData->GuiInfo, &GuiInfo, sizeof(GUI_CONSOLE_INFO)); /* Change the font */ InitFonts(GuiData, GuiInfo.FaceName, GuiInfo.FontFamily, GuiInfo.FontSize, GuiInfo.FontWeight); // HACK, needed because changing font may change the size of the window /**/TermResizeTerminal(Console);/**/ /* Move the window to the user's values */ GuiData->GuiInfo.AutoPosition = GuiInfo.AutoPosition; GuiData->GuiInfo.WindowOrigin = GuiInfo.WindowOrigin; GuiConsoleMoveWindow(GuiData); InvalidateRect(GuiData->hWindow, NULL, TRUE); /* * Apply full-screen mode. */ if (GuiInfo.FullScreen != GuiData->GuiInfo.FullScreen) { SwitchFullScreen(GuiData, GuiInfo.FullScreen); } } #if 0 /* * Save settings if needed */ // FIXME: Do it in the console properties applet ?? if (SaveSettings) { DWORD ProcessId = HandleToUlong(ProcessData->Process->ClientId.UniqueProcess); ConSrvWriteUserSettings(&ConInfo, ProcessId); GuiConsoleWriteUserSettings(&GuiInfo, ConInfo.ConsoleTitle, ProcessId); } #endif Status = STATUS_SUCCESS; }
// FIXME: Maybe return a NTSTATUS static BOOL GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle, IN OUT PGUI_INIT_INFO GuiInitInfo) { BOOL Success = TRUE; UNICODE_STRING DesktopPath; DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo; HWINSTA hWinSta; HDESK hDesk; NTSTATUS Status; HANDLE hInputThread; CLIENT_ID ClientId; /* * Initialize and register the console window class, if needed. */ if (!ConsInitialized) { if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE; ConsInitialized = TRUE; } /* * Set-up the console input thread. We have * one console input thread per desktop. */ if (!CsrImpersonateClient(NULL)) // return STATUS_BAD_IMPERSONATION_LEVEL; return FALSE; if (ConsoleInitInfo->DesktopLength) { DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength; DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL); DesktopPath.Buffer = ConsoleInitInfo->Desktop; } else { RtlInitUnicodeString(&DesktopPath, L"Default"); } hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle, &DesktopPath, 0, &hWinSta); DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n", &DesktopPath, hDesk, hWinSta); CsrRevertToSelf(); if (hDesk == NULL) return FALSE; /* * We need to see whether we need to create a * new console input thread for this desktop. */ DesktopConsoleThreadInfo.DesktopHandle = hDesk; DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value to say we just want to retrieve the thread ID. NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, &DesktopConsoleThreadInfo, sizeof(DesktopConsoleThreadInfo)); DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId); /* * Save the opened window station and desktop handles in the initialization * structure. They will be used later on, and released, by the GUI frontend. */ GuiInitInfo->WinSta = hWinSta; GuiInitInfo->Desktop = hDesk; /* Here GuiInitInfo contains original handles */ /* If we already have a console input thread on this desktop... */ if (DesktopConsoleThreadInfo.ThreadId != 0) { /* ... just use it... */ DPRINT("Using input thread InputThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId); GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId; goto Quit; } /* ... otherwise create a new one. */ /* Initialize a startup event for the thread to signal it */ Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { Success = FALSE; goto Quit; } /* * Duplicate the desktop handle for the console input thread internal needs. * If it happens to need also a window station handle in the future, then * it is there that you also need to duplicate the window station handle! * * Note also that we are going to temporarily overwrite the stored handles * in GuiInitInfo because it happens that we use also this structure to give * the duplicated handles to the input thread that is going to initialize. * After the input thread finishes its initialization, we restore the handles * in GuiInitInfo to their old values. */ Status = NtDuplicateObject(NtCurrentProcess(), hDesk, NtCurrentProcess(), (PHANDLE)&GuiInitInfo->Desktop, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { Success = FALSE; goto Quit; } /* Here GuiInitInfo contains duplicated handles */ Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, // Start the thread in suspended state 0, 0, 0, (PVOID)GuiConsoleInputThread, (PVOID)GuiInitInfo, &hInputThread, &ClientId); if (NT_SUCCESS(Status)) { /* Add it as a static server thread and resume it */ CsrAddStaticServerThread(hInputThread, &ClientId, 0); Status = NtResumeThread(hInputThread, NULL); } DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status = 0x%08lx\n", hInputThread, ClientId.UniqueThread, Status); if (!NT_SUCCESS(Status) || hInputThread == NULL) { /* Close the thread's handle */ if (hInputThread) NtClose(hInputThread); /* We need to close here the duplicated desktop handle */ CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop /* Close the startup event and bail out */ NtClose(GuiInitInfo->GuiThreadStartupEvent); DPRINT1("CONSRV: Failed to create graphics console thread.\n"); Success = FALSE; goto Quit; } /* No need to close hInputThread, this is done by CSR automatically */ /* Wait for the thread to finish its initialization, and close the startup event */ NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL); NtClose(GuiInitInfo->GuiThreadStartupEvent); /* * Save the input thread ID for later use, and restore the original handles. * The copies are held by the console input thread. */ GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread; GuiInitInfo->WinSta = hWinSta; GuiInitInfo->Desktop = hDesk; /* Here GuiInitInfo contains again original handles */ Quit: if (!Success) { /* * Close the original handles. Do not use the copies in GuiInitInfo * because we may have failed in the middle of the duplicate operation * and the handles stored in GuiInitInfo may have changed. */ CloseDesktop(hDesk); // NtUserCloseDesktop CloseWindowStation(hWinSta); // NtUserCloseWindowStation } return Success; }
NTSTATUS NTAPI SmpExecuteInitialCommand(IN ULONG MuSessionId, IN PUNICODE_STRING InitialCommand, IN HANDLE InitialCommandProcess, OUT PHANDLE ReturnPid) { NTSTATUS Status; RTL_USER_PROCESS_INFORMATION ProcessInfo; UNICODE_STRING Arguments, ImageFileDirectory, ImageFileName; ULONG Flags = 0; /* Check if we haven't yet connected to ourselves */ if (!SmApiPort) { /* Connect to ourselves, as a client */ Status = SmConnectToSm(0, 0, 0, &SmApiPort); if (!NT_SUCCESS(Status)) { DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status); return Status; } } /* Parse the initial command line */ Status = SmpParseCommandLine(InitialCommand, &Flags, &ImageFileName, &ImageFileDirectory, &Arguments); if (Flags & SMP_INVALID_PATH) { /* Fail if it doesn't exist */ DPRINT1("SMSS: Initial command image (%wZ) not found\n", &ImageFileName); if (ImageFileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer); return STATUS_OBJECT_NAME_NOT_FOUND; } /* And fail if any other reason is also true */ if (!NT_SUCCESS(Status)) { DPRINT1("SMSS: SmpParseCommandLine( %wZ ) failed - Status == %lx\n", InitialCommand, Status); return Status; } /* Execute the initial command -- but defer its full execution */ Status = SmpExecuteImage(&ImageFileName, &ImageFileDirectory, InitialCommand, MuSessionId, SMP_DEFERRED_FLAG, &ProcessInfo); /* Free any buffers we had lying around */ if (ImageFileName.Buffer) { RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer); } if (ImageFileDirectory.Buffer) { RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileDirectory.Buffer); } if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer); /* Bail out if we couldn't execute the initial command */ if (!NT_SUCCESS(Status)) return Status; /* Now duplicate the handle to this process */ Status = NtDuplicateObject(NtCurrentProcess(), ProcessInfo.ProcessHandle, NtCurrentProcess(), InitialCommandProcess, PROCESS_ALL_ACCESS, 0, 0); if (!NT_SUCCESS(Status)) { /* Kill it utterly if duplication failed */ DPRINT1("SMSS: DupObject Failed. Status == %lx\n", Status); NtTerminateProcess(ProcessInfo.ProcessHandle, Status); NtResumeThread(ProcessInfo.ThreadHandle, NULL); NtClose(ProcessInfo.ThreadHandle); NtClose(ProcessInfo.ProcessHandle); return Status; } /* Return PID to the caller, and set this as the initial command PID */ if (ReturnPid) *ReturnPid = ProcessInfo.ClientId.UniqueProcess; if (!MuSessionId) SmpInitialCommandProcessId = ProcessInfo.ClientId.UniqueProcess; /* Now call our server execution function to wrap up its initialization */ Status = SmExecPgm(SmApiPort, &ProcessInfo, FALSE); if (!NT_SUCCESS(Status)) DPRINT1("SMSS: SmExecPgm Failed. Status == %lx\n", Status); return Status; }
BOOL GetProcessIdByMutantName(LPCWSTR mutant_name, std::vector<ULONG> &pids) { _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress(TEXT("ntdll.dll"), "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress(TEXT("ntdll.dll"), "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress(TEXT("ntdll.dll"), "NtQueryObject"); if (NtQuerySystemInformation == NULL || NtDuplicateObject == NULL || NtQueryObject == NULL) { return FALSE; } PSYSTEM_HANDLE_INFORMATION handle_info; ULONG handle_info_size = 0x10000; CHeapPtr<UCHAR> handle_info_buffer; handle_info_buffer.Allocate(handle_info_size); NTSTATUS ns; while ((ns = NtQuerySystemInformation( SystemHandleInformation, handle_info_buffer.m_pData, handle_info_size, NULL )) == STATUS_INFO_LENGTH_MISMATCH) { handle_info_buffer.Reallocate(handle_info_size *= 2); } if (!NT_SUCCESS(ns)) { return FALSE; } handle_info = (PSYSTEM_HANDLE_INFORMATION)handle_info_buffer.m_pData; ULONG process_id = 0; HANDLE cur_handle = NULL; for (ULONG i = 0; i < handle_info->HandleCount; i++) { SYSTEM_HANDLE handle = handle_info->Handles[i]; ULONG info_size = 0x1000; if (handle.GrantedAccess == 0x0012019f) { continue; } if (process_id != handle.ProcessId) { process_id = handle.ProcessId; if (cur_handle != NULL) { CloseHandle(cur_handle); cur_handle = NULL; } if (cur_handle == NULL) { cur_handle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, process_id); } if (cur_handle == NULL) { continue; } } HANDLE dup_handle = NULL; if (!NT_SUCCESS(NtDuplicateObject( cur_handle, (HANDLE)handle.Handle, GetCurrentProcess(), &dup_handle, 0, 0, 0 ))) { continue; } CHandle auto_handle(dup_handle); CHeapPtr<UCHAR> obj_type_buffer; obj_type_buffer.Allocate(info_size); POBJECT_TYPE_INFORMATION obj_type_info = (POBJECT_TYPE_INFORMATION)obj_type_buffer.m_pData; if (!NT_SUCCESS(NtQueryObject( dup_handle, ObjectTypeInformation, obj_type_info, info_size, NULL ))) { continue; } if (memcmp(obj_type_info->Name.Buffer, L"Mutant", 12) != 0) { continue; } CHeapPtr<UCHAR> obj_name_buffer; obj_name_buffer.Allocate(info_size); PVOID obj_name_info = obj_name_buffer.m_pData; ULONG return_length; if (!NT_SUCCESS(NtQueryObject( dup_handle, ObjectNameInformation, obj_name_info, info_size, &return_length ))) { continue; } UNICODE_STRING object_name = *(PUNICODE_STRING)obj_name_info; if (object_name.Length) { CStringW object_name(object_name.Buffer, object_name.Length / 2); if (object_name == mutant_name) { pids.push_back(process_id); } //wprintf(L"%u %s\n", process_id, object_name.GetString()); } } if (cur_handle != NULL) { CloseHandle(cur_handle); cur_handle = NULL; } return TRUE; }