Search in sources :

Example 81 with ReilInstruction

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

the class Helpers method signedSat.

/**
   * @param offset
   * @param environment
   * @param instruction
   * @param instructions
   * @param firstOperand
   * @param secondOperand
   * @param resultOperand
   * @param operation
   * @param tmpResultVar
   * @param size
   * @param signedDoesSat
   */
public static void signedSat(final long offset, final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> oldInstructions, final OperandSize firstOperandSize, final String firstOperand, final OperandSize secondOperandSize, final String secondOperand, final OperandSize resultOperandSize, final String resultOperand, final String operation, final String tmpResultVar, final long size, final String signedDoesSat) {
    final OperandSize bt = OperandSize.BYTE;
    final OperandSize dw = OperandSize.DWORD;
    final String signedSatMaskLess = posBitMask(size - 1);
    final String lowSatResult = highestNegativeValue(size - 1);
    final String highSatResult = signedSatMaskLess;
    final String inRange = environment.getNextVariableString();
    final String inRangeMask = environment.getNextVariableString();
    final String isGreaterCondition = environment.getNextVariableString();
    final String isGreaterMask = environment.getNextVariableString();
    final String isLessCondition = environment.getNextVariableString();
    final String isLessMask = environment.getNextVariableString();
    final String tmpLowResult1 = environment.getNextVariableString();
    final String tmpLowResult2 = environment.getNextVariableString();
    final String tmpLowResult3 = environment.getNextVariableString();
    final String tmpLowResult4 = environment.getNextVariableString();
    final String tmpVar1 = environment.getNextVariableString();
    final String overflow = environment.getNextVariableString();
    final String isNegative = environment.getNextVariableString();
    final String isPositive = environment.getNextVariableString();
    long baseOffset = offset;
    final List<ReilInstruction> instructions = new ArrayList<ReilInstruction>();
    final String addOperation = "ADD";
    if ((operation.equalsIgnoreCase(addOperation)) || (operation.equalsIgnoreCase("SUB"))) {
        if (operation.equalsIgnoreCase(addOperation)) {
            addOverflow(baseOffset, environment, instructions, firstOperandSize, firstOperand, secondOperandSize, secondOperand, resultOperandSize, resultOperand, overflow, size);
        } else if (operation.equalsIgnoreCase("SUB")) {
            subOverflow(baseOffset, environment, instruction, instructions, firstOperandSize, firstOperand, secondOperandSize, secondOperand, resultOperandSize, resultOperand, overflow, size);
        }
        baseOffset = baseOffset + instructions.size();
        // extract the sign of the result to see which way to overflow
        instructions.add(ReilHelpers.createBsh(baseOffset++, dw, resultOperand, dw, "-" + String.valueOf(size - 1), bt, tmpVar1));
        instructions.add(ReilHelpers.createAnd(baseOffset++, bt, tmpVar1, bt, String.valueOf(1L), bt, isNegative));
        instructions.add(ReilHelpers.createBisz(baseOffset++, bt, isNegative, bt, isPositive));
        // combine the results to get the true answer
        instructions.add(ReilHelpers.createAnd(baseOffset++, bt, isPositive, bt, overflow, bt, isLessCondition));
        instructions.add(ReilHelpers.createAnd(baseOffset++, bt, isNegative, bt, overflow, bt, isGreaterCondition));
        instructions.add(ReilHelpers.createBisz(baseOffset++, bt, overflow, bt, inRange));
        // create low half masks
        instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, isLessCondition, dw, isLessMask));
        instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, isGreaterCondition, dw, isGreaterMask));
        instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, inRange, dw, inRangeMask));
        // return the result
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, resultOperand, dw, inRangeMask, dw, tmpLowResult1));
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, lowSatResult, dw, isLessMask, dw, tmpLowResult2));
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, highSatResult, dw, isGreaterMask, dw, tmpLowResult3));
        instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpLowResult1, dw, tmpLowResult2, dw, tmpLowResult4));
        instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpLowResult4, dw, tmpLowResult3, dw, tmpResultVar));
    } else /* sat without computation SSAT16 */
    {
        final String needsShiftCompare = environment.getNextVariableString();
        final String xMinusy = environment.getNextVariableString();
        final String xMinusyXorx = environment.getNextVariableString();
        final String xXory = environment.getNextVariableString();
        final String xXoryAndxMinusXorx = environment.getNextVariableString();
        final String lowOverflow = environment.getNextVariableString();
        final String highOverflow = environment.getNextVariableString();
        /*
       * -2(n-1) if X is < -2(n-1) X if -2(n-1) <= X <= 2(n-1) - 1 2(n-1) - 1 if X > 2(n-1) - 1
       */
        // ( x - y ) XOR [(x XOR y) AND ((x - y) XOR x)]
        // low overflow
        instructions.add(ReilHelpers.createSub(baseOffset++, dw, firstOperand, dw, lowSatResult, dw, xMinusy));
        instructions.add(ReilHelpers.createXor(baseOffset++, dw, firstOperand, dw, lowSatResult, dw, xXory));
        instructions.add(ReilHelpers.createXor(baseOffset++, dw, xMinusy, dw, firstOperand, dw, xMinusyXorx));
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, xXory, dw, xMinusyXorx, dw, xXoryAndxMinusXorx));
        instructions.add(ReilHelpers.createXor(baseOffset++, dw, xMinusy, dw, xXoryAndxMinusXorx, dw, needsShiftCompare));
        instructions.add(ReilHelpers.createBsh(baseOffset++, dw, needsShiftCompare, dw, String.valueOf(-31L), bt, lowOverflow));
        // high overflow
        instructions.add(ReilHelpers.createSub(baseOffset++, dw, highSatResult, dw, firstOperand, dw, xMinusy));
        instructions.add(ReilHelpers.createXor(baseOffset++, dw, highSatResult, dw, firstOperand, dw, xXory));
        instructions.add(ReilHelpers.createXor(baseOffset++, dw, xMinusy, dw, highSatResult, dw, xMinusyXorx));
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, xXory, dw, xMinusyXorx, dw, xXoryAndxMinusXorx));
        instructions.add(ReilHelpers.createXor(baseOffset++, dw, xMinusy, dw, xXoryAndxMinusXorx, dw, needsShiftCompare));
        instructions.add(ReilHelpers.createBsh(baseOffset++, dw, needsShiftCompare, dw, String.valueOf(-31L), bt, highOverflow));
        instructions.add(ReilHelpers.createOr(baseOffset++, bt, lowOverflow, bt, highOverflow, bt, overflow));
        instructions.add(ReilHelpers.createBisz(baseOffset++, bt, overflow, bt, inRange));
        if (operation.equalsIgnoreCase("SSAT")) {
            // create low half masks
            instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, lowOverflow, dw, isLessMask));
            instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, highOverflow, dw, isGreaterMask));
            instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, inRange, dw, inRangeMask));
        } else {
            // create low half masks
            instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, highOverflow, dw, isLessMask));
            instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, lowOverflow, dw, isGreaterMask));
            instructions.add(ReilHelpers.createSub(baseOffset++, dw, String.valueOf(0), bt, inRange, dw, inRangeMask));
        }
        // return the result
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, resultOperand, dw, inRangeMask, dw, tmpLowResult1));
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, lowSatResult, dw, isLessMask, dw, tmpLowResult2));
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, highSatResult, dw, isGreaterMask, dw, tmpLowResult3));
        instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpLowResult1, dw, tmpLowResult2, dw, tmpLowResult4));
        instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpLowResult4, dw, tmpLowResult3, dw, tmpResultVar));
    }
    oldInstructions.addAll(instructions);
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ArrayList(java.util.ArrayList) OperandSize(com.google.security.zynamics.reil.OperandSize)

