Example #1
0
        /// <summary>
        /// Fill jumps
        /// </summary>
        /// <param name="bag">Bag</param>
        /// <param name="ins">Instruction</param>
        /// <param name="offsetToIndexCache">Cache</param>
        public override void ProcessInstruction(InstructionCollection bag, Instruction ins, OffsetRelationCache offsetToIndexCache)
        {
            if (ins.OpCode == null)
            {
                return;
            }

            switch (ins.OpCode.Name)
            {
            // Detect bad property optimization
            case nameof(NeoOpCode.DROP):
            {
                /*
                 * 0x03C5	PUSH0		Method 0x03C5 [R4S]
                 * 0x03C6	NEWARRAY
                 * 0x03C7	TOALTSTACK
                 * That is the only valid > 0x03C8	PUSHBYTES3	0x523453	R4S
                 * 0x03CC	NOP
                 * 0x03CD	FROMALTSTACK
                 * > 0x03CE	DROP
                 */

                int y = 1;
                for (int x = (int)ins.Location.Index - 1; x >= 0 && y <= 6; x--, y++)
                {
                    Instruction i = bag[x];
                    if (i == null || i.OpCode == null)
                    {
                        return;
                    }

                    switch (y)
                    {
                    case 1:
                    {
                        if (i.OpCode.Name != nameof(NeoOpCode.FROMALTSTACK))
                        {
                            // Detect Push / Drop
                            if (i.OpCode.Name.StartsWith("PUSH"))
                            {
                                ins.Flags = InstructionFlag.UnusableCode;
                                ins.ApplyColorForFlags();
                                i.Flags = InstructionFlag.UnusableCode;
                                i.ApplyColorForFlags();
                            }
                            return;
                        }
                        break;
                    }

                    case 2:
                    {
                        if (i.OpCode.Name != nameof(NeoOpCode.NOP))
                        {
                            return;
                        }
                        break;
                    }

                    case 3:
                    {
                        if (!i.OpCode.Name.StartsWith("PUSH"))
                        {
                            return;
                        }

                        break;
                    }

                    case 4:
                    {
                        if (i.OpCode.Name != nameof(NeoOpCode.TOALTSTACK))
                        {
                            return;
                        }
                        break;
                    }

                    case 5:
                    {
                        if (i.OpCode.Name != nameof(NeoOpCode.NEWARRAY))
                        {
                            return;
                        }
                        break;
                    }

                    case 6:
                    {
                        if (i.OpCode.Name != nameof(NeoOpCode.PUSH0))
                        {
                            return;
                        }
                        break;
                    }
                    }
                }

                if (y == 7)
                {
                    ins.Flags = InstructionFlag.UnusableCode;
                    ins.ApplyColorForFlags();

                    y = 1;
                    for (int x = (int)ins.Location.Index - 1, m = x - 6; x > m; x--, y++)
                    {
                        if (y == 3)
                        {
                            continue;
                        }

                        Instruction i = bag[x];

                        i.Flags = InstructionFlag.UnusableCode;
                        i.ApplyColorForFlags();
                    }
                }
                break;
            }

            // Detect NOP
            case nameof(NeoOpCode.NOP):
            {
                ins.Flags = InstructionFlag.UnusableCode;
                ins.ApplyColorForFlags();
                break;
            }

            // Detect To/From ALTSTACK
            case nameof(NeoOpCode.FROMALTSTACK):
            {
                if (ins.Location.Index != 0)
                {
                    Instruction prev = bag[ins.Location.Index - 1];
                    if (prev != null && prev.OpCode != null && prev.OpCode.Name == nameof(NeoOpCode.TOALTSTACK))
                    {
                        prev.Flags = InstructionFlag.UnusableCode;
                        ins.Flags  = InstructionFlag.UnusableCode;

                        prev.ApplyColorForFlags();
                        ins.ApplyColorForFlags();
                    }
                }
                break;
            }

            case nameof(NeoOpCode.RET):
            {
                ins.Jump = new Jump(new OnJumpDelegate(
                                        (d, i) =>
                    {
                        if (d == null || d.CurrentInstructionIndex != i.Location.Index || !(d is NeoDebugger neodebug))
                        {
                            return(null);
                        }

                        try
                        {
                            return((uint)neodebug.Engine.InvocationStack.Peek().InstructionPointer);
                        }
                        catch { }

                        return(null);
                    })
                                    );
                break;
            }

            case nameof(NeoOpCode.CALL):
            case nameof(NeoOpCode.CALL_E):
            case nameof(NeoOpCode.CALL_ED):
            case nameof(NeoOpCode.CALL_EDT):
            case nameof(NeoOpCode.CALL_ET):
            case nameof(NeoOpCode.CALL_I):
            case nameof(NeoOpCode.JMP):
            {
                uint offset;

                if (ins.Argument is OpCodeShortArgument a)
                {
                    offset = (uint)a.Value;
                }
                else
                {
                    if (ins.Argument is OpCodeCall_IArgument c)
                    {
                        // TODO: Check this

                        offset = (uint)c.Value - 2;
                    }
                    else
                    {
                        return;
                    }
                }

                if (offset == 3)
                {
                    // Detect JMP to next line
                    ins.Flags = InstructionFlag.UnusableCode;
                    ins.ApplyColorForFlags();
                }

                offset = ins.Location.Offset + offset;

                if (offsetToIndexCache.TryGetValue(offset, out uint ix, OffsetIndexRelation.OffsetToIndex))
                {
                    ins.Jump = new Jump(offset, ix);
                }