Example #1
0
bool SymEval::expand(Result_t &res,
                     std::set<InstructionPtr> &failedInsns,
                     bool applyVisitors) {
    // Symbolic evaluation works off an Instruction
    // so we have something to hand to ROSE.
    failedInsns.clear();
    for (Result_t::iterator i = res.begin(); i != res.end(); ++i) {
        if (i->second != AST::Ptr()) {
            // Must've already filled it in from a previous instruction crack
            continue;
        }
        Assignment::Ptr ptr = i->first;

        bool success = expandInsn(ptr->insn(),
                                  ptr->addr(),
                                  res);
        if (!success) failedInsns.insert(ptr->insn());
    }

    if (applyVisitors) {
        // Must apply the visitor to each filled in element
        for (Result_t::iterator i = res.begin(); i != res.end(); ++i) {
            if (!i->second) continue;
            AST::Ptr tmp = simplifyStack(i->second, i->first->addr(), i->first->func(), i->first->block());
            BooleanVisitor b;
            AST::Ptr tmp2 = tmp->accept(&b);
            i->second = tmp2;
        }
    }
    return (failedInsns.empty());
}
Example #2
0
StackTamper StackTamperVisitor::tampersStack(AST::Ptr a, Address &newAddr) {

    if(tamper_ != TAMPER_UNSET) {
        newAddr = modpc_;
        return tamper_;
    }

    a->accept(this);

    if (tamper_ == TAMPER_NONZERO) {
        return tamper_;
    }

    assert(diffs_.size() == 1);

    modpc_ = diffs_.top().a.x;

    switch(diffs_.top().b.x) {
    case 0:
        tamper_ = TAMPER_ABS;
        break;
    case 1:
        if (modpc_) {
            tamper_ = TAMPER_REL;
        } else {
            tamper_ = TAMPER_NONE;
        }
        break;
    default:
        tamper_ = TAMPER_NONZERO;
        break;
    }
    newAddr = modpc_;
    return tamper_;
}
Example #3
0
AST::Ptr SymEval::simplifyStack(AST::Ptr ast, Address addr, ParseAPI::Function *func, ParseAPI::Block *block) {
    if (!ast) return ast;
    // Let's experiment with simplification
    StackAnalysis sA(func);
    StackAnalysis::Height sp = sA.findSP(block, addr);
    StackAnalysis::Height fp = sA.find(block, addr, MachRegister::getFramePointer(func->isrc()->getArch()));

    StackVisitor sv(addr, func, sp, fp);

    AST::Ptr simplified = ast->accept(&sv);

    return simplified;
}
Example #4
0
void IndirectControlFlowAnalyzer::ReadTable(AST::Ptr jumpTargetExpr,
                                            AbsRegion index,
					    StridedInterval &indexBound,
					    int memoryReadSize,
					    bool isZeroExtend,
					    bool scanTable,
					    set<Address> &constAddr,
					    std::vector<std::pair<Address, Dyninst::ParseAPI::EdgeTypeEnum> > &targetEdges) {
    CodeSource *cs = block->obj()->cs();
    set<Address> jumpTargets;
    int start = 0;
    if (indexBound.low > 0) start = indexBound.low = start;
    for (int v = start; v <= indexBound.high; v += indexBound.stride) {
        JumpTableReadVisitor jtrv(index, v, cs, block->region(), isZeroExtend, memoryReadSize);
	jumpTargetExpr->accept(&jtrv);
	if (jtrv.valid && cs->isCode(jtrv.targetAddress)) {
        if (cs->getArch() == Arch_x86_64 && FindJunkInstruction(jtrv.targetAddress)) {
            parsing_printf("WARNING: resolving jump tables leads to junk instruction from %lx\n", jtrv.targetAddress);
            break;
        }
	    jumpTargets.insert(jtrv.targetAddress);
	} else {
	    // We have a bad entry. We stop here, as we have wrong information
	    // In this case, we keep the good entries
	    parsing_printf("WARNING: resolving jump tables leads to a bad address %lx\n", jtrv.targetAddress);
	    break;
	}
	if (indexBound.stride == 0) break;
    }
    for (auto ait = constAddr.begin(); ait != constAddr.end(); ++ait) {
        if (block->region()->isCode(*ait)) {
	    jumpTargets.insert(*ait);
	}
    }
    for (auto tit = jumpTargets.begin(); tit != jumpTargets.end(); ++tit) {
        targetEdges.push_back(make_pair(*tit, INDIRECT));
    }
}
Example #5
0
void BoundFactsCalculator::CalcTransferFunction(Node::Ptr curNode, BoundFact *newFact){
    SliceNode::Ptr node = boost::static_pointer_cast<SliceNode>(curNode);
    if (!node->assign()) return;
    if (node->assign() && node->assign()->out().absloc().type() == Absloc::Register &&
	    (node->assign()->out().absloc().reg() == x86::zf || node->assign()->out().absloc().reg() == x86_64::zf)) {
	    // zf should be only predecessor of this node
        parsing_printf("\t\tThe predecessor node is zf assignment!\n");
	newFact->SetPredicate(node->assign(), ExpandAssignment(node->assign()) );
	return;
    }
    entryID id = node->assign()->insn()->getOperation().getID();
    // The predecessor is not a conditional jump,
    // then we can determine buond fact based on the src assignment
    parsing_printf("\t\tThe predecessor node is normal node\n");
    parsing_printf("\t\t\tentry id %d\n", id);

    AbsRegion &ar = node->assign()->out();
    Instruction::Ptr insn = node->assign()->insn();
    pair<AST::Ptr, bool> expandRet = ExpandAssignment(node->assign());

    if (expandRet.first == NULL) {
        parsing_printf("\t\t\t No semantic support for this instruction. Assume it does not affect jump target calculation. Ignore it (Treat as identity function) except for ptest. ptest should kill the current predicate\n");
	if (id == e_ptest) {
	    parsing_printf("\t\t\t\tptest instruction, kill predciate.\n");
	    newFact->pred.valid = false;
	}
	return;
    } else {
        parsing_printf("\tAST: %s\n", expandRet.first->format().c_str());
    }

    AST::Ptr calculation = expandRet.first;
    BoundCalcVisitor bcv(*newFact, node->block(), handleOneByteRead);
    calculation->accept(&bcv);
    AST::Ptr outAST;
    // If the instruction writes memory,
    // we need the AST that represents the memory access and the address.
    // When the AbsRegion represents memory,
    // the generator of the AbsRegion is set to be the AST that represents
    // the memory address during symbolic expansion.
    // In other cases, if the AbsRegion represents a register,
    // the generator is not set.
    if (ar.generator() != NULL)
        outAST = SimplifyAnAST(RoseAST::create(ROSEOperation(ROSEOperation::derefOp, ar.size()), ar.generator()), node->assign()->insn()->size());
    else
        outAST = VariableAST::create(Variable(ar));
/*
 * Naively, bsf and bsr produces a bound from 0 to the number of bits of the source operands.
 * In pratice, especially in libc, the real bound is usually smaller than the size of the source operand.
 * Ex 1: shl    %cl,%edx
 *       bsf    %rdx,%rcx
 * Here rcx is in range [0,31] rather than [0,63] even though rdx has 64 bits.
 *
 * Ex 2: pmovmskb %xmm0,%edx
 *       bsf    %rdx, %rdx
 * Here rdx is in range[0,15] because pmovmskb only sets the least significat 16 bits
 * In addition, overapproximation of the bound can lead to bogus control flow
 * that causes overlapping blocks or function.
 * It is important to further anaylze the operand in bsf rather than directly conclude the bound
    if (id == e_bsf || id == e_bsr) {
	int size = node->assign()->insn()->getOperand(0).getValue()->size();
	newFact->GenFact(outAST, new BoundValue(StridedInterval(1,0, size * 8 - 1)), false);
        parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
	newFact->Print();
	return;

    }
*/
    if (id == e_xchg) {
        newFact->SwapFact(calculation, outAST);
        parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
	newFact->Print();
	return;
    }

    if (id == e_push) {
         if (calculation->getID() == AST::V_ConstantAST) {
	     ConstantAST::Ptr c = boost::static_pointer_cast<ConstantAST>(calculation);
	     newFact->PushAConst(c->val().val);
	     parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
	     newFact->Print();
	     return;
	 }
    }

    if (id == e_pop) {
        if (newFact->PopAConst(outAST)) {
	     parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
	     newFact->Print();
	     return;
        }
    }

    // Assume all SETxx entry ids are contiguous
    if (id >= e_setb && id <= e_setz) {
        newFact->GenFact(outAST, new BoundValue(StridedInterval(1,0,1)), false);
	parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
	newFact->Print();
	return;
    }


    if (bcv.IsResultBounded(calculation)) {
        parsing_printf("\t\t\tGenerate bound fact for %s\n", outAST->format().c_str());
	newFact->GenFact(outAST, new BoundValue(*bcv.GetResultBound(calculation)), false);
    }
    else {
        parsing_printf("\t\t\tKill bound fact for %s\n", outAST->format().c_str());
	newFact->KillFact(outAST, false);
    }
    if (calculation->getID() == AST::V_VariableAST) {
        // We only track alising between registers
	parsing_printf("\t\t\t%s and %s are equal\n", calculation->format().c_str(), outAST->format().c_str());
	newFact->InsertRelation(calculation, outAST, BoundFact::Equal);
    }
    newFact->AdjustPredicate(outAST, calculation);

    // Now try to track all aliasing.
    // Currently, all variables in the slice are presented as an AST
    // consists of input variables to the slice (the variables that
    // we do not the sources of their values).
    newFact->TrackAlias(DeepCopyAnAST(calculation), outAST);

    // Apply tracking relations to the calculation to generate a
    // potentially stricter bound
    BoundValue *strictValue = newFact->ApplyRelations(outAST);
    if (strictValue != NULL) {
        parsing_printf("\t\t\tGenerate stricter bound fact for %s\n", outAST->format().c_str());
	newFact->GenFact(outAST, strictValue, false);
    }
    parsing_printf("\t\t\tCalculating transfer function: Output facts\n");
    newFact->Print();

}
Example #6
0
AST::Ptr SimplifyAnAST(AST::Ptr ast, Address addr) {
    SimplifyVisitor sv(addr);
    ast->accept(&sv);
    return SimplifyRoot(ast, addr);
}