Beispiel #1
0
        private void WriteOperandValue(X86OperandType method, X86OperandSize size, X86Operand operand)
        {
            switch (method)
            {
            case X86OperandType.MemoryAddress:
            case X86OperandType.DirectAddress:
            case X86OperandType.ImmediateData:
            {
                WriteNumber(operand.Value, size);
                break;
            }

            case X86OperandType.RegisterOrMemoryAddress:
            {
                if ((operand.ScaledIndex != null) ||
                    (operand.OperandUsage != X86OperandUsage.Normal && operand.Value is X86Register &&
                     (X86Register)operand.Value == X86Register.Esp))
                {
                    _writer.WriteByte(ComputeRegOrMemSibToken(operand));
                }
                else if (!(operand.Value is X86Register))
                {
                    WriteNumber(operand.Value, X86OperandSize.Dword);
                }
                break;
            }

            case X86OperandType.RelativeOffset:
            {
                WriteNumber(Convert.ToUInt32(operand.Value) - (_writer.Position + sizeof(sbyte)), size);
                break;
            }
            }
        }
Beispiel #2
0
        private X86Operand GetRegOrMemOperand32(byte registerToken, X86OperandSize size)
        {
            // Mechanism:
            // http://ref.x86asm.net/coder32.html#modrm_byte_32

            // ModR/M byte:
            //  mod | reg/mem | (reg2)
            // -----+---------+-------
            //  7 6 |  5 4 3  | (2 1 0)

            var modifier = (X86RegOrMemModifier)(registerToken >> 6);
            var operand  = new X86Operand();

            // Register-only operands:
            if (modifier == X86RegOrMemModifier.RegisterOnly)
            {
                operand.Value        = GetRegisterFromToken((byte)(registerToken & 0x7), GetRegisterSize(size));
                operand.OperandUsage = X86OperandUsage.Normal;
                return(operand);
            }

            // Register-pointer operands are always 32-bit registers.
            var register = GetRegisterFromToken((byte)(registerToken & 0x7), X86RegisterSize.Dword);

            operand.OperandUsage = GetOperandType(size);
            operand.Value        = register;

            // EBP register is replaced by a direct address.
            if (modifier == X86RegOrMemModifier.RegisterPointer && register == X86Register.Ebp)
            {
                operand.Value = _reader.ReadUInt32();
                return(operand);
            }

            // ESP register are replaced by a scaled index operand.
            if (register == X86Register.Esp)
            {
                MakeScaledIndexOperandFromToken(operand, _reader.ReadByte());
            }

            // Read correction based on modifier.
            switch (modifier)
            {
            case X86RegOrMemModifier.RegisterDispShortPointer:
                operand.Offset     = _reader.ReadSByte();
                operand.OffsetType = X86OffsetType.Short;
                break;

            case X86RegOrMemModifier.RegisterDispLongPointer:
                operand.Offset     = _reader.ReadInt32();
                operand.OffsetType = X86OffsetType.Long;
                break;
            }

            return(operand);
        }
Beispiel #3
0
 private static X86OperandUsage GetOperandType(X86OperandSize size)
 {
     switch (size)
     {
         case X86OperandSize.Byte:
             return X86OperandUsage.BytePointer;
         case X86OperandSize.Dword:
             return X86OperandUsage.DwordPointer;
         case X86OperandSize.WordOrDword:
             return X86OperandUsage.DwordPointer; // TODO: use operand-size override opcode
         case X86OperandSize.Fword:
             return X86OperandUsage.FwordPointer;
     }
     throw new ArgumentException();
 }
Beispiel #4
0
 private static byte ComputeRegisterTokenPart(X86OperandType method, X86OperandSize size, X86Operand operand)
 {
     switch (method)
     {
         case X86OperandType.Register:
         {
             return (byte)(ComputeRegisterToken((X86Register)operand.Value) << 3);
         }
         case X86OperandType.RegisterOrMemoryAddress:
         {
             return ComputeRegOrMemToken(operand);
         }
     }
     return 0;
 }
