Search in sources :

Example 1 with ReilOperandNode

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

the class StoreGenerator method generate.

public static void generate(long baseOffset, final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions, final String mnemonic, final OperandSize opSize, final boolean isIndexed, final boolean withUpdate, final boolean storeMultiple, final boolean isByteReverse) throws InternalTranslationException {
    TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, mnemonic);
    final IOperandTreeNode sourceRegister = instruction.getOperands().get(0).getRootNode().getChildren().get(0);
    // there is a case where we only have 1 operand in the export due to the fact that we do not get
    // an
    // offset this case must be taken care of.
    IOperandTreeNode sourceRegisterOperand1 = null;
    IOperandTreeNode sourceRegisterOperand2 = null;
    if ((instruction.getOperands().size() == 2) && !(instruction.getOperands().get(1).getRootNode().getChildren().get(0).getChildren().get(0).getChildren().size() == 2)) {
        sourceRegisterOperand1 = new ReilOperandNode("0", ExpressionType.IMMEDIATE_INTEGER);
        sourceRegisterOperand2 = instruction.getOperands().get(1).getRootNode().getChildren().get(0);
    } else {
        sourceRegisterOperand1 = isIndexed ? instruction.getOperands().get(1).getRootNode().getChildren().get(0) : instruction.getOperands().get(1).getRootNode().getChildren().get(0).getChildren().get(0).getChildren().get(0);
        sourceRegisterOperand2 = isIndexed ? instruction.getOperands().get(2).getRootNode().getChildren().get(0) : instruction.getOperands().get(1).getRootNode().getChildren().get(0).getChildren().get(0).getChildren().get(1);
    }
    // TODO: check if the condition sourceRegisterOperand == "0" is handled in the applicable cases.
    final OperandSize bt = OperandSize.BYTE;
    final OperandSize wd = OperandSize.WORD;
    final OperandSize dw = OperandSize.DWORD;
    final OperandSize qw = OperandSize.QWORD;
    final String effectiveAddress = environment.getNextVariableString();
    final String tmpEffectiveAddress = environment.getNextVariableString();
    final String tmpData = environment.getNextVariableString();
    instructions.add(ReilHelpers.createAdd(baseOffset++, dw, sourceRegisterOperand1.getValue(), dw, sourceRegisterOperand2.getValue(), qw, tmpEffectiveAddress));
    instructions.add(ReilHelpers.createAnd(baseOffset++, qw, tmpEffectiveAddress, dw, String.valueOf(0xFFFFFFFFL), dw, effectiveAddress));
    // resize it to match with instruction
    if (opSize == bt) {
        instructions.add(ReilHelpers.createAnd(baseOffset++, dw, sourceRegister.getValue(), dw, String.valueOf(0x000000FFL), bt, tmpData));
        instructions.add(ReilHelpers.createStm(baseOffset++, bt, tmpData, dw, effectiveAddress));
    } else if (opSize == wd) {
        if (isByteReverse) {
            final String tmpHighByte = environment.getNextVariableString();
            final String tmpLowByte = environment.getNextVariableString();
            final String tmpHighByteShifted = environment.getNextVariableString();
            final String tmpLowByteShifted = environment.getNextVariableString();
            instructions.add(ReilHelpers.createAnd(baseOffset++, wd, sourceRegister.getValue(), dw, String.valueOf(0x000000FFL), dw, tmpLowByte));
            instructions.add(ReilHelpers.createAnd(baseOffset++, wd, sourceRegister.getValue(), dw, String.valueOf(0x0000FF00L), dw, tmpHighByte));
            instructions.add(ReilHelpers.createBsh(baseOffset++, dw, tmpLowByte, bt, String.valueOf(8L), dw, tmpLowByteShifted));
            instructions.add(ReilHelpers.createBsh(baseOffset++, dw, tmpHighByte, bt, String.valueOf(-8L), dw, tmpHighByteShifted));
            instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpHighByteShifted, dw, tmpLowByteShifted, dw, tmpData));
        } else {
            instructions.add(ReilHelpers.createAnd(baseOffset++, dw, sourceRegister.getValue(), dw, String.valueOf(0x0000FFFFL), wd, tmpData));
        }
        instructions.add(ReilHelpers.createStm(baseOffset++, wd, tmpData, dw, effectiveAddress));
    } else if (opSize == dw) {
        if (!isByteReverse && !storeMultiple) {
            instructions.add(ReilHelpers.createAnd(baseOffset++, dw, sourceRegister.getValue(), dw, String.valueOf(0xFFFFFFFFL), dw, tmpData));
            instructions.add(ReilHelpers.createStm(baseOffset++, dw, tmpData, dw, effectiveAddress));
        } else if (storeMultiple && !isByteReverse) {
            int index = Helpers.getRegisterIndex(sourceRegister.getValue());
            while (index <= 31) {
                instructions.add(ReilHelpers.createStm(baseOffset++, dw, "%r" + index, dw, effectiveAddress));
                instructions.add(ReilHelpers.createAdd(baseOffset++, dw, effectiveAddress, bt, String.valueOf(4L), dw, effectiveAddress));
                index++;
            }
        } else if (!storeMultiple && isByteReverse) {
            final String tmpByte1 = environment.getNextVariableString();
            final String tmpByte2 = environment.getNextVariableString();
            final String tmpByte3 = environment.getNextVariableString();
            final String tmpByte4 = environment.getNextVariableString();
            final String tmpByte1Shifted = environment.getNextVariableString();
            final String tmpByte2Shifted = environment.getNextVariableString();
            final String tmpByte3Shifted = environment.getNextVariableString();
            final String tmpByte4Shifted = environment.getNextVariableString();
            final String tmpTargetValue1 = environment.getNextVariableString();
            final String tmpTargetValue2 = environment.getNextVariableString();
            // extract bytes
            instructions.add(ReilHelpers.createAnd(baseOffset++, wd, sourceRegister.getValue(), dw, String.valueOf(0x000000FFL), dw, tmpByte1));
            instructions.add(ReilHelpers.createAnd(baseOffset++, wd, sourceRegister.getValue(), dw, String.valueOf(0x0000FF00L), dw, tmpByte2));
            instructions.add(ReilHelpers.createAnd(baseOffset++, wd, sourceRegister.getValue(), dw, String.valueOf(0x00FF0000L), dw, tmpByte3));
            instructions.add(ReilHelpers.createAnd(baseOffset++, wd, sourceRegister.getValue(), dw, String.valueOf(0xFF000000L), dw, tmpByte4));
            // shift bytes
            instructions.add(ReilHelpers.createBsh(baseOffset++, dw, tmpByte1, bt, String.valueOf(24L), dw, tmpByte1Shifted));
            instructions.add(ReilHelpers.createBsh(baseOffset++, dw, tmpByte2, bt, String.valueOf(8L), dw, tmpByte2Shifted));
            instructions.add(ReilHelpers.createBsh(baseOffset++, dw, tmpByte3, bt, String.valueOf(-8L), dw, tmpByte3Shifted));
            instructions.add(ReilHelpers.createBsh(baseOffset++, dw, tmpByte4, bt, String.valueOf(-24L), dw, tmpByte4Shifted));
            // compose register store statement
            instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpByte1Shifted, dw, tmpByte2Shifted, dw, tmpTargetValue1));
            instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpByte3Shifted, dw, tmpByte4Shifted, dw, tmpTargetValue2));
            instructions.add(ReilHelpers.createOr(baseOffset++, dw, tmpTargetValue1, dw, tmpTargetValue2, dw, tmpData));
            instructions.add(ReilHelpers.createStm(baseOffset++, dw, tmpData, dw, effectiveAddress));
        }
    }
    if (withUpdate) {
        // Update the register specified in the instruction with the effective address
        instructions.add(ReilHelpers.createStr(baseOffset++, dw, effectiveAddress, dw, sourceRegisterOperand1.getValue()));
    }
}
Also used : IOperandTreeNode(com.google.security.zynamics.zylib.disassembly.IOperandTreeNode) OperandSize(com.google.security.zynamics.reil.OperandSize) ReilOperandNode(com.google.security.zynamics.reil.ReilOperandNode)

Example 2 with ReilOperandNode

use of com.google.security.zynamics.reil.ReilOperandNode 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)

Aggregations

OperandSize (com.google.security.zynamics.reil.OperandSize)2 ReilOperandNode (com.google.security.zynamics.reil.ReilOperandNode)2 ReilInstruction (com.google.security.zynamics.reil.ReilInstruction)1 ReilOperand (com.google.security.zynamics.reil.ReilOperand)1 InternalTranslationException (com.google.security.zynamics.reil.translators.InternalTranslationException)1 TranslationResult (com.google.security.zynamics.reil.translators.TranslationResult)1 IOperandTree (com.google.security.zynamics.zylib.disassembly.IOperandTree)1 IOperandTreeNode (com.google.security.zynamics.zylib.disassembly.IOperandTreeNode)1 ArrayList (java.util.ArrayList)1