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