From 6f1b6b77bbf7dd0ee64ad6e7eaf3e45898b5726c Mon Sep 17 00:00:00 2001 From: Mattiwatti Date: Sat, 21 Oct 2017 22:59:38 +0200 Subject: [PATCH] dbg changes for TEB->LastStatusValue: - Add LASTSTATUS struct - Add LastStatus members to REGDUMP and THREADALLINFO - Add ThreadGetLastStatus()/ThreadGetLastStatusTEB() - Make "laststatus" a supported pseudo-register in isregister() / getregister() / setregister() similar to "lasterror" - _dbg_getregdump(): copy the full name of the last NTSTATUS value - ThreadGetList(): add the last status value to the thread list for each thread - TraceRecordManager: account for the size change of REGDUMP to keep REGDUMPWORD the same size --- src/dbg/TraceRecord.h | 6 +++--- src/dbg/_exports.cpp | 5 +++++ src/dbg/thread.cpp | 22 ++++++++++++++++++++++ src/dbg/thread.h | 2 ++ src/dbg/value.cpp | 11 +++++++++++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/dbg/TraceRecord.h b/src/dbg/TraceRecord.h index 3abc4f3c..7dbded47 100644 --- a/src/dbg/TraceRecord.h +++ b/src/dbg/TraceRecord.h @@ -87,8 +87,8 @@ private: { REGDUMP registers; // 172 qwords on x64, 216 dwords on x86. Almost no space left for AVX512 - // strip off 128 bytes of lastError.name member. - duint regword[(sizeof(REGDUMP) - 128) / sizeof(duint)]; + // strip off lastStatus and 128 bytes of lastError.name member. + duint regword[(FIELD_OFFSET(REGDUMP, lastError) + sizeof(DWORD)) / sizeof(duint)]; } REGDUMPWORD; //Key := page base, value := trace record raw data @@ -102,7 +102,7 @@ private: HANDLE rtFile; REGDUMPWORD rtOldContext; - bool rtOldContextChanged[(sizeof(REGDUMP) - 128) / sizeof(duint)]; + bool rtOldContextChanged[(FIELD_OFFSET(REGDUMP, lastError) + sizeof(DWORD)) / sizeof(duint)]; DWORD rtOldThreadId; bool rtNeedThreadId; duint rtOldMemory[32]; diff --git a/src/dbg/_exports.cpp b/src/dbg/_exports.cpp index 4e086532..2aefb206 100644 --- a/src/dbg/_exports.cpp +++ b/src/dbg/_exports.cpp @@ -666,6 +666,11 @@ extern "C" DLL_EXPORT bool _dbg_getregdump(REGDUMP* regdump, size_t size) lastError.code = ThreadGetLastError(ThreadGetId(hActiveThread)); strncpy_s(lastError.name, ErrorCodeToName(lastError.code).c_str(), _TRUNCATE); regdump->lastError = lastError; + LASTSTATUS lastStatus; + memset(&lastStatus.name, 0, sizeof(lastStatus.name)); + lastStatus.code = ThreadGetLastStatus(ThreadGetId(hActiveThread)); + strncpy_s(lastStatus.name, NtStatusCodeToName(lastStatus.code).c_str(), _TRUNCATE); + regdump->lastStatus = lastStatus; if(size >= sizeof(REGDUMP_V2)) { diff --git a/src/dbg/thread.cpp b/src/dbg/thread.cpp index 5ee887d7..16294dac 100644 --- a/src/dbg/thread.cpp +++ b/src/dbg/thread.cpp @@ -129,6 +129,7 @@ void ThreadGetList(THREADLIST* List) List->list[index].SuspendCount = ThreadGetSuspendCount(threadHandle); List->list[index].Priority = ThreadGetPriority(threadHandle); List->list[index].LastError = ThreadGetLastErrorTEB(itr.second.ThreadLocalBase); + List->list[index].LastStatus = ThreadGetLastStatusTEB(itr.second.ThreadLocalBase); GetThreadTimes(threadHandle, &List->list[index].CreationTime, &threadExitTime, &List->list[index].KernelTime, &List->list[index].UserTime); List->list[index].Cycles = ThreadQueryCycleTime(threadHandle); index++; @@ -228,6 +229,27 @@ DWORD ThreadGetLastError(DWORD ThreadId) return 0; } +NTSTATUS ThreadGetLastStatusTEB(ULONG_PTR ThreadLocalBase) +{ + // Get the offset for the TEB::LastStatusValue and read it + NTSTATUS lastStatus = 0; + duint structOffset = ThreadLocalBase + offsetof(TEB, LastStatusValue); + + MemReadUnsafe(structOffset, &lastStatus, sizeof(NTSTATUS)); + return lastStatus; +} + +NTSTATUS ThreadGetLastStatus(DWORD ThreadId) +{ + SHARED_ACQUIRE(LockThreads); + + if(threadList.find(ThreadId) != threadList.end()) + return ThreadGetLastStatusTEB(threadList[ThreadId].ThreadLocalBase); + + ASSERT_ALWAYS("Trying to get last status of a thread that doesn't exist!"); + return 0; +} + bool ThreadSetName(DWORD ThreadId, const char* Name) { EXCLUSIVE_ACQUIRE(LockThreads); diff --git a/src/dbg/thread.h b/src/dbg/thread.h index eef8f986..07611f90 100644 --- a/src/dbg/thread.h +++ b/src/dbg/thread.h @@ -19,6 +19,8 @@ int ThreadGetSuspendCount(HANDLE Thread); THREADPRIORITY ThreadGetPriority(HANDLE Thread); DWORD ThreadGetLastErrorTEB(ULONG_PTR ThreadLocalBase); DWORD ThreadGetLastError(DWORD ThreadId); +NTSTATUS ThreadGetLastStatusTEB(ULONG_PTR ThreadLocalBase); +NTSTATUS ThreadGetLastStatus(DWORD ThreadId); bool ThreadSetName(DWORD dwThreadId, const char* name); bool ThreadGetName(DWORD ThreadId, char* Name); HANDLE ThreadGetHandle(DWORD ThreadId); diff --git a/src/dbg/value.cpp b/src/dbg/value.cpp index 760d6a19..92509ce7 100644 --- a/src/dbg/value.cpp +++ b/src/dbg/value.cpp @@ -199,6 +199,8 @@ static bool isregister(const char* string) if(scmp(string, "lasterror")) return true; + if(scmp(string, "laststatus")) + return true; if(scmp(string, "gs")) return true; @@ -711,6 +713,13 @@ duint getregister(int* size, const char* string) return error; } + if(scmp(string, "laststatus")) + { + duint status = 0; + MemReadUnsafe((duint)GetTEBLocation(hActiveThread) + ArchValue(0xBF4, 0x1250), &status, 4); + return status; + } + if(size) *size = 2; if(scmp(string, "ax")) @@ -1166,6 +1175,8 @@ bool setregister(const char* string, duint value) if(scmp(string, "lasterror")) return MemWrite((duint)GetTEBLocation(hActiveThread) + ArchValue(0x34, 0x68), &value, 4); + if(scmp(string, "laststatus")) + return MemWrite((duint)GetTEBLocation(hActiveThread) + ArchValue(0xBF4, 0x1250), &value, 4); if(scmp(string, "gs")) return SetContextDataEx(hActiveThread, UE_SEG_GS, value & 0xFFFF);