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()));
}
}
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()));
}
Aggregations