static void Main() { Console.WriteAscii("Rhydon v1.0.0", Color.Coral); Console.WriteLine(new string(' ', 44) + "by xsilent007 & TobitoFatito\n", Color.White); var ctx = new RhydonContext { Module = ModuleDefMD.Load("Test.exe"), Logger = new Logger() }; Resolver.ResolveAssemblies(ctx); KoiHeader.Parse(ctx); OpCodeMap.Parse(ctx); VirtualizedMethods.Parse(ctx); var emu = new KoiEmulator(ctx, ctx.Header.Methods[2]); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); emu.EmulateNext(); Console.ReadLine(); }
public void TestInvalidOpCodeMap() { var random = new Random(); var mod = new ModuleDefUser("test"); var type = new TypeDefUser("Constants"); for (var i = 0; i < random.Next(0, 100); i++) { type.Fields.Add(new FieldDefUser("randomName" + random.Next(), new FieldSig(mod.CorLibTypes.Byte))); } mod.Types.Add(type); var ms = new MemoryStream(); mod.Write(ms); var ctx = new RhydonContext { Module = ModuleDefMD.Load(ms), Logger = new DummyLogger() }; OpCodeMap.Parse(ctx); Assert.IsNull(ctx.Constants); }
public static void Parse(RhydonContext ctx) { var VirtedMethods = new Dictionary <int, MethodDef>(); var VirtedMethods2 = new Dictionary <int, MethodDef>(); foreach (var type in ctx.Module.Types) { foreach (var method in type.Methods) { if (method.HasBody && method.Body.HasInstructions && method.Body.Instructions.Count() >= 6) { if (IsVirtedMethod(method)) { ctx.Logger.Info("Found Virtualized Method " + method.FullName + " With ID " + method.Body.Instructions[1].GetLdcI4Value()); VirtedMethods.Add(method.Body.Instructions[1].GetLdcI4Value(), method); } } } } var methods = VirtedMethods.OrderBy(q => q.Key); foreach (var method in methods) { VirtedMethods2.Add(method.Key, method.Value); } ctx.VirtualizedMethods = VirtedMethods2; }
public KoiEmulator(RhydonContext ctx, MethodExport export) { _emuCtx = new EmuContext(ctx, export); ctx.Reader.BaseStream.Position = export.Offset; foreach (var h in typeof(KoiEmulator).Assembly.DefinedTypes .Where(t => !t.IsAbstract && typeof(KoiHandler).IsAssignableFrom(t)) .Select(ha => Activator.CreateInstance(ha, _emuCtx)).Cast <KoiHandler>().ToArray()) { _emuCtx.Handlers[h.Handles] = h; } foreach (var v in typeof(KoiEmulator).Assembly.DefinedTypes .Where(t => !t.IsAbstract && typeof(VCallHandler).IsAssignableFrom(t)) .Select(ha => Activator.CreateInstance(ha, _emuCtx)).Cast <VCallHandler>().ToArray()) { _emuCtx.VCallHandlers[v.VCall] = v; } ctx.Logger.Info($"Emulating virtualized method at offset: 0x{export.Offset:X8}"); _emuCtx.Registers[ctx.Constants.REG_K1] = new VMSlot { U4 = export.Key }; _emuCtx.Registers[ctx.Constants.REG_BP] = new VMSlot { U4 = 0 }; _emuCtx.Registers[ctx.Constants.REG_SP] = new VMSlot { U4 = (uint)(export.ArgumentTypes.Length + 1) }; _emuCtx.Registers[ctx.Constants.REG_IP] = new VMSlot { U8 = (ulong)ctx.Reader.BaseStream.Position }; }
void ReadMethods(RhydonContext ctx, int count) { for (var i = 0; i < count; i++) { var id = ctx.ReadCompressedUint(); var export = MethodExport.Create(ctx); ctx.Logger.Debug($"Methods[{id:D3}]: Offset: 0x{export.Offset:X8} Key: 0x{export.Key:X8}"); Methods[id] = export; } }
void ReadStrings(RhydonContext ctx, int count) { for (var i = 0; i < count; i++) { var id = ctx.ReadCompressedUint(); var len = (int)ctx.ReadCompressedUint() << 1; var str = Encoding.Unicode.GetString(ctx.ReadBytes(len)); ctx.Logger.Debug($"Strings[{id:D3}]: \"{str}\""); Strings[id] = str; } }
void ReadReferences(RhydonContext ctx, int count) { for (var i = 0; i < count; i++) { var id = ctx.ReadCompressedUint(); var token = FromCodedToken(ctx.ReadCompressedUint()); var resolved = (IMemberRef)ctx.Module.ResolveToken(token); ctx.Logger.Debug($"Reference[{id:D3}]: Token: 0x{token:X8} | MemberRef: {resolved.Name}"); References[id] = resolved; } }
public void TestNoKoiHeader() { var mod = new ModuleDefUser("test"); var ms = new MemoryStream(); mod.Write(ms); var ctx = new RhydonContext { Module = ModuleDefMD.Load(ms), Logger = new DummyLogger() }; KoiHeader.Parse(ctx); Assert.IsNull(ctx.Header); ms.Close(); }
internal EmuContext(RhydonContext ctx, MethodExport exp) { Export = exp; MethodBody = new List <KoiInstruction>(); Stack = new Stack <VMSlot>(); Registers = new VMSlot[16]; Handlers = new Dictionary <byte, KoiHandler>(); VCallHandlers = new Dictionary <byte, VCallHandler>(); Module = ctx.Module; Reader = ctx.Reader; Header = ctx.Header; StartOffset = ctx.StartOffset; Constants = ctx.Constants; Decompiled = ctx.Decompiled; Logger = ctx.Logger; Parameters = ctx.Parameters; }
public void TestValidOpCodeMap() { var random = new Random(); var mod = new ModuleDefUser("test"); var type = new TypeDefUser("Constants"); for (var i = 0; i < 119; i++) { type.Fields.Add(new FieldDefUser("randomName" + random.Next(), new FieldSig(mod.CorLibTypes.Byte))); } mod.Types.Add(type); var ctor = type.FindOrCreateStaticConstructor(); var body = new CilBody(); for (var i = 1; i < 119; i++) { body.Instructions.Insert(0, Instruction.Create(OpCodes.Stfld, type.Fields[i])); body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldc_I4, random.Next(0, 0xFF))); body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldnull)); } body.Instructions.Add(Instruction.Create(OpCodes.Ldnull)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, 112)); body.Instructions.Add(Instruction.Create(OpCodes.Stfld, type.Fields[0])); body.Instructions.Add(Instruction.Create(OpCodes.Ret)); ctor.Body = body; var ms = new MemoryStream(); mod.Write(ms); var ctx = new RhydonContext { Module = ModuleDefMD.Load(ms), Logger = new DummyLogger() }; OpCodeMap.Parse(ctx); Assert.IsNotNull(ctx.Constants); Assert.IsTrue(ctx.Constants.REG_R0 == 112); ms.Close(); }
public static void Parse(RhydonContext ctx) { var heapname = ctx.Parameters["heap", "Koi"]; ctx.Logger.Debug($"Looking for #{heapname} stream..."); var heap = ctx.Module.Metadata.AllStreams.SingleOrDefault(s => s.Name == $"#{heapname}"); if (heap == null) { ctx.Logger.Error($"#{heapname} stream not found..."); return; } ctx.Logger.Info("Parsing KoiVM header"); var dnlibreader = heap.CreateReader(); ctx.StartOffset = dnlibreader.StartOffset; ctx.Reader = new BinaryReader(dnlibreader.AsStream()); var magic = ctx.ReadUInt32(); if (magic != 0x68736966) { ctx.Logger.Warning($"Magic wasn't 'fish' (0x68736966), instead: 0x{magic:X}"); } var refCount = (int)ctx.ReadUInt32(); var strCount = (int)ctx.ReadUInt32(); var metCount = (int)ctx.ReadUInt32(); var hdr = new KoiHeader(); hdr.ReadReferences(ctx, refCount); ctx.Logger.Success($"Parsed {refCount} references"); hdr.ReadStrings(ctx, strCount); ctx.Logger.Success($"Parsed {strCount} strings"); hdr.ReadMethods(ctx, metCount); ctx.Logger.Success($"Parsed {metCount} exports"); ctx.Header = hdr; }
public static MethodExport Create(RhydonContext ctx) { var obj = new MethodExport { Offset = ctx.Reader.ReadUInt32() }; if (obj.Offset != 0) { obj.Key = ctx.Reader.ReadUInt32(); } obj.Flags = ctx.Reader.ReadByte(); obj.ArgumentTypes = new ITypeDefOrRef[ctx.Reader.ReadCompressedUint()]; for (var i = 0; i < obj.ArgumentTypes.Length; i++) { obj.ArgumentTypes[i] = (ITypeDefOrRef)ctx.Module.ResolveToken(KoiHeader.FromCodedToken(ctx.Reader.ReadCompressedUint())); } obj.ReturnType = (ITypeDefOrRef)ctx.Module.ResolveToken(KoiHeader.FromCodedToken(ctx.Reader.ReadCompressedUint())); return(obj); }
public static void Parse(RhydonContext ctx) { var constantstype = ctx.Module.Types.SingleOrDefault(t => t.HasFields && t.Fields.Count == 119); if (constantstype == null) { return; } var fields = constantstype.Fields.OrderBy(f => f.MDToken.Raw).ToList(); var ctor = constantstype.FindStaticConstructor(); if (ctor == null) { return; } var constants = new Constants(); var body = ctor.Body.Instructions; var sortedconstants = constants.GetType().GetFields().OrderBy(f => f.MetadataToken).ToArray(); for (var i = 1; i < body.Count; i++) { var curr = body[i]; if (curr.OpCode != OpCodes.Stfld) { continue; } var constant = (FieldDef)curr.Operand; var value = (byte)body[i - 1].GetLdcI4Value(); sortedconstants[fields.IndexOf(constant)].SetValue(constants, value); } ctx.Constants = constants; }