Beispiel #5
0
        private static byte ComputeRegisterTokenPart(X86OperandType method, X86OperandSize size, X86Operand operand)
        {
            switch (method)
            {
            case X86OperandType.Register:
            {
                return((byte)(ComputeRegisterToken((X86Register)operand.Value) << 3));
            }

            case X86OperandType.RegisterOrMemoryAddress:
            {
                return(ComputeRegOrMemToken(operand));
            }
            }
            return(0);
        }
        private static int GetTotalOperandSize(X86OperandType operandType, X86OperandSize operandSize, X86Operand operand)
        {
            int size = (int)operand.OffsetType;

            switch (operandType)
            {
            case X86OperandType.None:
            case X86OperandType.ControlRegister:
            case X86OperandType.DebugRegister:
            case X86OperandType.StackRegister:
            case X86OperandType.Register:
            case X86OperandType.RegisterCl:
            case X86OperandType.RegisterDx:
            case X86OperandType.RegisterEax:
            case X86OperandType.RegisterAl:
            case X86OperandType.ImmediateOne:
            case X86OperandType.SegmentRegister:
            case X86OperandType.OpCodeRegister:
                break;

            case X86OperandType.DirectAddress:
            case X86OperandType.MemoryAddress:
                size += 4;
                break;

            case X86OperandType.RelativeOffset:
            case X86OperandType.ImmediateData:
                size += GetSize(operandSize);
                break;

            case X86OperandType.RegisterOrMemoryAddress:
            case X86OperandType.StackRegisterOrMemoryAddress:
                if ((operand.ScaledIndex != null) ||
                    (operand.OperandUsage != X86OperandUsage.Normal && operand.Value is X86Register &&
                     (X86Register)operand.Value == X86Register.Esp))
                {
                    size += 1;
                }
                if (!(operand.Value is X86Register))
                {
                    size += 4;
                }
                break;
            }

            return(size);
        }
Beispiel #7
0
        private static X86RegisterSize GetRegisterSize(X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                return(X86RegisterSize.Byte);

            case X86OperandSize.Word:
                return(X86RegisterSize.Word);

            case X86OperandSize.Dword:
                return(X86RegisterSize.Dword);

            case X86OperandSize.WordOrDword:
                return(X86RegisterSize.Dword);     // TODO: use operand-size override opcode
            }
            throw new ArgumentException();
        }
Beispiel #8
0
        private static X86OperandUsage GetOperandType(X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                return(X86OperandUsage.BytePointer);

            case X86OperandSize.Dword:
                return(X86OperandUsage.DwordPointer);

            case X86OperandSize.WordOrDword:
                return(X86OperandUsage.DwordPointer);    // TODO: use operand-size override opcode

            case X86OperandSize.Fword:
                return(X86OperandUsage.FwordPointer);
            }
            throw new ArgumentException();
        }
Beispiel #9
0
        private object ReadImmediateData(X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                return(_reader.ReadByte());

            case X86OperandSize.Word:
                return(_reader.ReadUInt16());

            case X86OperandSize.Dword:
                return(_reader.ReadUInt32());

            case X86OperandSize.WordOrDword:
                return(_reader.ReadUInt32());    // TODO: use operand-size override opcode
                // TODO: fword
            }
            throw new NotSupportedException();
        }
        private static int GetSize(X86OperandSize operandSize)
        {
            switch (operandSize)
            {
            case X86OperandSize.Byte:
                return(1);

            case X86OperandSize.Word:
                return(2);

            case X86OperandSize.WordOrDword:
            case X86OperandSize.Dword:
                return(4);

            case X86OperandSize.Fword:
                return(6);
            }
            throw new NotSupportedException();
        }
