void BaseInstructions::killState(S2EExecutionState *state)
{
    std::string message;
    uint32_t messagePtr;
    bool ok = true;
    klee::ref<klee::Expr> status = state->readCpuRegister(CPU_OFFSET(regs[R_EAX]), klee::Expr::Int32);
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]), &messagePtr, 4);

    if (!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_kill_state \n";
    } else {
        message="<NO MESSAGE>";
        if(messagePtr && !state->readString(messagePtr, message)) {
            s2e()->getWarningsStream(state)
                << "Error reading message string from the guest\n";
        }
    }

    //Kill the current state
    s2e()->getMessagesStream(state) << "Killing state "  << state->getID() << '\n';
    std::ostringstream os;
    os << "State was terminated by opcode\n"
       << "            message: \"" << message << "\"\n"
       << "            status: " << status;
    s2e()->getExecutor()->terminateStateEarly(*state, os.str());
}
void BaseInstructions::concretize(S2EExecutionState *state, bool addConstraint)
{
    uint32_t address, size;

    bool ok = true;
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]),
                                         &address, 4);
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]),
                                         &size, 4);

    if(!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_op "
               " get_example opcode\n";
        return;
    }

    for(unsigned i = 0; i < size; ++i) {
        if (!state->readMemoryConcrete8(address + i, NULL, S2EExecutionState::VirtualAddress, addConstraint)) {
            s2e()->getWarningsStream(state)
                << "Can not concretize memory"
                << " at " << hexval(address + i) << '\n';
        }
    }
}
Example #3
0
/**
 *  A call handler can invoke this function to register a return handler.
 *  XXX: We assume that the passed execution state corresponds to the state in which
 *  this instance of FunctionMonitorState is used.
 */
void FunctionMonitorState::registerReturnSignal(S2EExecutionState *state, FunctionMonitor::ReturnSignal &sig)
{
    if(sig.empty()) {
        return;
    }

    uint32_t sp;

#ifdef TARGET_ARM
    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[13]),
                                             &sp, sizeof(target_ulong));
#elif defined(TARGET_I386)
    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ESP]),
                                             &sp, sizeof(target_ulong));
#else
    assert(false);
