/***************************************************************************************************
* Copyright (C) - Andrea Bertolotto - 2006-2012
*
* a.bertolotto - 2012/12/02 19.07.05 - Refactoring to support PE and PE+ file formats and grid
* sorting (with help of sendersu)
* a.bertolotto - 2007/04/24 09.17.45 - Added Credits form
* a.bertolotto - 2006/08/22 12.11.10 - Created
***************************************************************************************************/
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace StrongNameRemove
{
public partial class MainForm : Form
{
private enum ImageListIcon
{
Error,
Alert,
Info,
OK
}
private long cliHeaderFlagOffset;
private uint cliHeaderFlag;
private long strongNameSignatureOffset;
private long publicKeyOffset;
private long publicKeyIndexOffset;
private long assemblyFlagOffset;
private uint assemblyFlag;
private string compiledRuntimeVersion = String.Empty;
private string peKind = String.Empty;
private ArrayList assemblyReferences = new ArrayList();
private int blobIndexSize;
private int sortColumn = -1;
public MainForm(string fileName)
{
this.InitializeComponent();
if (!String.IsNullOrEmpty(fileName))
{
this.txtFileName.Text = fileName;
}
}
private void MainForm_Load(object sender, EventArgs e)
{
this.lblVersion.Text = "Version: " + Assembly.GetExecutingAssembly().GetName().Version;
}
private void lnkCredits_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
CreditsForm creditsForm = new CreditsForm();
creditsForm.ShowDialog(this);
}
private void btnBrowse_Click(object sender, EventArgs e)
{
this.openFileDialog.CheckFileExists = true;
this.openFileDialog.DefaultExt = "exe";
this.openFileDialog.Filter = "Assemblies files (*.exe, *.dll)|*.exe;*.dll|All files (*.*)|*.*";
if (this.txtFileName.Text.Trim().Length > 0)
{
this.openFileDialog.InitialDirectory = Path.GetDirectoryName(this.txtFileName.Text);
}
this.openFileDialog.Multiselect = false;
this.openFileDialog.Title = "Select assembly file to patch";
this.openFileDialog.FileName = String.Empty;
if (this.openFileDialog.ShowDialog(this) == DialogResult.OK)
{
this.txtFileName.Text = this.openFileDialog.FileName;
}
}
private void txtFileName_TextChanged(object sender, EventArgs e)
{
this.btnVerify.Enabled = (this.txtFileName.Text.Trim().Length > 0);
this.btnPatch.Enabled = false;
this.btnPatchReferences.Enabled = false;
}
private void AppendMessage(string message, ImageListIcon icon)
{
this.lstResults.Items.Add(new ListViewItem(message, (int) icon));
}
private void btnVerify_Click(object sender, EventArgs e)
{
string fileName = this.txtFileName.Text.Trim();
this.lstResults.Items.Clear();
this.lstReferences.Items.Clear();
if (fileName.Length == 0)
{
this.AppendMessage("Please choose a valid filename" + fileName, ImageListIcon.Alert);
return;
}
if (!Utility.CheckFileExistsAndWriteable(fileName))
{
this.AppendMessage("File not found or not writable: " + fileName, ImageListIcon.Error);
}
else
{
bool canReadAssembly = Utility.GetAssemblyData(fileName, ref this.cliHeaderFlag, ref this.cliHeaderFlagOffset,
ref this.strongNameSignatureOffset, ref this.publicKeyIndexOffset,
ref this.publicKeyOffset, ref this.assemblyFlag, ref this.assemblyFlagOffset,
ref this.compiledRuntimeVersion, ref this.assemblyReferences, ref this.blobIndexSize,
ref this.peKind);
if (canReadAssembly)
{
foreach (AssemblyReference reference in this.assemblyReferences)
{
ListViewItem lvwReference =
new ListViewItem(new[]
{
reference.ReferenceName, reference.Version, reference.PublicKeyOrToken,
"0x" + reference.ReferenceOffset.ToString("X8")
}) {Tag = reference};
this.lstReferences.Items.Add(lvwReference);
}
this.AppendMessage("Assembly compiled runtime: " + this.compiledRuntimeVersion, ImageListIcon.Info);
this.AppendMessage("Image file type: " + this.peKind, ImageListIcon.Info);
this.AppendMessage(
"CLI Header Assembly flags: 0x" + this.cliHeaderFlag.ToString("X8") + " (" + Utility.CLIHeaderFlagToString(this.cliHeaderFlag) +
") at file offset: 0x" + this.cliHeaderFlagOffset.ToString("X8"), ImageListIcon.Info);
this.AppendMessage(
"Assembly Table flags: 0x" + this.assemblyFlag.ToString("X8") + " (" + Utility.AssemblyFlagToString(this.assemblyFlag) +
") at file offset: 0x" + this.assemblyFlagOffset.ToString("X8"), ImageListIcon.Info);
if (this.strongNameSignatureOffset == 0)
{
this.AppendMessage("Assembly Strong Name Signature not available", ImageListIcon.Info);
}
else
{
this.AppendMessage(
"Assembly Strong Name Signature Index in CLI Header file offset: 0x" + this.strongNameSignatureOffset.ToString("X8"),
ImageListIcon.Info);
if (this.publicKeyOffset > 0)
{
this.AppendMessage("Assembly Public Key file offset: 0x" + this.publicKeyOffset.ToString("X8"), ImageListIcon.Info);
}
if (this.publicKeyIndexOffset > 0)
{
this.AppendMessage(
"Assembly Public Key Index in Assembly Table file offset: 0x" + this.publicKeyIndexOffset.ToString("X8"),
ImageListIcon.Info);
}
}
this.btnPatchReferences.Enabled = true;
if (Utility.IsAssemblyStrongSigned(this.cliHeaderFlag))
{
this.btnPatch.Enabled = true;
if ((Path.GetExtension(fileName) ?? string.Empty).Equals(".dll", StringComparison.OrdinalIgnoreCase))
{
// If we are patching a DLL, we are probably breaking references in some other assembly, so we alert user accordingly
{
this.AppendMessage("Removing strong-signing from a DLL prevents main executable to load it. Patch it accordingly",
ImageListIcon.Alert);
}
}
}
else
{
this.AppendMessage("Assembly doesn't seem to be strong signed. Nothing to do", ImageListIcon.Alert);
this.btnPatch.Enabled = false;
}
}
else
{
this.AppendMessage("Unable to open assembly or not a valid .NET assembly", ImageListIcon.Error);
this.btnPatchReferences.Enabled = false;
}
}
}
private void btnPatch_Click(object sender, EventArgs e)
{
string fileName = this.txtFileName.Text.Trim();
if (fileName.Length == 0)
{
this.AppendMessage("Please choose a valid filename", ImageListIcon.Alert);
return;
}
if (!Utility.CheckFileExistsAndWriteable(fileName))
{
this.AppendMessage("File not found or not writable: " + fileName, ImageListIcon.Error);
}
else
{
string backupFileName = Path.GetDirectoryName(fileName) + "\\" + "Backup of (" + DateTime.Now.ToString("yyyyMMddHHmm") + ") - " +
Path.GetFileName(fileName);
if (this.chkBackup.Checked)
{
File.Copy(fileName, backupFileName, true);
}
if (Utility.IsAssemblyStrongSigned(this.cliHeaderFlag))
{
if (Utility.PatchAssemblyStrongSigning(fileName, this.cliHeaderFlag, this.cliHeaderFlagOffset, this.strongNameSignatureOffset,
this.publicKeyIndexOffset, this.assemblyFlag, this.assemblyFlagOffset, this.blobIndexSize))
{
this.AppendMessage("CLI Header Strong Name flag reset to unsigned", ImageListIcon.OK);
this.AppendMessage("Strong Name signature offset reset to 0x00", ImageListIcon.OK);
this.AppendMessage("Public Key index in Assembly Table reset to 0x00", ImageListIcon.OK);
this.AppendMessage("Flags in Assembly Table reset to unsigned", ImageListIcon.OK);
this.btnPatch.Enabled = false;
}
else
{
this.AppendMessage("Unable to open assembly or not a valid .NET assembly", ImageListIcon.Error);
}
}
else
{
this.AppendMessage("Assembly doesn't seem to be strong signed. Nothing to do", ImageListIcon.Alert);
if (this.chkBackup.Checked)
{
File.Delete(backupFileName);
}
}
}
}
private void btnPatchReferences_Click(object sender, EventArgs e)
{
string fileName = this.txtFileName.Text.Trim();
if (fileName.Length == 0)
{
this.AppendMessage("Please choose a valid filename", ImageListIcon.Alert);
return;
}
if (!Utility.CheckFileExistsAndWriteable(fileName))
{
this.AppendMessage("File not found or not writable: " + fileName, ImageListIcon.Error);
}
else
{
string backupFileName = Path.GetDirectoryName(fileName) + "\\" + "Backup of (" + DateTime.Now.ToString("yyyyMMddHHmm") + ") - " +
Path.GetFileName(fileName);
if (this.chkBackup.Checked)
{
File.Copy(fileName, backupFileName, true);
}
bool patchResult = false;
foreach (ListViewItem lvwReference in this.lstReferences.CheckedItems)
{
if (((AssemblyReference) lvwReference.Tag).PublicKeyOrToken.Length > 0)
{
if (Utility.PatchReference(fileName, ((AssemblyReference) lvwReference.Tag).ReferenceOffset, this.blobIndexSize))
{
this.AppendMessage(
"PublicKeyOrToken removed correctly from " + ((AssemblyReference) lvwReference.Tag).ReferenceName + " reference",
ImageListIcon.OK);
patchResult = true;
lvwReference.Checked = false;
this.btnPatchReferences.Enabled = false;
}
else
{
this.AppendMessage(
"Error removing PublicKeyOrToken from " + ((AssemblyReference) lvwReference.Tag).ReferenceName + " reference",
ImageListIcon.Error);
}
}
else
{
this.AppendMessage(
"PublicKeyOrToken not available on reference " + ((AssemblyReference) lvwReference.Tag).ReferenceName + ". Nothing to do",
ImageListIcon.Alert);
lvwReference.Checked = false;
}
}
if ((!patchResult) && (this.chkBackup.Checked))
{
File.Delete(backupFileName);
}
}
}
private void lstReferences_ColumnClick(object sender, ColumnClickEventArgs e)
{
if (e.Column != this.sortColumn)
{
this.sortColumn = e.Column;
this.lstReferences.Sorting = SortOrder.Ascending;
}
else
{
this.lstReferences.Sorting = this.lstReferences.Sorting == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
}
this.lstReferences.Sort();
this.lstReferences.ListViewItemSorter = new ListViewItemComparer(e.Column, lstReferences.Sorting);
}
}
}