Skip to content

Commit

Permalink
feat: identify TB DR
Browse files Browse the repository at this point in the history
  • Loading branch information
hwk2077 committed Apr 13, 2023
1 parent e8cc852 commit 650f57f
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 14 deletions.
2 changes: 0 additions & 2 deletions klee/lib/Core/Executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,6 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
executeMemoryOperation(state, false, base, 0, ki);
break;
}
// TODO
case Instruction::Store: {
ref<Expr> base = eval(ki, 1, state).value;
ref<Expr> value = eval(ki, 0, state).value;
Expand Down Expand Up @@ -1791,7 +1790,6 @@ ref<Expr> Executor::executeMemoryOperation(ExecutionState &state, const ObjectSt
return NULL;
}

// TODO
void Executor::executeMemoryOperation(ExecutionState &state, bool isWrite, ref<Expr> address,
ref<Expr> value /* undef if read */, KInstruction *target /* undef if write */) {
Expr::Width type = (isWrite ? value->getWidth() : kmodule->getWidthForLLVMType(target->inst->getType()));
Expand Down
10 changes: 10 additions & 0 deletions libs2ecore/include/s2e/CorePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,16 @@ class CorePlugin : public Plugin {
uint64_t /* address */>
onInvalidPCAccess;

///
/// Signal that is emitted before accessing memory at symbolic address.
///
sigc::signal<void,
S2EExecutionState*,
uint64_t /* concrete address */,
klee::ref<klee::Expr> /* symbolic Data */,
bool /* is write */>
onSymbolicDataAccessConcreteMemory;

// clang-format on
};

Expand Down
8 changes: 5 additions & 3 deletions libs2ecore/src/FunctionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ static void handlerBeforeMemoryAccess(klee::Executor *executor, klee::ExecutionS

// 1st arg: virtual address
klee::ref<Expr> vaddr = args[0];
if (isa<klee::ConstantExpr>(vaddr)) {
return;
}

// 3rd arg: width
Expr::Width width = cast<klee::ConstantExpr>(args[2])->getZExtValue() * 8;
Expand All @@ -187,6 +184,11 @@ static void handlerBeforeMemoryAccess(klee::Executor *executor, klee::ExecutionS
S2EExecutionState *s2eState = static_cast<S2EExecutionState *>(state);

g_s2e->getCorePlugin()->onBeforeSymbolicDataMemoryAccess.emit(s2eState, vaddr, value, flags);

if (isa<klee::ConstantExpr>(vaddr) && isa<klee::Expr>(value) && !value->isZero()) {
g_s2e->getCorePlugin()->onSymbolicDataAccessConcreteMemory.emit(
s2eState, cast<klee::ConstantExpr>(vaddr)->getZExtValue(), value, flags);
}
}

void handlerAfterMemoryAccess(Executor *executor, ExecutionState *state, klee::KInstruction *target,
Expand Down
4 changes: 1 addition & 3 deletions libs2ecore/src/S2EExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,6 @@ void S2EExecutor::prepareFunctionExecution(S2EExecutionState *state, llvm::Funct
}
}

// TODO
inline bool S2EExecutor::executeInstructions(S2EExecutionState *state, unsigned callerStackSize) {
try {
while (state->stack.size() != callerStackSize) {
Expand All @@ -1097,7 +1096,6 @@ inline bool S2EExecutor::executeInstructions(S2EExecutionState *state, unsigned
}

state->stepInstruction();
// TODO
executeInstruction(*state, ki);

updateStates(state);
Expand Down Expand Up @@ -1369,7 +1367,7 @@ void S2EExecutor::cleanupTranslationBlock(S2EExecutionState *state) {
state->prevPC = 0;
state->pc = m_dummyMain->getInstructions();
}
// TODO

klee::ref<klee::Expr> S2EExecutor::executeFunction(S2EExecutionState *state, llvm::Function *function,
const std::vector<klee::ref<klee::Expr>> &args) {
assert(!state->isRunningConcrete());
Expand Down
105 changes: 101 additions & 4 deletions libs2eplugins/src/s2e/Plugins/uEmu/DataInputChannelDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ void DataInputChannelDetector::initialize() {

m_onStateForkConn =
s2e()->getCorePlugin()->onStateFork.connect(sigc::mem_fun(*this, &DataInputChannelDetector::onStateFork));
m_onSymbolicDataAccessConcreteMemoryConn = s2e()->getCorePlugin()->onSymbolicDataAccessConcreteMemory.connect(
sigc::mem_fun(*this, &DataInputChannelDetector::onSymbolicDataAccessConcreteMemory));
m_onBeforeSymbolicDataMemoryAccessConn = s2e()->getCorePlugin()->onBeforeSymbolicDataMemoryAccess.connect(
sigc::mem_fun(*this, &DataInputChannelDetector::onBeforeSymbolicDataMemoryAccess));
}

void DataInputChannelDetector::onMMIORead(S2EExecutionState *state, SymbolicHardwareAccessType type, uint32_t perifAddr,
Expand Down Expand Up @@ -99,6 +103,62 @@ void DataInputChannelDetector::onMMIORead(S2EExecutionState *state, SymbolicHard
}
}

void DataInputChannelDetector::onSymbolicDataAccessConcreteMemory(S2EExecutionState *state, uint64_t concreteAddr,
klee::ref<klee::Expr> symbVal, bool isWrite) {
s2e()->getDebugStream() << "[DataInputChannelDetector] onSymbolicDataAccessConcreteMemory"
<< "[concrete address: " << hexval(concreteAddr) << "] "
<< "[symbolic value: " << symbVal << "] "
<< "\n";

DECLARE_PLUGINSTATE(DataInputChannelDetectorState, state);
ReadPerifMap curStateReadPerifSizeMap = plgState->getReadPerifSizeMap();
ArrayVec results;
findSymbolicObjects(symbVal, results);
s2e()->getDebugStream() << "[size of results: " << results.size() << "] "
<< "\n";
for (int i = results.size() - 1; i >= 0; --i) {
uint32_t perifAddr;
uint32_t pc;
uint64_t hashVal;
uint64_t no;
auto &result = results[i];
std::vector<uint8_t> data;

getPeripheralExecutionState(result->getName(), &perifAddr, &pc, &hashVal, &no);

for (unsigned s = 0; s < result->getSize(); ++s) {
ref<Expr> e = state->concolics->evaluate(result, s);
if (!isa<ConstantExpr>(e)) {
getWarningsStream() << "Failed to evaluate concrete value\n";
pabort("Failed to evaluate concrete value");
}

uint8_t byteVal = dyn_cast<ConstantExpr>(e)->getZExtValue();
data.push_back(byteVal);
}

uint32_t condConcreteVal =
data[0] | ((uint32_t) data[1] << 8) | ((uint32_t) data[2] << 16) | ((uint32_t) data[3] << 24);

uint64_t LSB = ((uint64_t) 1 << (curStateReadPerifSizeMap[perifAddr].first * 8));
uint32_t val = condConcreteVal & (LSB - 1);

s2e()->getDebugStream() << "solve symbolic value: "
<< "[peripheral address: " << hexval(perifAddr) << "]"
<< "[pc: " << hexval(pc) << "]"
<< "[hash of pc and context: " << hexval(hashVal) << "]"
<< "[number of value: " << no << "]"
<< "[value: " << hexval(val) << "]"
<< "\n";
identifyTB(perifAddr, pc);
}
}

void DataInputChannelDetector::onBeforeSymbolicDataMemoryAccess(S2EExecutionState *state, klee::ref<klee::Expr> addr,
klee::ref<klee::Expr> val, bool isWrite) {
// for onSymbolicDataAccessConcreteMemory can be emitted
}

void DataInputChannelDetector::onStateFork(S2EExecutionState *state, const std::vector<S2EExecutionState *> &newStates,
const std::vector<klee::ref<klee::Expr>> &newConditions) {
s2e()->getDebugStream() << "[DataInputChannelDetector] onStateFork" << '\n';
Expand Down Expand Up @@ -163,14 +223,14 @@ void DataInputChannelDetector::onStateFork(S2EExecutionState *state, const std::
if (val != 0) {
m_IRQMMIOReadPerifPCToValSetMap[perifAddr][pc].insert(val);
}
identifyTA(state, perifAddr, pc);
identifyTA(perifAddr, pc);
}
}
}
identifyTC();
identifyTC();
}

void DataInputChannelDetector::identifyTA(S2EExecutionState *state, const uint32_t &perifAddr, const uint32_t &pc) {
void DataInputChannelDetector::identifyTA(const uint32_t &perifAddr, const uint32_t &pc) {
s2e()->getDebugStream() << "[DataInputChannelDetector] identifyTA "
<< "[peripheral address: " << hexval(perifAddr) << "] "
<< "[pc: " << hexval(pc) << "] " << '\n';
Expand Down Expand Up @@ -207,6 +267,43 @@ void DataInputChannelDetector::identifyTA(S2EExecutionState *state, const uint32
<< "\n";
}

void DataInputChannelDetector::identifyTB(const uint32_t &perifAddr, const uint32_t &pc) {
s2e()->getDebugStream() << "[DataInputChannelDetector] identifyTB "
<< "[peripheral address: " << hexval(perifAddr) << "] "
<< "[pc: " << hexval(pc) << "] " << '\n';
const auto &foundPossIRQCRSR = m_IRQMMIOReadPossCRSR.find(perifAddr);
if (foundPossIRQCRSR != m_IRQMMIOReadPossCRSR.end()) {
s2e()->getDebugStream() << "return, peripheral is a possible CR/SR in IRQ: " << hexval(perifAddr) << '\n';
return;
}

const auto &foundSamePerif = m_DRDetected.find(perifAddr);
if (foundSamePerif != m_DRDetected.end()) {
const auto &foundSamePC = m_DRDetected[perifAddr].find(pc);
if (foundSamePC != m_DRDetected[perifAddr].end()) {
s2e()->getDebugStream() << "return, already identified as DR: " << hexval(perifAddr) << '\n';
return;
}
m_DRDetected[perifAddr][pc] = m_IRQMMIOReadPerifPCToPerifSizeSetMap[perifAddr][pc];
s2e()->getDebugStream() << "Identified by TB: "
<< "[peripheral address: " << hexval(perifAddr) << "] "
<< "[pc: " << hexval(pc) << "] "
<< "\n";
return;
}

const auto &foundOverlap = m_IRQMMIOReadPerifPCToPerifSizeSetMap.find(perifAddr);
if (foundOverlap == m_IRQMMIOReadPerifPCToPerifSizeSetMap.end()) {
s2e()->getDebugStream() << "return, unable to find a overlap: " << hexval(perifAddr) << '\n';
return;
}
m_DRDetected[perifAddr][pc] = m_IRQMMIOReadPerifPCToPerifSizeSetMap[perifAddr][pc];
s2e()->getDebugStream() << "Identified by TB: "
<< "[peripheral address: " << hexval(perifAddr) << "] "
<< "[pc: " << hexval(pc) << "] "
<< "\n";
}

void DataInputChannelDetector::identifyTC() {
s2e()->getDebugStream() << "[DataInputChannelDetector] identifyTC" << '\n';
for (const auto &it : m_IRQMMIOReadPerifPCToValSetMap) {
Expand All @@ -223,7 +320,7 @@ void DataInputChannelDetector::identifyTC() {
const auto &foundSamePC = m_DRDetected[it.first].find(it2.first);
if (foundSamePC != m_DRDetected[it.first].end()) {
s2e()->getDebugStream() << "continue, already identified as DR: " << hexval(it.first) << '\n';
continue ;
continue;
}
}

Expand Down
27 changes: 25 additions & 2 deletions libs2eplugins/src/s2e/Plugins/uEmu/DataInputChannelDetector.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class DataInputChannelDetector : public Plugin {

private:
sigc::connection m_onStateForkConn;
sigc::connection m_onSymbolicDataAccessConcreteMemoryConn;
sigc::connection m_onBeforeSymbolicDataMemoryAccessConn;
hw::SymbolicHardware *m_symbolicHardwareConn;

PerifAddrPCToPerifSizeSetMap m_DRDetected;
Expand Down Expand Up @@ -71,11 +73,18 @@ class DataInputChannelDetector : public Plugin {
/**
* identify TA DR.
*
* @param state state to identify whether IRQ is triggered
* @param perifAddr peripheral address
* @param pc pc address
*/
void identifyTA(S2EExecutionState *state, const uint32_t &perifAddr, const uint32_t &pc);
void identifyTA(const uint32_t &perifAddr, const uint32_t &pc);

/**
* identify TB DR.
*
* @param perifAddr peripheral address
* @param pc pc address
*/
void identifyTB(const uint32_t &perifAddr, const uint32_t &pc);

/**
* identify TC DR.
Expand All @@ -97,6 +106,20 @@ class DataInputChannelDetector : public Plugin {
void onMMIORead(S2EExecutionState *state, SymbolicHardwareAccessType type, uint32_t perifAddr, unsigned perifSize,
uint32_t *val, bool *perifFlag, std::stringstream *ss);

/**
* callback for symbolic data access concrete memory.
*
* @param state s2e state
* @param concreteAddr concrete address
* @param symbVal symbolic data
* @param isWrite whether write or not
*/
void onSymbolicDataAccessConcreteMemory(S2EExecutionState *state, uint64_t concreteAddr,
klee::ref<klee::Expr> symbVal, bool isWrite);

void onBeforeSymbolicDataMemoryAccess(S2EExecutionState *state, klee::ref<klee::Expr> addr,
klee::ref<klee::Expr> val, bool isWrite);

/**
* callback when state fork
* @param state
Expand Down

0 comments on commit 650f57f

Please sign in to comment.