Example #1
0
        private void WriteCallInstruction(HtmlWriter writer, Instruction inst, ref MethodContext context)
        {
            // we should be able to find the call targets for R11/relative immediate
            ulong callTarget = GetBranchTarget(inst, context.R11?.LvalUQWord ?? 0);

            StartNote(writer, ref context);
            if (callTarget != 0)
            {
                var target = Mono.GetJitInfoAnyDomain((IntPtr)callTarget, out _);
                if (target.Method != null)
                {
                    if (target.Method.IsConstructor)
                    {
                        WriteCtorPrefix(writer, target.Method);
                        writer.Write(" ");
                        WriteCtorDeclaration(writer, target.Method as ConstructorInfo);
                    }
                    else if (target.Method != null)
                    {
                        WriteMethodPrefix(writer, target.Method);
                        writer.Write(" ");
                        WriteMethodReturnType(writer, target.Method as MethodInfo);
                        writer.Write(" ");
                        if (target.Method.DeclaringType != null)
                        {
                            TypeLink(writer, target.Method.DeclaringType);
                            writer.Write(".");
                        }

                        WriteMethodDeclaration(writer, target.Method as MethodInfo);
                    }
                }
                else
                {
                    writer.Write("unknown target @ " + callTarget.ToString("X16"));
                }
            }
            else if (context.DebugEnabled)
            {
                var     r11 = context.R11;
                ud_type stackFrameRegister = context.HasBasePointer ? ud_type.UD_R_RBP : ud_type.UD_R_RSP;
                if (r11 != null && r11.Base == stackFrameRegister && r11.Type == ud_type.UD_OP_MEM && r11.Value == context.SinglestepTrampolineOffset)
                {
                    writer.Write("check for singlestep");
                    return;
                }

                writer.Write("unknown target; native, virtual, or unpatched JIT trampoline");
            }
            else
            {
                writer.Write("unknown target; native, virtual, or unpatched JIT trampoline");
            }
        }
Example #2
0
        private void WriteCallInstruction(HtmlWriter writer, Instruction inst, ulong r11)
        {
            // we should be able to find the call targets for R11/relative immediate
            ulong callTarget = GetBranchTarget(inst, r11);

            writer.Write(" ; ");
            if (callTarget != 0)
            {
                var target = Mono.GetJitInfo((IntPtr)callTarget);
                if (target.Method != null)
                {
                    if (target.Method.IsConstructor)
                    {
                        WriteCtorPrefix(writer, target.Method);
                        writer.Write(" ");
                        WriteCtorDeclaration(writer, target.Method as ConstructorInfo);
                    }
                    else if (target.Method != null)
                    {
                        WriteMethodPrefix(writer, target.Method);
                        writer.Write(" ");
                        WriteMethodReturnType(writer, target.Method as MethodInfo);
                        writer.Write(" ");
                        if (target.Method.DeclaringType != null)
                        {
                            TypeLink(writer, target.Method.DeclaringType);
                            writer.Write(".");
                        }
                        WriteMethodDeclaration(writer, target.Method as MethodInfo);
                    }
                }
                else
                {
                    writer.Write("unknown target @ " + callTarget.ToString("X16"));
                }
            }
            else
            {
                writer.Write("unsupported call, probably virtual");
            }
        }
        void ExecuteLookup(HtmlWriter writer, HttpListenerRequest request)
        {
            const string addresses = nameof(addresses);

            using (writer.Tag("form", "action", CommandUrl("lookup"), "method", "post"))
                using (writer.ContainerFluid())
                    using (writer.Tag("div", "class", "form-group"))
                    {
                        writer.Inline("h2", "Paste addresses to look up (hex)");
                        writer.Tag("textarea", "class", "form-control", "name", addresses, "rows", "10").Dispose();
                        writer.Break();
                        writer.InlineTag("input", "type", "submit", "value", "Submit");
                    }

            NameValueCollection postValues;

            using (StreamReader reader = new StreamReader(request.InputStream, request.ContentEncoding))
                postValues = System.Web.HttpUtility.ParseQueryString(reader.ReadToEnd());
            if (postValues[addresses] != null)
            {
                var modules = Process.GetCurrentProcess().Modules;
                string FindModule(long address)
                {
                    for (int i = 0; i < modules.Count; i++)
                    {
                        var  m           = modules[i];
                        long baseAddress = m.BaseAddress.ToInt64();
                        if (baseAddress <= address && address < baseAddress + m.ModuleMemorySize)
                        {
                            return(modules[i].ModuleName);
                        }
                    }
                    return("unknown module");
                }

                using (writer.ContainerFluid())
                {
                    writer.Inline("h4", "Results");
                    var lines = postValues[addresses].Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    using (writer.Tag("textarea", "class", "form-control", "rows", "10"))
                    {
                        foreach (var line in lines)
                        {
                            writer.Write(line);
                            writer.Write(", ");
                            int start = line.IndexOf("0x");
                            if (start >= 0)
                            {
                                int end = line.IndexOf(',', start);
                                if (end < 0)
                                {
                                    end = line.Length;
                                }
                                var numberString = line.Substring(start + 2, end - start - 2);
                                if (long.TryParse(numberString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long address))
                                {
                                    var jitInfo = Mono.GetJitInfo(new IntPtr(address));
                                    if (jitInfo.Method == null)
                                    {
                                        writer.Write("unknown method");
                                    }
                                    else if (jitInfo.Method is MethodInfo m)
                                    {
                                        WriteTypeName(writer, m.DeclaringType, true);
                                        writer.Write(".");
                                        WriteMethodDeclaration(writer, m, true);
                                    }
                                    else if (jitInfo.Method is ConstructorInfo c)
                                    {
                                        WriteCtorDeclaration(writer, c, true);
                                    }
                                    writer.Write(", ");
                                    writer.Write(FindModule(address));
                                }
                                else
                                {
                                    writer.Write("failed to parse " + numberString + ",");
                                }
                            }
                            else
                            {
                                writer.Write("failed to parse,");
                            }


                            writer.Write("\n");
                        }
                    }
                }
            }
        }
