SymbolicElement *AnalysisProcessor::createRegSE(Inst &inst, std::stringstream &expr, uint64_t regID, uint64_t regSize, std::string comment) { std::stringstream finalExpr, origReg; origReg << this->buildSymbolicRegOperand(regID, REG_SIZE); switch (regSize) { case BYTE_SIZE: finalExpr << smt2lib::concat(smt2lib::extract(63, 8, origReg.str()), expr.str()); break; case WORD_SIZE: finalExpr << smt2lib::concat(smt2lib::extract(63, 16, origReg.str()), expr.str()); break; case DWORD_SIZE: /* In AMD64, if a reg32 is written, it clears the 32-bit MSB of the corresponding register (Thx Wisk!) */ finalExpr << smt2lib::zx(expr.str(), DWORD_SIZE_BIT); break; case QWORD_SIZE: finalExpr << expr.str(); break; case DQWORD_SIZE: finalExpr << expr.str(); break; } SymbolicElement *se = this->symEngine.newSymbolicElement(finalExpr, comment); this->symEngine.symbolicReg[regID] = se->getID(); inst.addElement(se); return se; }
SymbolicElement *AnalysisProcessor::createMemSE(Inst &inst, std::stringstream &expr, uint64_t address, uint64_t writeSize, std::string comment) { SymbolicElement *ret = nullptr; std::stringstream tmp; /* * As the x86's memory can be accessed without alignment, each byte of the * memory must be assigned to an unique reference. */ while (writeSize){ /* Extract each byte if the size > 1 byte (8 bits) */ if (writeSize > BYTE_SIZE){ tmp.str(smt2lib::extract(((writeSize * REG_SIZE) - 1), ((writeSize * REG_SIZE) - REG_SIZE), expr.str())); SymbolicElement *se = symEngine.newSymbolicElement(tmp, "byte reference"); inst.addElement(se); /* Assign memory with little endian */ this->symEngine.addMemoryReference((address + writeSize) - 1, se->getID()); } /* Otherwise keep the full formula */ else { SymbolicElement *se = symEngine.newSymbolicElement(expr, comment); inst.addElement(se); this->symEngine.addMemoryReference(address, se->getID()); ret = se; } writeSize--; } return ret; }
SymbolicElement *AnalysisProcessor::createRegSE(Inst &inst, std::stringstream &expr, uint64_t regID, std::string comment) { SymbolicElement *se = this->symEngine.newSymbolicElement(expr, comment); this->symEngine.symbolicReg[regID] = se->getID(); inst.addElement(se); return se; }
uint64 SymbolicEngine::convertRegToSymVar(uint64 regId, uint64 symVarSize) { SymbolicVariable *symVar = nullptr; SymbolicElement *element = nullptr; std::stringstream newExpr; uint64 regSymId = UNSET; if (regId >= ID_LAST_ITEM) throw std::runtime_error("SymbolicEngine::convertRegToSymVar() - Invalid register ID"); regSymId = this->getRegSymbolicID(regId); if (regSymId == UNSET) throw std::runtime_error("SymbolicEngine::convertRegToSymVar() - This register ID is UNSET"); element = this->getElementFromId(regSymId); if (element == nullptr) return UNSET; if (symVarSize != BYTE_SIZE && symVarSize != WORD_SIZE && symVarSize != DWORD_SIZE && symVarSize != QWORD_SIZE && symVarSize != DQWORD_SIZE) throw std::runtime_error("SymbolicEngine::convertRegToSymVar() - Invalid symVarSize"); symVar = this->addSymbolicVariable(SymVar::kind::REG, regId, symVarSize); newExpr << symVar->getSymVarName(); element->setSrcExpr(newExpr); return symVar->getSymVarId(); }
void JnleIRBuilder::imm(AnalysisProcessor &ap, Inst &inst) const { SymbolicElement *se; std::stringstream expr, sf, of, zf; uint64 imm = this->operands[0].getValue(); /* Create the SMT semantic */ sf << ap.buildSymbolicFlagOperand(ID_SF); of << ap.buildSymbolicFlagOperand(ID_OF); zf << ap.buildSymbolicFlagOperand(ID_ZF); /* * Finale expr * JNLE: Jump if not less or equal ((SF^OF | ZF) == 0). * SMT: (= (bvor (bvxor sf of) zf) FALSE) */ expr << smt2lib::ite( smt2lib::equal( smt2lib::bvor(smt2lib::bvxor(sf.str(), of.str()), zf.str()), smt2lib::bvfalse() ), smt2lib::bv(imm, REG_SIZE_BIT), smt2lib::bv(this->nextAddress, REG_SIZE_BIT)); /* Create the symbolic element */ se = ap.createRegSE(inst, expr, ID_RIP, REG_SIZE, "RIP"); /* Add the constraint in the PathConstraints list */ ap.addPathConstraint(se->getID()); }
uint64 SymbolicEngine::convertMemToSymVar(uint64 memAddr, uint64 symVarSize) { SymbolicVariable *symVar = nullptr; SymbolicElement *element = nullptr; std::stringstream newExpr; uint64 memSymId = UNSET; memSymId = this->getMemSymbolicID(memAddr); if (memSymId == UNSET) throw std::runtime_error("SymbolicEngine::convertMemToSymVar() - This memory address is UNSET"); element = this->getElementFromId(memSymId); if (element == nullptr) return UNSET; if (symVarSize != BYTE_SIZE && symVarSize != WORD_SIZE && symVarSize != DWORD_SIZE && symVarSize != QWORD_SIZE && symVarSize != DQWORD_SIZE) throw std::runtime_error("SymbolicEngine::convertMemToSymVar() - Invalid symVarSize"); symVar = this->addSymbolicVariable(SymVar::kind::MEM, memAddr, symVarSize); newExpr << symVar->getSymVarName(); element->setSrcExpr(newExpr); return symVar->getSymVarId(); }
void JnbeIRBuilder::imm(AnalysisProcessor &ap, Inst &inst) const { SymbolicElement *se; std::stringstream expr, cf, zf; uint64 imm = this->operands[0].getValue(); /* Create the SMT semantic */ cf << ap.buildSymbolicFlagOperand(ID_CF); zf << ap.buildSymbolicFlagOperand(ID_ZF); /* * Finale expr * JNBE: Jump if not below or equal (CF=0 and ZF=0). * SMT: (= (bvand (bvnot zf) (bvnot cf)) (_ bv1 1)) */ expr << smt2lib::ite( smt2lib::equal( smt2lib::bvand( smt2lib::bvnot(cf.str()), smt2lib::bvnot(zf.str()) ), smt2lib::bvtrue() ), smt2lib::bv(imm, REG_SIZE_BIT), smt2lib::bv(this->nextAddress, REG_SIZE_BIT)); /* Create the symbolic element */ se = ap.createRegSE(inst, expr, ID_RIP, REG_SIZE, "RIP"); /* Add the constraint in the PathConstraints list */ ap.addPathConstraint(se->getID()); }
/* Returns the symbolic expression backtracked from an ID. */ std::string SymbolicEngine::getBacktrackedExpressionFromId(uint64 id) { SymbolicElement *element; std::stringstream formula; element = this->getElementFromId(id); if (element == nullptr) return ""; formula.str(element->getSource()->str()); while (formula.str().find("#") != std::string::npos) formula.str(this->deepReplace(formula)); return formula.str(); }
/* * Converts an expression ID to a symbolic variable. * e.g: * #43 = (_ bv10 8) * convertExprToSymVar(43, 8) * #43 = SymVar_4 */ uint64 SymbolicEngine::convertExprToSymVar(uint64 exprId, uint64 symVarSize) { SymbolicVariable *symVar = nullptr; SymbolicElement *element = this->getElementFromId(exprId); std::stringstream newExpr; if (element == nullptr) return UNSET; if (symVarSize != BYTE_SIZE && symVarSize != WORD_SIZE && symVarSize != DWORD_SIZE && symVarSize != QWORD_SIZE && symVarSize != DQWORD_SIZE) throw std::runtime_error("SymbolicEngine::convertExprToSymVar() - Invalid symVarSize"); symVar = this->addSymbolicVariable(SymVar::kind::UNDEF, 0, symVarSize); newExpr << symVar->getSymVarName(); element->setSrcExpr(newExpr); return symVar->getSymVarId(); }
void JbIRBuilder::imm(AnalysisProcessor &ap, Inst &inst) const { SymbolicElement *se; std::stringstream expr, cf; uint64 imm = this->operands[0].getValue(); /* Create the SMT semantic */ cf << ap.buildSymbolicFlagOperand(ID_CF); /* Finale expr */ expr << smt2lib::ite( smt2lib::equal( cf.str(), smt2lib::bvtrue()), smt2lib::bv(imm, REG_SIZE_BIT), smt2lib::bv(this->nextAddress, REG_SIZE_BIT)); /* Create the symbolic element */ se = ap.createRegSE(inst, expr, ID_RIP, REG_SIZE, "RIP"); /* Add the constraint in the PathConstraints list */ ap.addPathConstraint(se->getID()); }