Search in sources :

Example 31 with TranslationResult

use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.

the class SarTranslator method translate.

/**
   * Translates a SAR instruction to REIL code by first performing an unsigned division and then
   * (possibly) correcting the result afterwards.
   *
   * @param environment A valid translation environment.
   * @param instruction The SAR instruction to translate.
   * @param instructions The generated REIL code will be added to this list
   * @throws InternalTranslationException if any of the arguments are null the passed instruction is
   *         not an SAR instruction
   */
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
    TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "sar");
    Preconditions.checkArgument(instruction.getOperands().size() == 2, "Error: Argument instruction is not a sar instruction (invalid number of operands)");
    final long baseOffset = instruction.getAddress().toLong() * 0x100;
    long offset = baseOffset;
    final List<? extends IOperandTree> operands = instruction.getOperands();
    final IOperandTree targetOperand = operands.get(0);
    final IOperandTree sourceOperand = operands.get(1);
    // Load source operand.
    final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
    instructions.addAll(sourceResult.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    // Load target operand.
    final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
    instructions.addAll(targetResult.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    final OperandSize sourceSize = sourceResult.getSize();
    final OperandSize targetSize = targetResult.getSize();
    final OperandSize resultSize = TranslationHelpers.getNextSize(sourceSize);
    final String sourceRegister = sourceResult.getRegister();
    final String targetRegister = targetResult.getRegister();
    final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(sourceSize));
    final String truncateMask = String.valueOf(TranslationHelpers.getAllBitsMask(sourceSize));
    final String modValue = String.valueOf(targetSize.getBitSize());
    final String shiftMask = environment.getNextVariableString();
    final String shiftMaskZero = environment.getNextVariableString();
    final String shiftMaskLessOne = environment.getNextVariableString();
    final String shiftMaskOne = environment.getNextVariableString();
    final String shiftMaskNeg = environment.getNextVariableString();
    final String result = environment.getNextVariableString();
    final String truncatedResult = environment.getNextVariableString();
    final String msbResult = environment.getNextVariableString();
    final String isPositive = environment.getNextVariableString();
    final String divisor = environment.getNextVariableString();
    final String divisionResult = environment.getNextVariableString();
    final String negateMask = environment.getNextVariableString();
    final String twoComplementResult = environment.getNextVariableString();
    final String shiftBit = environment.getNextVariableString();
    final String shiftedBitsMask = environment.getNextVariableString();
    final String shiftedBits = environment.getNextVariableString();
    final String shiftedBitsZero = environment.getNextVariableString();
    final String shiftedBitsNonZero = environment.getNextVariableString();
    final String shiftAmountMinOne = environment.getNextVariableString();
    final String isNegative = environment.getNextVariableString();
    final String roundTowNegInf = environment.getNextVariableString();
    final String cfBitMask = environment.getNextVariableString();
    final String cfBitResult = environment.getNextVariableString();
    final String tmpCf = environment.getNextVariableString();
    // Generate the unsigned value of the shift value
    // Note: this code must not be moved further down, otherwise all the offset become invalid
    final Pair<String, String> targetRegister1Abs = Helpers.generateAbs(environment, offset, targetRegister, targetSize, instructions);
    final String targetRegister1Absolute = targetRegister1Abs.second();
    offset = baseOffset + instructions.size();
    // Since the Reil infrastructure lacks ability to establish branches between instructions
    // objects in (as opposed to raw offsets) we need this hack to correct the jump target offsets
    // The reason is that the are already some instructions in the list so, e.g., createMod(offset +
    // 1) does not actually create an instruction at offset 1 but at offset delta + 1
    final int delta = instructions.size();
    // Make sure to shift less than the size of the target register
    instructions.add(ReilHelpers.createMod(offset, sourceSize, sourceRegister, targetSize, modValue, targetSize, shiftMask));
    // Find out if the shift mask is zero or non-zero
    instructions.add(ReilHelpers.createBisz(offset + 1, targetSize, shiftMask, OperandSize.BYTE, shiftMaskZero));
    // Bail out if shift count is zero
    final String jmpEnd = String.format("%s.%s", instruction.getAddress().toLong(), delta + 39);
    instructions.add(ReilHelpers.createJcc(offset + 2, OperandSize.BYTE, shiftMaskZero, OperandSize.ADDRESS, jmpEnd));
    // AF is undefined if shift count is non-zero
    instructions.add(ReilHelpers.createUndef(offset + 3, OperandSize.BYTE, Helpers.AUXILIARY_FLAG));
    // The carry flag corresponds to the last bit shifted out of the operand
    instructions.add(ReilHelpers.createSub(offset + 4, OperandSize.BYTE, shiftMask, OperandSize.BYTE, "1", OperandSize.BYTE, shiftAmountMinOne));
    instructions.add(ReilHelpers.createBsh(offset + 5, OperandSize.BYTE, "1", OperandSize.BYTE, shiftAmountMinOne, OperandSize.BYTE, cfBitMask));
    instructions.add(ReilHelpers.createAnd(offset + 6, targetSize, targetRegister, OperandSize.BYTE, cfBitMask, OperandSize.BYTE, cfBitResult));
    instructions.add(ReilHelpers.createBisz(offset + 7, OperandSize.BYTE, cfBitResult, OperandSize.BYTE, tmpCf));
    instructions.add(ReilHelpers.createXor(offset + 8, OperandSize.BYTE, "1", OperandSize.BYTE, tmpCf, OperandSize.BYTE, Helpers.CARRY_FLAG));
    // Find out if the shift mask is 1
    instructions.add(ReilHelpers.createSub(offset + 9, targetSize, "1", targetSize, shiftMask, targetSize, shiftMaskLessOne));
    instructions.add(ReilHelpers.createBisz(offset + 10, targetSize, shiftMaskLessOne, OperandSize.BYTE, shiftMaskOne));
    // Negate the shift-mask so we can perform a right shift
    instructions.add(ReilHelpers.createSub(offset + 11, targetSize, "0", targetSize, shiftMask, targetSize, shiftMaskNeg));
    // Test if the highest bit of the input value was set; if so, we need to perform a sign
    // extension on the shift result
    instructions.add(ReilHelpers.createAnd(offset + 12, sourceSize, msbMask, targetSize, targetRegister, sourceSize, msbResult));
    instructions.add(ReilHelpers.createBisz(offset + 13, sourceSize, msbResult, OperandSize.BYTE, isPositive));
    instructions.add(ReilHelpers.createXor(offset + 14, OperandSize.BYTE, "1", OperandSize.BYTE, isPositive, OperandSize.BYTE, isNegative));
    // Create divisor based on shift amount and calculate unsigned division
    instructions.add(ReilHelpers.createBsh(offset + 15, OperandSize.DWORD, "1", OperandSize.BYTE, shiftMask, OperandSize.DWORD, divisor));
    instructions.add(ReilHelpers.createDiv(offset + 16, targetSize, targetRegister1Absolute, OperandSize.DWORD, divisor, OperandSize.DWORD, divisionResult));
    // If the MSB of the value to be shifted is set, we create a mask of 0xFFFFFFFF to convert the
    // result to two's complement
    instructions.add(ReilHelpers.createSub(offset + 17, OperandSize.BYTE, "0", OperandSize.BYTE, isNegative, OperandSize.DWORD, negateMask));
    instructions.add(ReilHelpers.createXor(offset + 18, OperandSize.DWORD, divisionResult, OperandSize.DWORD, negateMask, OperandSize.DWORD, result));
    // If the source value is positive we need to skip adding one to the result
    final String jmpSkipTwosComplement = String.format("%s.%s", instruction.getAddress().toLong(), delta + 28);
    instructions.add(ReilHelpers.createJcc(offset + 19, OperandSize.BYTE, isPositive, OperandSize.ADDRESS, jmpSkipTwosComplement));
    // Convert to two's complement by adding one to the result
    instructions.add(ReilHelpers.createAdd(offset + 20, OperandSize.DWORD, result, OperandSize.BYTE, "1", OperandSize.DWORD, twoComplementResult));
    // We need to subtract one to realize "rounding towards infinity" iff the bits shifted out are
    // not all zeros
    // First we need to mask out all the bits which are shifted out on the right side
    instructions.add(ReilHelpers.createBsh(offset + 21, OperandSize.BYTE, "1", targetSize, shiftMask, targetSize, shiftBit));
    instructions.add(ReilHelpers.createSub(offset + 22, targetSize, shiftBit, OperandSize.BYTE, "1", targetSize, shiftedBitsMask));
    instructions.add(ReilHelpers.createAnd(offset + 23, targetSize, targetRegister, targetSize, shiftedBitsMask, targetSize, shiftedBits));
    // Possibly subtract one from the result, i.e. round towards negative infinity
    instructions.add(ReilHelpers.createBisz(offset + 24, targetSize, shiftedBits, OperandSize.BYTE, shiftedBitsZero));
    instructions.add(ReilHelpers.createXor(offset + 25, OperandSize.BYTE, "1", OperandSize.BYTE, shiftedBitsZero, OperandSize.BYTE, shiftedBitsNonZero));
    instructions.add(ReilHelpers.createAnd(offset + 26, OperandSize.BYTE, isNegative, OperandSize.BYTE, shiftedBitsNonZero, OperandSize.BYTE, roundTowNegInf));
    instructions.add(ReilHelpers.createSub(offset + 27, OperandSize.DWORD, twoComplementResult, OperandSize.BYTE, roundTowNegInf, targetSize, result));
    // Truncate the result to the correct size (skip two complement conversion jump target)
    instructions.add(ReilHelpers.createAnd(offset + 28, resultSize, result, sourceSize, truncateMask, sourceSize, truncatedResult));
    // Don't change the flags if the shift value was zero
    final String jmpGoal = String.format("%s.%s", instruction.getAddress().toLong(), delta + 39);
    instructions.add(ReilHelpers.createJcc(offset + 29, OperandSize.BYTE, shiftMaskZero, OperandSize.ADDRESS, jmpGoal));
    // The SF is always 0
    instructions.add(ReilHelpers.createBisz(offset + 30, OperandSize.BYTE, isPositive, OperandSize.BYTE, Helpers.SIGN_FLAG));
    // Set the ZF
    instructions.add(ReilHelpers.createBisz(offset + 31, sourceSize, truncatedResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
    // If shift count is one, we need to zero the OF
    final String jmpDontZeroOF = String.format("%s.%s", instruction.getAddress().toLong(), delta + 34);
    instructions.add(ReilHelpers.createJcc(offset + 32, OperandSize.BYTE, shiftMaskOne, OperandSize.ADDRESS, jmpDontZeroOF));
    instructions.add(ReilHelpers.createStr(offset + 33, OperandSize.BYTE, "0", OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
    // Set the OF to undefined if the shift-mask was not zero and not one
    final String shiftCountZeroOrOne = environment.getNextVariableString();
    instructions.add(ReilHelpers.createOr(offset + 34, OperandSize.BYTE, shiftMaskOne, OperandSize.BYTE, shiftMaskZero, OperandSize.BYTE, shiftCountZeroOrOne));
    final String jmpSkipUndefOF = String.format("%s.%s", instruction.getAddress().toLong(), delta + 38);
    instructions.add(ReilHelpers.createJcc(offset + 35, OperandSize.BYTE, shiftCountZeroOrOne, OperandSize.ADDRESS, jmpSkipUndefOF));
    instructions.add(ReilHelpers.createUndef(offset + 36, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
    // always jump to writeback instruction if OF was undefined
    final String jmpGoal3 = String.format("%s.%s", instruction.getAddress().toLong(), delta + 39);
    instructions.add(ReilHelpers.createJcc(offset + 37, OperandSize.BYTE, "1", OperandSize.ADDRESS, jmpGoal3));
    // OF is always zero for the SAR instruction
    instructions.add(ReilHelpers.createStr(offset + 38, OperandSize.BYTE, "0", OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
    final int sizeBefore = instructions.size();
    Helpers.writeBack(environment, offset + 39, targetOperand, result, targetSize, targetResult.getAddress(), targetResult.getType(), instructions);
    final int sizeAfter = instructions.size();
    instructions.add(ReilHelpers.createNop((sizeAfter - sizeBefore - 1) + offset + 40));
}
Also used : IOperandTree(com.google.security.zynamics.zylib.disassembly.IOperandTree) TranslationResult(com.google.security.zynamics.reil.translators.TranslationResult) OperandSize(com.google.security.zynamics.reil.OperandSize)

Example 32 with TranslationResult

use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.

the class SbbTranslator method translate.

/**
   * Translates a SBB instruction to REIL code.
   *
   * @param environment A valid translation environment.
   * @param instruction The SBB instruction to translate.
   * @param instructions The generated REIL code will be added to this list
   *
   * @throws InternalTranslationException if any of the arguments are null the passed instruction is
   *         not an SBB instruction
   */
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
    TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "sbb");
    if (instruction.getOperands().size() != 2) {
        throw new InternalTranslationException("Error: Argument instruction is not a sbb instruction (invalid number of operand)");
    }
    final long baseOffset = instruction.getAddress().toLong() * 0x100;
    long offset = baseOffset;
    final List<? extends IOperandTree> operands = instruction.getOperands();
    final IOperandTree targetOperand = operands.get(0);
    final IOperandTree sourceOperand = operands.get(1);
    // Load source operand.
    final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
    instructions.addAll(sourceResult.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    // Load target operand.
    final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
    instructions.addAll(targetResult.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    if (sourceResult.getSize() != targetResult.getSize()) {
        throw new InternalTranslationException("Error: The operands of SBB instructions must have equal size");
    }
    final OperandSize size = sourceResult.getSize();
    final String sourceRegister = sourceResult.getRegister();
    final String targetRegister = targetResult.getRegister();
    final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(size));
    final String carryMask = String.valueOf(Helpers.getCarryMask(size));
    final String truncateMask = String.valueOf(TranslationHelpers.getAllBitsMask(size));
    final String shiftValue = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(size));
    final String shiftCarry = String.valueOf(-size.getBitSize());
    final OperandSize resultSize = TranslationHelpers.getNextSize(size);
    final String msb1 = environment.getNextVariableString();
    final String msb2 = environment.getNextVariableString();
    final String subResult = environment.getNextVariableString();
    final String subResultTemp = environment.getNextVariableString();
    final String msbResult = environment.getNextVariableString();
    final String msbSameBefore = environment.getNextVariableString();
    final String msbChanged = environment.getNextVariableString();
    final String tempOf = environment.getNextVariableString();
    final String tempCf = environment.getNextVariableString();
    final String truncatedResult = environment.getNextVariableString();
    // Isolate the MSBs of the two operands
    instructions.add(ReilHelpers.createAnd(offset, size, sourceRegister, size, msbMask, size, msb1));
    instructions.add(ReilHelpers.createAnd(offset + 1, size, targetRegister, size, msbMask, size, msb2));
    // Perform the subtraction
    instructions.add(ReilHelpers.createSub(offset + 2, size, sourceRegister, size, targetRegister, resultSize, subResultTemp));
    instructions.add(ReilHelpers.createSub(offset + 3, resultSize, subResultTemp, OperandSize.BYTE, Helpers.CARRY_FLAG, resultSize, subResult));
    // Isolate the MSB of the result and put it into the Sign Flag
    instructions.add(ReilHelpers.createAnd(offset + 4, resultSize, subResult, resultSize, msbMask, size, msbResult));
    instructions.add(ReilHelpers.createBsh(offset + 5, size, msbResult, size, shiftValue, OperandSize.BYTE, Helpers.SIGN_FLAG));
    // Find out if the MSB of the two operands were different and whether the MSB of the first
    // operand changed
    instructions.add(ReilHelpers.createXor(offset + 6, size, msb1, size, msb2, size, msbSameBefore));
    instructions.add(ReilHelpers.createXor(offset + 7, size, msb1, size, msbResult, size, msbChanged));
    instructions.add(ReilHelpers.createAnd(offset + 8, size, msbSameBefore, size, msbChanged, size, tempOf));
    // Write the result into the Overflow Flag
    instructions.add(ReilHelpers.createBsh(offset + 9, size, tempOf, size, shiftValue, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
    // Update the Carry Flag
    instructions.add(ReilHelpers.createAnd(offset + 10, resultSize, subResult, resultSize, carryMask, resultSize, tempCf));
    instructions.add(ReilHelpers.createBsh(offset + 11, resultSize, tempCf, resultSize, shiftCarry, OperandSize.BYTE, Helpers.CARRY_FLAG));
    // Truncate the result to fit into the target
    instructions.add(ReilHelpers.createAnd(offset + 12, resultSize, subResult, resultSize, truncateMask, size, truncatedResult));
    // Update the Zero Flag
    instructions.add(ReilHelpers.createBisz(offset + 13, size, truncatedResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
    // Write the result of the subtraction back to the target register
    Helpers.writeBack(environment, offset + 14, targetOperand, truncatedResult, size, targetResult.getAddress(), targetResult.getType(), instructions);
}
Also used : IOperandTree(com.google.security.zynamics.zylib.disassembly.IOperandTree) InternalTranslationException(com.google.security.zynamics.reil.translators.InternalTranslationException) TranslationResult(com.google.security.zynamics.reil.translators.TranslationResult) OperandSize(com.google.security.zynamics.reil.OperandSize)

Example 33 with TranslationResult

use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.

the class SetccTranslator method translate.

/**
   * Translates a SETcc instruction to REIL code.
   * 
   * @param environment A valid translation environment.
   * @param instruction The SETcc instruction to translate.
   * @param instructions The generated REIL code will be added to this list
   * 
   * @throws InternalTranslationException if any of the arguments are null the passed instruction is
   *         not a conditional set instruction
   */
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
    Preconditions.checkNotNull(environment, "Error: Argument environment can't be null");
    Preconditions.checkNotNull(instruction, "Error: Argument instruction can't be null");
    Preconditions.checkNotNull(instructions, "Error: Argument instructions can't be null");
    if (instruction.getOperands().size() != 1) {
        throw new InternalTranslationException("Error: Argument instruction is not a conditional setcc instruction (invalid number of operands)");
    }
    final long reilOffsetBase = instruction.getAddress().toLong() * 0x100;
    long reilOffset = reilOffsetBase;
    // SETCC instructions have exactly one operand.
    final IOperandTree operand = instruction.getOperands().get(0);
    // Load the operand.
    final TranslationResult result = Helpers.translateOperand(environment, reilOffset, operand, false);
    final OperandSize size = result.getSize();
    final TranslationResultType type = result.getType();
    final String address = result.getAddress();
    instructions.addAll(result.getInstructions());
    // Adjust the offset of the next REIL instruction.
    reilOffset = reilOffsetBase + instructions.size();
    final Pair<OperandSize, String> condition = conditionGenerator.generate(environment, reilOffset, instructions);
    reilOffset = reilOffsetBase + instructions.size();
    final String conditionRegister = condition.second();
    Helpers.writeBack(environment, reilOffset, operand, conditionRegister, size, address, type, instructions);
}
Also used : IOperandTree(com.google.security.zynamics.zylib.disassembly.IOperandTree) TranslationResultType(com.google.security.zynamics.reil.translators.TranslationResultType) InternalTranslationException(com.google.security.zynamics.reil.translators.InternalTranslationException) TranslationResult(com.google.security.zynamics.reil.translators.TranslationResult) OperandSize(com.google.security.zynamics.reil.OperandSize)

Example 34 with TranslationResult

use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.

the class CmpxchgTranslator method translate.

/**
   * Translates a CMPXCHG instruction to REIL code.
   *
   * @param environment A valid translation environment.
   * @param instruction The CMPXCHG instruction to translate.
   * @param instructions The generated REIL code will be added to this list
   *
   * @throws InternalTranslationException if any of the arguments are null the passed instruction is
   *         not a CMPXCHG instruction
   *
   */
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
    TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "cmpxchg");
    Preconditions.checkArgument(instruction.getOperands().size() == 2, "Error: Argument instruction is not a cmp instruction (invalid number of operands)");
    final long baseOffset = instruction.getAddress().toLong() * 0x100;
    long offset = baseOffset;
    final List<? extends IOperandTree> operands = instruction.getOperands();
    final IOperandTree targetOperand = operands.get(0);
    final IOperandTree sourceOperand = operands.get(1);
    // Load first operand.
    final TranslationResult targetResult = Helpers.translateOperand(environment, offset, targetOperand, true);
    instructions.addAll(targetResult.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    // Load second operand.
    final TranslationResult sourceResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
    instructions.addAll(sourceResult.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    // Compare the first operand to AL/AX/EAX
    String xaxRegister;
    switch(targetResult.getSize()) {
        case BYTE:
            xaxRegister = "al";
            break;
        case WORD:
            xaxRegister = "ax";
            break;
        case DWORD:
            xaxRegister = "eax";
            break;
        default:
            throw new InternalTranslationException("Error: The first operand has to be BYTE/WORD/DWORD !");
    }
    String comparisonResult = environment.getNextVariableString();
    OperandSize currentSize = targetResult.getSize();
    // Subtract the first operand from AL/AX/EAX
    instructions.add(ReilHelpers.createSub(baseOffset + instructions.size(), currentSize, xaxRegister, currentSize, targetResult.getRegister(), currentSize, comparisonResult));
    // Set the ZF if the two values were equal
    instructions.add(ReilHelpers.createBisz(baseOffset + instructions.size(), currentSize, comparisonResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
    // The control flow is as follows:
    // Jump to secondWriteBack if not equal
    // firstWriteBack
    // Jump to terminatingNop (avoid falling through from the first case)
    // secondWriteBack
    // terminatingNop
    // firstWriteBack: if the content of AL/AX/EAX is equal to the source operand,
    // move sourceOperand to targetOperand.
    final List<ReilInstruction> firstWriteBack = new ArrayList<ReilInstruction>();
    Helpers.writeBack(environment, // reserve space for the first JCC
    baseOffset + instructions.size() + 1, targetOperand, sourceResult.getRegister(), sourceResult.getSize(), targetResult.getAddress(), targetResult.getType(), firstWriteBack);
    // Jump to secondWriteBack if not equal.
    // Reserve space for the two JCC and firstWriteBack when calculating target address.
    final long secondWriteBackOffset = instructions.size() + firstWriteBack.size() + 3;
    final String secondWriteBackGoal = String.format("%d.%d", instruction.getAddress().toLong(), secondWriteBackOffset);
    instructions.add(ReilHelpers.createJcc(baseOffset + instructions.size(), currentSize, comparisonResult, OperandSize.ADDRESS, secondWriteBackGoal));
    // Add the mov code that's executed if the condition is true.
    instructions.addAll(firstWriteBack);
    // Create an operand representing the AL/AX/EAX register so that we can write back to it.
    ReilOperandNode xAXOperandRoot = new ReilOperandNode(currentSize.toSizeString(), ExpressionType.SIZE_PREFIX);
    ReilOperandNode xAXOperandLeaf = new ReilOperandNode(xaxRegister, ExpressionType.REGISTER);
    ReilOperandNode.link(xAXOperandRoot, xAXOperandLeaf);
    ReilOperand xAXOperand = new ReilOperand(xAXOperandRoot);
    // secondWriteBack: if the content of AL/AX/EAX is not equal to the source operand,
    // move targetOperand to AL/AX/EAX.
    final List<ReilInstruction> secondWriteBack = new ArrayList<ReilInstruction>();
    Helpers.writeBack(environment, // reserve space for the second JCC
    baseOffset + instructions.size() + 1, xAXOperand, targetResult.getRegister(), currentSize, null, /* Memory address of the writeBack target. Empty since target is a register. */
    TranslationResultType.REGISTER, secondWriteBack);
    // Jump to terminatingNop (avoid falling through from firstWriteBack).
    // Reserve addresses for JCC and for secondWriteBack when calculating target address.
    final long terminatingNopOffset = instructions.size() + secondWriteBack.size() + 2;
    final String terminatingNopGoal = String.format("%d.%d", instruction.getAddress().toLong(), terminatingNopOffset);
    instructions.add(ReilHelpers.createJcc(baseOffset + instructions.size(), OperandSize.BYTE, "1", OperandSize.ADDRESS, terminatingNopGoal));
    // Add the mov code that's executed if the condition is true.
    instructions.addAll(secondWriteBack);
    // Add a terminating NOP, this makes it easier to get a target for the conditional jump.
    instructions.add(ReilHelpers.createNop(baseOffset + instructions.size()));
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) IOperandTree(com.google.security.zynamics.zylib.disassembly.IOperandTree) ArrayList(java.util.ArrayList) ReilOperand(com.google.security.zynamics.reil.ReilOperand) InternalTranslationException(com.google.security.zynamics.reil.translators.InternalTranslationException) TranslationResult(com.google.security.zynamics.reil.translators.TranslationResult) OperandSize(com.google.security.zynamics.reil.OperandSize) ReilOperandNode(com.google.security.zynamics.reil.ReilOperandNode)

Example 35 with TranslationResult

use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.

the class DecTranslator method translate.

/**
   * Translates an DEC instruction to REIL code.
   * 
   * @param environment A valid translation environment
   * @param instruction The DEC instruction to translate
   * @param instructions The generated REIL code will be added to this list
   * 
   * @throws InternalTranslationException if any of the arguments are null the passed instruction is
   *         not an DEC instruction
   */
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
    TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "dec");
    if (instruction.getOperands().size() != 1) {
        throw new InternalTranslationException("Error: Argument instruction is not an dec instruction (invalid number of operand)");
    }
    final long baseOffset = instruction.getAddress().toLong() * 0x100;
    long offset = baseOffset;
    // DEC instructions have exactly one operand.
    final IOperandTree operand = instruction.getOperands().get(0);
    // Load the operand.
    final TranslationResult result = Helpers.translateOperand(environment, offset, operand, true);
    instructions.addAll(result.getInstructions());
    // Adjust the offset of the next REIL instruction.
    offset = baseOffset + instructions.size();
    final String loadedRegister = result.getRegister();
    final OperandSize registerSize = result.getSize();
    final OperandSize nextSize = TranslationHelpers.getNextSize(registerSize);
    final String msbMask = String.valueOf(TranslationHelpers.getMsbMask(registerSize));
    final String shiftMsbLsbMask = String.valueOf(TranslationHelpers.getShiftMsbLsbMask(registerSize));
    final String truncMask = String.valueOf(TranslationHelpers.getAllBitsMask(registerSize));
    final String maskedMsb = environment.getNextVariableString();
    final String decResult = environment.getNextVariableString();
    final String maskedMsbResult = environment.getNextVariableString();
    final String maskedMsbNeg = environment.getNextVariableString();
    final String tempOF = environment.getNextVariableString();
    final String truncatedResult = environment.getNextVariableString();
    // Isolate the MSB of the operand
    instructions.add(ReilHelpers.createAnd(offset, registerSize, loadedRegister, registerSize, msbMask, registerSize, maskedMsb));
    // Decrement the value
    instructions.add(ReilHelpers.createSub(offset + 1, registerSize, loadedRegister, registerSize, "1", nextSize, decResult));
    // Isolate the MSB of the result and put it into the Sign Flag
    instructions.add(ReilHelpers.createAnd(offset + 2, nextSize, decResult, registerSize, msbMask, registerSize, maskedMsbResult));
    instructions.add(ReilHelpers.createBsh(offset + 3, registerSize, maskedMsbResult, registerSize, shiftMsbLsbMask, OperandSize.BYTE, Helpers.SIGN_FLAG));
    // The OF is only set if the result of the dec operation is 0x7F
    // OF = ( MSB(old) == 1 ) AND ( MSB(new) == 0 )
    // OF = MSB(old) AND NOT(MSB(new))
    instructions.add(ReilHelpers.createXor(offset + 4, registerSize, maskedMsbResult, registerSize, msbMask, registerSize, maskedMsbNeg));
    instructions.add(ReilHelpers.createAnd(offset + 5, registerSize, maskedMsb, registerSize, maskedMsbNeg, registerSize, tempOF));
    // Write the result into the Overflow Flag
    instructions.add(ReilHelpers.createBsh(offset + 6, registerSize, tempOF, registerSize, shiftMsbLsbMask, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
    // Truncate the result to fit into the target
    instructions.add(ReilHelpers.createAnd(offset + 7, nextSize, decResult, registerSize, truncMask, registerSize, truncatedResult));
    // Update the Zero Flag
    instructions.add(ReilHelpers.createBisz(offset + 8, registerSize, truncatedResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
    // Write the truncated result back into the operand
    Helpers.writeBack(environment, offset + 9, operand, truncatedResult, registerSize, result.getAddress(), result.getType(), instructions);
}
Also used : IOperandTree(com.google.security.zynamics.zylib.disassembly.IOperandTree) InternalTranslationException(com.google.security.zynamics.reil.translators.InternalTranslationException) TranslationResult(com.google.security.zynamics.reil.translators.TranslationResult) OperandSize(com.google.security.zynamics.reil.OperandSize)

Aggregations

TranslationResult (com.google.security.zynamics.reil.translators.TranslationResult)55 OperandSize (com.google.security.zynamics.reil.OperandSize)45 InternalTranslationException (com.google.security.zynamics.reil.translators.InternalTranslationException)42 IOperandTree (com.google.security.zynamics.zylib.disassembly.IOperandTree)39 ReilInstruction (com.google.security.zynamics.reil.ReilInstruction)9 ArrayList (java.util.ArrayList)9 TranslationResultType (com.google.security.zynamics.reil.translators.TranslationResultType)3 OperandType (com.google.security.zynamics.reil.OperandType)2 ReilOperand (com.google.security.zynamics.reil.ReilOperand)1 ReilOperandNode (com.google.security.zynamics.reil.ReilOperandNode)1 IOperandTreeNode (com.google.security.zynamics.zylib.disassembly.IOperandTreeNode)1