use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.
the class ImulTranslator method generateImul.
private TranslationResult generateImul(final ITranslationEnvironment environment, final long offset, final String operand1, final String operand2, final OperandSize size1, final OperandSize size2) {
// The three steps to simulate signed multiplication using unsigned multiplication:
// 1. Get the absolute values of the two operands
// 2. Multiply the absolute values
// 3. Change the sign of the result if the two operands had different signs.
final long baseOffset = offset;
long newOffset = baseOffset;
final OperandSize resultSize = TranslationHelpers.getNextSize(size1);
final ArrayList<ReilInstruction> instructions = new ArrayList<ReilInstruction>();
final Pair<String, String> abs1 = Helpers.generateAbs(environment, newOffset, operand1, size1, instructions);
newOffset = baseOffset + instructions.size();
final Pair<String, String> abs2 = Helpers.generateAbs(environment, newOffset, operand2, size2, instructions);
newOffset = baseOffset + instructions.size();
final String lowerHalfMask = String.valueOf(TranslationHelpers.getAllBitsMask(size1));
final String multResult = environment.getNextVariableString();
final String xoredSigns = environment.getNextVariableString();
final String toggleMask = environment.getNextVariableString();
final String decResult = environment.getNextVariableString();
final String realResult = environment.getNextVariableString();
final String maskedLowerHalf = environment.getNextVariableString();
// Multiply the two operands
instructions.add(ReilHelpers.createMul(newOffset, size1, abs1.second(), size2, abs2.second(), resultSize, multResult));
// Find out if the two operands had different signs and adjust the result accordingly
instructions.add(ReilHelpers.createXor(newOffset + 1, size1, abs1.first(), size2, abs2.first(), size1, xoredSigns));
instructions.add(ReilHelpers.createSub(newOffset + 2, size1, "0", size1, xoredSigns, resultSize, toggleMask));
instructions.add(ReilHelpers.createSub(newOffset + 3, resultSize, multResult, size1, xoredSigns, resultSize, decResult));
instructions.add(ReilHelpers.createXor(newOffset + 4, resultSize, toggleMask, resultSize, decResult, resultSize, realResult));
// Extract lower half of the result
instructions.add(ReilHelpers.createAnd(newOffset + 5, resultSize, realResult, size1, lowerHalfMask, size1, maskedLowerHalf));
// Extend the sign of the lower half of the result
final TranslationResult foo = Helpers.extendSign(environment, newOffset + 6, maskedLowerHalf, size1, resultSize);
instructions.addAll(foo.getInstructions());
newOffset = newOffset + 6 + foo.getInstructions().size();
final String cmpResult = environment.getNextVariableString();
final String resultsEqual = environment.getNextVariableString();
// Compare result to sign extension of lower half
instructions.add(ReilHelpers.createSub(newOffset, resultSize, realResult, resultSize, foo.getRegister(), resultSize, cmpResult));
instructions.add(ReilHelpers.createBisz(newOffset + 1, resultSize, cmpResult, OperandSize.BYTE, resultsEqual));
// Set the flags according to the result
instructions.add(ReilHelpers.createBisz(newOffset + 2, OperandSize.BYTE, resultsEqual, OperandSize.BYTE, Helpers.CARRY_FLAG));
instructions.add(ReilHelpers.createBisz(newOffset + 3, OperandSize.BYTE, resultsEqual, OperandSize.BYTE, Helpers.OVERFLOW_FLAG));
instructions.add(ReilHelpers.createUndef(newOffset + 4, OperandSize.BYTE, Helpers.ZERO_FLAG));
instructions.add(ReilHelpers.createUndef(newOffset + 5, OperandSize.BYTE, Helpers.AUXILIARY_FLAG));
instructions.add(ReilHelpers.createUndef(newOffset + 6, OperandSize.BYTE, Helpers.PARITY_FLAG));
return new TranslationResult(realResult, resultSize, TranslationResultType.REGISTER, null, instructions, offset);
}
use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.
the class ImulTranslator method generateImul3.
private void generateImul3(final ITranslationEnvironment environment, final long offset, final OperandSize size1, final String register1, final OperandSize size2, final String register2, final OperandSize size3, final String register3, final List<ReilInstruction> instructions) throws InternalTranslationException {
final TranslationResult result = generateImul(environment, offset, register2, register3, size2, size3);
instructions.addAll(result.getInstructions());
final String resultRegister = result.getRegister();
writeSingleRegisterMulResult(environment, offset + result.getInstructions().size(), resultRegister, register1, size1, instructions);
}
use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.
the class CmpTranslator method translate.
/**
* Translates a CMP instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The CMP 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 CMP instruction
*/
@Override
public void translate(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "cmp");
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 firstResult = Helpers.translateOperand(environment, offset, targetOperand, true);
instructions.addAll(firstResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
// Load second operand.
final TranslationResult secondResult = Helpers.translateOperand(environment, offset, sourceOperand, true);
instructions.addAll(secondResult.getInstructions());
// Adjust the offset of the next REIL instruction.
offset = baseOffset + instructions.size();
final String firstRegister = firstResult.getRegister();
final String secondRegister = secondResult.getRegister();
final OperandSize size = firstResult.getSize();
// CMP = SUB without writing the result back into the target operand
Helpers.generateSub(environment, offset, size, firstRegister, secondRegister, instructions);
}
use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.
the class Cmpxchg8bTranslator method translate.
/**
* Translates a CMPXCHG8B instruction to REIL code.
*
* @param environment A valid translation environment.
* @param instruction The CMPXCHG8B 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 {
// CMPXCHG8B:
// Compares the 64-bit value in EDX:EAX with the operand (destination
// operand). If the values are equal, the 64-bit value in ECX:EBX is stored
// in the destination operand. Otherwise, the value in the destination
// operand is loaded into EDX:EAX. The destination operand is an 8-byte
// memory location. For the EDX:EAX and ECX:EBX register pairs, EDX and ECX
// contain the high-order 32 bits and EAX and EBX contain the low-order 32
// bits of a 64-bit value.
//
// In order to translate this, we perform the following steps:
// 1) Translate the (single) operand properly. The operand can be of
// complex form, e.g. [ebx+0x20] etc., so we will obtain a group of
// instructions for it.
// 2) Load 64 bit into memory using a 64-bit LDM REIL instruction
// 3) Combine the value in EDX:EAX into one 64-bit REIL register
// 4) Compare the two values (by subtracting them)
// 5) If the ZF is not set, load the value obtained in step (2) into
// EDX:EAX, then jump to 7)
// 6) If the ZF is set (e.g. the values were equal), combine ECX and
// EBX into one value, and emit a 64-bit STM. Then jump to 7)
// 7) End.
//
// We see that the translated code will contain two JCCs -- one conditional
// at the beginning of step 5, leading to 6, and one unconditional at the
// end of step 5, leading to 7.
TranslationHelpers.checkTranslationArguments(environment, instruction, instructions, "cmpxchg8b");
Preconditions.checkArgument(instruction.getOperands().size() == 1, "Error: Argument instruction is not a cmpxchg8b instruction (invalid number of operands)");
final long baseOffset = instruction.getAddress().toLong() * 0x100;
final long offset = baseOffset;
// Step (1) Translate the (single) operand properly.
final List<? extends IOperandTree> operands = instruction.getOperands();
final IOperandTree targetOperand = operands.get(0);
final TranslationResult firstResult = Helpers.translateOperand(environment, offset, targetOperand, false);
instructions.addAll(firstResult.getInstructions());
// Step (2) Load 64 bit into memory using a 64-bit LDM REIL instruction.
final String loadResult = environment.getNextVariableString();
instructions.add(ReilHelpers.createLdm(baseOffset + instructions.size(), OperandSize.DWORD, firstResult.getAddress(), OperandSize.QWORD, loadResult));
// Step (3) Combine the value in EDX:EAX into one 64-bit REIL register
final String combinedEdxEax = environment.getNextVariableString();
instructions.add(ReilHelpers.createBsh(baseOffset + instructions.size(), OperandSize.DWORD, "edx", OperandSize.DWORD, "32", OperandSize.QWORD, combinedEdxEax));
instructions.add(ReilHelpers.createOr(baseOffset + instructions.size(), OperandSize.QWORD, "eax", OperandSize.QWORD, combinedEdxEax, OperandSize.QWORD, combinedEdxEax));
final String comparisonResult = environment.getNextVariableString();
// Step (4) Compare the two values (by subtracting them).
instructions.add(ReilHelpers.createSub(baseOffset + instructions.size(), OperandSize.QWORD, combinedEdxEax, OperandSize.QWORD, loadResult, OperandSize.QWORD, comparisonResult));
// Set the ZF if the two values were equal.
instructions.add(ReilHelpers.createBisz(baseOffset + instructions.size(), OperandSize.QWORD, comparisonResult, OperandSize.BYTE, Helpers.ZERO_FLAG));
// Beginning of step (5) - if the ZF is set, jump to step (6). The reason
// for the constant "+4" in the jump offset is that the size of the body of
// step (5) is exactly 4 instructions:
// JCC ZF, --, step 6
// AND val, 0xFFFFFFFF, eax
// BSH val, -32, edx
// JCC 1, --, step 7
// "val" is the value obtained in step (2).
final String jmpGoal = String.format("%d.%d", instruction.getAddress().toLong(), instructions.size() + 4);
instructions.add(ReilHelpers.createJcc(baseOffset + instructions.size(), OperandSize.BYTE, Helpers.ZERO_FLAG, OperandSize.ADDRESS, jmpGoal));
// The body of step (5) - load the value obtained in step (2) into EDX:EAX
instructions.add(ReilHelpers.createAnd(baseOffset + instructions.size(), OperandSize.QWORD, loadResult, OperandSize.QWORD, String.valueOf(TranslationHelpers.getAllBitsMask(OperandSize.DWORD)), OperandSize.DWORD, "eax"));
instructions.add(ReilHelpers.createBsh(baseOffset + instructions.size(), OperandSize.QWORD, loadResult, OperandSize.DWORD, "-32", OperandSize.DWORD, "edx"));
// Create a non-conditional JMP that skips step 6. Step 6, again, consists of
// 4 instructions.
final String jmpGoal2 = String.format("%d.%d", instruction.getAddress().toLong(), instructions.size() + 4);
instructions.add(ReilHelpers.createJcc(baseOffset + instructions.size(), OperandSize.BYTE, "1", OperandSize.ADDRESS, jmpGoal2));
// Step (6) If the ZF is set (e.g. the values were equal), combine ECX and
// EBX into one value, and emit a 64-bit STM. Then fall through to step (7)
instructions.add(ReilHelpers.createBsh(baseOffset + instructions.size(), OperandSize.DWORD, "ecx", OperandSize.DWORD, "32", OperandSize.QWORD, combinedEdxEax));
instructions.add(ReilHelpers.createOr(baseOffset + instructions.size(), OperandSize.QWORD, "ebx", OperandSize.QWORD, combinedEdxEax, OperandSize.QWORD, combinedEdxEax));
instructions.add(ReilHelpers.createStm(baseOffset + instructions.size(), OperandSize.QWORD, combinedEdxEax, OperandSize.DWORD, firstResult.getAddress()));
// Step (7): Just a final NOP, needed as jump destination.
instructions.add(ReilHelpers.createNop(baseOffset + instructions.size()));
}
use of com.google.security.zynamics.reil.translators.TranslationResult in project binnavi by google.
the class ImulTranslator method translate_1.
private void translate_1(final ITranslationEnvironment environment, final IInstruction instruction, final List<ReilInstruction> instructions) throws InternalTranslationException {
final List<? extends IOperandTree> operands = instruction.getOperands();
final long baseOffset = instruction.getAddress().toLong() * 0x100;
long offset = baseOffset;
// Load source operand.
final TranslationResult firstResult = Helpers.translateOperand(environment, offset, operands.get(0), true);
instructions.addAll(firstResult.getInstructions());
offset = baseOffset + instructions.size();
// Generate multiplication code
final TranslationResult multResult = generateImul(environment, offset, "eax", firstResult.getRegister(), OperandSize.DWORD, firstResult.getSize());
instructions.addAll(multResult.getInstructions());
offset = baseOffset + instructions.size();
final OperandSize size = Helpers.getOperandSize(operands.get(0));
// Write the result of the multiplication back to the proper registers
instructions.addAll(Helpers.writeMulResult(environment, offset, multResult.getRegister(), size));
}
Aggregations