Skip to content

Commit

Permalink
[FEATURE] In ThreadScanReport: added information about last syscall a…
Browse files Browse the repository at this point in the history
…nd function called. Cleaned up report formatting
  • Loading branch information
hasherezade committed Feb 9, 2025
1 parent 6db9ed4 commit a7a4e3a
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 22 deletions.
8 changes: 6 additions & 2 deletions scanners/thread_scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ std::string pesieve::ThreadScanner::choosePreferredFunctionName(const std::strin
return dbgSymbol;
}

bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vector<ULONGLONG>& callStack)
bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vector<ULONGLONG>& 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
Expand All @@ -187,12 +187,14 @@ bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vector<ULONG
return true; // skip the check
}
const std::string lastFuncCalled = choosePreferredFunctionName(debugFuncName, manualSymbol);
my_report.lastFunction = lastFuncCalled;
if (lastFuncCalled.empty()) {
#ifdef _DEBUG
std::cout << "ERR: Can't fetch the name of the last function called!\n";
#endif
return false;
}

if (callStack.size() == 1) {
if (this->info.ext.wait_reason == Suspended && lastFuncCalled == "RtlUserThreadStart" && this->info.last_syscall == 0) {
return true; //normal for suspended threads
Expand All @@ -208,9 +210,11 @@ bool pesieve::ThreadScanner::checkReturnAddrIntegrity(IN const std::vector<ULONG
}
#endif
const std::string syscallFuncName = g_SyscallTable.getSyscallName(this->info.last_syscall);
my_report.lastSyscall = syscallFuncName;
if (syscallFuncName.empty()) {
return true; // skip the check
}

if (SyscallTable::isSameSyscallFunc(syscallFuncName, lastFuncCalled)) {
return true; // valid
}
Expand Down Expand Up @@ -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;
}
Expand Down
72 changes: 52 additions & 20 deletions scanners/thread_scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -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\" : [");
Expand All @@ -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)
Expand All @@ -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);

Expand Down Expand Up @@ -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<ULONGLONG> shcCandidates;
std::set<ThSusIndicator> indicators;
Expand Down Expand Up @@ -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<ULONGLONG>& shcCandidates);

bool checkReturnAddrIntegrity(IN const std::vector<ULONGLONG>& callStack);
bool checkReturnAddrIntegrity(IN const std::vector<ULONGLONG>& callStack, IN OUT ThreadScanReport& my_report);

bool fillAreaStats(ThreadScanReport* my_report);
bool reportSuspiciousAddr(ThreadScanReport* my_report, ULONGLONG susp_addr);
Expand Down

0 comments on commit a7a4e3a

Please sign in to comment.