#endif

    uint64_t pid = state->getPid();
    if (m_plugin->m_monitor) {
        pid = m_plugin->m_monitor->getPid(state, state->getPc());
    }

    if(!ok) {
        m_plugin->s2e()->getWarningsStream(state)
            << "Function call with symbolic SP!" << std::endl
            << "  PC=" << hexval(state->getPc()) << " PID=" << hexval(pid) << std::endl;
        return;
    }

    ReturnDescriptor descriptor = {pid, sig };
    m_returnDescriptors.insert(std::make_pair(sp, descriptor));
}
void BaseInstructions::isSymbolic(S2EExecutionState *state)
{
    uint32_t address;
    uint32_t result;
    char buf;
    bool ok = true;
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ECX]),
                                         &address, 4);

    if(!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_op is_symbolic\n";
        return;
    }

    s2e()->getMessagesStream(state)
            << "Testing whether data at " << hexval(address)
            << " is symbolic:";

    // readMemoryConcrete fails if the value is symbolic
    result = !state->readMemoryConcrete(address, &buf, 1);
    s2e()->getMessagesStream(state)
            << (result ? " true" : " false") << '\n';
    state->writeCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &result, 4);
}
Example #5
0
void DasosPreproc::fuzzFork1 (S2EExecutionState* state, unsigned int value) {
   /** Emulate fork via WindowsApi forkRange Code */
   klee::ref<klee::Expr> symb = state->createSymbolicValue (klee::Expr::Int32, "fuzz_symb");
   klee::ref<klee::Expr> cond = klee::NeExpr::create (symb, klee::ConstantExpr::create (value, klee::Expr::Int32) );
   klee::Executor::StatePair sp = s2e()->getExecutor()->fork (*state, cond, false);
   S2EExecutionState *fs = static_cast<S2EExecutionState *>(sp.second);
   // set the return value for state 1 to given value
   fs->writeCpuRegisterConcrete (CPU_OFFSET(regs[R_EAX]), &(value), 4);
   // set the return value for state 0 to a canary
   value = 0xffffffff;
   state->writeCpuRegisterConcrete (CPU_OFFSET(regs[R_EAX]), &(value), 4);
   return;
} // end fn fuzzFork1
void BaseInstructions::printExpression(S2EExecutionState *state)
{
    //Print the expression
    uint32_t name; //xxx
    bool ok = true;
    ref<Expr> val = state->readCpuRegister(offsetof(CPUX86State, regs[R_EAX]), klee::Expr::Int32);
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ECX]),
                                         &name, 4);

    if(!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_op "
               "print_expression opcode\n";
        return;
    }

    std::string nameStr = "<NO NAME>";
    if(name && !state->readString(name, nameStr)) {
        s2e()->getWarningsStream(state)
                << "Error reading string from the guest\n";
    }


    s2e()->getMessagesStream() << "SymbExpression " << nameStr << " - "
                               <<val << '\n';
}
void BaseInstructions::printMessage(S2EExecutionState *state, bool isWarning)
{
    uint32_t address = 0; //XXX
    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]),
                                                &address, 4);
    if(!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_op "
               " message opcode\n";
        return;
    }

    std::string str="";
    if(!address || !state->readString(address, str)) {
        s2e()->getWarningsStream(state)
                << "Error reading string message from the guest at address "
                << hexval(address) << '\n';
    } else {
        llvm::raw_ostream *stream;
        if(isWarning)
            stream = &s2e()->getWarningsStream(state);
        else
            stream = &s2e()->getMessagesStream(state);
        (*stream) << "Message from guest (" << hexval(address) <<
                     "): " <<  str << '\n';
    }
}
Example #8
0
/**
 *  When emitSignal is false, this function simply removes all the return descriptors
 * for the current stack pointer. This can be used when a return handler manually changes the
 * program counter and/or wants to exit to the cpu loop and avoid being called again.
 *
 *  Note: all the return handlers will be erased if emitSignal is false, not just the one
 * that issued the call. Also note that it not possible to return from the handler normally
 * whenever this function is called from within a return handler.
 */
void X86FunctionMonitorState::slotRet(S2EExecutionState *state, uint64_t pc, bool emitSignal)
{
    target_ulong cr3 = state->readCpuState(CPU_OFFSET(cr[3]), 8*sizeof(target_ulong));

    target_ulong esp;
    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ESP]),
                                             &esp, sizeof(target_ulong));
    if(!ok) {
        target_ulong eip = state->readCpuState(CPU_OFFSET(eip),
                                               8*sizeof(target_ulong));
        m_plugin->s2e()->getWarningsStream(state)
            << "Function return with symbolic ESP!" << '\n'
            << "  EIP=" << hexval(eip) << " CR3=" << hexval(cr3) << '\n';
        return;
    }

    if (m_returnDescriptors.empty()) {
        return;
    }

    //m_plugin->s2e()->getDebugStream() << "ESP AT RETURN 0x" << std::hex << esp <<
    //        " plgstate=0x" << this << " EmitSignal=" << emitSignal <<  std::endl;

    bool finished = true;
    do {
        finished = true;
        std::pair<ReturnDescriptorsMap::iterator, ReturnDescriptorsMap::iterator>
                range = m_returnDescriptors.equal_range(esp);
        for(ReturnDescriptorsMap::iterator it = range.first; it != range.second; ++it) {
            if (m_plugin->m_monitor) {
                cr3 = m_plugin->m_monitor->getPid(state, pc);
            }

            if(it->second.cr3 == cr3) {
                if (emitSignal) {
                    it->second.signal.emit(state);
                }
                m_returnDescriptors.erase(it);
                finished = false;
                break;
            }
        }
    } while(!finished);
}
Example #9
0
void S2EEventLogger::extractCallStack(S2EExecutionState *state,
        int &stack_size) {
#ifdef TARGET_I386
    stack_size = 0;
    target_long frame_pointer;

    callstack_[stack_size++] = state->getPc();

    if (!state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBP]),
            &frame_pointer, sizeof(frame_pointer))) {
        return;
    }

    // XXX: Hack, hack, hack: Handle the case where EBP was pushed
    // on the stack by a concrete syscall.
    if (!frame_pointer) {
        ref<Expr> head = state->readMemory(state->getSp(), Expr::Int32,
                S2EExecutionState::VirtualAddress);
        if (ConstantExpr *ce = dyn_cast<ConstantExpr>(head)) {
            frame_pointer = ce->getZExtValue();
        } else {
            return;
        }
    }

    while (frame_pointer && stack_size < CollectEventMaxStackDepth) {
        ref<Expr> next_expr = state->readMemory(frame_pointer, Expr::Int32,
                S2EExecutionState::VirtualAddress);
        ref<Expr> retaddr_expr = state->readMemory(frame_pointer + sizeof(target_ulong),
                Expr::Int32, S2EExecutionState::VirtualAddress);

        if (retaddr_expr.isNull())
            return;

        if (ConstantExpr *ce = dyn_cast<ConstantExpr>(retaddr_expr)) {
            callstack_[stack_size++] = ce->getZExtValue();
        } else {
            return;
        }

        if (next_expr.isNull())
            return;

        if (ConstantExpr *ce = dyn_cast<ConstantExpr>(next_expr)) {
            frame_pointer = ce->getZExtValue();
        } else {
            return;
        }
    }