Beispiel #11
0
        private X86Operand ReadOperand(X86OperandType method, X86OperandSize size, byte opcode, byte registerToken)
        {
            switch (method)
            {
            case X86OperandType.OpCodeRegister:
                return(new X86Operand(GetRegisterFromToken((byte)(opcode & 7), GetRegisterSize(size))));

            case X86OperandType.Register:
                return(new X86Operand(GetRegisterFromToken((byte)((registerToken >> 3) & 7),
                                                           GetRegisterSize(size))));

            case X86OperandType.RegisterOrMemoryAddress:
                return(GetRegOrMemOperand32(registerToken, size));

            case X86OperandType.ImmediateData:
                return(new X86Operand(ReadImmediateData(size)));

            case X86OperandType.MemoryAddress:
                return(new X86Operand(GetOperandType(size), _reader.ReadUInt32()));

            case X86OperandType.RegisterAl:
                return(new X86Operand(X86Register.Al));

            case X86OperandType.RegisterCl:
                return(new X86Operand(X86Register.Cl));

            case X86OperandType.RegisterDx:
                return(new X86Operand(X86Register.Dx));

            case X86OperandType.RegisterEax:
                return(new X86Operand(X86Register.Eax));

            case X86OperandType.ImmediateOne:
                return(new X86Operand(1));

            case X86OperandType.RelativeOffset:
                return(new X86Operand((ulong)(Convert.ToInt64(ReadSignedImmediateData(size)) + BaseAddress + _reader.Position)));

            case X86OperandType.None:
                return(null);
            }
            throw new NotSupportedException("Unrecognized or unsupported addressing method.");
        }
Beispiel #12
0
        private void WriteNumber(object value, X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                if (value is sbyte || value is short || value is int || value is long)
                {
                    _writer.WriteSByte(Convert.ToSByte(value));
                }
                else
                {
                    _writer.WriteByte(Convert.ToByte(value));
                }
                break;

            case X86OperandSize.Word:
                if (value is sbyte || value is short || value is int || value is long)
                {
                    _writer.WriteInt16(Convert.ToInt16(value));
                }
                else
                {
                    _writer.WriteUInt16(Convert.ToUInt16(value));
                }
                break;

            case X86OperandSize.WordOrDword:
            case X86OperandSize.Dword:
                if (value is sbyte || value is short || value is int || value is long)
                {
                    _writer.WriteInt32(Convert.ToInt32(value));
                }
                else
                {
                    _writer.WriteUInt32(Convert.ToUInt32(value));
                }
                break;

            default:
                throw new NotSupportedException();
            }
        }
Beispiel #13
0
        private object ReadImmediateData(ICollection <X86Prefix> prefixes, X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                return(_reader.ReadByte());

            case X86OperandSize.Word:
                return(_reader.ReadUInt16());

            case X86OperandSize.Dword:
                return(_reader.ReadUInt32());

            case X86OperandSize.WordOrDword:
                return(prefixes.Contains(X86Prefixes.OperandSizeOverride)
                        ? _reader.ReadUInt16()
                        : _reader.ReadUInt32());
                // TODO: fword
            }
            throw new NotSupportedException();
        }
Beispiel #14
0
        private static int GetSize(ICollection <X86Prefix> prefixes, X86OperandSize operandSize)
        {
            switch (operandSize)
            {
            case X86OperandSize.Byte:
                return(1);

            case X86OperandSize.Word:
                return(2);

            case X86OperandSize.WordOrDword:
                return(prefixes.Contains(X86Prefixes.OperandSizeOverride) ? 2 : 4);

            case X86OperandSize.Dword:
                return(4);

            case X86OperandSize.Fword:
                return(6);
            }
            throw new NotSupportedException();
        }
Beispiel #15
0
        private static X86RegisterSize GetRegisterSize(ICollection <X86Prefix> prefixes, X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                return(X86RegisterSize.Byte);

            case X86OperandSize.Word:
                return(X86RegisterSize.Word);

            case X86OperandSize.Dword:
                return(X86RegisterSize.Dword);

            case X86OperandSize.WordOrDword:
                return(prefixes.Contains(X86Prefixes.OperandSizeOverride)
                        ? X86RegisterSize.Word
                        : X86RegisterSize.Dword);
            }
            throw new ArgumentException();
        }
