diff --git a/scanners/thread_scanner.cpp b/scanners/thread_scanner.cpp index 7cec0ec1..f414ef14 100644 --- a/scanners/thread_scanner.cpp +++ b/scanners/thread_scanner.cpp @@ -175,7 +175,7 @@ std::string pesieve::ThreadScanner::choosePreferredFunctionName(const std::strin return dbgSymbol; } -bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vector& callStack) +bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vector& callStack, IN OUT ThreadScanReport& my_report) { if (this->info.last_syscall == INVALID_SYSCALL || !symbols || !callStack.size() || !info.is_extended || !g_SyscallTable.isReady()) { return true; // skip the check @@ -187,12 +187,14 @@ bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vectorinfo.ext.wait_reason == Suspended && lastFuncCalled == "RtlUserThreadStart" && this->info.last_syscall == 0) { return true; //normal for suspended threads @@ -208,9 +210,11 @@ bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vectorinfo.last_syscall); + my_report.lastSyscall = syscallFuncName; if (syscallFuncName.empty()) { return true; // skip the check } + if (SyscallTable::isSameSyscallFunc(syscallFuncName, lastFuncCalled)) { return true; // valid } @@ -370,7 +374,7 @@ size_t pesieve::ThreadScanner::analyzeCallStackInfo(IN OUT ThreadScanReport& my_ checkCalls = false; } if (checkCalls) { - my_report.cDetails.is_ret_as_syscall = checkReturnAddrIntegrity(my_report.cDetails.callStack); + my_report.cDetails.is_ret_as_syscall = checkReturnAddrIntegrity(my_report.cDetails.callStack, my_report); } return analyzedCount; } diff --git a/scanners/thread_scanner.h b/scanners/thread_scanner.h index b0124b8d..19fa12e2 100644 --- a/scanners/thread_scanner.h +++ b/scanners/thread_scanner.h @@ -137,6 +137,49 @@ namespace pesieve { return true; } + const bool threadInfoToJSON(std::stringstream& outs, size_t level, const pesieve::t_json_level& jdetails) + { + OUT_PADDED(outs, level, "\"state\" : "); + if (thread_state == THREAD_STATE_UNKNOWN) { + outs << "\"" << "UNKNOWN" << "\""; + } + else { + outs << "\"" << translate_thread_state(thread_state) << "\""; + } + if (thread_state == THREAD_STATE_WAITING) { + outs << ",\n"; + OUT_PADDED(outs, level, "\"wait_reason\" : "); + outs << "\"" << translate_wait_reason(thread_wait_reason) << "\""; + } + if (stack_ptr) { + outs << ",\n"; + OUT_PADDED(outs, level, "\"callstack\" : {\n"); + callstackToJSON(outs, level + 1, jdetails); + outs << "\n"; + OUT_PADDED(outs, level, "}"); + } + bool showLastCall = (jdetails >= JSON_DETAILS) ? true : false; + if ((this->indicators.find(THI_SUS_CALLS_INTEGRITY) != this->indicators.end()) || + (this->indicators.find(THI_SUS_CALLSTACK_CORRUPT) != this->indicators.end()) ) + { + showLastCall = true; + } + if (showLastCall) { + if (!this->lastSyscall.empty()) { + outs << ",\n"; + OUT_PADDED(outs, level, "\"last_sysc\" : "); + outs << "\"" << this->lastSyscall << "\""; + } + if (!this->lastFunction.empty() && (this->lastFunction != this->lastSyscall)) { + outs << ",\n"; + OUT_PADDED(outs, level, "\"last_func\" : "); + outs << "\"" << this->lastFunction << "\""; + } + } + outs << "\n"; + return true; + } + const bool indicatorsToJSON(std::stringstream& outs, size_t level, const pesieve::t_json_level& jdetails) { OUT_PADDED(outs, level, "\"indicators\" : ["); @@ -147,6 +190,7 @@ namespace pesieve { outs << "\"" << indicator_to_str(*itr) << "\""; } outs << "]"; + return true; } const virtual void fieldsToJSON(std::stringstream &outs, size_t level, const pesieve::t_json_level &jdetails) @@ -155,25 +199,10 @@ namespace pesieve { outs << ",\n"; OUT_PADDED(outs, level, "\"thread_id\" : "); outs << std::dec << tid; - if (thread_state != THREAD_STATE_UNKNOWN) { - outs << ",\n"; - OUT_PADDED(outs, level, "\"thread_state\" : "); - outs << "\"" << translate_thread_state(thread_state) << "\""; - - if (thread_state == THREAD_STATE_WAITING) { - outs << ",\n"; - OUT_PADDED(outs, level, "\"thread_wait_reason\" : "); - outs << "\"" << translate_wait_reason(thread_wait_reason) << "\""; - } - } - if (stack_ptr) { - outs << ",\n"; - OUT_PADDED(outs, level, "\"callstack\" : {\n"); - callstackToJSON(outs, level + 1, jdetails); - outs << "\n"; - OUT_PADDED(outs, level, "}"); - } - + outs << ",\n"; + OUT_PADDED(outs, level, "\"thread_info\" : {\n"); + threadInfoToJSON(outs, level + 1, jdetails); + OUT_PADDED(outs, level, "}"); outs << ",\n"; indicatorsToJSON(outs, level, jdetails); @@ -207,6 +236,9 @@ namespace pesieve { DWORD thread_wait_reason; DWORD thread_wait_time; + std::string lastSyscall; + std::string lastFunction; + ctx_details cDetails; std::set shcCandidates; std::set indicators; @@ -242,7 +274,7 @@ namespace pesieve { size_t analyzeCallStackInfo(IN OUT ThreadScanReport& my_report); size_t _analyzeCallStack(IN OUT ctx_details& cDetails, OUT IN std::set& shcCandidates); - bool checkReturnAddrIntegrity(IN const std::vector& callStack); + bool checkReturnAddrIntegrity(IN const std::vector& callStack, IN OUT ThreadScanReport& my_report); bool fillAreaStats(ThreadScanReport* my_report); bool reportSuspiciousAddr(ThreadScanReport* my_report, ULONGLONG susp_addr);