#else
    stack_size = 0;
#endif
}
Example #10
0
void MemoryManager::onFunctionReturn(S2EExecutionState* state,bool test)
{
	//s2e()->getMessagesStream() << "---onFunctionReturn" << '\n';
	//get address
	state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]),&address , 4);
	//s2e()->getMessagesStream() << "分配的address (eax):" << hexval(address) << '\n';
	//check?
	//因为s2e本身的机制,在此处得到的分配长度size会是具体化过的,
	//所以不能在此处检测分配的size,应当在调用的时候进行检测
	//而return之后会再符号化
	
	//grant();//如果保存所有的__kmalloc,vector会崩 TODO
}
Example #11
0
void BaseInstructions::concretize(S2EExecutionState *state, bool addConstraint)
{
    uint32_t address, size;

    bool ok = true;
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]),
                                         &address, 4);
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]),
                                         &size, 4);

    if(!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_op "
               " get_example opcode" << std::endl;
        return;
    }

    for(unsigned i = 0; i < size; ++i) {
        ref<Expr> expr = state->readMemory8(address + i);
        if(!expr.isNull()) {
            if(addConstraint) { /* concretize */
                expr = s2e()->getExecutor()->toConstant(*state, expr, "request from guest");
            } else { /* example */
                expr = s2e()->getExecutor()->toConstantSilent(*state, expr);
            }

            if(!state->writeMemory(address + i, expr)) {
                s2e()->getWarningsStream(state)
                    << "Can not write to memory"
                    << " at " << hexval(address + i) << std::endl;
            }
        } else {
            s2e()->getWarningsStream(state)
                << "Can not read from memory"
                << " at " << hexval(address + i) << std::endl;
        }
    }
}
Example #12
0
void DasosPreproc::fuzzFork (S2EExecutionState* state, unsigned int start, unsigned int end) {
   /** Emulate fork via WindowsApi forkRange Code */
   unsigned int i;
   
   //assert(m_functionMonitor);
   klee::ref<klee::Expr> symb = state->createSymbolicValue (klee::Expr::Int32, "fuzz_symb");
   S2EExecutionState *curState = state;
   // by making this 1 shy of iterations you can leverage i value afterwards and the first input state so it doesn't go to waste
   for (i = start; i < end; i++) {
      //s2e()->getDebugStream () << "fuzzClone: 2 " << std::endl;
      klee::ref<klee::Expr> cond = klee::NeExpr::create (symb, klee::ConstantExpr::create (i, klee::Expr::Int32) );
      //s2e()->getDebugStream () << "fuzzClone: 3 " << std::endl;
      klee::Executor::StatePair sp = s2e()->getExecutor()->fork (*curState, cond, false);
      //s2e()->getDebugStream () << "fuzzClone: 4 " << std::endl;
      S2EExecutionState *ts = static_cast<S2EExecutionState *>(sp.first);
      S2EExecutionState *fs = static_cast<S2EExecutionState *>(sp.second);
      fs->writeCpuRegisterConcrete (CPU_OFFSET(regs[R_EAX]), &(i), 4); // set the return value
      curState = ts;
   }
   
   state->writeCpuRegisterConcrete (CPU_OFFSET(regs[R_EAX]), &(i), 4); // set the return value
   return;
} // end fn fuzzFork
void BaseInstructions::printMemory(S2EExecutionState *state)
{
    uint32_t address, size, name; // XXX should account for 64 bits archs
    bool ok = true;
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]),
                                         &address, 4);
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]),
                                         &size, 4);
    ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ECX]),
                                         &name, 4);

    if(!ok) {
        s2e()->getWarningsStream(state)
            << "ERROR: symbolic argument was passed to s2e_op "
               "print_expression opcode\n";
        return;
    }

    std::string nameStr = "<NO NAME>";
    if(name && !state->readString(name, nameStr)) {
        s2e()->getWarningsStream(state)
                << "Error reading string from the guest\n";
    }

    s2e()->getMessagesStream() << "Symbolic memory dump of " << nameStr << '\n';

    for (uint32_t i=0; i<size; ++i) {

        s2e()->getMessagesStream() << hexval(address+i) << ": ";
        ref<Expr> res = state->readMemory8(address+i);
        if (res.isNull()) {
            s2e()->getMessagesStream() << "Invalid pointer\n";
        }else {
            s2e()->getMessagesStream() << res << '\n';
        }
    }
}
void BaseInstructions::sleep(S2EExecutionState *state)
{
    uint32_t duration = 0;
    state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &duration, sizeof(uint32_t));
    s2e()->getDebugStream() << "Sleeping " << duration << " seconds\n";

    llvm::sys::TimeValue startTime = llvm::sys::TimeValue::now();

    while (llvm::sys::TimeValue::now().seconds() - startTime.seconds() < duration) {
        #ifdef _WIN32
        Sleep(1000);
        #else
        ::sleep(1);
        #endif
    }
}
Example #15
0
/**
 *  A call handler can invoke this function to register a return handler.
 *  XXX: We assume that the passed execution state corresponds to the state in which
 *  this instance of FunctionMonitorState is used.
 */
