diff --git a/PipeViewer/Form1.cs b/PipeViewer/Form1.cs index 2b451e1..cf537b8 100644 --- a/PipeViewer/Form1.cs +++ b/PipeViewer/Form1.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Data; using System.Drawing; @@ -213,14 +213,18 @@ private void initializePipeListOrig() //} // # version 3 - private void initializePipeList() + private async void initializePipeList() { string[] listOfPipes = System.IO.Directory.GetFiles(@"\\.\pipe\"); - Parallel.ForEach(listOfPipes, namedPipe => + foreach(var pipe in listOfPipes) { - addNamedPipeToDataGridView(namedPipe); - }); + if (pipe.StartsWith(@"\\.\pipe\")) + { + await addNamedPipeToDataGridView(pipe); + } + + } this.Invoke(new Action(() => { @@ -284,123 +288,128 @@ private void dataGridView1_SelectionChanged(object sender, EventArgs e) //} // https://blog.cjwdev.co.uk/2011/06/28/permissions-not-included-in-net-accessrule-filesystemrights-enum/ - private void addNamedPipeToDataGridView(string i_NamedPipe) + private async Task addNamedPipeToDataGridView(string namedPipe) { - // i_NamedPipe = @"\\.\pipe\myPipe"; - string permissions; - if (this.InvokeRequired) + try { - addNamedPipeToDataGridViewCallBack s = new addNamedPipeToDataGridViewCallBack(addNamedPipeToDataGridView); - this.Invoke(s, i_NamedPipe); + // Perform heavy work in a background thread + var rowData = await Task.Run(() => + { + var row = new DataGridViewRow(); + row.CreateCells(dataGridView1); + row.Cells[m_ColumnIndexes[ColumnName.HeaderText]].Value = namedPipe; + + NtNamedPipeFileBase namedPipeObject = Engine.GetNamedPipeObject(namedPipe, Engine.NamedPipeFunctionEndType.Client) + ?? Engine.GetNamedPipeObject(namedPipe, Engine.NamedPipeFunctionEndType.Server); + + if (namedPipeObject != null) + { + // Process security descriptors and pipe information + ProcessNamedPipeObject(namedPipeObject, row); + } + + return row; + }); + + // Update the UI on the main thread + this.Invoke((Action)(() => + { + dataGridView1.Rows.Add(rowData); + this.m_NamedPipesNumber++; + this.toolStripStatusLabelTotalNamedPipes.Text = "Total Named Pipes: " + this.m_NamedPipesNumber; + })); } - else + catch (Exception ex) { - DataGridViewRow row = new DataGridViewRow(); - row.CreateCells(dataGridView1); - row.Cells[m_ColumnIndexes[ColumnName.HeaderText]].Value = i_NamedPipe; - row.DefaultCellStyle.Font = new Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Regular); + //TODO - Log the exception - NtNamedPipeFileBase namedPipeObject = Engine.GetNamedPipeObject(i_NamedPipe, Engine.NamedPipeFunctionEndType.Client); - if (namedPipeObject == null) - { - namedPipeObject = Engine.GetNamedPipeObject(i_NamedPipe, Engine.NamedPipeFunctionEndType.Server); - } + } + } - // NtNamedPipeFileBase namedPipeObjectClient = Engine.GetNamedPipeClientObject(i_NamedPipe); - // We added a check for empty name because it caused an exception with named pipe \\.\pipe\dbxsvc which wasn't NULL - // but add partial value exist on one machine. + private void ProcessNamedPipeObject(NtNamedPipeFileBase namedPipeObject, DataGridViewRow row) + { + try + { + string permissions = ""; + Color cellColor = Color.White; - // We added try\catch because one specific bug with \\.\pipe\dbxsvc (DropBox). Maybe there is a better way to handle it? - try + // Check for null or empty SecurityDescriptor or DACL + if (namedPipeObject.SecurityDescriptor == null || namedPipeObject.SecurityDescriptor.Dacl == null || namedPipeObject.SecurityDescriptor.Dacl.Count == 0) + { + row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Value = "NO DACL -> FULL permissions"; + row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Style.BackColor = Color.Red; + return; + } + + foreach (Ace dacl in namedPipeObject.SecurityDescriptor.Dacl) { + string permissionReadOrWrite = Engine.ConvertAccessMaskToSimplePermissions(dacl.Mask.Access); + string allowedOrNotAllowed = dacl.Type.ToString(); - if (namedPipeObject != null) + // Check if the current user or their groups have permissions + foreach (IdentityReference group in m_CurrentIdentity.Groups) { - row.Cells[m_ColumnIndexes[ColumnSddl.HeaderText]].Value = namedPipeObject.Sddl; - - Color cellColor = Color.White; - if (namedPipeObject.SecurityDescriptor.Dacl.Count != 0) + SecurityIdentifier sid = (SecurityIdentifier)group.Translate(typeof(SecurityIdentifier)); + if ((m_CurrentUserSid.Equals(dacl.Sid.ToString()) || sid.Value.Equals(dacl.Sid.ToString())) && allowedOrNotAllowed.Contains("Allowed")) { - permissions = ""; - - foreach (Ace dacl in namedPipeObject.SecurityDescriptor.Dacl) + // Add SID to dictionary if not already present + if (!m_SidDict.ContainsKey(dacl.Sid.Name)) { - string permissionReadOrWrite = Engine.ConvertAccessMaskToSimplePermissions(dacl.Mask.Access); - string allowedOrNotAllowed = dacl.Type.ToString(); - - // TODO: why adding to a new group doesn't show the new group - foreach (IdentityReference group in m_CurrentIdentity.Groups) - { - SecurityIdentifier sid = (SecurityIdentifier)group.Translate(typeof(SecurityIdentifier)); - if ((m_CurrentUserSid.Equals(dacl.Sid.ToString()) || sid.Value.Equals(dacl.Sid.ToString())) && allowedOrNotAllowed.Contains("Allowed")) - { - if (!m_SidDict.ContainsKey(dacl.Sid.Name)) - { - m_SidDict.Add(dacl.Sid.Name, dacl.Sid.ToString()); - } - if (permissionReadOrWrite.Contains("R")) - { - cellColor = Color.Yellow; - } - if (permissionReadOrWrite.Contains("W") || permissionReadOrWrite.Contains("Full") || permissionReadOrWrite.Contains("RW")) - { - cellColor = Color.LightGreen; - break; - } - } - } - - row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Style.BackColor = cellColor; - permissions += allowedOrNotAllowed + " "; - permissions += permissionReadOrWrite; - permissions += " " + dacl.Sid.Name + "; \n"; + m_SidDict.Add(dacl.Sid.Name, dacl.Sid.ToString()); } - row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Value = permissions; - } else - { - row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Value = "NO DACL -> FULL permissions"; - //row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Style.Font = new Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Bold); - row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Style.BackColor = Color.Red; + // Determine cell color based on permissions + if (permissionReadOrWrite.Contains("R")) + { + cellColor = Color.Yellow; + } + if (permissionReadOrWrite.Contains("W") || permissionReadOrWrite.Contains("Full") || permissionReadOrWrite.Contains("RW")) + { + cellColor = Color.LightGreen; + break; + } } - - row.Cells[m_ColumnIndexes[ColumnOwnerSid.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Owner.Sid.ToString(); - row.Cells[m_ColumnIndexes[ColumnOwnerName.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Owner.Sid.Name; - row.Cells[m_ColumnIndexes[ColumnGroupSid.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Group.Sid.ToString(); - row.Cells[m_ColumnIndexes[ColumnGroupName.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Group.Sid.Name; - row.Cells[m_ColumnIndexes[ColumnIntegrityLevel.HeaderText]].Value = namedPipeObject.SecurityDescriptor.IntegrityLevel; - row.Cells[m_ColumnIndexes[ColumnEndPointType.HeaderText]].Value = namedPipeObject.EndPointType; - row.Cells[m_ColumnIndexes[ColumnConfiguration.HeaderText]].Value = namedPipeObject.Configuration; - - row.Cells[m_ColumnIndexes[ColumnPipeType.HeaderText]].Value = namedPipeObject.PipeType; - row.Cells[m_ColumnIndexes[ColumnReadMode.HeaderText]].Value = namedPipeObject.ReadMode; - row.Cells[m_ColumnIndexes[ColumnDirectoryGrantedAccess.HeaderText]].Value = namedPipeObject.DirectoryGrantedAccess; - row.Cells[m_ColumnIndexes[ColumnGrantedAccess.HeaderText]].Value = namedPipeObject.GrantedAccess; - row.Cells[m_ColumnIndexes[ColumnGrantedAccessGeneric.HeaderText]].Value = namedPipeObject.GrantedAccessGeneric; - row.Cells[m_ColumnIndexes[ColumnHandle.HeaderText]].Value = namedPipeObject.Handle.ToString(); - row.Cells[m_ColumnIndexes[ColumnCreationTime.HeaderText]].Value = namedPipeObject.CreationTime; - - row.Cells[m_ColumnIndexes[ColumnClientPID.HeaderText]].Value = getProcessNameWithProcessPIDs(namedPipeObject); - row.Cells[m_ColumnIndexes[ColumnNumberOfLinks.HeaderText]].Value = namedPipeObject.NumberOfLinks; - row.Cells[m_ColumnIndexes[ColumnFileCreationTime.HeaderText]].Value = namedPipeObject.FileCreationTime; - row.Cells[m_ColumnIndexes[ColumnLastAccessTime.HeaderText]].Value = namedPipeObject.LastAccessTime; - row.Cells[m_ColumnIndexes[ColumnLastWriteTime.HeaderText]].Value = namedPipeObject.LastWriteTime; - row.Cells[m_ColumnIndexes[ColumnChangeTime.HeaderText]].Value = namedPipeObject.ChangeTime; } - } - catch (Exception) - { - // TODO: write to log - } + permissions += $"{allowedOrNotAllowed} {permissionReadOrWrite} {dacl.Sid.Name}; \n"; + } - dataGridView1.Rows.Add(row); - this.m_NamedPipesNumber += 1; - this.toolStripStatusLabelTotalNamedPipes.Text = "Total Named Pipes: " + this.m_NamedPipesNumber; + // Assign permissions and color + row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Value = permissions; + row.Cells[m_ColumnIndexes[ColumnPermissions.HeaderText]].Style.BackColor = cellColor; + + // Fill other row columns with named pipe object data + row.Cells[m_ColumnIndexes[ColumnOwnerSid.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Owner.Sid.ToString(); + row.Cells[m_ColumnIndexes[ColumnOwnerName.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Owner.Sid.Name; + row.Cells[m_ColumnIndexes[ColumnGroupSid.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Group.Sid.ToString(); + row.Cells[m_ColumnIndexes[ColumnGroupName.HeaderText]].Value = namedPipeObject.SecurityDescriptor.Group.Sid.Name; + row.Cells[m_ColumnIndexes[ColumnIntegrityLevel.HeaderText]].Value = namedPipeObject.SecurityDescriptor.IntegrityLevel; + row.Cells[m_ColumnIndexes[ColumnEndPointType.HeaderText]].Value = namedPipeObject.EndPointType; + row.Cells[m_ColumnIndexes[ColumnConfiguration.HeaderText]].Value = namedPipeObject.Configuration; + row.Cells[m_ColumnIndexes[ColumnPipeType.HeaderText]].Value = namedPipeObject.PipeType; + row.Cells[m_ColumnIndexes[ColumnReadMode.HeaderText]].Value = namedPipeObject.ReadMode; + row.Cells[m_ColumnIndexes[ColumnDirectoryGrantedAccess.HeaderText]].Value = namedPipeObject.DirectoryGrantedAccess; + row.Cells[m_ColumnIndexes[ColumnGrantedAccess.HeaderText]].Value = namedPipeObject.GrantedAccess; + row.Cells[m_ColumnIndexes[ColumnGrantedAccessGeneric.HeaderText]].Value = namedPipeObject.GrantedAccessGeneric; + row.Cells[m_ColumnIndexes[ColumnHandle.HeaderText]].Value = namedPipeObject.Handle.ToString(); + row.Cells[m_ColumnIndexes[ColumnCreationTime.HeaderText]].Value = namedPipeObject.CreationTime; + row.Cells[m_ColumnIndexes[ColumnClientPID.HeaderText]].Value = getProcessNameWithProcessPIDs(namedPipeObject); + row.Cells[m_ColumnIndexes[ColumnNumberOfLinks.HeaderText]].Value = namedPipeObject.NumberOfLinks; + row.Cells[m_ColumnIndexes[ColumnFileCreationTime.HeaderText]].Value = namedPipeObject.FileCreationTime; + row.Cells[m_ColumnIndexes[ColumnLastAccessTime.HeaderText]].Value = namedPipeObject.LastAccessTime; + row.Cells[m_ColumnIndexes[ColumnLastWriteTime.HeaderText]].Value = namedPipeObject.LastWriteTime; + row.Cells[m_ColumnIndexes[ColumnChangeTime.HeaderText]].Value = namedPipeObject.ChangeTime; + } + catch (Exception ex) + { + // Log the exception for debugging purposes + Console.WriteLine($"Error processing named pipe object: {ex.Message}"); } } + + private string getProcessNameWithProcessPIDs(NtNamedPipeFileBase i_NamedPipe) { var processNames = i_NamedPipe.GetUsingProcessIds() @@ -517,30 +526,41 @@ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) } else if (keyData == (Keys.Control | Keys.B)) { - Font boldFont = new Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Bold); - Font font = new Font(dataGridView1.DefaultCellStyle.Font, FontStyle.Regular); + Font baseFont = dataGridView1.DefaultCellStyle.Font; + Font boldFont = new Font(baseFont, FontStyle.Bold); + Font regularFont = new Font(baseFont, FontStyle.Regular); foreach (DataGridViewCell cell in dataGridView1.SelectedCells) { - - if (!dataGridView1.Rows[cell.RowIndex].DefaultCellStyle.Font.Bold) + var rowStyle = dataGridView1.Rows[cell.RowIndex].DefaultCellStyle; + if (rowStyle.Font == null) { - font = boldFont; + rowStyle.Font = baseFont; + } + if (!rowStyle.Font.Bold) + { + rowStyle.Font = boldFont; + } + else + { + rowStyle.Font = regularFont; } - - dataGridView1.Rows[cell.RowIndex].DefaultCellStyle.Font = font; } foreach (DataGridViewRow selectedRow in dataGridView1.SelectedRows) { - + if (selectedRow.DefaultCellStyle.Font == null) + { + selectedRow.DefaultCellStyle.Font = baseFont; + } if (!selectedRow.DefaultCellStyle.Font.Bold) { - font = boldFont; + selectedRow.DefaultCellStyle.Font = boldFont; + } + else + { + selectedRow.DefaultCellStyle.Font = regularFont; } - - dataGridView1.Rows[selectedRow.Index].DefaultCellStyle.Font = font; - } result = true; } @@ -557,12 +577,18 @@ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) else if (keyData == (Keys.F3)) { // We need to implement the options for the search + dataGridView1.Columns["ColumnName"].SortMode = DataGridViewColumnSortMode.NotSortable; FindWindow_searchForMatch(m_LastSearchValue, true, false, false); + dataGridView1.Columns["ColumnName"].SortMode = DataGridViewColumnSortMode.Automatic; + } else if (keyData == (Keys.Shift | Keys.F3)) { // We need to implement the options for the search + dataGridView1.Columns["ColumnName"].SortMode = DataGridViewColumnSortMode.NotSortable; FindWindow_searchForMatch(m_LastSearchValue, false, false, false); + dataGridView1.Columns["ColumnName"].SortMode = DataGridViewColumnSortMode.Automatic; + } return result; @@ -666,19 +692,25 @@ private void FindWindow_searchForMatch(string i_SearchString, bool i_SearchDown, { break; } + DataGridViewRow row = dataGridView1.Rows[i]; + if (row == null || !row.Visible || i_SearchString == null) + { + continue; + } - foreach (DataGridViewCell cell in dataGridView1.Rows[i].Cells) + foreach (DataGridViewCell cell in row.Cells) { - // TODO: Add support in Case Sensitive, replicate to RPCMon. - if (dataGridView1.Rows[i].Visible && cell.Value != null && cell.Value.ToString().ToLower().Contains(i_SearchString.ToLower())) + string cellText = cell.Value?.ToString(); + + if (cellText != null && cellText.ToLower().Contains(i_SearchString.ToLower())) { cleanAllSelectedCells(); - dataGridView1.Rows[i].Selected = true; + row.Selected = true; foundMatch = true; - dataGridView1.CurrentCell = dataGridView1.Rows[i].Cells[0]; + dataGridView1.CurrentCell = row.Cells[0]; dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.SelectedRows[0].Index; - + break; } }