Exemple #1
0
      /* Add a path constraint */
      void PathManager::addPathConstraint(const triton::arch::Instruction& inst, triton::engines::symbolic::SymbolicExpression* expr) {
        triton::engines::symbolic::PathConstraint pco;
        triton::ast::AbstractNode* pc = nullptr;
        triton::uint64 srcAddr        = 0;
        triton::uint64 dstAddr        = 0;
        triton::uint32 size           = 0;

        pc = expr->getAst();
        if (pc == nullptr)
          throw triton::exceptions::PathManager("PathManager::addPathConstraint(): The PC node cannot be null.");

        /* If PC_TRACKING_SYMBOLIC is enabled, Triton will track path constraints only if they are symbolized. */
        if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::PC_TRACKING_SYMBOLIC) && !pc->isSymbolized())
          return;

        /* If ONLY_ON_TAINTED is enabled and the expression untainted, Triton will skip the storing process. */
        if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_TAINTED) && !expr->isTainted)
          return;

        /* Basic block taken */
        srcAddr = inst.getAddress();
        dstAddr = pc->evaluate().convert_to<triton::uint64>();
        size    = pc->getBitvectorSize();

        if (size == 0)
          throw triton::exceptions::PathManager("PathManager::addPathConstraint(): The PC node size cannot be zero.");

        if (pc->getKind() == triton::ast::ZX_NODE)
          pc = pc->getChilds()[1];

        /* Multiple branches */
        if (pc->getKind() == triton::ast::ITE_NODE) {
          triton::uint64 bb1 = pc->getChilds()[1]->evaluate().convert_to<triton::uint64>();
          triton::uint64 bb2 = pc->getChilds()[2]->evaluate().convert_to<triton::uint64>();

          triton::ast::AbstractNode* bb1pc = (bb1 == dstAddr) ? triton::ast::equal(pc, triton::ast::bv(dstAddr, size)) :
                                                                triton::ast::lnot(triton::ast::equal(pc, triton::ast::bv(dstAddr, size)));

          triton::ast::AbstractNode* bb2pc = (bb2 == dstAddr) ? triton::ast::equal(pc, triton::ast::bv(dstAddr, size)) :
                                                                triton::ast::lnot(triton::ast::equal(pc, triton::ast::bv(dstAddr, size)));

          pco.addBranchConstraint(bb1 == dstAddr, srcAddr, bb1, bb1pc);
          pco.addBranchConstraint(bb2 == dstAddr, srcAddr, bb2, bb2pc);

          this->pathConstraints.push_back(pco);
        }

        /* Direct branch */
        else {
          pco.addBranchConstraint(true, srcAddr, dstAddr, triton::ast::equal(pc, triton::ast::bv(dstAddr, size)));
          this->pathConstraints.push_back(pco);
        }

      }
Exemple #2
0
    void Architecture::buildSemantics(triton::arch::Instruction& inst) const {
      if (!this->cpu)
        throw std::runtime_error("Architecture::buildSemantics(): You must define an architecture.");

      /* Pre IR processing */
      inst.preIRInit();

      /* If the symbolic and taint engine are disable we skip the processing */
      if (!triton::api.isSymbolicEngineEnabled() && !triton::api.isTaintEngineEnabled())
        return;

      /* Backup the symbolic engine in the case where only taint is available. */
      if (!triton::api.isSymbolicEngineEnabled())
        triton::api.backupSymbolicEngine();

      /* Processing */
      this->cpu->buildSemantics(inst);

      /* Post IR processing */
      inst.postIRInit();

      /*
       * If the symbolic engine is disable we delete symbolic
       * expressions and AST nodes. Note that if the taint engine
       * is enable we must compute semanitcs to spread the taint.
       */
      if (!triton::api.isSymbolicEngineEnabled()) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
          triton::api.removeSymbolicExpression((*it)->getId());
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions.clear();
        triton::api.restoreSymbolicEngine();
      }

      /*
       * If the symbolic engine is defined to process symbolic
       * execution only on tainted instructions, we delete all
       * expressions untainted and their AST nodes.
       */
      if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_TAINTED)) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*> newVector;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          if ((*it)->isTainted == triton::engines::taint::UNTAINTED) {
            triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
            triton::api.removeSymbolicExpression((*it)->getId());
          }
          else
            newVector.push_back(*it);
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions = newVector;
      }

      /*
       * If the symbolic engine is defined to process symbolic
       * execution only on symbolized expressions, we delete all
       * concrete expressions and their AST nodes.
       */
      if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_SYMBOLIZED)) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*> newVector;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          if ((*it)->getAst()->isSymbolized() == false) {
            triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
            triton::api.removeSymbolicExpression((*it)->getId());
          }
          else
            newVector.push_back(*it);
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions = newVector;
      }

    }
