Roger, hi!
Yes! I done some code tricks at the same problem in our team project.
First and only way is to install all unsigned assemblies in GAC.
I done this workaround as follows:
1. Copy all dependent required assemblies (excluding system components which is already in gac) that is not in GAC into one folder\.
2. Create install.cmd:
@echo off
dir *.dll /b > filelist.txt
for /f %%i in (filelist.txt) do gacutil /u %%~ni
asm filelist.txt
for /f %%i in (filelist.txt) do gacutil /i %%i
del filelist.txt
3. Write an assembly processor asm.cs and compile into asm.exe:
asm.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.IO; using System.Text.RegularExpressions;
namespace DASM { public class Program { public const string fileExt = "il"; public const string keyName = "private.snk"; public static void Main(string[] argv) { if (argv.Length > 0) { try {
Console.Out.WriteLine("---"); StreamReader sr = new StreamReader(argv[0]); while (sr.Peek() != -1) { string fileName = sr.ReadLine(); if (File.Exists(fileName)) { FileInfo fi = new FileInfo(fileName); string outputName = fi.Name.Substring(0, fi.Name.LastIndexOf('.') + 1) + fileExt; Console.Out.WriteLine(fileName);
Console.Out.WriteLine("Disassembling"); Disassemble(fileName, outputName); Console.Out.WriteLine("Patching"); Patch(outputName); Console.Out.WriteLine("Assembing"); Assemble(outputName); } } Console.Out.WriteLine("---"); } catch (Exception ex) { Console.Out.WriteLine(ex.Message); } }
}
private static void Assemble(string outputName) { ProcessStartInfo pi = new ProcessStartInfo("ilasm.exe"); pi.UseShellExecute = false; pi.Arguments = string.Format("{0} /DLL /KEY={1}", outputName, keyName); Process myProcess = new Process(); myProcess.StartInfo = pi; myProcess.Start(); myProcess.WaitForExit(); }
private static void Patch(string outputName) { ProcessStartInfo pi = new ProcessStartInfo("patch.exe"); pi.UseShellExecute = false; pi.Arguments = string.Format("{0}", outputName); Process myProcess = new Process(); myProcess.StartInfo = pi; myProcess.Start(); myProcess.WaitForExit(); }
private static void Disassemble(string fileName, string outputName) { ProcessStartInfo pi = new ProcessStartInfo("ildasm.exe"); pi.UseShellExecute = false; pi.Arguments = string.Format("{0} /OUT={1}", fileName, outputName); Process myProcess = new Process(); myProcess.StartInfo = pi; myProcess.Start(); myProcess.WaitForExit(); } } } |
4. Generate strong name public key pair private.snk and extract public key token from it:
sn.exe /k ...
5. Write simple MSIL-patcher patch.cs and compile it into patch.exe, it shold looks like like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.IO; using System.Text.RegularExpressions;
namespace DASM { public class Program { private const string unsignedAssembly = ".assembly extern {0}"; private const string unsignedAssemblyNewPublicKeyToken = " .publickeytoken = (FA 75 CE 9D D3 2D 00 DC )"; private const string oldPublicKeyToken = " .hash algorithm 0x00008004"; private const string newPublicKeyToken = @" .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 // .$.............. 00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00 // .$..RSA1........ FB E4 78 0A 50 AF B1 36 F1 2E 3E 47 E5 A1 1B 3E // ..x.P..6..>G...> BF 60 B6 0D D1 2F 13 BA E7 D2 07 B1 7F 72 5D 5E // .`.../.......r]^ 98 C9 9B 6E 8E 0B 9B A9 4B 98 FD 18 53 58 0D B4 // ...n....K...SX.. 28 C2 57 67 AB 09 49 CC 4D 5D 9D B4 6E C5 77 29 // (.Wg..I.M]..n.w) 28 0B D3 45 50 2C AC 8C 03 9D 81 47 B6 80 CA 07 // (..EP,.....G.... 01 15 38 07 35 70 0D C7 28 4B A4 7A FE 03 04 43 // ..8.5p..(K.z...C 62 8D 98 D0 86 07 8D FE 0C 63 24 4E A5 2A 85 C6 // b........c$N.*.. 2F 07 B8 39 D4 A5 5E BC BD BC FD A6 FA F0 4B B9 ) // /..9..^.......K. .hash algorithm 0x00008004";
private const string hackToken = " .hash algorithm 0x00008004"; private const string newVersionToken = " .ver 1:9:7:8"; private const string versionToken = " .ver 0:0:0:0";
public static void Main(string[] argv) { if (argv.Length > 0) { try { List<string> list = new List<string>(); using (StreamReader reader = new StreamReader(argv[0])) { while (reader.Peek() != -1) list.Add(reader.ReadLine()); } Console.Out.WriteLine("Replacing"); Console.Out.WriteLine(string.Format("--------{0}--------", argv[0])); for (int i = 0; i < list.Count; i++) { string s = list[i]; if (s.Contains(oldPublicKeyToken)) { Console.Out.WriteLine(newPublicKeyToken); list[i] = newPublicKeyToken; continue; } if (i > 0 && list[i - 1] == "{" && list[i + 1] == "}") { Console.Out.WriteLine(unsignedAssemblyNewPublicKeyToken); list.Insert(i, unsignedAssemblyNewPublicKeyToken); i++; }
} StringBuilder sb = new StringBuilder(); foreach (string s in list) { sb.AppendLine(s); } Console.Out.WriteLine(string.Format("--------{0}--------", argv[0])); using (StreamWriter writer = new StreamWriter(argv[0])) { writer.Write(sb.ToString()); } } catch (Exception ex) { Console.Out.WriteLine(ex.Message); } } } } } |
This one means that all assemblieas are not signed by the private strong name key pair.
or like this (this one was used to hack devBiz Team Plain Web Access TFS integration solution):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.IO; using System.Text.RegularExpressions;
namespace DASM { public class Program { private const string oldPublicKeyToken = " .publickeytoken = (D3 E5 E5 03 F8 B0 D4 4E )"; private const string newPublicKeyToken = " .publickeytoken = (FA 75 CE 9D D3 2D 00 DC )"; private const string hackToken = " .hash algorithm 0x00008004"; private const string newVersionToken = " .ver 1:9:7:8"; private const string versionToken = " .ver 0:0:0:0";
public static void Main(string[] argv) { if (argv.Length > 0) { try { List<string> list = new List<string>(); using (StreamReader reader = new StreamReader(argv[0])) { while (reader.Peek() != -1) list.Add(reader.ReadLine()); } Console.Out.WriteLine("Replacing"); Console.Out.WriteLine(string.Format("--------{0}--------", argv[0])); for (int i = 0; i < list.Count; i++) { string s = list[i]; if (s.Contains(oldPublicKeyToken)) { list[i] = newPublicKeyToken; list[i + 1] = newVersionToken; Console.Out.WriteLine(list[i - 2]); Console.Out.WriteLine(list[i - 1]); Console.Out.WriteLine(list[i]); Console.Out.WriteLine(list[i + 1]); Console.Out.WriteLine(list[i + 2]); i += 2; continue; } if (s.Contains(versionToken)) { if (list[i - 1] == "{" && list[i + 1] == "}") { list.Insert(i, newPublicKeyToken); list[i + 1] = newVersionToken; Console.Out.WriteLine(list[i - 1]); Console.Out.WriteLine(list[i]); Console.Out.WriteLine(list[i + 1]); Console.Out.WriteLine(list[i + 2]); Console.Out.WriteLine(list[i+3]); i+=2; } } if (s.Contains(hackToken)) { list[i + 1] = newVersionToken; Console.Out.WriteLine(list[i - 2]); Console.Out.WriteLine(list[i - 1]); Console.Out.WriteLine(list[i]); Console.Out.WriteLine(list[i + 1]); Console.Out.WriteLine(list[i + 2]); } } StringBuilder sb = new StringBuilder(); foreach (string s in list) { sb.AppendLine(s); } Console.Out.WriteLine(string.Format("--------{0}--------", argv[0])); using (StreamWriter writer = new StreamWriter(argv[0])) { writer.Write(sb.ToString()); } } catch (Exception ex) { Console.Out.WriteLine(ex.Message); } } } } } |
this one is slightly different because all assemblies was already signed by unknown private strong name key and are to be used as precompiled Web solution assemblies...
6. Run install.cmd once, and you have all assemblies working at GAC! Of cause, you need additional not listed here steps if it is not yours assemblies, or they are obfuscated.
Read license agreement carefully :).
Good luck!