Example #1
0
 private string FormatInstruction(DisassembleEntry e)
 {
     if (e.data != null)
     {
         if (IsAscii(e.data))
         {
             if (e.name == "SYSCALL")
             {
                 return($"{e.opcode:X}\t{e.name} {Encoding.UTF8.GetString(e.data)}");
             }
             else
             {
                 return($"{e.opcode:X}\t{e.name} \"{Encoding.UTF8.GetString(e.data)}\"");
             }
         }
         else
         {
             return($"{e.opcode:X}\t{e.name} {e.data.ToHexString()}");
         }
     }
     else
     {
         return($"{e.opcode:X}\t{e.name}");
     }
 }
Example #2
0
        public static AVMDisassemble Disassemble(byte[] script)
        {
            InitHints();
            var output = new List <DisassembleEntry>();

            using (var stream = new MemoryStream(script))
            {
                using (var reader = new BinaryReader(stream))
                {
                    while (reader.BaseStream.Position != reader.BaseStream.Length)
                    {
                        var entry = new DisassembleEntry();
                        output.Add(entry);

                        entry.startOfs = (int)reader.BaseStream.Position;

                        var opcode = (OpCode)reader.ReadByte();

                        entry.opcode = opcode;
                        entry.name   = opcode.ToString();

                        entry.comment = hints.ContainsKey(opcode) ? hints[opcode] : "";

                        if (opcode >= OpCode.PUSHBYTES1 && opcode <= OpCode.PUSHBYTES75)
                        {
                            var len = (byte)opcode;
                            entry.data    = reader.ReadBytes(len);
                            entry.name    = "PUSHBYTES" + len;
                            entry.comment = "Pushes " + len + " bytes into the stack: $$";
                        }
                        else
                        {
                            switch (opcode)
                            {
                            // Push value
                            //case OpCode.PUSH0:

                            case OpCode.PUSHDATA1:
                            {
                                var len = reader.ReadByte();
                                entry.data    = reader.ReadBytes(len);
                                entry.comment = "Pushes " + len + " bytes into the stack: $$";
                                break;
                            }

                            case OpCode.PUSHDATA2:
                            {
                                var len = reader.ReadUInt16();
                                entry.data    = reader.ReadBytes(len);
                                entry.comment = "Pushes " + len + " bytes into the stack: $$";
                                break;
                            }


                            case OpCode.PUSHDATA4:
                            {
                                var len = reader.ReadInt32();
                                entry.data    = reader.ReadBytes(len);
                                entry.comment = "Pushes " + len + " bytes into the stack: $$";
                                break;
                            }

                            /*case OpCode.PUSHM1:
                            *  case OpCode.PUSH1:
                            *  case OpCode.PUSH2:
                            *  case OpCode.PUSH3:
                            *  case OpCode.PUSH4:
                            *  case OpCode.PUSH5:
                            *  case OpCode.PUSH6:
                            *  case OpCode.PUSH7:
                            *  case OpCode.PUSH8:
                            *  case OpCode.PUSH9:
                            *  case OpCode.PUSH10:
                            *  case OpCode.PUSH11:
                            *  case OpCode.PUSH12:
                            *  case OpCode.PUSH13:
                            *  case OpCode.PUSH14:
                            *  case OpCode.PUSH15:
                            *  case OpCode.PUSH16:*/

                            // Control
                            //case OpCode.NOP:

                            case OpCode.CALL:
                            case OpCode.CALL_I:
                            {
                                int other  = reader.ReadInt16();
                                int offset = reader.ReadInt16();
                                break;
                            }

                            case OpCode.CALL_E:
                            case OpCode.CALL_ET:
                            {
                                int    other       = reader.ReadInt16();
                                byte[] script_hash = reader.ReadBytes(20);
                                entry.data    = script_hash.Reverse().ToArray();
                                entry.comment = "NEP8-calls script with hash: $XX";
                                break;
                            }

                            case OpCode.CALL_ED:
                            case OpCode.CALL_EDT:
                            case OpCode.JMP:
                            case OpCode.JMPIF:
                            case OpCode.JMPIFNOT:
                            {
                                int offset = reader.ReadInt16();
                                //offset = context.InstructionPointer + offset - 3;
                                break;
                            }


                            /*case OpCode.CALL:
                             *  InvocationStack.Push(context.Clone());
                             *  context.InstructionPointer += 2;
                             *  ExecuteOp(OpCode.JMP, CurrentContext);
                             *  break;*/

                            /*case OpCode.RET:
                             *  InvocationStack.Pop().Dispose();
                             *  if (InvocationStack.Count == 0)
                             *      State |= VMState.HALT;
                             *  break;*/

                            case OpCode.APPCALL:
                            case OpCode.TAILCALL:
                            {
                                byte[] script_hash = reader.ReadBytes(20);
                                entry.data    = script_hash.Reverse().ToArray();
                                entry.comment = "Calls script with hash: $XX";
                                break;
                            }

                            case OpCode.SYSCALL:
                            {
                                entry.data    = reader.ReadVarBytes(252);
                                entry.comment = "System call with data: $$";
                                break;
                            }

                            // Stack ops

                            /*case OpCode.DUPFROMALTSTACK:
                             * case OpCode.TOALTSTACK:
                             * case OpCode.FROMALTSTACK:
                             * case OpCode.XDROP:
                             * case OpCode.XSWAP:
                             * case OpCode.XTUCK:
                             * case OpCode.DEPTH:
                             * case OpCode.DROP:
                             * case OpCode.DUP:
                             * case OpCode.NIP:
                             * case OpCode.OVER:
                             * case OpCode.PICK:
                             * case OpCode.ROLL:
                             * case OpCode.ROT:
                             * case OpCode.SWAP:
                             * case OpCode.TUCK:
                             * case OpCode.CAT:
                             * case OpCode.SUBSTR:
                             * case OpCode.LEFT:
                             * case OpCode.RIGHT:
                             * case OpCode.SIZE:
                             */


                            // Bitwise logic

                            /*case OpCode.INVERT:
                             * case OpCode.AND:
                             * case OpCode.OR:
                             * case OpCode.XOR:
                             * case OpCode.EQUAL:
                             |                            */



                            // Numeric

                            /*case OpCode.INC:
                             * case OpCode.DEC:
                             * case OpCode.SIGN:
                             * case OpCode.NEGATE:
                             * case OpCode.ABS:
                             * case OpCode.NOT:
                             * case OpCode.NZ:
                             * case OpCode.ADD:
                             * case OpCode.SUB:
                             * case OpCode.MUL:
                             * case OpCode.DIV:
                             * case OpCode.MOD:
                             * case OpCode.SHL:
                             * case OpCode.SHR:
                             * case OpCode.BOOLAND:
                             * case OpCode.BOOLOR:
                             * case OpCode.NUMEQUAL:
                             * case OpCode.NUMNOTEQUAL:
                             * case OpCode.LT:
                             * case OpCode.GT:
                             * case OpCode.LTE:
                             * case OpCode.GTE:
                             * case OpCode.MIN:
                             * case OpCode.MAX:
                             * case OpCode.WITHIN:
                             */

                            // Crypto

                            /*
                             * case OpCode.SHA1:
                             * case OpCode.SHA256:
                             * case OpCode.HASH160:
                             * case OpCode.HASH256:
                             * case OpCode.CHECKSIG:
                             * case OpCode.CHECKMULTISIG:
                             * case OpCode.ARRAYSIZE:
                             * case OpCode.PACK:
                             * case OpCode.UNPACK:
                             * case OpCode.PICKITEM:
                             * case OpCode.SETITEM:
                             * case OpCode.NEWARRAY:
                             * case OpCode.NEWSTRUCT:
                             */

                            // Exceptions

                            /*case OpCode.THROW:
                             * case OpCode.THROWIFNOT:
                             */

                            default:
                            {
                                if (!Enum.IsDefined(typeof(OpCode), opcode))
                                {
                                    var s = ((byte)opcode).ToString();
                                    Console.WriteLine($"Invalid opcode {s} at {entry.startOfs}");
                                }

                                break;
                            }
                            }
                        }

                        entry.endOfs = (int)(reader.BaseStream.Position - 1);
                    }
                }
            }

            return(new AVMDisassemble(output));
        }
Example #3
0
        private string DisassembleInstruction(int offset)
        {
            DisassembleEntry e = InstructionAt(offset);

            return(FormatInstruction(e));
        }