Click here to Skip to main content
Click here to Skip to main content

Removing Strong-Signing from Assemblies at File Level (byte patching)

By , 9 Mar 2013
 
StrongNameRemove.zip
StrongNameRemove.exe
strongnameremove20.zip
StrongNameRemove20.exe
strongnameremove20_src.zip
alert.png
Asmex
decrypted.ico
decrypted.png
folder_blue.png
info.png
ok.png
Properties
Settings.settings
remove.png
vu.ch.argee.MemoryMapping
strongnameremove21.zip
StrongNameRemove.exe
strongnameremove21_src.zip
Settings.settings
Resources
alert.png
folder_explore.png
info.png
ok.png
remove.png
System_Locked.png
Sistema_Locked.ico
StrongNameRemove_src.zip
app.manifest
Other-Power-Lock-Metro.ico
alert.png
folder_explore.png
info.png
ok.png
Other-Power-Lock-Metro-icon.png
remove.png
/***************************************************************************************************
 * 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);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of use and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Andrea Bertolotto
Software Developer (Senior)
Italy Italy
No Biography provided

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 10 Mar 2013
Article Copyright 2006 by Andrea Bertolotto
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid