実行ファイルの暗号化
.NET(というかIL)の場合、逆コンパイルで中身がまる見えになり、商用アプリだとそこが嫌われることがあります。ぶっちゃけ、x86ネイティブコードなら問題ないか?と言えば、全然そんなことないのですが、ILがあまりに手軽なのが駄目なんでしょうね。あと、難読化ツールは試したことがないので、どの程度効果があるのか分かってませんです。(^^;
全くのノーガードが気になる場合、気休めにライブラリ(DLL)を暗号化して、実行時に復号するのはどうでしょうか?
暗号化プログラム
using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Security.Cryptography; class Program { static void Main(string args) { // 引数で渡されたファイルを暗号化し、 // .crypt(暗号化済みファイル)と.key(キーファイル)を作成する if (args.Length == 0) return; string original = args[0]; RijndaelManaged rj = new RijndaelManaged(); byte key; byte IV; rj.GenerateKey(); rj.GenerateIV(); key = rj.Key; IV = rj.IV; ICryptoTransform encryptor = rj.CreateEncryptor(key, IV); MemoryStream msEncrypt = new MemoryStream(); CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); byte toEncript = File.ReadAllBytes(original); csEncrypt.Write(toEncript, 0, toEncript.Length); csEncrypt.FlushFinalBlock(); // 暗号化したDLLは元の名前+.cryptにする File.WriteAllBytes(original + ".crypt", msEncrypt.ToArray()); // KeyとIVを元の名前+.keyファイルとして保存する using (BinaryWriter bw = new BinaryWriter(File.Create(original + ".key"))) { bw.Write(key.Length); bw.Write(key); bw.Write(IV.Length); bw.Write(IV); } } }
暗号化したいDLLを引数に渡すと
- xxx.dll.crypt
- xxx.dll.key
の2つのファイルが出来ます。xxx.dllを使いたいプログラムにこの暗号化したファイル(xxx.dll.crypt)を埋め込みます。で、実行時に埋め込みリソースから読み込んで復号すればいいです。例えば、こんな感じ。
using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Resources; using System.Security.Cryptography; using System.Reflection; class Program { static void Main(string args) { if (args.Length == 0) return; int n; string keyfile = args[0]; byte key; byte IV; using (BinaryReader br = new BinaryReader(File.OpenRead(keyfile))) { n = br.ReadInt32(); key = br.ReadBytes(n); n = br.ReadInt32(); IV = br.ReadBytes(n); } Assembly asm = Assembly.GetEntryAssembly(); Stream stm = asm.GetManifestResourceStream("ConsoleApplication2.ClassLibrary1.dll.crypt"); // 復号 RijndaelManaged rj = new RijndaelManaged(); ICryptoTransform decryptor = rj.CreateDecryptor(key, IV); CryptoStream csDecrpt = new CryptoStream(stm, decryptor, CryptoStreamMode.Read); byte dll = new byte[stm.Length]; csDecrpt.Read(dll, 0, dll.Length); asm = Assembly.Load(dll); object o = asm.CreateInstance("Calc"); Console.WriteLine (o.GetType().GetMethod("Add").Invoke(o, new object[] {10, 20})); } } /* 結果 0.5 */
正しいキーファイルがないとILコードが全然でたらめなので実行不可能です。凄い人なら簡単に破るのかも知れませんが、私程度の実力なら諦めるでしょう。(^^;
メソッドがAddなのに割り算を行っているのは意図的です。名前のまんまだと結果が分かってしまってつまんないし。