public void Execute(DevirtualizationCtx ctx) { ctx.VirtualizedMethods = new List <VirtualizedMethod>(); foreach (var type in ctx.Module.TopLevelTypes) { foreach (var method in type.Methods.Where(q => !q.IsNative && q.CilMethodBody != null && q.CilMethodBody.Instructions.Count >= 6 && q.CustomAttributes.Count >= 1)) { var vmAttribute = method.CustomAttributes.First(q => q.Signature.FixedArguments.Count == 2 && q.Signature.FixedArguments[0].ArgumentType == ctx.Module.CorLibTypeFactory.String && q.Signature.FixedArguments[1].ArgumentType == ctx.Module.CorLibTypeFactory.Int32); if (vmAttribute == null) { continue; } var virtualizedMethod = new VirtualizedMethod(method, (string)vmAttribute.Signature.FixedArguments[0].Element.Value, (int)vmAttribute.Signature.FixedArguments[1].Element.Value); ctx.VirtualizedMethods.Add(virtualizedMethod); if (ctx.Options.Verbose) { ctx.Logger.Success( $"Found Virtualized Method [{method.Name}] with ID [{virtualizedMethod.Id}] and Key [{virtualizedMethod.Key}]"); } } } }
public void Run(DevirtualizationCtx Ctx) { Ctx.PatternMatcher = new PatternMatcher(); var opcodeHandlerMethod = FindOpCodeMethod(Ctx.Module); if (opcodeHandlerMethod == null) { throw new DevirtualizationException("Could not locate Opcode Handler method."); } Ctx.Options.Logger.Success($"Found method {opcodeHandlerMethod.Name} that contains Opcode Handlers!"); var switchOpCode = opcodeHandlerMethod.CilMethodBody.Instructions.First(q => q.OpCode == CilOpCodes.Switch); var values = (List <ICilLabel>)switchOpCode.Operand; for (var i = 0; i < values.Count; i++) { var instructionLabel = (CilInstructionLabel)values[i]; var index = opcodeHandlerMethod.CilMethodBody.Instructions.IndexOf(instructionLabel.Instruction); var opCode = Ctx.PatternMatcher.FindOpCode(opcodeHandlerMethod, index); if (opCode != VMOpCode.Nop) { Ctx.PatternMatcher.SetOpCodeValue(opCode, i); } } }
public void Run(DevirtualizationCtx Ctx) { Ctx.Parser = new ResourceParser().Parse(Ctx); Ctx.Options.Logger.Success("Successfully Parsed Resource!"); Ctx.Options.Logger.InfoStr("Strings Read", Ctx.Parser.Strings.Length.ToString()); Ctx.Options.Logger.InfoStr("MethodKeys Read", Ctx.Parser.MethodKeys.Length.ToString()); Ctx.Options.Logger.InfoStr("Operands Read", Ctx.Parser.Operands.Length.ToString()); }
public Devirtualizer(DevirtualizationCtx Ctx) { this.Ctx = Ctx; Stages = new List <IStage> { new ResourceParsing(), new OpcodeMapping(), new MethodDisassembling() }; }
public void Run(DevirtualizationCtx Ctx) { Ctx.VirtualizedMethods = new List <VMMethod>(); var disassembler = new VMDisassembler(Ctx); for (var i = 0; i < Ctx.Parser.MethodKeys.Length; i++) { var method = disassembler.DisassembleMethod(Ctx.Parser.MethodKeys[i]); Ctx.VirtualizedMethods.Add(method); } }
private static void Main(string[] args) { var logger = new ConsoleLogger(); Console.Title = $"Krypton - {CurrentVersion}"; var opts = new DevirtualizationOptions(args[0], logger); var ctx = new DevirtualizationCtx(opts); var devirtualizer = new Devirtualizer(ctx); devirtualizer.Devirtualize(); devirtualizer.Save(); Console.ReadLine(); }
public ResourceParser Parse(DevirtualizationCtx Ctx) { var resource = Ctx.Module.Resources.First(q => q.Name.Length == 37); if (resource == null) { throw new DevirtualizationException("Could not locate Resource!"); } var data = resource.GetData(); Ctx.Options.Logger.Success( $"Located Resource With Name {resource.Name} And Byte Data Length {data.Length}"); Reader = new BinaryReader(new MemoryStream(data)); Operands = new byte[255]; var length = ReadEncryptedByte(); for (var i = 0; i < length; i++) { var index = Reader.ReadByte(); Operands[index] = Reader.ReadByte(); } length = ReadEncryptedByte(); Strings = new string[length]; for (var i = 0; i < length; i++) { Strings[i] = Encoding.Unicode.GetString(Reader.ReadBytes(ReadEncryptedByte())); } length = ReadEncryptedByte(); MethodKeys = new int[length]; for (var i = 0; i < length; i++) { MethodKeys[i] = ReadEncryptedByte(); } var pos = (int)Reader.BaseStream.Position; for (var i = 0; i < length; i++) { var res = MethodKeys[i]; MethodKeys[i] = pos; pos += res; } return(this); }
public void Execute(DevirtualizationCtx ctx) { foreach (var virtualizedMethod in ctx.VirtualizedMethods) { if (virtualizedMethod.Instructions == null || virtualizedMethod.Instructions.Count == 0) { ctx.Logger.Error($"Couldn't find any instructions for method [{virtualizedMethod.Parent.Name}]"); continue; } var recompiledBody = virtualizedMethod.CreateBody(); virtualizedMethod.Parent.CilMethodBody = recompiledBody; if (ctx.Options.Verbose) { ctx.Logger.Success($"Recompiled CilMethodBody for method [{virtualizedMethod.Parent.Name}]"); } } }
private static void Main(string[] args) { var logger = new Logger(); if (args.Length == 0) { logger.Error("This is a command line executable."); Console.ReadKey(true); Environment.Exit(0); } logger.ShowInfo(CurrentVersion); var options2 = Parser.Default.ParseArguments <CommandLineOptions>(args) .WithParsed(o => { if (o.Verbose) { logger.Info("Verbose Output Enabled!"); } }); if (options2.Tag == ParserResultType.NotParsed) { return; } var options = (Parsed <CommandLineOptions>)options2; var ctx = new DevirtualizationCtx(args[0], options.Value, logger); var devirt = new Devirtualizor(ctx); if (options.Value.Verbose) { for (var i = 0; i < devirt.Stages.Count; i++) { logger.Info($"Stage[{i + 1}] ({devirt.Stages[i].Name}) - ({devirt.Stages[i].Description})"); } } devirt.Devirtualize(); devirt.Write(); Console.ReadLine(); }
public void Execute(DevirtualizationCtx ctx) { if (!ctx.Options.RecoverVariableTypes) { return; } foreach (var method in ctx.VirtualizedMethods) { var parentMethod = method.Parent; CleanupUnusedVariables(parentMethod); RecoverVariableTypes(parentMethod); if (ctx.Options.Verbose) { foreach (var variable in method.Parent.CilMethodBody.LocalVariables.Where(q => q.VariableType != ctx.Module.CorLibTypeFactory.Object)) { ctx.Logger.Success( $"Recovered Variable Type [{variable.VariableType.Name}] on Variable Index [{variable.Index}] On Method [{method.Parent.Name}]"); } } } }
public void Execute(DevirtualizationCtx ctx) { foreach (var virtualizedMethod in ctx.VirtualizedMethods) { if (virtualizedMethod.Instructions != null && virtualizedMethod.Instructions.Count == 0) { continue; } var vmAttribute = virtualizedMethod.Parent.CustomAttributes.First(q => q.Signature.FixedArguments.Count == 2 && q.Signature.FixedArguments[0].ArgumentType == ctx.Module.CorLibTypeFactory.String && q.Signature.FixedArguments[1].ArgumentType == ctx.Module.CorLibTypeFactory.Int32); virtualizedMethod.Parent.CustomAttributes.Remove(vmAttribute); var stream = ctx.Module.Resources.First(q => q.Name == virtualizedMethod.Id); ctx.Module.Resources.Remove(stream); if (ctx.Options.Verbose) { ctx.Logger.Success( $"Removed vmAttribute And Resource Stream On Method [{virtualizedMethod.Parent.Name}]"); } virtualizedMethod.Parent.CilMethodBody.Instructions.OptimizeMacros(); } }
public VMDisassembler(DevirtualizationCtx Ctx) { this.Ctx = Ctx; }
public void Execute(DevirtualizationCtx ctx) { foreach (var virtualizedMethod in ctx.VirtualizedMethods) { var stream = ctx.Module.Resources.First(q => q.Name == virtualizedMethod.Id); if (stream == null) { ctx.Logger.Error($"Coulnd't find resource stream {virtualizedMethod.Id}"); continue; } var instructions = stream.GetData(); if (instructions == null) { ctx.Logger.Error($"Resource {virtualizedMethod.Id} has no instructions!"); continue; } instructions = instructions.Select(q => (byte)(q ^ virtualizedMethod.Key)).ToArray(); var binaryReader = new BinaryReader(new MemoryStream(instructions)); virtualizedMethod.Instructions = new List <vmInstruction>(binaryReader.ReadInt32()); for (var i = 0; i < virtualizedMethod.Instructions.Capacity; i++) { var instruction = new vmInstruction((vmOpCode)binaryReader.ReadInt32()); if (binaryReader.ReadBoolean()) { switch (binaryReader.ReadInt32()) { case 0: instruction.Operand = binaryReader.ReadString(); break; case 1: instruction.Operand = binaryReader.ReadInt16(); break; case 2: instruction.Operand = binaryReader.ReadInt32(); break; case 3: instruction.Operand = binaryReader.ReadInt64(); break; case 4: instruction.Operand = binaryReader.ReadUInt16(); break; case 5: instruction.Operand = binaryReader.ReadUInt32(); break; case 6: instruction.Operand = binaryReader.ReadUInt64(); break; case 7: instruction.Operand = binaryReader.ReadDouble(); break; case 8: instruction.Operand = binaryReader.ReadDecimal(); break; case 9: instruction.Operand = binaryReader.ReadByte(); break; case 10: instruction.Operand = binaryReader.ReadSByte(); break; case 11: instruction.Operand = binaryReader.ReadSingle(); break; case 12: instruction.Operand = null; break; } } virtualizedMethod.Instructions.Add(instruction); } if (virtualizedMethod.Instructions.Count != 0 && ctx.Options.Verbose) { ctx.Logger.Success( $"Dissasembled [{virtualizedMethod.Instructions.Count}] VM Instructions on method [{virtualizedMethod.Parent.Name}]"); } } }
public Devirtualizor(DevirtualizationCtx ctx) { Ctx = ctx; }