use of com.google.security.zynamics.zylib.disassembly.IOperandTree 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);
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree 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.zylib.disassembly.IOperandTree 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);
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class DivTranslator method translate.
/**
* Translates a DIV instruction to REIL code.
*
* @param environment A valid translation environment
* @param instruction The DIV 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 DIV instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "div");
if (instruction.getOperands().size() != 1) {
throw new InternalTranslationException("Error: Argument instruction is not a div instruction (invalid number of operands)");
}
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree divisorOperand = operands.get(0);
final OperandSize size = Helpers.getOperandSize(divisorOperand);
// Load the dividend
final TranslationResult resultDividend = Helpers.loadFirstDivOperand(environment, offset, size);
instructions.addAll(resultDividend.getInstructions());
// Adjust the offset of the next REIL instruction
offset = baseOffset + instructions.size();
final String dividend = resultDividend.getRegister();
// Load the divisor
final TranslationResult resultDivisor = Helpers.translateOperand(environment, offset, divisorOperand, true);
instructions.addAll(resultDivisor.getInstructions());
// Adjust the offset of the next REIL instruction
offset = baseOffset + instructions.size();
final String divisor = resultDivisor.getRegister();
final String divResult = environment.getNextVariableString();
final String modResult = environment.getNextVariableString();
// Perform divison and modulo operation
instructions.add(ReilHelpers.createDiv(offset++, size, dividend, size, divisor, size, divResult));
instructions.add(ReilHelpers.createMod(offset++, size, dividend, size, divisor, size, modResult));
// Write the result back and set the flags
instructions.addAll(Helpers.writeDivResult(environment, offset++, divResult, modResult, size));
offset = baseOffset + instructions.size();
// Undefine flags
instructions.add(ReilHelpers.createUndef(offset++, OperandSize.BYTE, Helpers.AUXILIARY_FLAG));
instructions.add(ReilHelpers.createUndef(offset++, OperandSize.BYTE, Helpers.CARRY_FLAG));
instructions.add(ReilHelpers.createUndef(offset++, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
instructions.add(ReilHelpers.createUndef(offset++, OperandSize.BYTE, Helpers.PARITY_FLAG));
instructions.add(ReilHelpers.createUndef(offset++, OperandSize.BYTE, Helpers.SIGN_FLAG));
instructions.add(ReilHelpers.createUndef(offset++, OperandSize.BYTE, Helpers.ZERO_FLAG));
}
use of com.google.security.zynamics.zylib.disassembly.IOperandTree in project binnavi by google.
the class IdivTranslator method translate.
/**
* Translates a IDIV instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The IDIV 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 IDIV instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "idiv");
if (instruction.getOperands().size() != 1) {
throw new InternalTranslationException("Error: Argument instruction is not a idiv instruction (invalid number of operands)");
}
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree divisorOperand = operands.get(0);
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
final OperandSize size = Helpers.getOperandSize(operands.get(0));
// Load the dividend
final TranslationResult resultDividend = Helpers.loadFirstDivOperand(environment, offset, size);
instructions.addAll(resultDividend.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final String dividend = resultDividend.getRegister();
// Load the divisor
final TranslationResult resultDivisor = Helpers.translateOperand(environment, offset, divisorOperand, true);
instructions.addAll(resultDivisor.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final String divisor = resultDivisor.getRegister();
// Here's how to express signed division using unsigned division:
// 1. Get the absolute value of both operands
// 2. Divide unsigned
// 3. Change the sign of the result if the signs of the operands were different
// Get the absolute value of the two factors for unsigned multiplication
final Pair<String, String> absDividend = Helpers.generateAbs(environment, offset, dividend, size, instructions);
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final Pair<String, String> absDivisor = Helpers.generateAbs(environment, offset, divisor, size, instructions);
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Perform division and modulo operation
final String divResult = environment.getNextVariableString();
final String modResult = environment.getNextVariableString();
instructions.add(ReilHelpers.createDiv(offset, size, absDividend.second(), size, absDivisor.second(), size, divResult));
instructions.add(ReilHelpers.createMod(offset + 1, size, absDividend.second(), size, absDivisor.second(), size, modResult));
// Find out if the two operands had different signs and create a sign mask
final String xoredSigns = environment.getNextVariableString();
final String toggleMask = environment.getNextVariableString();
instructions.add(ReilHelpers.createXor(offset + 2, size, absDividend.first(), size, absDividend.second(), size, xoredSigns));
instructions.add(ReilHelpers.createSub(offset + 3, size, "0", size, xoredSigns, size, toggleMask));
// Adjust the div result
final String decDivResult = environment.getNextVariableString();
final String realDivResult = environment.getNextVariableString();
instructions.add(ReilHelpers.createSub(offset + 4, size, divResult, size, xoredSigns, size, decDivResult));
instructions.add(ReilHelpers.createXor(offset + 5, size, decDivResult, size, toggleMask, size, realDivResult));
// Adjust the mod result (the sign of the mod result is the sign of the first operand)
final String modToggleMask = environment.getNextVariableString();
final String decModResult = environment.getNextVariableString();
final String realModResult = environment.getNextVariableString();
instructions.add(ReilHelpers.createSub(offset + 6, size, "0", size, absDividend.first(), size, modToggleMask));
instructions.add(ReilHelpers.createSub(offset + 7, size, modResult, size, absDividend.first(), size, decModResult));
instructions.add(ReilHelpers.createXor(offset + 8, size, decModResult, size, modToggleMask, size, realModResult));
// Write the result back and set the flags
instructions.addAll(Helpers.writeDivResult(environment, offset + 9, realDivResult, realModResult, size));
}
Aggregations