Beispiel #16
0
        private X86Operand GetRegOrMemOperand32(byte registerToken, X86OperandSize size)
        {
            // Mechanism:
            // http://ref.x86asm.net/coder32.html#modrm_byte_32

            // ModR/M byte:
            //  mod | reg/mem | (reg2)
            // -----+---------+-------
            //  7 6 |  5 4 3  | (2 1 0)

            var modifier = (X86RegOrMemModifier)(registerToken >> 6);
            var operand = new X86Operand();

            // Register-only operands:
            if (modifier == X86RegOrMemModifier.RegisterOnly)
            {
                operand.Value = GetRegisterFromToken((byte)(registerToken & 0x7), GetRegisterSize(size));
                operand.OperandUsage = X86OperandUsage.Normal;
                return operand;
            }

            // Register-pointer operands are always 32-bit registers.
            var register = GetRegisterFromToken((byte)(registerToken & 0x7), X86RegisterSize.Dword);
            operand.OperandUsage = GetOperandType(size);
            operand.Value = register;

            // EBP register is replaced by a direct address.
            if (modifier == X86RegOrMemModifier.RegisterPointer && register == X86Register.Ebp)
            {
                operand.Value = _reader.ReadUInt32();
                return operand;
            }

            // ESP register are replaced by a scaled index operand.
            if (register == X86Register.Esp)
                MakeScaledIndexOperandFromToken(operand, _reader.ReadByte());

            // Read correction based on modifier.
            switch (modifier)
            {
                case X86RegOrMemModifier.RegisterDispShortPointer:
                    operand.Offset = _reader.ReadSByte();
                    operand.OffsetType = X86OffsetType.Short;
                    break;
                case X86RegOrMemModifier.RegisterDispLongPointer:
                    operand.Offset = _reader.ReadInt32();
                    operand.OffsetType = X86OffsetType.Long;
                    break;
            }

            return operand;
        }
Beispiel #17
0
 private static int GetSize(X86OperandSize operandSize)
 {
     switch (operandSize)
     {
         case X86OperandSize.Byte:
             return 1;
         case X86OperandSize.Word:
             return 2;
         case X86OperandSize.WordOrDword:
         case X86OperandSize.Dword:
             return 4;
         case X86OperandSize.Fword:
             return 6;
     }
     throw new NotSupportedException();
 }
Beispiel #18
0
        private static X86OperandUsage GetOperandType(ICollection <X86Prefix> prefixes, X86OperandSize size)
        {
            switch (size)
            {
            case X86OperandSize.Byte:
                return(X86OperandUsage.BytePointer);

            case X86OperandSize.Word:
                return(X86OperandUsage.WordPointer);

            case X86OperandSize.Dword:
                return(X86OperandUsage.DwordPointer);

            case X86OperandSize.WordOrDword:
                return(prefixes.Contains(X86Prefixes.OperandSizeOverride)
                        ? X86OperandUsage.WordPointer
                        : X86OperandUsage.DwordPointer);

            case X86OperandSize.Fword:
                return(X86OperandUsage.FwordPointer);
            }
            throw new ArgumentException();
        }
Beispiel #19
0
 private void WriteNumber(object value, X86OperandSize size)
 {
     switch (size)
     {
         case X86OperandSize.Byte:
             if (value is sbyte || value is short || value is int || value is long)
                 _writer.WriteSByte(Convert.ToSByte(value));
             else
                 _writer.WriteByte(Convert.ToByte(value));
             break;
         case X86OperandSize.Word:
             if (value is sbyte || value is short || value is int || value is long)
                 _writer.WriteInt16(Convert.ToInt16(value));
             else
                 _writer.WriteUInt16(Convert.ToUInt16(value));
             break;
         case X86OperandSize.WordOrDword:
         case X86OperandSize.Dword:
             if (value is sbyte || value is short || value is int || value is long)
                 _writer.WriteInt32(Convert.ToInt32(value));
             else
                 _writer.WriteUInt32(Convert.ToUInt32(value));
             break;
         default:
             throw new NotSupportedException();
     }
 }
