// .NET Assembly Strong Name Replacer // (C) 2004 Michael Giagnocavo // www.atrevido.net using System; using System.Diagnostics; using System.IO; using System.Reflection; public class SNReplace { public static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Usage: SNReplace "); return; } SNReplace snr = new SNReplace(); snr.AssemblyFile = args[0]; snr.KeyFile = args[1]; snr.Replace(); } public string KeyFile; public string AssemblyFile; byte[] currentKey; byte[] newKey; byte[] assembly; private int keyStart; public void Replace() { readKeys(); readAssembly(); findKeyStart(); replaceKey(); save(); resign(); } private void readKeys() { this.currentKey = AssemblyName.GetAssemblyName(this.AssemblyFile).GetPublicKey(); FileStream keyStream = File.OpenRead(this.KeyFile); this.newKey = new StrongNameKeyPair(keyStream).PublicKey; keyStream.Close(); } private void readAssembly() { using (FileStream fs = File.OpenRead(this.AssemblyFile)) { this.assembly = new byte[fs.Length]; fs.Read(this.assembly, 0, (int)fs.Length); } } private void findKeyStart() { // Yes, it's a slow algorithm. byte startByte = currentKey[0]; for(int i = 0; i < this.assembly.Length; i++) { if (assembly[i] == startByte) { // Possible match if (isKeyFound(i)) { this.keyStart = i; return; } } } // Not found... Console.WriteLine("Something's wrong. Public key not found."); Environment.Exit(1); } private bool isKeyFound(int startIndex) { for(int i = 0; i < currentKey.Length; i++) { if (currentKey[i] != assembly[i + startIndex]) { return false; } } return true; } private void replaceKey() { for(int i = 0; i < newKey.Length; i++) { assembly[keyStart + i] = newKey[i]; } } private void save() { using (FileStream fs = File.Create(this.AssemblyFile)) { fs.Write(assembly, 0, assembly.Length); } } private void resign() { ProcessStartInfo si = new ProcessStartInfo("sn.exe"); si.Arguments = string.Format("-R {0} {1}", this.AssemblyFile, this.KeyFile); try { Process p = Process.Start(si); if (!p.WaitForExit(15000)) { Console.WriteLine("Timeout while waiting for SN to resign the assembly."); p.Kill(); Environment.Exit(2); } } catch (System.ComponentModel.Win32Exception) { Console.WriteLine("The assembly's public key has been replaced, but SN.exe could not be started. Ensure SN.exe (in the .NET Framework SDK) is in your path, then run SN -R ."); } } }