Example 82 with ReilInstruction

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

the class RepeTranslator method translate.

@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
    final long baseOffset = ReilHelpers.toReilAddress(instruction.getAddress()).toLong();
    final long offset = baseOffset;
    final OperandSize archSize = environment.getArchitectureSize();
    final String invertedEcx = environment.getNextVariableString();
    final List<ReilInstruction> innerInstructions = new ArrayList<ReilInstruction>();
    translator.generate(environment, ReilHelpers.toReilAddress(instruction.getAddress()).toLong() + 2, operandSize, innerInstructions);
    final String firstInstruction = String.format("%d.0", instruction.getAddress().toLong());
    final String jmpGoal = String.format("%d.%d", instruction.getAddress().toLong(), innerInstructions.size() + 6);
    instructions.add(ReilHelpers.createBisz(offset, archSize, "ecx", OperandSize.BYTE, invertedEcx));
    instructions.add(ReilHelpers.createJcc(offset + 1, OperandSize.BYTE, invertedEcx, OperandSize.ADDRESS, jmpGoal));
    instructions.addAll(innerInstructions);
    final String decrementedEcx = environment.getNextVariableString();
    final String truncateMask = String.valueOf(TranslationHelpers.getAllBitsMask(OperandSize.DWORD));
    instructions.add(ReilHelpers.createSub(baseOffset + instructions.size(), OperandSize.DWORD, "ecx", OperandSize.DWORD, "1", OperandSize.QWORD, decrementedEcx));
    instructions.add(ReilHelpers.createAnd(baseOffset + instructions.size(), OperandSize.QWORD, decrementedEcx, OperandSize.DWORD, truncateMask, OperandSize.DWORD, "ecx"));
    instructions.add(ReilHelpers.createJcc(baseOffset + instructions.size(), OperandSize.DWORD, "ZF", OperandSize.ADDRESS, firstInstruction));
    instructions.add(ReilHelpers.createNop(baseOffset + instructions.size()));
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ArrayList(java.util.ArrayList) OperandSize(com.google.security.zynamics.reil.OperandSize)