void X86FunctionMonitorState::registerReturnSignal(S2EExecutionState *state, X86FunctionMonitor::ReturnSignal &sig)
{
    if(sig.empty()) {
        return;
    }

    target_ulong esp;

    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ESP]),
                                             &esp, sizeof esp);
    if(!ok) {
        m_plugin->s2e()->getWarningsStream(state)
            << "Function call with symbolic ESP!\n"
            << "  EIP=" << hexval(state->getPc()) << " CR3=" << hexval(state->getPid()) << '\n';
        return;
    }

    uint64_t pid = state->getPid();
    if (m_plugin->m_monitor) {
        pid = m_plugin->m_monitor->getPid(state, state->getPc());
    }
    ReturnDescriptor descriptor = {pid, sig };
    m_returnDescriptors.insert(std::make_pair(esp, descriptor));
}
Example #16
0
/* Uses a custom instruction within the binary
 * must #include s2e.h in guest code source 
 * (our custom insns start around line 350 in s2e.h
 * Also must #define DASOS_PREPROC_OPCODE 0xFA line 49 in Opcodes.h
 */
void DasosPreproc::onCustomInstruction (S2EExecutionState* state, uint64_t opcode) {
   if (!OPCODE_CHECK(opcode, DASOS_PREPROC_OPCODE)) {
      return;
   }

   bool ok = true;
         
   opcode >>= 16;
   uint8_t op = opcode & 0xFF;
   opcode >>= 8;
   switch (op) {
      case 1:
         //static inline void s2e_dasospreproc_init (unsigned base, unsigned size, unsigned eip, unsigned sysc)
         // Module load
         // eax = runtime load base
         // ebx = length of memory
         // ecx = goal eip
      
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &(cfg.base_addr), 4);
         cfg.base_addr = cfg.base_addr & 0xffffffff;
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]), &(cfg.byte_len), 4);
         cfg.byte_len = cfg.byte_len & 0xffffffff;
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ECX]), &(cfg.eip_addr), 4);
         cfg.eip_addr = cfg.eip_addr & 0xffffffff;
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EDX]), &(cfg.sysc), 4);
         cfg.sysc = cfg.sysc & 0xffffffff;
         cfg.end_addr = cfg.base_addr + cfg.byte_len;

         if (!ok) {
            s2e()->getWarningsStream (state) << "ERROR: symbolic argument was passed to s2e_op in DasosPreproc loadmodule" << std::endl;
            return;
         }
         onActivateModule (state);
         break;
      case 2:
         // static inline unsigned int s2e_dasospreproc_fuzz (unsigned int start, unsigned int end)
         // time to start fuzzing a particular variable
         // eax = return value
         // ebx = start of range value
         // ecx = end of range value
         uint64_t start;
         uint64_t end;
         
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]), &(start), 4);
         start = start & 0xffffffff;
         if (!ok) s2e()->getWarningsStream (state) << "ERROR: bad argument was passed to s2e_op: start " << start << " in DasosPreproc start fuzzing" << std::endl;
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ECX]), &(end), 4);
         end = end & 0xffffffff;
         if (!ok) s2e()->getWarningsStream (state) << "ERROR: bad argument was passed to s2e_op: end " << end << " in DasosPreproc start fuzzing" << std::endl;

         if (!ok) return;
         
         if (start > end) {
            s2e()->getWarningsStream (state) << "ERROR: start (" << start << ") > end (" << end << ") is invalid range in DasosPreproc start fuzzing" << std::endl;
            return;
         }
         
         s2e()->getDebugStream () << ">> fuzzInit: datum to be iterated from " << start << " to " << end << std::endl; 

         // if there is no need to fork
         if (start == end) {
            state->writeCpuRegisterConcrete (CPU_OFFSET(regs[R_EAX]), &(start), 4);
            break;
         }
         // the following functions found in S2EExecutionState
         if (state->needToJumpToSymbolic () ) {
            // the state must be symbolic in order to fork
            state->jumpToSymbolic ();
         }
         // in case forking isn't enabled, enable it here
         if (!(state->isForkingEnabled () ) ) {
            state->enableForking ();
         }
         fuzzFork (state, start, end);
         break;
      case 4:
         // static inline unsigned int s2e_dasospreproc_createFork (unsigned int value)
         // return 2 states, 0 set to 0xffffffff and 1 set to value
         // eax = return value
         // ebx = value
         
         uint64_t value;
         ok &= state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_EBX]), &(value), 4);
         value = value & 0xffffffff;
         if (!ok) {
            s2e()->getWarningsStream (state) << "ERROR: bad argument was passed to s2e_op: start " << value << " in DasosPreproc start fuzzing" << std::endl;
            return;
         }
         s2e()->getDebugStream () << ">> fuzzInit: datum forking for value " << value << std::endl; 
         
         // the following functions found in S2EExecutionState
         if (state->needToJumpToSymbolic () ) {
            // the state must be symbolic in order to fork
            state->jumpToSymbolic ();
         }
         // in case forking isn't enabled, enable it here
         if (!(state->isForkingEnabled () ) ) {
            state->enableForking ();
         }
         fuzzFork1 (state, value);
         break;
      case 6 :
         onFini (state);
         break;
      default :
         s2e()->getWarningsStream (state) << "ERROR: invalid opcode" << std::endl;
   }
   return;
} // end fn DasosPreproc::onCustomInstruction
Example #17
0
/**
 *  When emitSignal is false, this function simply removes all the return descriptors
 * for the current stack pointer. This can be used when a return handler manually changes the
 * program counter and/or wants to exit to the cpu loop and avoid being called again.
 *
 *  Note: all the return handlers will be erased if emitSignal is false, not just the one
 * that issued the call. Also note that it is not possible to return from the handler normally
 * whenever this function is called from within a return handler.
 */
