예제 #1
0
        public static UInt32 GetOffsetFor(Byte[] code)
        {
            var offsetBeginsAt = opcode.GetOpcodeLengthFor(code);

            offsetBeginsAt++; // for modRM byte

            return(BitMath.BytesToDword(code, offsetBeginsAt));
        }
예제 #2
0
        public UInt32 GetImmediateFor(Byte[] code)
        {
            if (!HasImmediate(code))
            {
                throw new InvalidOperationException("Can't get immediate from an opcode that doesn't have one");
            }

            Byte valueIndex = 1;

            if (HasModRM(code))
            {
                valueIndex++;

                if (ModRM.HasIndex(code))
                {
                    valueIndex++;
                }

                if (ModRM.HasSIB(code))
                {
                    valueIndex++;
                }
            }

            switch (GetEncodingFor(code))
            {
            case OpcodeEncoding.EvIb:
            case OpcodeEncoding.EbIb:
            case OpcodeEncoding.Jb:
            {
                return(code[valueIndex]);
            }

            case OpcodeEncoding.EvIz:
            case OpcodeEncoding.rAxIz:
            case OpcodeEncoding.rAxIv:
            case OpcodeEncoding.Jz:
            case OpcodeEncoding.Iz:
            {
                return(BitMath.BytesToDword(code, valueIndex));
            }

            default:
            {
                throw new NotImplementedException("Don't know how to get the immediate for this opcode: " +
                                                  code[0]);
            }
            }
        }