Example #4
0
        private void WriteDissassembly(HtmlWriter writer, MethodBase method)
        {
            if (method.IsAbstract || method.ContainsGenericParameters)
            {
                writer.Write("Cannot display disassembly for generic or abstract methods.");
                return;
            }
            var jitInfo = Mono.GetJitInfo(method);

            writer.Write("Address: ");
            writer.Write(jitInfo.CodeStart.ToString("X16"));
            writer.Break();
            writer.Write("Code Size in Bytes: ");
            writer.Write(jitInfo.CodeSize.ToString());
            writer.Break();
            if (jitInfo.CodeSize <= 0)
            {
                return;
            }
            using (writer.Tag("pre")) {
                using (writer.Tag("code")) {
                    // some special help for calls using R11 and nops
                    int         nops            = 0;
                    Instruction lastInstruction = null;
                    ulong       r11Register     = 0;
                    lock (_disassemblerLock) {
                        foreach (var inst in GetInstructions(jitInfo))
                        {
                            // abbreviate excessive nopping
                            if (inst.Mnemonic == ud_mnemonic_code.UD_Inop)
                            {
                                nops++;
                                lastInstruction = inst;
                                continue;
                            }
                            if (nops > 0)
                            {
                                if (nops == 1)
                                {
                                    writer.Write(lastInstruction.ToString());
                                }
                                else
                                {
                                    writer.Write("nop (");
                                    writer.Write(nops.ToString());
                                    writer.Write(" bytes)");
                                }
                                nops = 0;
                                writer.Write("\n");
                            }
                            lastInstruction = inst;
                            using (writer.Tag("span").With("id", "X" + Address(inst).ToString("X16"))) {
                                writer.Write(inst.ToString());

                                if (inst.Mnemonic == ud_mnemonic_code.UD_Imov)
                                {
                                    var op0 = inst.Operands[0];
                                    // call targets on x64 are frequently placed in R11, so let's ensure that we catch that.
                                    if (op0.Type == ud_type.UD_OP_REG && op0.Base == ud_type.UD_R_R11)
                                    {
                                        r11Register = inst.Operands[1].LvalUQWord;
                                    }
                                }
                                else if (inst.Mnemonic == ud_mnemonic_code.UD_Icall)
                                {
                                    WriteCallInstruction(writer, inst, r11Register);
                                    r11Register = 0;
                                }
                                else if (IsJump(inst.Mnemonic))
                                {
                                    WriteJumpInstruction(writer, inst, r11Register);
                                }
                            }
                            writer.Write("\n");
                        }
                    }
                }
            }
        }
