RpcInvestigator/Windows/MainWindow.cs

352 lines
12 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 RpcInvestigator.TabPages;
using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using RpcInvestigator.Windows;
using static RpcInvestigator.TraceLogger;
namespace RpcInvestigator
{
public partial class MainWindow : Form
{
private Settings m_Settings;
private RpcLibrary m_Library;
private TabManager m_TabManager;
private Sniffer m_RpcSnifferWindow;
public MainWindow()
{
InitializeComponent();
DoubleBuffered = true;
TraceLogger.Initialize();
//
// Load settings and database
//
try
{
m_Settings = Settings.LoadDefault();
TraceLogger.SetLevel(m_Settings.m_TraceLevel);
}
catch (Exception) { } // swallow
try
{
m_Library = new RpcLibrary(null);
m_Library.Load();
}
catch (Exception) { } // swallow
m_TabManager = new TabManager(
mainTabControl, m_Settings, m_Library, progressBar, statusLabel);
}
private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
{
if (m_RpcSnifferWindow != null)
{
MessageBox.Show("Please close the RPC sniffer window.");
e.Cancel = true;
return;
}
}
private void mainTabControl_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage thisTab = mainTabControl.TabPages[e.Index];
string tabTitle = thisTab.Text;
Rectangle tabRect = mainTabControl.GetTabRect(e.Index);
tabRect.Inflate(-2, -2);
//
// Draw the icon for the tab's selected icon image.
//
var icon = imageList1.Images[thisTab.ImageIndex];
e.Graphics.DrawImage(icon,
(tabRect.Left + 5),
tabRect.Top + (tabRect.Height - icon.Height) / 2);
//
// Draw the close tab button
//
Image closeIcon = imageList2.Images[0];
e.Graphics.DrawImage(closeIcon,
(tabRect.Right - icon.Width) + 5,
tabRect.Top + (tabRect.Height - closeIcon.Height) / 2);
//
// Draw the tab title
//
var textRect = new Rectangle(tabRect.X + icon.Width + 5, tabRect.Y,
tabRect.Width - icon.Width - closeIcon.Width, tabRect.Height);
TextRenderer.DrawText(e.Graphics, tabTitle, thisTab.Font,
textRect, thisTab.ForeColor, TextFormatFlags.Left);
}
private void mainTabControl_MouseDown(object sender, MouseEventArgs e)
{
for (int i = 0; i < mainTabControl.TabCount; i++)
{
Rectangle tabRect = mainTabControl.GetTabRect(i);
tabRect.Inflate(-2, -2);
Image closeIcon = imageList2.Images[0];
var imageRect = new Rectangle(
(tabRect.Right - closeIcon.Width - 5),
tabRect.Top + (tabRect.Height - closeIcon.Height - 5) / 2,
closeIcon.Width + 5,
closeIcon.Height + 5);
if (imageRect.Contains(e.Location))
{
if (i > 0)
{
mainTabControl.SelectedIndex = i - 1;
}
mainTabControl.TabPages.RemoveAt(i);
break;
}
}
}
private void ToggleMenu(bool Enable)
{
menuStrip1.Enabled = Enable;
mainTabControl.Enabled = Enable;
}
#region Menu actions
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
{
var window = new SettingsWindow(m_Settings);
if (window.ShowDialog() == DialogResult.OK)
{
m_Settings = window.m_Settings;
TraceLogger.SetLevel(m_Settings.m_TraceLevel);
}
}
private void loadFromBinaryToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.CheckFileExists = true;
dialog.CheckPathExists = true;
dialog.Multiselect = false;
if (dialog.ShowDialog() != DialogResult.OK)
{
return;
}
ToggleMenu(false);
_ = m_TabManager.LoadRpcServersTab(new List<string>() { dialog.FileName });
ToggleMenu(true);
}
private void loadFromServiceToolStripMenuItem_Click(object sender, EventArgs e)
{
Services servicesForm = new Services(m_Settings);
if (servicesForm.ShowDialog() != DialogResult.OK)
{
return;
}
if (servicesForm.m_SelectedDlls.Count == 0)
{
return;
}
ToggleMenu(false);
_ = m_TabManager.LoadRpcServersTab(servicesForm.m_SelectedDlls);
ToggleMenu(true);
}
private void loadAllRPCALPCServersToolStripMenuItem_Click(object sender, EventArgs e)
{
ToggleMenu(false);
_ = m_TabManager.LoadRpcAlpcServersTab();
ToggleMenu(true);
}
private void logsToolStripMenuItem_Click(object sender, EventArgs e)
{
Process.Start(Settings.m_LogDir);
}
private async void libraryServersToolStripMenuItem_Click(object sender, EventArgs e)
{
if (DetectEmptyLibrary())
{
return;
}
ToggleMenu(false);
_ = await m_TabManager.LoadRpcLibraryServersTab(new RpcLibraryFilter());
ToggleMenu(true);
}
private async void libraryProceduresToolStripMenuItem_Click(object sender, EventArgs e)
{
if (DetectEmptyLibrary())
{
return;
}
ToggleMenu(false);
_ = await m_TabManager.LoadRpcLibraryProceduresTab(new RpcLibraryFilter());
ToggleMenu(true);
}
private void eraseToolStripMenuItem_Click(object sender, EventArgs e)
{
if (DetectEmptyLibrary())
{
return;
}
DialogResult result = MessageBox.Show(
"Are you sure you want to erase the library?",
"Confirmation",
MessageBoxButtons.YesNoCancel);
if (result != DialogResult.Yes)
{
return;
}
ToggleMenu(false);
try
{
m_Library.Clear();
m_Library.Save();
Trace(TraceLoggerType.RpcLibrary,
TraceEventType.Information,
"Database erased.");
}
catch (Exception ex)
{
MessageBox.Show("An error occurred when erasing the database: " +
ex.Message);
}
ToggleMenu(true);
}
private async void refreshLibraryToolStripMenuItem_Click(object sender, EventArgs e)
{
ToggleMenu(false);
int workSize = 0;
int max = 0;
_ = await m_Library.Refresh(
m_Settings,
//
// Initialize progress bar.
//
(ArrayList args) =>
{
statusStrip1.Invoke((MethodInvoker)(() =>
{
workSize = (int)args[0];
max = (int)args[1];
var message = (string)args[2];
progressBar.Visible = true;
progressBar.Step = 1;
progressBar.Value = 0;
progressBar.Visible = true;
progressBar.Maximum = max;
statusLabel.Text = message;
}));
},
//
// Update progress bar
//
(string message) =>
{
statusStrip1.Invoke((MethodInvoker)(() =>
{
progressBar.PerformStep();
statusLabel.Text = message.Replace("<current>",
(progressBar.Value * workSize).ToString()).Replace(
"<total>", (max * workSize).ToString());
}));
},
//
// Complete
//
(string message) =>
{
statusLabel.Text = message;
progressBar.Value = 0;
progressBar.Visible = false;
});
ToggleMenu(true);
}
private void exportLibraryAsTextToolStripMenuItem_Click(object sender, EventArgs e)
{
if (DetectEmptyLibrary())
{
return;
}
ToggleMenu(false);
var location = Path.Combine(new string[] { Settings.m_LogDir,
"library-text-"+Path.GetRandomFileName() + ".txt" });
File.WriteAllText(location, m_Library.ToString());
Process.Start(location);
ToggleMenu(true);
}
private void rPCSnifferToolStripMenuItem_Click(object sender, EventArgs e)
{
if (m_RpcSnifferWindow != null)
{
MessageBox.Show("Only one RPC sniffer window is allowed.");
return;
}
m_RpcSnifferWindow = new Sniffer(
m_Library,
new SnifferCallbackTable()
{
ShowRpcServerDetailsCallback = SnifferCallbackShowRpcServerDetails,
},
ref m_Settings);
m_RpcSnifferWindow.Show();
m_RpcSnifferWindow.FormClosed += delegate (object w, FormClosedEventArgs args) {
m_RpcSnifferWindow = null;
};
}
private async void SnifferCallbackShowRpcServerDetails(string InterfaceId)
{
if (DetectEmptyLibrary())
{
return;
}
if (!Guid.TryParse(InterfaceId, out Guid id))
{
MessageBox.Show(InterfaceId + " is not a valid GUID.");
return;
}
ToggleMenu(false);
var tab = await m_TabManager.LoadRpcLibraryServersTab(new RpcLibraryFilter());
tab.ScrollToServer(id);
ToggleMenu(true);
}
private bool DetectEmptyLibrary()
{
if (m_Library.GetServerCount() == 0)
{
MessageBox.Show("The library is empty. Please click the Refresh menu " +
"item under the Library menu to regenerate it.");
return true;
}
return false;
}
#endregion
}
}