void MemoryTracer::onCustomInstruction(S2EExecutionState* state, uint64_t opcode) { if (!OPCODE_CHECK(opcode, MEMORY_TRACER_OPCODE)) { return; } //XXX: remove this mess. Should have a function for extracting //info from opcodes. opcode >>= 16; uint8_t op = opcode & 0xFF; opcode >>= 8; MemoryTracerOpcodes opc = (MemoryTracerOpcodes)op; switch(opc) { case Enable: enableTracing(); break; case Disable: disableTracing(); break; default: s2e()->getWarningsStream() << "MemoryTracer: unsupported opcode " << hexval(opc) << '\n'; break; } }
void MemoryTracer::onCustomInstruction(S2EExecutionState* state, uint64_t opcode) { if (!OPCODE_CHECK(opcode, MEMORY_TRACER_OPCODE)) { return; } uint64_t subfunction = OPCODE_GETSUBFUNCTION(opcode); MemoryTracerOpcodes opc = (MemoryTracerOpcodes)subfunction; switch(opc) { case Enable: enableTracing(); break; case Disable: disableTracing(); break; default: s2e()->getWarningsStream() << "MemoryTracer: unsupported opcode " << hexval(opc) << '\n'; break; } }
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; } } }
/* 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