//css_co /unsafe //css_ref dnlib.dll using System; using dnlib.DotNet; using dnlib.DotNet.Emit; using dnlib.DotNet.Writer; using System.Diagnostics; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Windows.Forms; using System.IO; using System.Threading; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; class Script { public static AssemblyWriter assemblyWriter; public static Assembly assembly; public static MethodDef currentMethod; public static StackFrame[] mainFrames; public static List junkType = new List(); [STAThread] static public void Main(string[] args) { try { Console.BackgroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Black; Console.WriteLine("*********************************"); Console.WriteLine("*** ***"); Console.WriteLine("*** ILProtector Unpacker ***"); Console.WriteLine("*** Coded By RexProg ***"); Console.WriteLine("*** ***"); Console.WriteLine("*********************************"); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("[?] Enter Your Program Path : "); Console.ForegroundColor = ConsoleColor.Red; var path = Console.ReadLine(); if (path == string.Empty) return; if (path.StartsWith("\"") && path[path.Length - 1] == '"') path = path.Substring(1, path.Length - 2); if (!File.Exists(path)) { Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("[!] File not found"); Console.WriteLine("[!] Press key to exit..."); Console.Read(); return; } Console.ForegroundColor = ConsoleColor.DarkRed; assemblyWriter = new AssemblyWriter(path); assembly = Assembly.LoadFrom(path); Console.WriteLine("[+] Wait..."); mainFrames = new StackTrace().GetFrames(); Memory.Hook(typeof(StackTrace).GetMethod("CaptureStackTrace", BindingFlags.Instance | BindingFlags.NonPublic), typeof(Script).GetMethod("Hook3", BindingFlags.Instance | BindingFlags.Public)); var types = assemblyWriter.moduleDef.GetTypes(); var list = (types as IList) ?? types.ToList(); var globalType = assemblyWriter.moduleDef.GlobalType; var fieldMDToken = 0; foreach (FieldDef fieldDef in globalType.Fields) { if (fieldDef.Name == "Invoke") fieldMDToken = fieldDef.MDToken.ToInt32(); } if (fieldMDToken == 0) Console.WriteLine("[!] Couldn't find Invoke"); var fieldValue = assembly.Modules.FirstOrDefault().ResolveField(fieldMDToken).GetValue(null); var method = fieldValue.GetType().GetMethod("Invoke"); if (method == null) Console.WriteLine("[!] Couldn't find InvokeMethod"); InvokeDelegates(list, method, fieldValue); new StringDecrypter(assembly).ReplaceStrings(list); foreach (var typeDef in junkType) { typeDef.DeclaringType.NestedTypes.Remove(typeDef); } MethodDef methodDef = globalType.FindStaticConstructor(); if (methodDef.HasBody) { var startIndex = methodDef.Body.Instructions.IndexOf(methodDef.Body.Instructions.FirstOrDefault(inst => (inst.OpCode == OpCodes.Call && ((IMethod)inst.Operand).Name == "GetIUnknownForObject"))) - 2; var endindex = methodDef.Body.Instructions.IndexOf(methodDef.Body.Instructions.FirstOrDefault(inst => (inst.OpCode == OpCodes.Call && ((IMethod)inst.Operand).Name == "Release"))) + 2; methodDef.Body.ExceptionHandlers.Remove(methodDef.Body.ExceptionHandlers.FirstOrDefault(exh => exh.HandlerEnd == methodDef.Body.Instructions[endindex + 1])); for (int i = startIndex; i <= endindex; i++) methodDef.Body.Instructions.Remove(methodDef.Body.Instructions[startIndex]); } foreach (var meth in globalType.Methods.Where(met => (met.ImplMap?.Module.Name.ToString() == "Protect32.dll" || met.ImplMap?.Module.Name.ToString() == "Protect64.dll")).ToList()) globalType.Remove(meth); var invokeField = globalType.Fields.FirstOrDefault(fld => fld.Name == "Invoke"); assemblyWriter.moduleDef.Types.Remove(invokeField.FieldType.ToTypeDefOrRef().ResolveTypeDef()); globalType.Fields.Remove(invokeField); assemblyWriter.Save(); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("[!] Program Unpacked"); } catch (Exception ex) { Console.WriteLine("[!] Exception :\n" + ex.Message); } Console.WriteLine("[!] Press key to exit..."); Console.Read(); } private static void InvokeDelegates(IList typeDefs, MethodInfo invokeMethod, object invokeField) { foreach (TypeDef typeDef in typeDefs) { foreach (MethodDef methodDef in typeDef.Methods) { if (!(methodDef.Module.Name != assembly.ManifestModule.ScopeName) && methodDef.HasBody && methodDef.Body.Instructions.Count > 2 && methodDef.Body.Instructions[0].OpCode == OpCodes.Ldsfld && methodDef.Body.Instructions[0].Operand.ToString().Contains("Invoke") && methodDef.Body.Instructions[1].IsLdcI4()) { currentMethod = methodDef; var _MDToken = ((IType)methodDef.Body.Instructions[3].Operand).MDToken.ToInt32(); junkType.Add(typeDef.NestedTypes.FirstOrDefault(net => net.MDToken.ToInt32() == _MDToken)); object method = invokeMethod.Invoke(invokeField, new object[] { (int)methodDef.Body.Instructions[1].Operand }); try { var dynamicMethodBodyReader = new DynamicMethodBodyReader(assemblyWriter.moduleDef, method); dynamicMethodBodyReader.Read(); var method2 = dynamicMethodBodyReader.GetMethod(); assemblyWriter.WriteMethod(method2); } catch (Exception ex) { Console.WriteLine("Error in Read(): " + ex.Message + "\nMethod : " + method.ToString()); } } } } } public StackFrame Hook(int num) { StackFrame[] frames = new StackTrace().GetFrames(); for (int i = 0; i < frames.Length; i++) { MethodBase method = frames[i].GetMethod(); if (num == 0 && method.ToString().StartsWith("System.Delegate (")) { return frames[i]; } if (num == 1 && method.ToString().StartsWith("System.Delegate (")) { MethodBase value = assembly.Modules.FirstOrDefault().ResolveMethod(currentMethod.MDToken.ToInt32()); typeof(StackFrame).GetField("method", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(frames[i + 1], value); return frames[i + 1]; } } return null; } public void Hook2(MethodBase mb) { if (mb.Name == "InvokeMethod") typeof(StackFrame).GetField("method", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, assembly.Modules.FirstOrDefault().ResolveMethod(currentMethod.MDToken.ToInt32())); else typeof(StackFrame).GetField("method", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, mb); } public void Hook3(int iSkip, bool fNeedFileInfo, Thread targetThread, Exception e) { /////////////////////////////////////////////////////////////////////////////////////////////// // FrameCount | 2 | int // // METHODS_TO_SKIP | 0 | int // // frames | {System.Diagnostics.StackFrame[6]} | System.Diagnostics.StackFrame[] // // m_iMethodsToSkip | 4 | int // // m_iNumOfFrames | 2 | int // /////////////////////////////////////////////////////////////////////////////////////////////// typeof(StackFrame).GetField("method", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(mainFrames.Last(), assembly.Modules.FirstOrDefault().ResolveMethod(currentMethod.MDToken.ToInt32())); var mainFramesList = mainFrames.ToList(); for (int i = mainFramesList.Count(); i < 6; i++) mainFramesList.Add(mainFrames.Last()); for (int i = mainFramesList.Count(); i > 6; i--) mainFramesList.Remove(mainFramesList.First()); typeof(StackTrace).GetField("frames", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, mainFramesList.ToArray()); typeof(StackTrace).GetField("m_iMethodsToSkip", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, 4); typeof(StackTrace).GetField("m_iNumOfFrames", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, 2); } } internal class StringDecrypter { private readonly Assembly assembly; private object _decryptField; private MethodInfo decryptMethod; internal StringDecrypter(Assembly assembly) { this.assembly = assembly; } internal void ReplaceStrings(IList typeDefs) { foreach (TypeDef typeDef in typeDefs) { foreach (MethodDef methodDef in typeDef.Methods) { if (methodDef.HasBody) { IList instructions = methodDef.Body.Instructions; for (int i = 0; i < instructions.Count; i++) { Instruction instruction = instructions[i]; if (instruction.OpCode == OpCodes.Ldsfld && instruction.Operand.ToString().Contains("::String") && instructions[i + 1].IsLdcI4() && instructions[i + 2].OpCode == OpCodes.Callvirt && instructions[i + 2].Operand.ToString().Contains("Invoke")) { if (this._decryptField == null) { FieldDef fieldDef = (FieldDef)instruction.Operand; this.InitDecryptor(fieldDef); } int idx = (int)instructions[i + 1].Operand; instructions[i].OpCode = OpCodes.Ldstr; instructions[i].Operand = this.GetString(idx); instructions[i + 1].OpCode = OpCodes.Nop; instructions[i + 2].OpCode = OpCodes.Nop; } } } } } } private void InitDecryptor(FieldDef fieldDef) { FieldInfo fieldInfo = this.assembly.Modules.FirstOrDefault().ResolveField(fieldDef.MDToken.ToInt32()); this._decryptField = fieldInfo.GetValue(null); this.decryptMethod = this._decryptField.GetType().GetMethod("Invoke"); } private string GetString(int idx) { return (string)this.decryptMethod.Invoke(this._decryptField, new object[] { idx }); } } internal static class Memory { [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] private static extern bool VirtualProtect(IntPtr lpAddress, IntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); internal unsafe static void Hook(MethodBase from, MethodBase to) { IntPtr address = Memory.GetAddress(from); IntPtr address2 = Memory.GetAddress(to); uint flNewProtect; Memory.VirtualProtect(address, (IntPtr)8, 64u, out flNewProtect); if (IntPtr.Size == 8) { byte* ptr = (byte*)address.ToPointer(); *ptr = 73; ptr[1] = 187; *(long*)(ptr + 2) = address2.ToInt64(); ptr[10] = 65; ptr[11] = 255; ptr[12] = 227; Console.WriteLine("[!] Prefer use a 32-bit processor "); } else if (IntPtr.Size == 4) { byte* ptr2 = (byte*)address.ToPointer(); ptr2[1] = 144; ptr2[2] = 144; ptr2[3] = 233; *(long*)(ptr2 + 4) = (long)(address2.ToInt32() - address.ToInt32() - 5); ptr2[8] = 195; } uint num; Memory.VirtualProtect(address, (IntPtr)8, flNewProtect, out num); } public static IntPtr GetAddress(MethodBase methodBase) { RuntimeHelpers.PrepareMethod(methodBase.MethodHandle); return methodBase.MethodHandle.GetFunctionPointer(); } } internal class AssemblyWriter { private readonly string assemblyPath; internal ModuleDefMD moduleDef; internal AssemblyWriter(string assemblyPath) { this.assemblyPath = assemblyPath; AssemblyResolver assemblyResolver = new AssemblyResolver(); ModuleContext moduleContext = new ModuleContext(assemblyResolver); assemblyResolver.EnableTypeDefCache = true; assemblyResolver.DefaultModuleContext = moduleContext; moduleDef = ModuleDefMD.Load(assemblyPath, moduleContext); moduleDef.Context = moduleContext; moduleDef.Context.AssemblyResolver.AddToCache(moduleDef); } internal void WriteMethod(MethodDef methodDef) { MethodDef executingMethod = Script.currentMethod; if (executingMethod == null) { Console.WriteLine("[!] Failed to write " + methodDef); return; } Script.currentMethod = null; executingMethod.FreeMethodBody(); executingMethod.Body = methodDef.Body; } internal void Save() { try { string text = Path.GetDirectoryName(assemblyPath); if (!text.EndsWith("\\")) { text += "\\"; } string filename = text + Path.GetFileNameWithoutExtension(assemblyPath) + "_Unpacked" + Path.GetExtension(assemblyPath); ModuleWriterOptions options = new ModuleWriterOptions(moduleDef); options.Logger = DummyLogger.NoThrowInstance; moduleDef.Write(filename, options); } catch (Exception ex) { Console.WriteLine("[!] Exception :\n" + ex.Message); } } }