void FunctionMonitorState::slotRet(S2EExecutionState *state, uint64_t pc, bool emitSignal)
{
target_ulong pid;
target_ulong sp;
#ifdef TARGET_ARM
	assert(m_plugin->m_monitor);
	pid = m_plugin->m_monitor->getPid(state, pc);

    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[13]),
                                             &sp, sizeof(target_ulong));
    if(!ok) {
        target_ulong pc = state->readCpuState(CPU_OFFSET(regs[15]),
                                               8*sizeof(target_ulong));
        m_plugin->s2e()->getWarningsStream(state)
            << "Function return with symbolic ESP!" << std::endl
            << "  PC=" << hexval(pc) << /*" PID=" << hexval(pid) <<*/ std::endl;
        return;
    }
#elif defined(TARGET_I386)
	pid = state->readCpuState(CPU_OFFSET(cr[3]), 8*sizeof(target_ulong));
    bool ok = state->readCpuRegisterConcrete(CPU_OFFSET(regs[R_ESP]),
                                             &sp, sizeof(target_ulong));
    if(!ok) {
    	target_ulong pc = state->readCpuState(CPU_OFFSET(eip),
                                               8*sizeof(target_ulong));
        m_plugin->s2e()->getWarningsStream(state)
            << "Function return with symbolic ESP!" << std::endl
            << "  PC=" << hexval(pc) << /*" PID=" << hexval(pid) <<*/ std::endl;
        return;
    }
#else
	assert(false);
#endif

    if (m_returnDescriptors.empty()) {
        return;
    }

    //m_plugin->s2e()->getDebugStream() << "ESP AT RETURN 0x" << std::hex << esp <<
    //        " plgstate=0x" << this << " EmitSignal=" << emitSignal <<  std::endl;

    bool finished = true;

    do {
        finished = true;
        std::pair<ReturnDescriptorsMap::iterator, ReturnDescriptorsMap::iterator>
                range = m_returnDescriptors.equal_range(sp);
        for(ReturnDescriptorsMap::iterator it = range.first; it != range.second; ++it) {
            if (m_plugin->m_monitor) {
                pid = m_plugin->m_monitor->getPid(state, pc);
            }

            if(it->second.pid == pid) {
                if (emitSignal) {
                    it->second.signal.emit(state);
                }
                m_returnDescriptors.erase(it);
                finished = false;
                break;
            }
        }
    } while(!finished);
}
Example #18
0
void CooperativeSearcher::onCustomInstruction(S2EExecutionState* state, uint64_t opcode)
{
    //XXX: find a better way of allocating custom opcodes
    if (!OPCODE_CHECK(opcode, COOPSEARCHER_OPCODE)) {
        return;
    }

    uint8_t op = OPCODE_GETSUBFUNCTION(opcode);

    bool ok = true;
    target_ulong nextState = 0;

    CoopSchedulerOpcodes opc = (CoopSchedulerOpcodes)op;
    switch(opc) {
        //Pick the next state specified as input ergument
        case ScheduleNext:
        {
            ok &= state->readCpuRegisterConcrete(CPU_OFFSET(COOPSEARCHER_NEXTSTATE),
                                                 &nextState, sizeof nextState);
            if(!ok) {
                s2e()->getWarningsStream(state)
                    << "ERROR: symbolic argument was passed to s2e_op "
                       "CooperativeSearcher ScheduleNext" << '\n';
                break;
            }

            States::iterator it = m_states.find(nextState);
            if (it == m_states.end()) {
                s2e()->getWarningsStream(state)
                    << "ERROR: Invalid state passed to " <<
                    "CooperativeSearcher ScheduleNext: " << nextState << '\n';
            }

            m_currentState = (*it).second;

            s2e()->getMessagesStream(state) <<
                    "CooperativeSearcher picked the state " << nextState << '\n';

            //Force rescheduling
            state->setPc(state->getPc() + S2E_OPCODE_SIZE);
            throw CpuExitException();
            break;
        }

        //Deschedule the current state. Will pick the state with strictly lower id.
        case Yield:
        {
            if (m_states.size() == 1) {
                break;
            }

            States::iterator it = m_states.find(m_currentState->getID());
            if (it == m_states.begin()) {
                m_currentState = (*m_states.rbegin()).second;
            }else {
                --it;
                m_currentState = (*it).second;
            }

            //Force rescheduling
            state->setPc(state->getPc() + S2E_OPCODE_SIZE);
            throw CpuExitException();
            break;
        }
    }
}
/** Handle s2e_op instruction. Instructions:
    0f 3f XX XX XX XX XX XX XX XX
    XX: opcode
 */