Beispiel #20
0
        private static int GetTotalOperandSize(X86OperandType operandType, X86OperandSize operandSize, X86Operand operand)
        {
            int size = (int)operand.OffsetType;
            switch (operandType)
            {
                case X86OperandType.None:
                case X86OperandType.ControlRegister:
                case X86OperandType.DebugRegister:
                case X86OperandType.StackRegister:
                case X86OperandType.Register:
                case X86OperandType.RegisterCl:
                case X86OperandType.RegisterDx:
                case X86OperandType.RegisterEax:
                case X86OperandType.RegisterAl:
                case X86OperandType.ImmediateOne:
                case X86OperandType.SegmentRegister:
                case X86OperandType.OpCodeRegister:
                    break;

                case X86OperandType.DirectAddress:
                case X86OperandType.MemoryAddress:
                    size += 4;
                    break;

                case X86OperandType.RelativeOffset:
                case X86OperandType.ImmediateData:
                    size += GetSize(operandSize);
                    break;

                case X86OperandType.RegisterOrMemoryAddress:
                case X86OperandType.StackRegisterOrMemoryAddress:
                    if ((operand.ScaledIndex != null) ||
                        (operand.OperandUsage != X86OperandUsage.Normal && operand.Value is X86Register &&
                         (X86Register)operand.Value == X86Register.Esp))
                        size += 1;
                    if (!(operand.Value is X86Register))
                        size += 4;
                    break;
            }

            return size;
        }
Beispiel #21
0
 private void WriteOperand(X86OperandType method, X86OperandSize size, X86Operand operand)
 {
     WriteOperandValue(method, size, operand);
     WriteOperandOffset(operand.OffsetType, operand.Offset);
 }
Beispiel #22
0
 private void WriteOperand(X86OperandType method, X86OperandSize size, X86Operand operand)
 {
     WriteOperandValue(method, size, operand);
     WriteOperandOffset(operand.OffsetType, operand.Offset);
 }
Beispiel #23
0
 private void WriteOperandValue(X86OperandType method, X86OperandSize size, X86Operand operand)
 {
     switch (method)
     {
         case X86OperandType.MemoryAddress:
         case X86OperandType.DirectAddress:
         case X86OperandType.ImmediateData:
         {
             WriteNumber(operand.Value, size);
             break;
         }
         case X86OperandType.RegisterOrMemoryAddress:
         {
             if ((operand.ScaledIndex != null) ||
                 (operand.OperandUsage != X86OperandUsage.Normal && operand.Value is X86Register &&
                  (X86Register)operand.Value == X86Register.Esp))
                 _writer.WriteByte(ComputeRegOrMemSibToken(operand));
             else if (!(operand.Value is X86Register))
                 WriteNumber(operand.Value, X86OperandSize.Dword);
             break;
         }
         case X86OperandType.RelativeOffset:
         {
             WriteNumber(Convert.ToUInt32(operand.Value) - (_writer.Position + sizeof (sbyte)), size);
             break;
         }
     }
 }