Example 83 with ReilInstruction

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

the class CmovccTranslator method translate.

/**
   * Translates a Cmovcc instruction to REIL code.
   * 
   * @param environment A valid translation environment.
   * @param instruction The Cmovcc instruction to translate.
   * @param instructions The generated REIL code will be added to this list
   * 
   * @throws InternalTranslationException Thrown if any of the arguments are null or if the
   *         instruction is not a valid conditional move 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");
    Preconditions.checkArgument(instruction.getOperands().size() == 2, "Error: Argument instruction is not a conditional move instruction (invalid number of operands)");
    final long baseOffset = instruction.getAddress().toLong() * 0x100;
    long offset = baseOffset;
    // Generate the condition code
    final Pair<OperandSize, String> conditionResult = conditionGenerator.generate(environment, offset, instructions);
    final OperandSize conditionRegisterSize = conditionResult.first();
    final String conditionRegister = conditionResult.second();
    // Adjust the offset of the next REIL instruction
    offset = baseOffset + instructions.size();
    // Flip the condition
    final String flippedCondition = environment.getNextVariableString();
    instructions.add(ReilHelpers.createBisz(offset, conditionRegisterSize, conditionRegister, OperandSize.BYTE, flippedCondition));
    // Generate the mov code (offset + 2 is correct; the code is placed behind the next JCC)
    final ArrayList<ReilInstruction> movCode = new ArrayList<ReilInstruction>();
    Helpers.generateMov(environment, offset + 2, instruction, movCode);
    // ESCA-JAVA0264: We will not get an overflow here
    final long lastOffset = instructions.size() + movCode.size() + 1;
    // Jump to the end of the block if the condition is not met
    final String jmpGoal = String.format("%d.%d", instruction.getAddress().toLong(), lastOffset);
    instructions.add(ReilHelpers.createJcc(offset + 1, OperandSize.BYTE, flippedCondition, OperandSize.ADDRESS, jmpGoal));
    // Add the mov code that's executed if the condition is true
    instructions.addAll(movCode);
    // Adjust the offset of the next REIL instruction
    offset = baseOffset + instructions.size();
    // Add a terminating NOP, this makes it easier to get a target for the conditional jump
    instructions.add(ReilHelpers.createNop(offset));
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ArrayList(java.util.ArrayList) OperandSize(com.google.security.zynamics.reil.OperandSize)

Example 84 with ReilInstruction

use of com.google.security.zynamics.reil.ReilInstruction 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 85 with ReilInstruction

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

the class Helpers method extractRegister.

/**
   * Extracts a subregister (like AX, AL, AH) from a parent register (like EAX)
   *
   * @param environment A valid translation environment
   * @param offset The next unused REIL offset where the new REIL code can be placed
   * @param subRegister The subregister that should be extracted
   *
   * @return The result of the translation
   *
   * @throws InternalTranslationException Thrown if an internal problem occurs
   */
