private ProcessHandle OpenProcessCsr(int pid, ProcessAccess access) { var csrProcesses = this.GetCsrProcesses(); foreach (var csrProcess in csrProcesses) { foreach (var handle in csrProcess.GetHandles()) { try { // Assume that the handle is a process handle. int handlePid = KProcessHacker.Instance.KphGetProcessId(csrProcess, handle.Handle); if (handlePid == pid) { return(ProcessHandle.FromHandle( new NativeHandle <ProcessAccess>(csrProcess, handle.Handle, access) )); } else if (handlePid == 0) { throw new Exception(); // HACK } } catch { try { // Assume that the handle is a thread handle. int handlePid; int tid = KProcessHacker.Instance.KphGetThreadId(csrProcess, handle.Handle, out handlePid); if (tid == 0) { throw new Exception(); } if (handlePid == pid) { using (var dupHandle = new NativeHandle <ThreadAccess>(csrProcess, handle.Handle, Program.MinThreadQueryRights)) return(ThreadHandle.FromHandle(dupHandle).GetProcess(access)); } } catch { } } } csrProcess.Dispose(); } throw new Exception("Could not find process (hidden from handle table)."); }
public static ObjectInformation GetHandleInfo(this SystemHandleEntry thisHandle, ProcessHandle process, bool getName) { IntPtr handle = new IntPtr(thisHandle.Handle); IntPtr objectHandleI; int retLength; GenericHandle objectHandle = null; if (thisHandle.Handle == 0 || thisHandle.Handle == -1 || thisHandle.Handle == -2) { throw new WindowsException(NtStatus.InvalidHandle); } // Duplicate the handle if we're not using KPH //if (KProcessHacker.Instance == null) { Win32.NtDuplicateObject( process, handle, ProcessHandle.Current, out objectHandleI, 0, 0, 0 ).ThrowIf(); objectHandle = new GenericHandle(objectHandleI); } ObjectInformation info = new ObjectInformation(); // If the cache contains the object type's name, use it. Otherwise, query the type // for its name. Windows.ObjectTypesLock.AcquireShared(); try { if (Windows.ObjectTypes.ContainsKey(thisHandle.ObjectTypeNumber)) { info.TypeName = Windows.ObjectTypes[thisHandle.ObjectTypeNumber]; } } finally { Windows.ObjectTypesLock.ReleaseShared(); } if (string.IsNullOrEmpty(info.TypeName)) { Win32.NtQueryObject( objectHandle, ObjectInformationClass.ObjectTypeInformation, IntPtr.Zero, 0, out retLength ); if (retLength > 0) { using (MemoryAlloc otiMem = new MemoryAlloc(retLength)) { Win32.NtQueryObject( objectHandle, ObjectInformationClass.ObjectTypeInformation, otiMem, otiMem.Size, out retLength ).ThrowIf(); ObjectTypeInformation oti = otiMem.ReadStruct <ObjectTypeInformation>(); UnicodeString str = oti.Name; //if (KProcessHacker.Instance != null) //str.Buffer = str.Buffer.Increment(otiMem.Memory.Decrement(baseAddress)); info.TypeName = str.Text; Windows.ObjectTypesLock.AcquireExclusive(); try { if (!Windows.ObjectTypes.ContainsKey(thisHandle.ObjectTypeNumber)) { Windows.ObjectTypes.Add(thisHandle.ObjectTypeNumber, info.TypeName); } } finally { Windows.ObjectTypesLock.ReleaseExclusive(); } } } } if (!getName) { return(info); } // Get the object's name. If the object is a file we must take special // precautions so that we don't hang. if (string.Equals(info.TypeName, "File", StringComparison.OrdinalIgnoreCase)) { //if (KProcessHacker.Instance != null) //{ // // Use KProcessHacker for files to avoid hangs. // info.OrigName = KProcessHacker.Instance.GetHandleObjectName(process, handle); //} //else { // 0: No hack, query the thing normally. // 1: No hack, use NProcessHacker. // 2: Hack. int hackLevel = 1; // If we already tried to use NPH but it wasn't present, // skip to level 2. if (NphNotAvailable) { hackLevel = 2; } // Can't use NPH because XP had a bug where a thread hanging // on NtQueryObject couldn't be terminated. if (OSVersion.IsBelowOrEqual(WindowsVersion.XP)) { hackLevel = 2; } // On Windows 7 and above the hanging bug appears to have // been fixed. Query the object normally. // UPDATE: Not so. It still happens. //if (OSVersion.IsAboveOrEqual(WindowsVersion.Seven)) // hackLevel = 0; if (hackLevel == 1) { try { // Use NProcessHacker. using (MemoryAlloc oniMem = new MemoryAlloc(0x4000)) { NProcessHacker.PhQueryNameFileObject( objectHandle, oniMem, oniMem.Size, out retLength ).ThrowIf(); var oni = oniMem.ReadStruct <ObjectNameInformation>(); info.OrigName = oni.Name.Text; } } catch (DllNotFoundException) { hackLevel = 2; NphNotAvailable = true; } } if (hackLevel == 0) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } else if (hackLevel == 2) { // KProcessHacker and NProcessHacker not available. Fall back to using hack // (i.e. not querying the name at all if the access is 0x0012019f). if (thisHandle.GrantedAccess != 0x0012019f) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } } } } else { // Not a file. Query the object normally. info.OrigName = GetObjectNameNt(process, handle, objectHandle); } // Get a better name for the handle. try { switch (info.TypeName) { case "File": // Resolves \Device\HarddiskVolume1 into C:, for example. if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = FileUtils.GetFileName(info.OrigName); } break; case "Key": info.BestName = NativeUtils.FormatNativeKeyName(info.OrigName); break; case "Process": { int processId; using (NativeHandle <ProcessAccess> processHandle = new NativeHandle <ProcessAccess>(process, handle, OSVersion.MinProcessQueryInfoAccess)) { if ((processId = Win32.GetProcessId(processHandle)) == 0) { Win32.Throw(); } } info.BestName = (new ClientId(processId, 0)).GetName(false); } break; case "Thread": { int processId; int threadId; using (var threadHandle = new NativeHandle <ThreadAccess>(process, handle, OSVersion.MinThreadQueryInfoAccess)) { var basicInfo = ThreadHandle.FromHandle(threadHandle).GetBasicInformation(); threadId = basicInfo.ClientId.ThreadId; processId = basicInfo.ClientId.ProcessId; } info.BestName = (new ClientId(processId, threadId)).GetName(true); } break; case "TmEn": { using (NativeHandle <EnlistmentAccess> enHandleDup = new NativeHandle <EnlistmentAccess>(process, handle, EnlistmentAccess.QueryInformation)) using (EnlistmentHandle enHandle = EnlistmentHandle.FromHandle(enHandleDup)) { info.BestName = enHandle.BasicInformation.EnlistmentId.ToString("B"); } } break; case "TmRm": { using (var rmHandleDup = new NativeHandle <ResourceManagerAccess>(process, handle, ResourceManagerAccess.QueryInformation)) { var rmHandle = ResourceManagerHandle.FromHandle(rmHandleDup); info.BestName = rmHandle.Description; if (string.IsNullOrEmpty(info.BestName)) { info.BestName = rmHandle.Guid.ToString("B"); } } } break; case "TmTm": { using (NativeHandle <TmAccess> tmHandleDup = new NativeHandle <TmAccess>(process, handle, TmAccess.QueryInformation)) using (TmHandle tmHandle = TmHandle.FromHandle(tmHandleDup)) { info.BestName = FileUtils.GetFileName(FileUtils.GetFileName(tmHandle.LogFileName)); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = tmHandle.BasicInformation.TmIdentity.ToString("B"); } } } break; case "TmTx": { using (var transactionHandleDup = new NativeHandle <TransactionAccess>(process, handle, TransactionAccess.QueryInformation)) { TransactionHandle transactionHandle = TransactionHandle.FromHandle(transactionHandleDup); info.BestName = transactionHandle.Description; if (string.IsNullOrEmpty(info.BestName)) { info.BestName = transactionHandle.BasicInformation.TransactionId.ToString("B"); } } } break; case "Token": { using (var tokenHandleDup = new NativeHandle <TokenAccess>(process, handle, TokenAccess.Query)) using (TokenHandle tokenHandle = TokenHandle.FromHandle(tokenHandleDup)) using (tokenHandle.User) { info.BestName = tokenHandle.User.GetFullName(true) + ": 0x" + tokenHandle.Statistics.AuthenticationId; } } break; default: if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = info.OrigName; } else { info.BestName = null; } break; } } catch { if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = info.OrigName; } else { info.BestName = null; } } if (objectHandle != null) { objectHandle.Dispose(); } return(info); }
private void ScanCsrHandles() { this.Cursor = Cursors.WaitCursor; listProcesses.BeginUpdate(); listProcesses.Items.Clear(); try { var processes = Windows.GetProcesses(); int totalCount = 0; int hiddenCount = 0; int terminatedCount = 0; processes.Remove(0); List <int> foundPids = new List <int>(); var csrProcesses = this.GetCsrProcesses(); // Duplicate each process handle and check if they exist in the normal list. foreach (var csrhandle in csrProcesses) { try { var handles = csrhandle.GetHandles(); foreach (var handle in handles) { int pid = 0; bool isThread = false; try { pid = KProcessHacker.Instance.KphGetProcessId(csrhandle, handle.Handle); // HACK: Using exception for program flow! if (pid == 0) { throw new Exception(); } } catch { // Probably not a process handle. // Try opening it as a thread. try { int tid = KProcessHacker.Instance.KphGetThreadId(csrhandle, handle.Handle, out pid); isThread = true; if (tid == 0) { throw new Exception(); } } catch { continue; } } // Avoid duplicate PIDs. if (foundPids.Contains(pid)) { continue; } foundPids.Add(pid); try { ProcessHandle phandle; if (!isThread) { var dupHandle = new NativeHandle <ProcessAccess>(csrhandle, handle.Handle, Program.MinProcessQueryRights); phandle = ProcessHandle.FromHandle(dupHandle); } else { using (var dupHandle = new NativeHandle <ThreadAccess>(csrhandle, handle.Handle, Program.MinThreadQueryRights)) phandle = ThreadHandle.FromHandle(dupHandle). GetProcess(Program.MinProcessQueryRights); } AddProcessItem( phandle, pid, ref totalCount, ref hiddenCount, ref terminatedCount, (pid_) => processes.ContainsKey(pid_) ); phandle.Dispose(); } catch (WindowsException ex2) { AddErrorItem(ex2, pid, ref totalCount, ref hiddenCount, ref terminatedCount); } } } catch (WindowsException ex) { PhUtils.ShowException("Unable to get the CSR handle list", ex); return; } csrhandle.Dispose(); } labelCount.Text = totalCount.ToString() + " running processes (excl. kernel, idle, non-Windows), " + hiddenCount.ToString() + " hidden, " + terminatedCount.ToString() + " terminated."; if (hiddenCount > 0) { labelCount.ForeColor = Color.Red; } else { labelCount.ForeColor = SystemColors.WindowText; } } finally { listProcesses.EndUpdate(); this.Cursor = Cursors.Default; } }
public static ObjectInformation GetHandleInfo(this SystemHandleEntry thisHandle, ProcessHandle process, bool getName) { IntPtr handle = new IntPtr(thisHandle.Handle); IntPtr objectHandleI; int retLength = 0; GenericHandle objectHandle = null; if (thisHandle.Handle == 0 || thisHandle.Handle == -1 || thisHandle.Handle == -2) { throw new WindowsException(NtStatus.InvalidHandle); } // Duplicate the handle if we're not using KPH if (KProcessHacker.Instance == null) { NtStatus status; if ((status = Win32.NtDuplicateObject( process, handle, ProcessHandle.Current, out objectHandleI, 0, 0, 0)) >= NtStatus.Error) { Win32.ThrowLastError(status); } objectHandle = new GenericHandle(objectHandleI); } ObjectInformation info = new ObjectInformation(); // If the cache contains the object type's name, use it. Otherwise, query the type // for its name. lock (Windows.ObjectTypes) { if (Windows.ObjectTypes.ContainsKey(thisHandle.ObjectTypeNumber)) { info.TypeName = Windows.ObjectTypes[thisHandle.ObjectTypeNumber]; } else { int baseAddress = 0; if (KProcessHacker.Instance != null) { KProcessHacker.Instance.ZwQueryObject(process, handle, ObjectInformationClass.ObjectTypeInformation, IntPtr.Zero, 0, out retLength, out baseAddress); } else { Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectTypeInformation, IntPtr.Zero, 0, out retLength); } if (retLength > 0) { using (MemoryAlloc otiMem = new MemoryAlloc(retLength)) { if (KProcessHacker.Instance != null) { if (KProcessHacker.Instance.ZwQueryObject(process, handle, ObjectInformationClass.ObjectTypeInformation, otiMem, otiMem.Size, out retLength, out baseAddress) >= NtStatus.Error) { throw new Exception("ZwQueryObject failed."); } } else { if (Win32.NtQueryObject(objectHandle, ObjectInformationClass.ObjectTypeInformation, otiMem, otiMem.Size, out retLength) >= NtStatus.Error) { throw new Exception("NtQueryObject failed."); } } var oti = otiMem.ReadStruct <ObjectTypeInformation>(); var str = oti.Name; if (KProcessHacker.Instance != null) { str.Buffer = str.Buffer.Increment(otiMem.Memory.Decrement(baseAddress)); } info.TypeName = str.Read(); Windows.ObjectTypes.Add(thisHandle.ObjectTypeNumber, info.TypeName); } } } } if (!getName) { return(info); } // Get the object's name. If the object is a file we must take special // precautions so that we don't hang. if (info.TypeName == "File") { if (KProcessHacker.Instance != null) { // Use KProcessHacker for files to avoid hangs. info.OrigName = KProcessHacker.Instance.GetHandleObjectName(process, handle); } else { // 0: No hack, query the thing normally. // 1: No hack, use NProcessHacker. // 2: Hack. int hackLevel = 1; // Can't use NPH because XP had a bug where a thread hanging // on NtQueryObject couldn't be terminated. if (OSVersion.IsBelowOrEqual(WindowsVersion.XP)) { hackLevel = 2; } // On Windows 7 and above the hanging bug appears to have // been fixed. Query the object normally. // UPDATE: Not so. It still happens. //if (OSVersion.IsAboveOrEqual(WindowsVersion.Seven)) // hackLevel = 0; if (hackLevel == 1) { try { // Use NProcessHacker. using (MemoryAlloc oniMem = new MemoryAlloc(0x4000)) { if (NProcessHacker.PhQueryNameFileObject( objectHandle, oniMem, oniMem.Size, out retLength) >= NtStatus.Error) { throw new Exception("PhQueryNameFileObject failed."); } var oni = oniMem.ReadStruct <ObjectNameInformation>(); info.OrigName = oni.Name.Read(); } } catch (DllNotFoundException) { hackLevel = 2; } } if (hackLevel == 0) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } else if (hackLevel == 2) { // KProcessHacker and NProcessHacker not available. Fall back to using hack // (i.e. not querying the name at all if the access is 0x0012019f). if ((int)thisHandle.GrantedAccess != 0x0012019f) { info.OrigName = GetObjectNameNt(process, handle, objectHandle); } } } } else { // Not a file. Query the object normally. info.OrigName = GetObjectNameNt(process, handle, objectHandle); } // Get a better name for the handle. try { switch (info.TypeName) { case "File": // Resolves \Device\Harddisk1 into C:, for example. if (!string.IsNullOrEmpty(info.OrigName)) { info.BestName = FileUtils.GetFileName(info.OrigName); } break; case "Key": info.BestName = NativeUtils.FormatNativeKeyName(info.OrigName); break; case "Process": { int processId; if (KProcessHacker.Instance != null) { processId = KProcessHacker.Instance.KphGetProcessId(process, handle); if (processId == 0) { throw new Exception("Invalid PID"); } } else { using (var processHandle = new NativeHandle <ProcessAccess>(process, handle, OSVersion.MinProcessQueryInfoAccess)) { if ((processId = Win32.GetProcessId(processHandle)) == 0) { Win32.ThrowLastError(); } } } info.BestName = (new ClientId(processId, 0)).GetName(false); } break; case "Thread": { int processId; int threadId; if (KProcessHacker.Instance != null) { threadId = KProcessHacker.Instance.KphGetThreadId(process, handle, out processId); if (threadId == 0 || processId == 0) { throw new Exception("Invalid TID or PID"); } } else { using (var threadHandle = new NativeHandle <ThreadAccess>(process, handle, OSVersion.MinThreadQueryInfoAccess)) { var basicInfo = ThreadHandle.FromHandle(threadHandle).GetBasicInformation(); threadId = basicInfo.ClientId.ThreadId; processId = basicInfo.ClientId.ProcessId; } } info.BestName = (new ClientId(processId, threadId)).GetName(true); } break; case "TmEn": { using (var enHandleDup = new NativeHandle <EnlistmentAccess>(process, handle, EnlistmentAccess.QueryInformation)) { var enHandle = EnlistmentHandle.FromHandle(enHandleDup); info.BestName = enHandle.GetBasicInformation().EnlistmentId.ToString("B"); } } break; case "TmRm": { using (var rmHandleDup = new NativeHandle <ResourceManagerAccess>(process, handle, ResourceManagerAccess.QueryInformation)) { var rmHandle = ResourceManagerHandle.FromHandle(rmHandleDup); info.BestName = rmHandle.GetDescription(); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = rmHandle.GetGuid().ToString("B"); } } } break; case "TmTm": { using (var tmHandleDup = new NativeHandle <TmAccess>(process, handle, TmAccess.QueryInformation)) { var tmHandle = TmHandle.FromHandle(tmHandleDup); info.BestName = FileUtils.GetFileName(FileUtils.GetFileName(tmHandle.GetLogFileName())); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = tmHandle.GetBasicInformation().TmIdentity.ToString("B"); } } } break; case "TmTx": { using (var transactionHandleDup = new NativeHandle <TransactionAccess>(process, handle, TransactionAccess.QueryInformation)) { var transactionHandle = TransactionHandle.FromHandle(transactionHandleDup); info.BestName = transactionHandle.GetDescription(); if (string.IsNullOrEmpty(info.BestName)) { info.BestName = transactionHandle.GetBasicInformation().TransactionId.ToString("B"); } } } break; case "Token": { using (var tokenHandleDup = new NativeHandle <TokenAccess>(process, handle, TokenAccess.Query)) { var tokenHandle = TokenHandle.FromHandle(tokenHandleDup); var sid = tokenHandle.GetUser(); using (sid) info.BestName = sid.GetFullName(true) + ": 0x" + tokenHandle.GetStatistics().AuthenticationId.ToString(); } } break; default: if (info.OrigName != null && info.OrigName != "") { info.BestName = info.OrigName; } else { info.BestName = null; } break; } } catch { if (info.OrigName != null && info.OrigName != "") { info.BestName = info.OrigName; } else { info.BestName = null; } } if (objectHandle != null) { objectHandle.Dispose(); } return(info); }