Example #5
0
        private void WriteDissassembly(HtmlWriter writer, MethodBase method)
        {
            if (method.IsAbstract || method.ContainsGenericParameters)
            {
                writer.Write("Cannot display disassembly for generic or abstract methods.");
                return;
            }

            var context = new MethodContext()
            {
                DebugEnabled = MonoDebug.IsEnabled
            };

            var jitInfo = Mono.GetJitInfo(method);

            using (writer.ContainerFluid())
            {
                writer.Write("Address: ");
                writer.Write(jitInfo.CodeStart.ToString("X16"));
                writer.Break();
                writer.Write("Code Size in Bytes: ");
                writer.Write(jitInfo.CodeSize.ToString());
                writer.Break();
                writer.Write("Debug mode: ");
                writer.Write(context.DebugEnabled ? "enabled" : "disabled");
                writer.Break();
            }

            if (jitInfo.CodeSize <= 0)
            {
                return;
            }

            using (writer.Tag("pre"))
            {
                using (writer.Tag("code"))
                {
                    // some special help for calls using R11 and nops
                    int  nops  = 0;
                    bool first = true;
                    lock (_disassemblerLock)
                    {
                        foreach (var inst in GetInstructions(jitInfo))
                        {
                            context.HasLineNote = false;

                            if (first)
                            {
                                context.HasBasePointer =
                                    inst.Mnemonic == ud_mnemonic_code.UD_Ipush &&
                                    inst.Operands[0].Type == ud_type.UD_OP_REG &&
                                    inst.Operands[0].Base == ud_type.UD_R_RBP;
                                first = false;
                            }

                            // abbreviate excessive nopping
                            if (inst.Mnemonic == ud_mnemonic_code.UD_Inop)
                            {
                                nops++;
                                context.LastInstruction = inst;
                                continue;
                            }

                            if (nops > 0)
                            {
                                if (nops == 1)
                                {
                                    writer.Write(context.LastInstruction.ToString());
                                }
                                else
                                {
                                    var str = context.LastInstruction.ToString();
                                    writer.Write(str);
                                    context.LineLength = str.Length;
                                    StartNote(writer, ref context);

                                    writer.Write("repeated nops (");
                                    writer.Write(nops.ToString());
                                    writer.Write(" bytes)");
                                }

                                nops = 0;
                                context.HasLineNote = false;
                                writer.Write("\n");
                            }

                            using (writer.Tag("span", "id", "X" + Address(inst).ToString("X16")))
                            {
                                var str = inst.ToString();
                                context.LineLength = str.Length;
                                writer.Write(str);

                                if (inst.Mnemonic == ud_mnemonic_code.UD_Imov)
                                {
                                    var op0 = inst.Operands[0];
                                    var op1 = inst.Operands[1];

                                    // call targets on x64 are frequently placed in R11, so let's ensure that we catch that.
                                    if (IsR11(op0))
                                    {
                                        context.R11 = op1;
                                    }
                                    if (context.DebugEnabled)
                                    {
                                        if (IsLocalStore(inst) && IsR11(op1) && context.R11 != null && context.R11.Type == ud_type.UD_OP_IMM)
                                        {
                                            if (context.BreakpointTrampolineOffset == 0)
                                            {
                                                context.BreakpointTrampolineOffset = op0.Value;
                                                StartNote(writer, ref context);
                                                writer.Write("write breakpoint trampoline");
                                            }
                                            else if (context.SinglestepTrampolineOffset == 0)
                                            {
                                                context.SinglestepTrampolineOffset = op0.Value;
                                                StartNote(writer, ref context);
                                                writer.Write("write singlestep trampoline");
                                            }
                                        }
                                        else if (IsReadSinglestepTrampoline(inst))
                                        {
                                            StartNote(writer, ref context);
                                            writer.Write("read singlestep trampoline");
                                        }
                                        else if (IsReadBreakpointTrampoline(inst))
                                        {
                                            StartNote(writer, ref context);
                                            writer.Write("read breakpoint trampoline");
                                        }
                                    }
                                }
                                else if (inst.Mnemonic == ud_mnemonic_code.UD_Iadd)
                                {
                                    var op1 = inst.Operands[1];
                                    if (op1.Type == ud_type.UD_OP_IMM)
                                    {
                                        StartNote(writer, ref context);
                                        writer.Write(op1.Value.ToString());
                                    }
                                }
                                else if (inst.Mnemonic == ud_mnemonic_code.UD_Icall)
                                {
                                    WriteCallInstruction(writer, inst, ref context);
                                    context.R11 = null;
                                }
                                else if (IsJump(inst.Mnemonic))
                                {
                                    WriteJumpInstruction(writer, inst, ref context);
                                }
                            }

                            writer.Write("\n");

                            context.LastInstruction = inst;
                        }
                    }
                }
            }

            bool IsR11(Operand op) => op.Type == ud_type.UD_OP_REG && op.Base == ud_type.UD_R_R11;
            bool IsReadSinglestepTrampoline(Instruction inst) => IsLocalLoadOffset(inst, context.SinglestepTrampolineOffset);
            bool IsReadBreakpointTrampoline(Instruction inst) => IsLocalLoadOffset(inst, context.BreakpointTrampolineOffset);
            ud_type StackFrameRegister() => context.HasBasePointer ? ud_type.UD_R_RBP : ud_type.UD_R_RSP;

            bool IsLocalInteraction(Instruction inst, int operand)
            {
                if (inst.Mnemonic != ud_mnemonic_code.UD_Imov)
                {
                    return(false);
                }
                var op = inst.Operands[operand];

                return(op.Type == ud_type.UD_OP_MEM && op.Base == StackFrameRegister());
            }

            bool IsLocalStore(Instruction inst) => IsLocalInteraction(inst, 0);
            bool IsLocalLoad(Instruction inst) => IsLocalInteraction(inst, 1);
            bool IsLocalLoadOffset(Instruction inst, long offset) => IsLocalLoad(inst) && inst.Operands[1].Value == offset;
        }