예제 #3
0
        private static MachineState EmulateOpcode(ICollection <ReportItem> reportItems,
                                                  MachineState machineState,
                                                  Byte[] code)
        {
            var           state = machineState;
            RegisterName  sourceRegister, destinationRegister;
            AbstractValue sourceValue;
            Int32         index;

            var encoding = opcode.GetEncodingFor(code);
            var op = opcode.GetOperatorEffectFor(code);

            switch (encoding)
            {
            case OpcodeEncoding.rAxIv:
            case OpcodeEncoding.rAxIz:
            {
                destinationRegister = opcode.GetDestinationRegisterFor(code);
                var immediate = opcode.GetImmediateFor(code);
                state = state.DoOperation(destinationRegister, op, new AbstractValue(immediate));
                return(state);
            }

            case OpcodeEncoding.rAxOv:
            {
                state.Registers[RegisterName.EAX] = state.DataSegment[BitMath.BytesToDword(code, 1)];
                return(state);
            }

            case OpcodeEncoding.rBP:
            case OpcodeEncoding.rSI:
            case OpcodeEncoding.rSP:
            case OpcodeEncoding.rAX:
            case OpcodeEncoding.rBX:
            case OpcodeEncoding.rCX:
            case OpcodeEncoding.rDX:
            case OpcodeEncoding.Iz:
            {
                return(emulateStackEffectFor(code, state));
            }

            case OpcodeEncoding.EvIz:
            case OpcodeEncoding.EvIb:
            case OpcodeEncoding.EbIb:
            case OpcodeEncoding.EvGv:
            case OpcodeEncoding.EbGb:
            {
                destinationRegister = opcode.GetDestinationRegisterFor(code);
                index = 0;

                if (ModRM.HasIndex(code))
                {
                    index = ModRM.GetIndexFor(code);
                }

                if (opcode.HasImmediate(code))
                {
                    sourceValue = new AbstractValue(opcode.GetImmediateFor(code));
                }
                else
                {
                    sourceRegister = ModRM.GetGvFor(code);
                    sourceValue    = state.Registers[sourceRegister];
                }

                ////if (ModRM.HasOffset(code))
                ////{
                ////    UInt32 offset = ModRM.GetOffsetFor(code);
                ////    state.DataSegment[offset] = sourceValue;
                ////    return state;
                ////}

                if (ModRM.IsEffectiveAddressDereferenced(code))
                {
                    if (!state.Registers[destinationRegister].IsPointer)
                    {
                        throw new InvalidOperationException(
                                  "Trying to dereference non-pointer in register " + destinationRegister
                                  );
                    }

                    state = state.DoOperation(destinationRegister, index, op, sourceValue);
                    if (state.Registers[destinationRegister].PointsTo[index].IsOutOfBounds)
                    {
                        reportItems.Add(new ReportItem(state.InstructionPointer, sourceValue.IsTainted));
                    }
                }
                else
                {
                    state = state.DoOperation(destinationRegister, op, sourceValue);
                    if (state.Registers[destinationRegister].IsOutOfBounds)
                    {
                        reportItems.Add(new ReportItem(state.InstructionPointer, sourceValue.IsTainted));
                    }
                }

                return(state);
            }

            case OpcodeEncoding.GvEv:
            case OpcodeEncoding.GvEb:
            {
                sourceRegister      = ModRM.GetEvFor(code);
                destinationRegister = ModRM.GetGvFor(code);
                sourceValue         = state.Registers[sourceRegister];

                if (ModRM.HasOffset(code))
                {
                    var offset = ModRM.GetOffsetFor(code);
                    sourceValue = state.DataSegment[offset];
                }
                else if (ModRM.IsEffectiveAddressDereferenced(code))
                {
                    if (!sourceValue.IsPointer)
                    {
                        throw new InvalidOperationException(
                                  String.Format("Trying to dereference null pointer in register {0}.", sourceRegister));
                    }

                    index = 0;

                    if (ModRM.HasIndex(code))
                    {
                        index = ModRM.GetIndexFor(code);
                    }

                    sourceValue = sourceValue.PointsTo[index];

                    if (sourceValue.IsOutOfBounds)
                    {
                        reportItems.Add(new ReportItem(state.InstructionPointer, sourceValue.IsTainted));
                    }
                }

                state = state.DoOperation(destinationRegister, op, sourceValue);
                return(state);
            }

            case OpcodeEncoding.GvM:
            {
                // GvM, M may refer to [base register + offset]
                if (!ModRM.IsEffectiveAddressDereferenced(code))
                {
                    throw new InvalidOperationException("GvM must be dereferenced");
                }

                destinationRegister = opcode.GetDestinationRegisterFor(code);
                AbstractValue baseRegisterValue;
                index = 0;

                // TODO: handle the [dword] special case
                if (ModRM.HasSIB(code))
                {
                    var scaledRegisterValue = state.Registers[SIB.GetScaledRegister(code)].Value;
                    var scaler = SIB.GetScaler(code);
                    baseRegisterValue = state.Registers[SIB.GetBaseRegister(code)];
                    index             = (Int32)(scaledRegisterValue * scaler);
                }
                else
                {
                    sourceRegister = ModRM.GetEvFor(code);
                    if (ModRM.HasIndex(code))
                    {
                        index = ModRM.GetIndexFor(code);
                    }

                    baseRegisterValue = state.Registers[sourceRegister];
                }

                // TODO: review these casts of index for possible elimination
                sourceValue = new AbstractValue(
                    baseRegisterValue.PointsTo.DoOperation(
                        OperatorEffect.Add,
                        new AbstractValue((UInt32)index)
                        )
                    );

                state = state.DoOperation(destinationRegister, OperatorEffect.Assignment, sourceValue);
                if (state.Registers[destinationRegister].IsOutOfBounds)
                {
                    var reportItem = new ReportItem(state.InstructionPointer, sourceValue.IsTainted);
                    reportItems.Add(reportItem);
                }

                return(state);
            }

            case OpcodeEncoding.ObAL:
            {
                var dwordValue = state.Registers[RegisterName.EAX];
                var byteValue  = dwordValue.TruncateValueToByte();
                var offset     = BitMath.BytesToDword(code, 1);

                if (!state.DataSegment.ContainsKey(offset))
                {
                    state.DataSegment[offset] = new AbstractValue();
                }

                state = state.DoOperation(offset, op, byteValue);
                return(state);
            }

            case OpcodeEncoding.Jz:
            {
                // TODO: should push EIP + code.Length onto stack
                var contractSatisfied      = false;
                var mallocContract         = new MallocContract();
                var glibcStartMainContract = new GLibcStartMainContract();
                var contracts = new List <Contract>
                {
                    mallocContract,
                    glibcStartMainContract
                };

                foreach (var contract in contracts)
                {
                    if (contract.IsSatisfiedBy(state, code))
                    {
                        contractSatisfied = true;
                        state             = contract.Execute(state);
                    }
                }

                if (!contractSatisfied)
                {
                    var returnAddress = state.InstructionPointer + (UInt32)code.Length;
                    state = state.PushOntoStack(new AbstractValue(returnAddress));
                    state.InstructionPointer = opcode.GetEffectiveAddress(code, state.InstructionPointer);
                }

                return(state);
            }

            case OpcodeEncoding.Jb:
            {
                var offset = code[1];

                state = state.DoOperation(op, new AbstractValue(offset));
                state.InstructionPointer += opcode.GetInstructionLengthFor(code);

                return(state);
            }

            case OpcodeEncoding.None:
            {
                return(state);
            }

            default:
            {
                throw new InvalidOpcodeException(code);
            }
            }
        }
예제 #4
0
        public void OneTwoThreeFour()
        {
            var result = BitMath.BytesToDword(new Byte[] { 1, 2, 3, 4 }, 0);

            Assert.AreEqual(0x04030201, result);
        }
예제 #5
0
 public void NotEnoughBytesToDwordAtZeroIndex()
 {
     BitMath.BytesToDword(new Byte[] { 0 }, 0);
 }
예제 #6
0
 public void NotEnoughBytesToDwordAtNonZeroIndex()
 {
     BitMath.BytesToDword(new Byte[] { 0, 1, 2, 3 }, 1);
 }
예제 #7
0
 public void EmptyBytes()
 {
     BitMath.BytesToDword(new Byte[] {}, 0);
 }
예제 #8
0
        public void AllZeroes()
        {
            var result = BitMath.BytesToDword(new Byte[] { 0, 0, 0, 0 }, 0);

            Assert.AreEqual(0, result);
        }