KoiVM.Confuser
KoiInfo.cs
#region
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Forms;
using Confuser.Core;
#endregion
namespace KoiVM.Confuser
{
internal static clast KoiInfo
{
internal static KoiSettings settings;
private static bool inited;
private static readonly List astemblies = new List();
public static string KoiDirectory
{
get;
private set;
}
private static astembly OnastemblyResolve(object sender, ResolveEventArgs args)
{
var name = new astemblyName(args.Name).Name;
foreach(var asm in astemblies)
if(asm.GetName().Name == name)
return asm;
var folderPath = Path.GetDirectoryName(astembly.GetExecutingastembly().Location);
var astemblyPath = Path.Combine(folderPath, name + ".dll");
if(File.Exists(astemblyPath) == false)
return null;
var astembly = astembly.LoadFrom(astemblyPath);
return astembly;
}
internal static void Init()
{
lock(typeof(KoiInfo))
{
if(inited)
return;
AppDomain.CurrentDomain.astemblyResolve += OnastemblyResolve;
KoiDirectory = Path.GetDirectoryName(astembly.GetExecutingastembly().Location);
settings = new KoiSettings();
inited = true;
}
}
internal static void Init(ConfuserContext ctx)
{
lock(typeof(KoiInfo))
{
if(inited)
return;
AppDomain.CurrentDomain.astemblyResolve += OnastemblyResolve;
KoiDirectory = Path.GetDirectoryName(astembly.GetExecutingastembly().Location);
settings = new KoiSettings();
// Check if not yet processed.
if(astembly.GetExecutingastembly().ManifestModule.GetType("KoiVM.Confuser.Internal.Fish") != null)
return;
if(ctx != null)
{
var packPath = Path.Combine(KoiDirectory, "koi.pack");
if(!File.Exists(packPath))
RetrieveKoi(ctx);
else if(!settings.NoCheck)
CheckUpdate(ctx);
InitKoi();
}
inited = true;
}
}
private static void CheckUpdate(ConfuserContext ctx)
{
var ver = new KoiSystem().GetVersion(settings.KoiID);
if(ver == settings.Version)
return;
ctx.Logger.LogFormat("New version of KoiVM: {0}", ver);
ctx.Logger.LogFormat("Current version of KoiVM: {0}", settings.Version);
if(settings.NoUI)
{
ctx.Logger.LogFormat("Updating...");
var sys = new KoiSystem();
var hnd = new ManualResetEvent(false);
var okay = false;
sys.Progress += _ => { };
sys.Finish += f =>
{
okay = f;
hnd.Set();
};
sys.Login(settings.KoiID);
hnd.WaitOne();
if(!okay)
throw new InvalidOperationException("Authentication failed.");
settings.Version = ver;
settings.Save();
}
else
{
Application.EnableVisualStyles();
if(new UpdatePrompt(ver) {TopLevel = true}.ShowDialog() != DialogResult.OK)
throw new InvalidOperationException("Authentication failed.");
}
}
private static void RetrieveKoi(ConfuserContext ctx)
{
if(settings.NoUI)
{
ctx.Logger.Log("Retrieving Koi...");
var sys = new KoiSystem();
var hnd = new ManualResetEvent(false);
var okay = false;
sys.Progress += _ => { };
sys.Finish += f =>
{
okay = f;
hnd.Set();
};
sys.Login(settings.KoiID);
hnd.WaitOne();
if(!okay)
throw new InvalidOperationException("Authentication failed.");
}
else
{
Application.EnableVisualStyles();
if(new LoginPrompt {TopLevel = true}.ShowDialog() != DialogResult.OK)
throw new InvalidOperationException("Authentication failed.");
}
}
internal static void InitKoi(bool runCctor = true)
{
var rc4 = new RC4(Convert.FromBase64String("S29pVk0gaXMgY3V0ZSEhIQ=="));
var buf = File.ReadAllBytes(Path.Combine(KoiDirectory, "koi.pack"));
rc4.Crypt(buf, 0, buf.Length);
using(var deflate = new DeflateStream(new MemoryStream(buf), CompressionMode.Decompress))
using(var reader = new BinaryReader(deflate))
{
var count = reader.ReadInt32();
astemblies.Clear();
for(var i = 0; i < count; i++)
{
var asm = astembly.Load(reader.ReadBytes(reader.ReadInt32()));
astemblies.Add(asm);
}
}
if(!runCctor)
return;
foreach(var asm in astemblies) // Initialize the modules, since internal calls might not trigger module cctor
RuntimeHelpers.RunModuleConstructor(asm.ManifestModule.ModuleHandle);
}
}
}