Exemple #3
0
 void x86Cpu::buildSemantics(triton::arch::Instruction &inst) {
   if (!inst.getType())
     throw std::runtime_error("x8664Cpu::buildSemantics(): You must disassemble the instruction before.");
   triton::arch::x86::semantics::build(inst);
 }
Exemple #4
0
    void x86Cpu::disassembly(triton::arch::Instruction &inst) {
      csh       handle;
      cs_insn*  insn;
      size_t    count;

      /* Check if the opcodes and opcodes' size are defined */
      if (inst.getOpcodes() == nullptr || inst.getOpcodesSize() == 0)
        throw std::runtime_error("x86Cpu::disassembly(): Opcodes and opcodesSize must be definied.");

      /* Open capstone */
      if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK)
        throw std::runtime_error("x86Cpu::disassembly(): Cannot open capstone.");

      /* Init capstone's options */
      cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
      cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);

      /* Let's disass and build our operands */
      count = cs_disasm(handle, inst.getOpcodes(), inst.getOpcodesSize(), inst.getAddress(), 0, &insn);
      if (count > 0) {
        cs_detail* detail = insn->detail;
        for (triton::uint32 j = 0; j < count; j++) {

          /* Init the disassembly */
          std::stringstream str;
          str << insn[j].mnemonic << " " <<  insn[j].op_str;
          inst.setDisassembly(str.str());

          /* Init the instruction's type */
          inst.setType(capstoneInstToTritonInst(insn[j].id));

          /* Init operands */
          for (triton::uint32 n = 0; n < detail->x86.op_count; n++) {
            cs_x86_op *op = &(detail->x86.operands[n]);
            switch(op->type) {

              case X86_OP_IMM:
                inst.operands.push_back(triton::arch::OperandWrapper(triton::arch::ImmediateOperand(op->imm, op->size)));
                break;

              case X86_OP_MEM: {
                triton::arch::MemoryOperand mem = inst.popMemoryAccess();

                /* Set the size if the memory is not valid */
                if (!mem.isValid())
                  mem.setPair(std::make_pair(((op->size * BYTE_SIZE_BIT) - 1), 0));

                /* LEA if exists */
                triton::arch::RegisterOperand base(triton::arch::x86::capstoneRegToTritonReg(op->mem.base));
                triton::arch::RegisterOperand index(triton::arch::x86::capstoneRegToTritonReg(op->mem.index));
                triton::arch::ImmediateOperand disp(op->mem.disp, op->size);
                triton::arch::ImmediateOperand scale(op->mem.scale, op->size);

                mem.setBaseReg(base);
                mem.setIndexReg(index);
                mem.setDisplacement(disp);
                mem.setScale(scale);

                inst.operands.push_back(triton::arch::OperandWrapper(mem));
                break;
              }

              case X86_OP_REG:
                inst.operands.push_back(triton::arch::OperandWrapper(inst.getRegisterState(triton::arch::x86::capstoneRegToTritonReg(op->reg))));
                break;

              default:
                break;
            }
          }

        }
        /* Set branch */
        if (detail->groups_count > 0) {
          for (triton::uint32 n = 0; n < detail->groups_count; n++) {
            if (detail->groups[n] == X86_GRP_JUMP)
              inst.setBranch(true);
            if (detail->groups[n] == X86_GRP_JUMP || detail->groups[n] == X86_GRP_CALL || detail->groups[n] == X86_GRP_RET)
              inst.setControlFlow(true);
          }
        }
        cs_free(insn, count);
      }
      else
        throw std::runtime_error("x86Cpu::disassembly(): Failed to disassemble the given code.");

      cs_close(&handle);
      return;
    }