Beispiel #24
0
        private void DumpMemory(IDebuggeeProcess process, ulong address, int rows, X86OperandSize size, Logger logger)
        {
            const int rowSize = 0x10;

            var buffer = new byte[rows * rowSize];

            process.ReadMemory((IntPtr)address, buffer, 0, buffer.Length);

            int stepSize = 0;

            switch (size)
            {
            case X86OperandSize.Byte:
                stepSize = 1;
                break;

            case X86OperandSize.Word:
                stepSize = 2;
                break;

            case X86OperandSize.Dword:
                stepSize = 4;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            for (int row = 0; row < rows; row++)
            {
                logger.Write("{0:X8}:  ", address + (ulong)(row * rowSize));

                var builder = new StringBuilder();
                for (int col = 0; col < rowSize; col += stepSize)
                {
                    if (col % 4 == 0)
                    {
                        logger.Write(" ");
                    }

                    ulong currentValue = 0;
                    switch (size)
                    {
                    case X86OperandSize.Byte:
                        currentValue = buffer[row * rowSize + col];
                        break;

                    case X86OperandSize.Word:
                        currentValue = BitConverter.ToUInt16(buffer, row * rowSize + col);
                        break;

                    case X86OperandSize.Dword:
                        currentValue = BitConverter.ToUInt32(buffer, row * rowSize + col);
                        break;
                    }

                    logger.Write("{0} ", currentValue.ToString("X" + (stepSize * 2)));

                    if (stepSize == 1)
                    {
                        char currentChar = (char)currentValue;
                        builder.Append(char.IsControl(currentChar) ? '.' : currentChar);
                    }
                }

                logger.WriteLine("  " + builder.ToString());
            }
        }
Beispiel #25
0
 private static X86RegisterSize GetRegisterSize(X86OperandSize size)
 {
     switch (size)
     {
         case X86OperandSize.Byte:
             return X86RegisterSize.Byte;
         case X86OperandSize.Word:
             return X86RegisterSize.Word;
         case X86OperandSize.Dword:
             return X86RegisterSize.Dword;
         case X86OperandSize.WordOrDword:
             return X86RegisterSize.Dword ; // TODO: use operand-size override opcode
     }
     throw new ArgumentException();
 }
Beispiel #26
0
 private object ReadSignedImmediateData(X86OperandSize size)
 {
     switch (size)
     {
         case X86OperandSize.Byte:
             return _reader.ReadSByte();
         case X86OperandSize.Word:
             return _reader.ReadInt16();
         case X86OperandSize.Dword:
             return _reader.ReadInt32();
         case X86OperandSize.WordOrDword:
             return _reader.ReadInt32(); // TODO: use operand-size override opcode
         // TODO: fword
     }
     throw new NotSupportedException();
 }
Beispiel #27
0
        private X86Operand ReadOperand(X86OperandType method, X86OperandSize size, byte opcode, byte registerToken)
        {
            switch (method)
            {
                case X86OperandType.OpCodeRegister:
                    return new X86Operand(GetRegisterFromToken((byte)(opcode & 7), GetRegisterSize(size)));

                case X86OperandType.Register:
                    return new X86Operand(GetRegisterFromToken((byte)((registerToken >> 3) & 7),
                        GetRegisterSize(size)));

                case X86OperandType.RegisterOrMemoryAddress:
                    return GetRegOrMemOperand32(registerToken, size);

                case X86OperandType.ImmediateData:
                    return new X86Operand(ReadImmediateData(size));

                case X86OperandType.MemoryAddress:
                    return new X86Operand(GetOperandType(size), _reader.ReadUInt32());

                case X86OperandType.RegisterAl:
                    return new X86Operand(X86Register.Al);

                case X86OperandType.RegisterCl:
                    return new X86Operand(X86Register.Cl);

                case X86OperandType.RegisterDx:
                    return new X86Operand(X86Register.Dx);

                case X86OperandType.RegisterEax:
                    return new X86Operand(X86Register.Eax);

                case X86OperandType.ImmediateOne:
                    return new X86Operand(1);

                case X86OperandType.RelativeOffset:
                    return new X86Operand((ulong)(Convert.ToInt64(ReadSignedImmediateData(size)) + BaseAddress + _reader.Position));

                case X86OperandType.None:
                    return null;

            }
            throw new NotSupportedException("Unrecognized or unsupported addressing method.");
        }