コード例 #1
0
ファイル: Program.cs プロジェクト: Trollicus/Rhydon
        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();
        }
コード例 #2
0
ファイル: Parser.cs プロジェクト: Z01wvay/Rhydon
        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);
        }
コード例 #3
0
        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;
        }
コード例 #4
0
        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
            };
        }
コード例 #5
0
        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;
            }
        }
コード例 #6
0
        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;
            }
        }
コード例 #7
0
        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;
            }
        }
コード例 #8
0
ファイル: Parser.cs プロジェクト: Z01wvay/Rhydon
        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();
        }
コード例 #9
0
ファイル: EmuContext.cs プロジェクト: Z01wvay/Rhydon
        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;
        }
コード例 #10
0
ファイル: Parser.cs プロジェクト: Z01wvay/Rhydon
        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();
        }
コード例 #11
0
        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;
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        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;
        }