diff --git a/RpcInvestigator.csproj b/RpcInvestigator.csproj index 8f67aae..7fdee82 100644 --- a/RpcInvestigator.csproj +++ b/RpcInvestigator.csproj @@ -101,8 +101,8 @@ packages\NtApiDotNet.Forms.1.1.33\lib\net461\NtApiDotNet.Forms.dll - - packages\ObjectListView.Official.2.9.2-alpha2\lib\net20\ObjectListView.dll + + packages\ObjectListView-ToB.2.9.4\lib\net20\ObjectListView.dll diff --git a/TabPages/RpcAlpcServerList.cs b/TabPages/RpcAlpcServerList.cs index cfd81ba..24ff403 100644 --- a/TabPages/RpcAlpcServerList.cs +++ b/TabPages/RpcAlpcServerList.cs @@ -15,13 +15,6 @@ using BrightIdeasSoftware; using System.Drawing; using System.Diagnostics; using RpcInvestigator.TabPages; -using System.Runtime.InteropServices; -using System.Security.AccessControl; -using Newtonsoft.Json.Linq; -using RpcInvestigator.Util; -using System.ServiceModel.Channels; -using System.Text; -using RpcInvestigator.Windows; namespace RpcInvestigator { @@ -55,25 +48,35 @@ namespace RpcInvestigator m_Listview.View = View.Details; m_Listview.VirtualMode = true; m_Listview.ShowGroups = false; + m_Listview.UseFiltering = true; m_Listview.Alignment = ListViewAlignment.Left; Generator.GenerateColumns(m_Listview, typeof(RpcAlpcServer), true); foreach (var column in m_Listview.AllColumns) { - if (column.Name.ToLower() == "endpoints") + if (column.Name.ToLower() == "endpoints" || + column.Name.ToLower() == "securitydescriptor") { column.IsVisible = false; } + if (column.Name.ToLower() == "securitydescriptor") + { + column.AspectGetter = delegate (object Row) + { + if (Row == null) + { + return ""; + } + var server = Row as RpcAlpcServer; + if (server.SecurityDescriptor == null) + { + return ""; + } + return server.SecurityDescriptor.ToString(); + }; + } column.MaximumWidth = -1; } - m_Listview.AllColumns.ForEach(col => - { - if (col.Name == "SecurityDescriptor") - { - col.IsVisible = false; - } - }); - // // When a listview row is double-clicked, a new tab will open with endpoints // for the selected RPC server. Right-click shows context menu. @@ -90,9 +93,36 @@ namespace RpcInvestigator selectedRow.Name, selectedRow.Endpoints.ToList(), selectedRow.Name); }); m_Listview.CellRightClick += RightClickHandler; + m_Listview.ColumnRightClick += ColumnRightClickOverride; Controls.Add(m_Listview); } + private void ColumnRightClickOverride(object sender, ColumnClickEventArgs e) + { + // + // Some of the columns we hide by default should never be shown, + // either because they contain binary data or lists of binary data. + // Such information is not easy to disable in the listview, so we'll + // strip those columns from the column selector context menu. + // + var args = (ColumnRightClickEventArgs)e; + var list = new List(); + foreach (var item in args.MenuStrip.Items) + { + if (item.GetType() == typeof(ToolStripMenuItem)) + { + var toolstripItem = item as ToolStripMenuItem; + if (toolstripItem.Text.ToLower() == "endpoints") + { + continue; + } + } + list.Add((ToolStripItem)item); + } + args.MenuStrip.Items.Clear(); + args.MenuStrip.Items.AddRange(list.ToArray()); + } + public int GetCount() { if (m_Listview.Objects == null) @@ -200,9 +230,24 @@ namespace RpcInvestigator TabPages.ContextMenu.BuildRightClickMenu(Args, new List{ new ToolStripMenuItem("Open in Library", null, ContextMenuOpenAlpcServerInLibrary), new ToolStripMenuItem("View Security Descriptor", null, TabPages.ContextMenu.ContextMenuViewSecurityDescriptor), + new ToolStripMenuItem("View Procedures", null, ContextMenuViewProcedures), }); } + private void ContextMenuViewProcedures(object Sender, EventArgs Args) + { + object tag = ((ToolStripMenuItem)Sender).Tag; + if (tag == null) + { + return; + } + var args = (CellRightClickEventArgs)tag; + var server = args.Model as RpcAlpcServer; + _ = m_TabManager.LoadRpcLibraryProceduresTab(new RpcLibraryFilter{ + FilterType = RpcLibraryFilterType.FilterByKeyword, + Keyword = server.Name }); + } + private async void diff --git a/TabPages/RpcLibraryProcedureList.cs b/TabPages/RpcLibraryProcedureList.cs index e869fcf..afe7466 100644 --- a/TabPages/RpcLibraryProcedureList.cs +++ b/TabPages/RpcLibraryProcedureList.cs @@ -12,7 +12,7 @@ using System.Collections.Generic; using System.Drawing; using System.Threading.Tasks; using System.Windows.Forms; -using NtApiDotNet; +using NtApiDotNet.Win32; using System.Diagnostics; using System.Linq; @@ -65,45 +65,77 @@ namespace RpcInvestigator ToolStripStatusLabel ProgressLabel ) { - Text = "Procedures"; - Name = "Procedures"; + var tabName = "Procedures"; + if (Filter.FilterType != RpcLibraryFilterType.NoFilter) + { + tabName += " for '" + Filter.Keyword + "'"; + } + Text = tabName; + Name = tabName; ImageIndex = 3; try { - using (NtToken token = NtProcess.Current.OpenToken()) + var searchResults = new List(); + ProgressBar.Step = 1; + ProgressBar.Value = 0; + ProgressBar.Visible = true; + await Task.Run(() => { - var searchResults = new List(); - ProgressBar.Step = 1; - ProgressBar.Value = 0; - ProgressBar.Visible = true; - await Task.Run(() => + var results = m_Library.Find(Filter); + foreach (var server in results) { - var results = m_Library.Find(Filter); - foreach (var server in results) + foreach (var procedure in server.Procedures) { - foreach (var procedure in server.Procedures) + var formatter = DefaultNdrFormatter.Create(DefaultNdrFormatterFlags.RemoveComments); + string friendly = formatter.FormatProcedure(procedure); + searchResults.Add(new RpcLibraryProcedure() { - var formatter = DefaultNdrFormatter.Create(DefaultNdrFormatterFlags.RemoveComments); - string friendly = formatter.FormatProcedure(procedure); - searchResults.Add(new RpcLibraryProcedure() - { - FilePath = server.FilePath, - InterfaceId = server.InterfaceId, - InterfaceVersion = server.InterfaceVersion, - Name = friendly, - }); - }; - } - }); - - if (searchResults.Count > 0) - { - m_Listview.SetObjects(searchResults); - m_Listview.AutoResizeColumns(); - m_Listview.RebuildColumns(); + FilePath = server.FilePath, + InterfaceId = server.InterfaceId, + InterfaceVersion = server.InterfaceVersion, + Name = friendly, + }); + }; } - ProgressBar.Value = 0; - ProgressBar.Visible = false; + }); + + if (searchResults.Count > 0) + { + m_Listview.SetObjects(searchResults); + m_Listview.AutoResizeColumns(); + m_Listview.RebuildColumns(); + } + ProgressBar.Value = 0; + ProgressBar.Visible = false; + } + catch (Exception ex) + { + Trace(TraceLoggerType.RpcLibraryProcedureList, + TraceEventType.Error, + "Unable to retrieve RPC library procedure list: " + ex.Message); + } + return true; + } + + public bool Build(RpcServer Server) + { + Text = "Procedures"; + Name = "Procedures"; + ImageIndex = 3; + var procs = new List(); + try + { + foreach (var procedure in Server.Procedures) + { + var formatter = DefaultNdrFormatter.Create(DefaultNdrFormatterFlags.RemoveComments); + string friendly = formatter.FormatProcedure(procedure); + procs.Add(new RpcLibraryProcedure() + { + FilePath = Server.FilePath, + InterfaceId = Server.InterfaceId, + InterfaceVersion = Server.InterfaceVersion, + Name = friendly, + }); } } catch (Exception ex) @@ -112,6 +144,12 @@ namespace RpcInvestigator TraceEventType.Error, "Unable to retrieve RPC library procedure list: " + ex.Message); } + if (procs.Count > 0) + { + m_Listview.SetObjects(procs); + m_Listview.AutoResizeColumns(); + m_Listview.RebuildColumns(); + } return true; } diff --git a/TabPages/RpcLibraryServerList.cs b/TabPages/RpcLibraryServerList.cs index 6a18c2f..d71b53d 100644 --- a/TabPages/RpcLibraryServerList.cs +++ b/TabPages/RpcLibraryServerList.cs @@ -86,9 +86,39 @@ namespace RpcInvestigator } column.MaximumWidth = -1; } + m_Listview.ColumnRightClick += ColumnRightClickOverride; Controls.Add(m_Listview); } + private void ColumnRightClickOverride(object sender, ColumnClickEventArgs e) + { + // + // Some of the columns we hide by default should never be shown, + // either because they contain binary data or lists of binary data. + // Such information is not easy to disable in the listview, so we'll + // strip those columns from the column selector context menu. + // + var args = (ColumnRightClickEventArgs)e; + var list = new List(); + foreach (var item in args.MenuStrip.Items) + { + if (item.GetType() == typeof(ToolStripMenuItem)) + { + var toolstripItem = item as ToolStripMenuItem; + if (toolstripItem.Text.ToLower() == "procedures" || + toolstripItem.Text.ToLower() == "server" || + toolstripItem.Text.ToLower() == "complextypes" || + toolstripItem.Text.ToLower() == "endpoints") + { + continue; + } + } + list.Add((ToolStripItem)item); + } + args.MenuStrip.Items.Clear(); + args.MenuStrip.Items.AddRange(list.ToArray()); + } + public void ScrollToServer(Guid InterfaceId) { if (m_Listview.Objects == null) @@ -168,7 +198,8 @@ namespace RpcInvestigator { TabPages.ContextMenu.BuildRightClickMenu(Args, new List{ new ToolStripMenuItem("New Client", null, ContextMenuNewClient), - new ToolStripMenuItem("Reset", null, ContextMenuResetSearch) + new ToolStripMenuItem("Reset", null, ContextMenuResetSearch), + new ToolStripMenuItem("View Procedures", null, ContextMenuViewProcedures) }); TabPages.ContextMenu.AddSearchElements(Args); } @@ -178,6 +209,18 @@ namespace RpcInvestigator m_Listview.ModelFilter = null; } + private void ContextMenuViewProcedures(object Sender, EventArgs Args) + { + object tag = ((ToolStripMenuItem)Sender).Tag; + if (tag == null) + { + return; + } + var args = (CellRightClickEventArgs)tag; + var server = args.Model as RpcServer; + _ = m_Manager.LoadRpcLibraryProceduresTab(server); + } + private void ContextMenuNewClient(object Sender, EventArgs Args) { object tag = ((ToolStripMenuItem)Sender).Tag; diff --git a/TabPages/TabManager.cs b/TabPages/TabManager.cs index ae84b45..567257f 100644 --- a/TabPages/TabManager.cs +++ b/TabPages/TabManager.cs @@ -134,6 +134,38 @@ namespace RpcInvestigator.TabPages return libraryProceduresTab; } + public RpcLibraryProcedureList LoadRpcLibraryProceduresTab(RpcServer Server) + { + TabPage tab; + RpcLibraryProcedureList libraryProceduresTab; + var tabName = "Procedures for "; + if (!string.IsNullOrEmpty(Server.ServiceName)) + { + tabName += Server.ServiceName; + } + else if (!string.IsNullOrEmpty(Server.Name)) + { + tabName += Server.Name; + } + else + { + tabName += Server.InterfaceId.ToString(); + } + + if (!TabExists(tabName, out tab)) + { + tab = new RpcLibraryProcedureList(m_Library); + tab.Text = tabName; // override name + m_TabControl.TabPages.Add(tab); + } + libraryProceduresTab = tab as RpcLibraryProcedureList; + _ = libraryProceduresTab.Build(Server); + m_TabControl.SelectedTab = libraryProceduresTab; + m_StatusLabel.Text = "Loaded " + libraryProceduresTab.GetCount() + + " procedures from the library"; + return libraryProceduresTab; + } + public bool TabExists(string Name, out TabPage Match) { Match = null; diff --git a/Windows/Controls/SnifferListview.cs b/Windows/Controls/SnifferListview.cs index 11a4cb8..325c687 100644 --- a/Windows/Controls/SnifferListview.cs +++ b/Windows/Controls/SnifferListview.cs @@ -53,6 +53,7 @@ namespace RpcInvestigator.Windows.Controls AlternateRowBackColor = Color.LightBlue; UseCompatibleStateImageBehavior = false; VirtualMode = true; + UseFiltering = true; if (m_Settings.m_SnifferColumns.Count() == 0) { m_ChosenColumns = new List() { diff --git a/packages.config b/packages.config index 30acd00..18f9366 100644 --- a/packages.config +++ b/packages.config @@ -3,13 +3,13 @@ - - - + + + - - - - + + + + \ No newline at end of file