227 lines
8.2 KiB
C#
227 lines
8.2 KiB
C#
//
|
|
// Copyright (c) 2022-present, Trail of Bits, Inc.
|
|
// All rights reserved.
|
|
//
|
|
// This source code is licensed in accordance with the terms specified in
|
|
// the LICENSE file found in the root directory of this source tree.
|
|
//
|
|
using BrightIdeasSoftware;
|
|
using NtApiDotNet;
|
|
using NtApiDotNet.Win32;
|
|
using RpcInvestigator.TabPages;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
|
|
namespace RpcInvestigator
|
|
{
|
|
using static TraceLogger;
|
|
|
|
public class RpcServerList : TabPage
|
|
{
|
|
public FastObjectListView m_Listview;
|
|
private TabManager m_Manager;
|
|
|
|
public RpcServerList(TabManager Manager)
|
|
{
|
|
m_Manager = Manager;
|
|
m_Listview = new FastObjectListView();
|
|
Random random = new Random();
|
|
string rand = random.Next().ToString();
|
|
m_Listview.OwnerDraw = true;
|
|
m_Listview.BorderStyle = BorderStyle.FixedSingle;
|
|
m_Listview.CellEditUseWholeCell = false;
|
|
m_Listview.Cursor = Cursors.Default;
|
|
m_Listview.Dock = DockStyle.Fill;
|
|
m_Listview.FullRowSelect = true;
|
|
m_Listview.GridLines = true;
|
|
m_Listview.HideSelection = false;
|
|
m_Listview.Location = new Point(0, 0);
|
|
m_Listview.Margin = new Padding(5);
|
|
m_Listview.Name = "RpcServerListview" + rand;
|
|
m_Listview.UseAlternatingBackColors = true;
|
|
m_Listview.AlternateRowBackColor = Color.LightBlue;
|
|
m_Listview.UseCompatibleStateImageBehavior = false;
|
|
m_Listview.View = View.Details;
|
|
m_Listview.VirtualMode = true;
|
|
m_Listview.ShowGroups = false;
|
|
m_Listview.Alignment = ListViewAlignment.Left;
|
|
Generator.GenerateColumns(m_Listview, typeof(RpcServer), true);
|
|
foreach (var column in m_Listview.AllColumns)
|
|
{
|
|
if (column.Name.ToLower() == "procedures" ||
|
|
column.Name.ToLower() == "complextypes" ||
|
|
column.Name.ToLower() == "name" ||
|
|
column.Name.ToLower() == "offset" ||
|
|
column.Name.ToLower() == "endpoints")
|
|
{
|
|
column.IsVisible = false;
|
|
}
|
|
column.MaximumWidth = -1;
|
|
}
|
|
|
|
//
|
|
// When a listview row is double-clicked, a new tab will open with procedures
|
|
// for the selected interface on the given RPC server. When a row is right-clicked,
|
|
// a context menu shows.
|
|
//
|
|
m_Listview.DoubleClick += new EventHandler((object obj, EventArgs e2) =>
|
|
{
|
|
if (m_Listview.SelectedObjects == null ||
|
|
m_Listview.SelectedObjects.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
var selectedRow = m_Listview.SelectedObjects.Cast<RpcServer>().ToList()[0];
|
|
m_Manager.LoadRpcProceduresTab(selectedRow.Name, selectedRow.Procedures.ToList());
|
|
});
|
|
m_Listview.CellRightClick += RightClickHandler;
|
|
Controls.Add(m_Listview);
|
|
}
|
|
|
|
public void Build (
|
|
List<string> FileNames,
|
|
Settings Settings,
|
|
RpcLibrary Library
|
|
)
|
|
{
|
|
Text = BuildTabTitle(FileNames);
|
|
ImageIndex = 0;
|
|
try
|
|
{
|
|
using (NtToken token = NtProcess.Current.OpenToken())
|
|
{
|
|
var allservers = new List<RpcServer>();
|
|
token.SetPrivilege(TokenPrivilegeValue.SeDebugPrivilege, PrivilegeAttributes.Enabled, true);
|
|
foreach (var filename in FileNames)
|
|
{
|
|
try
|
|
{
|
|
var servers = RpcServer.ParsePeFile(filename,
|
|
Settings.m_DbghelpPath, Settings.m_SymbolPath);
|
|
if (servers.Count() == 0)
|
|
{
|
|
Trace(TraceLoggerType.RpcServerList,
|
|
TraceEventType.Warning,
|
|
"No RPC servers in file '" + filename + "'");
|
|
continue;
|
|
}
|
|
allservers.AddRange(servers);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Trace(TraceLoggerType.RpcServerList,
|
|
TraceEventType.Error,
|
|
"Unable to retrieve RPC server list for file '" +
|
|
filename + "': " + ex.Message);
|
|
}
|
|
}
|
|
|
|
if (allservers.Count > 0)
|
|
{
|
|
m_Listview.ClearObjects();
|
|
m_Listview.SetObjects(allservers);
|
|
m_Listview.RebuildColumns();
|
|
m_Listview.AutoResizeColumns();
|
|
|
|
//
|
|
// Cache any new RPC servers from this binary.
|
|
//
|
|
if (!Library.Merge(allservers))
|
|
{
|
|
Trace(TraceLoggerType.RpcServerList,
|
|
TraceEventType.Error,
|
|
"Unable to merge new RPC servers to database.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Trace(TraceLoggerType.RpcServerList,
|
|
TraceEventType.Error,
|
|
"Unable to retrieve RPC server list: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
public int GetCount()
|
|
{
|
|
if (m_Listview.Objects == null)
|
|
{
|
|
return 0;
|
|
}
|
|
return m_Listview.Objects.Cast<RpcServer>().Count();
|
|
}
|
|
|
|
public List<RpcServer> GetAll()
|
|
{
|
|
if (m_Listview.Objects == null)
|
|
{
|
|
return new List<RpcServer>();
|
|
}
|
|
return m_Listview.Objects.Cast<RpcServer>().ToList();
|
|
}
|
|
|
|
private
|
|
void
|
|
RightClickHandler(
|
|
object Obj,
|
|
CellRightClickEventArgs Args
|
|
)
|
|
{
|
|
TabPages.ContextMenu.BuildRightClickMenu(Args, new List<ToolStripMenuItem>{
|
|
new ToolStripMenuItem("New Client", null, ContextMenuNewClient),
|
|
});
|
|
}
|
|
|
|
private void ContextMenuNewClient(object Sender, EventArgs Args)
|
|
{
|
|
object tag = ((ToolStripMenuItem)Sender).Tag;
|
|
if (tag == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var args = (CellRightClickEventArgs)tag;
|
|
|
|
//
|
|
// RpcServer type comes from parsing RPC server information out of a
|
|
// binary (such as a DLL), so we have to scan for an ALPC port hosting
|
|
// the interface using the RPC endpoint mapper.
|
|
//
|
|
var server = args.Model as RpcServer;
|
|
var id = server.InterfaceId;
|
|
var version = server.InterfaceVersion;
|
|
var endpoint = RpcAlpcServerList.FindEndpoint(id, version);
|
|
if (endpoint == null)
|
|
{
|
|
MessageBox.Show("Unable to locate an endpoint for RPC server UUID " +
|
|
id.ToString() + ", version " + version.ToString());
|
|
return;
|
|
}
|
|
var clientWindow = new Client(server, endpoint);
|
|
clientWindow.ShowDialog();
|
|
}
|
|
|
|
private static string BuildTabTitle(List<string> FileNames)
|
|
{
|
|
if (FileNames.Count == 1)
|
|
{
|
|
var path = Path.GetDirectoryName(FileNames[0]);
|
|
string title = FileNames[0];
|
|
if (path.Length > 25)
|
|
{
|
|
title = path.Substring(0, 20) +
|
|
"...\\" + Path.GetFileName(FileNames[0]);
|
|
}
|
|
return title;
|
|
}
|
|
return "Multiple files";
|
|
}
|
|
}
|
|
}
|