Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...

Weblog

while (being(stubborn) + bruteforce < strongname) { !Sleep(); }

I was disappointed to see that the Hash class wasn't (enough) related to StrongName. It left me (again) clueless :-(. Being back to square one I needed another, more radical and systemic, approach to the problem. So there I was sleepless in the middle of the night (perhaps a coincidence?) thinking about going back to the most basic stuff, like:

My favorite "Hello world" program:

using System; using System.Reflection; [assembly: AssemblyKeyFile ("hello.snk")] [STAThread] public class MainClass { public static void Main (string[] args) { Console.WriteLine ("Hello world!"); } }

So far so good, next create a StrongName keypair (sn -k), compile and automatically strongname it with the included AssemblyKeyFile attribute - so for the moment it must be done with csc not mcs.

> sn -k helloworld.snk
> csc helloworld.cs

Now let's verify it with ... hmm... Microsoft's sn tool. What do I get? A success (somewhat expected) and an exit code equals to 0 (right now you'll need to trust me on this ;-).

> sn -v helloworld.exe

Armed with knowledge that my helloworld.exe was correctly strongnamed, it became obvious that I needed to bruteforce further knowledge (believe me being stubborn isn't always enough). So if I changed the very first byte, would it still be a valid strongnamed assembly? and if I changed the second byte ? ... until the last byte ? and all the while keeping the result on a map.

Actually I didn't do this in my head (nor in my bed). I waited to get back to my computer (and waiting doesn't help sleeping very much). Anyway this ended up looking like this:

using System; using System.Diagnostics; using System.IO; class StrongNameTheHardWay { static int CheckStrongName () { Process p = Process.Start ("sn", "-v hellosn.exe"); p.WaitForExit (); return p.ExitCode; } static byte[] ReadFile (string filename) { FileStream fs = File.OpenRead (filename); byte[] data = new byte [fs.Length]; fs.Read (data, 0, data.Length); fs.Close (); return data; } static void WriteFile (string filename, byte[] data) { FileStream fs = File.OpenWrite (filename); fs.Write (data, 0, data.Length); fs.Close (); } [STAThread] static void Main(string[] args) { byte[] data = ReadFile ("helloworld.exe"); fs.Read (data, 0, data.Length); fs.Close (); byte[] map = new byte [data.Length]; byte old; WriteFile ("hellosn.exe", data); if (CheckStrongName () == 0x00) { for (int i=0; i < data.Length; i++) { old = data [i]; data [i] ^= 0xFF; WriteFile ("hellosn.exe", data); if (CheckStrongName () != 0x00) map [i] = 1; data [i] = old; if (i % 1024 == 0) Console.WriteLine (i); } WriteFile ("hellosn.map", map); } else Console.WriteLine ("original not strongnamed"); } }

Compiling, running and waiting... (at that particular moment I had the distinct feeling I could easily sleep).

> csc brutesn.cs
> brutesn.exe

Note : It's possible that your anti-virus will not appreciate the full subtleties of systematically messing with an EXE. Also sn isn't always very happy about every possible mutation you can force on a PE file (in this case just click Ok to continue).

Note to self : Compiling with debugging information only makes it much longer than necessary.

Oops, did I fell asleep? Anyway it seems I now have my own personal treasure map to interpret... To be continued


10/7/2003 20:18:46 | Comments

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.