void BaseInstructions::handleBuiltInOps(S2EExecutionState* state, uint64_t opcode)
{
    switch((opcode>>8) & 0xFF) {
        case 0: { /* s2e_check */
                uint32_t v = 1;
                state->writeCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &v, 4);
            }
            break;
        case 1: state->enableSymbolicExecution(); break;
        case 2: state->disableSymbolicExecution(); break;

        case 3: { /* s2e_make_symbolic */
            makeSymbolic(state, false);
            break;
        }

        case 4: { /* s2e_is_symbolic */
            isSymbolic(state);
            break;
        }

        case 5: { /* s2e_get_path_id */
            state->writeCpuRegister(offsetof(CPUX86State, regs[R_EAX]),
                klee::ConstantExpr::create(state->getID(), klee::Expr::Int32));
            break;
        }

        case 6: { /* s2e_kill_state */
            killState(state);
            break;
            }

        case 7: { /* s2e_print_expression */
            printExpression(state);
            break;
        }

        case 8: { //Print memory contents
            printMemory(state);
            break;
        }

        case 9:
            state->enableForking();
            break;

        case 10:
            state->disableForking();
            break;

        case 0x10: { /* s2e_print_message */
            printMessage(state, opcode >> 16);
            break;
        }

        case 0x11: { /* s2e_make_concolic */
            makeSymbolic(state, true);
            break;
        }

        case 0x20: /* concretize */
            concretize(state, true);
            break;

        case 0x21: { /* replace an expression by one concrete example */
            concretize(state, false);
            break;
        }

        case 0x30: { /* Get number of active states */
            uint32_t count = s2e()->getExecutor()->getStatesCount();
            state->writeCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &count, sizeof(uint32_t));
            break;
        }

        case 0x31: { /* Get number of active S2E instances */
            uint32_t count = s2e()->getCurrentProcessCount();
            state->writeCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &count, sizeof(uint32_t));
            break;
        }
        case 0x32: { /* Sleep for a given number of seconds */
           sleep(state);
           break;
        }

        case 0x50: { /* disable/enable timer interrupt */
            uint64_t disabled = opcode >> 16;
            if(disabled)
                s2e()->getMessagesStream(state) << "Disabling timer interrupt\n";
            else
                s2e()->getMessagesStream(state) << "Enabling timer interrupt\n";
            state->writeCpuState(CPU_OFFSET(timer_interrupt_disabled),
                                 disabled, 8);
            break;
        }
        case 0x51: { /* disable/enable all apic interrupts */
            uint64_t disabled = opcode >> 16;
            if(disabled)
                s2e()->getMessagesStream(state) << "Disabling all apic interrupt\n";
            else
                s2e()->getMessagesStream(state) << "Enabling all apic interrupt\n";
            state->writeCpuState(CPU_OFFSET(all_apic_interrupts_disabled),
                                 disabled, 8);
            break;
        }

        case 0x52: { /* Gets the current S2E memory object size (in power of 2) */
                uint32_t size = S2E_RAM_OBJECT_BITS;
                state->writeCpuRegisterConcrete(CPU_OFFSET(regs[R_EAX]), &size, 4);
                break;
        }

        case 0x70: /* merge point */
            state->jumpToSymbolicCpp();
            s2e()->getExecutor()->queueStateForMerge(state);
            break;

        default:
            s2e()->getWarningsStream(state)
                << "BaseInstructions: Invalid built-in opcode " << hexval(opcode) << '\n';
            break;
    }
}