private static TranslationResult extractRegister(final ITranslationEnvironment environment, final long offset, final String subRegister) throws InternalTranslationException {
    final ArrayList<ReilInstruction> instructions = new ArrayList<ReilInstruction>();
    final String parentRegister = getParentRegister(subRegister);
    final OperandSize archSize = environment.getArchitectureSize();
    if (isHigher8BitRegister(subRegister)) {
        // The sub-register is not at the low end of the parent
        // register. Mask + shift is necessary here.
        final String maskResult = environment.getNextVariableString();
        final String shiftResult = environment.getNextVariableString();
        // Add the mask + shift instructions
        instructions.add(ReilHelpers.createAnd(offset, archSize, parentRegister, OperandSize.WORD, "65280", OperandSize.WORD, maskResult));
        instructions.add(ReilHelpers.createBsh(offset + 1, OperandSize.WORD, maskResult, OperandSize.WORD, "-8", OperandSize.BYTE, shiftResult));
        return new TranslationResult(shiftResult, OperandSize.BYTE, TranslationResultType.REGISTER, null, instructions, offset);
    } else {
        // The sub-register is already at the low end of the parent register.
        // Masking is enough.
        final OperandSize subRegisterSize = getRegisterSize(subRegister);
        final String mask = String.valueOf(TranslationHelpers.getAllBitsMask(subRegisterSize));
        final String result = environment.getNextVariableString();
        // Add the mask instruction
        instructions.add(ReilHelpers.createAnd(offset, archSize, parentRegister, subRegisterSize, mask, subRegisterSize, result));
        return new TranslationResult(result, subRegisterSize, TranslationResultType.REGISTER, null, instructions, offset);
    }
}
Also used : ReilInstruction(com.google.security.zynamics.reil.ReilInstruction) ArrayList(java.util.ArrayList) TranslationResult(com.google.security.zynamics.reil.translators.TranslationResult) OperandSize(com.google.security.zynamics.reil.OperandSize)

Aggregations

ReilInstruction (com.google.security.zynamics.reil.ReilInstruction)144 Test (org.junit.Test)102 TreeSet (java.util.TreeSet)73 ArrayList (java.util.ArrayList)35 IInstruction (com.google.security.zynamics.zylib.disassembly.IInstruction)18 OperandSize (com.google.security.zynamics.reil.OperandSize)16 ReilBlock (com.google.security.zynamics.reil.ReilBlock)16 MockInstruction (com.google.security.zynamics.zylib.disassembly.MockInstruction)16 MockOperandTree (com.google.security.zynamics.zylib.disassembly.MockOperandTree)16 MockOperandTreeNode (com.google.security.zynamics.zylib.disassembly.MockOperandTreeNode)16 ReilEdge (com.google.security.zynamics.reil.ReilEdge)12 HashMap (java.util.HashMap)12 TranslationResult (com.google.security.zynamics.reil.translators.TranslationResult)9 IAddress (com.google.security.zynamics.zylib.disassembly.IAddress)7 List (java.util.List)7 ReilGraph (com.google.security.zynamics.reil.ReilGraph)6 InternalTranslationException (com.google.security.zynamics.reil.translators.InternalTranslationException)6 BigInteger (java.math.BigInteger)6 INaviInstruction (com.google.security.zynamics.binnavi.disassembly.INaviInstruction)5 ValueTrackerElement (com.google.security.zynamics.reil.algorithms.mono.valuetracking.ValueTrackerElement)5