初窥Windows内核——学习Windows Research Kernel手记(四)

STEP 3——记录/恢复用户栈

    有了前面的基础,要完成用户栈的记录也不是难事了。基本思路就是想办法找到用户栈的栈底地址,再找到栈顶地址,计算出栈的大小,然后调用函数PspRecordOrCopyData即可。

    栈顶的地址是由栈顶指针esp寄存器保存的。前面已经说过,在系统调用时,使用的是内核栈,所以当前的esp寄存器并不是我们所期望的。那么这个栈顶地址应该去哪儿找呢。答案还是在那个“陷阱帧”TrapFrame里。TrapFrame记录了用户线程的寄存器状态,里面自然就包括esp寄存器的状态了。

    剩下的就是获得栈底地址了。在Windows里,一个线程的用户空间的信息都记录在了TEB中,而TEB中又有一个域叫做NtTib,这里面就存放着有关用户站的信息。由于TEB结构过于复杂,这里只列举涉及到的,完整的定义在这一部分的末尾给出。

typedef struct PEBTEB_STRUCT(_TEB) {

PEBTEB_STRUCT(NT_TIB) NtTib;

….

}

typedef struct _NT_TIB {

    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;

    PVOID StackBase;

    PVOID StackLimit;

    PVOID SubSystemTib;

    union {

        PVOID FiberData;

        ULONG Version;

    };

    PVOID ArbitraryUserPointer;

    struct _NT_TIB *Self;

} NT_TIB;

    其中NtTib中的StackBase就是用户栈的基地址了。用户栈的大小只要用通过栈底地址和栈顶地址简单相减就可以得到了。

    对于用户栈的记录/恢复就这样得到了完成。

    下面是关于TEB的完整定义:

typedef struct PEBTEB_STRUCT(_TEB) {

    PEBTEB_STRUCT(NT_TIB) NtTib;

    PEBTEB_POINTER(PVOID) EnvironmentPointer;

    PEBTEB_STRUCT(CLIENT_ID) ClientId;

    PEBTEB_POINTER(PVOID) ActiveRpcHandle;

    PEBTEB_POINTER(PVOID) ThreadLocalStoragePointer;

    PEBTEB_POINTER(PPEB) ProcessEnvironmentBlock;

    ULONG LastErrorValue;

    ULONG CountOfOwnedCriticalSections;

    PEBTEB_POINTER(PVOID) CsrClientThread;

    PEBTEB_POINTER(PVOID) Win32ThreadInfo;          // PtiCurrent

    ULONG User32Reserved[26];       // user32.dll items

    ULONG UserReserved[5];          // Winsrv SwitchStack

    PEBTEB_POINTER(PVOID) WOW32Reserved;            // used by WOW

    LCID CurrentLocale;

    ULONG FpSoftwareStatusRegister; // offset known by outsiders!

    PEBTEB_POINTER(PVOID) SystemReserved1[54];      // Used by FP emulator

    NTSTATUS ExceptionCode;         // for RaiseUserException

    // 4 bytes of padding here on native 64bit TEB and TEB64

    PEBTEB_POINTER(PACTIVATION_CONTEXT_STACK) ActivationContextStackPointer; // Fusion activation stack

#if (defined(PEBTEB_BITS) && (PEBTEB_BITS == 64)) || (!defined(PEBTEB_BITS) && defined(_WIN64))

    UCHAR SpareBytes1[28]; // native 64bit TEB and TEB64

#else

    UCHAR SpareBytes1[40]; // native 32bit TEB and TEB32

#endif

    PEBTEB_STRUCT(GDI_TEB_BATCH) GdiTebBatch;      // Gdi batching

    PEBTEB_STRUCT(CLIENT_ID) RealClientId;

    PEBTEB_POINTER(HANDLE) GdiCachedProcessHandle;

    ULONG GdiClientPID;

    ULONG GdiClientTID;

    PEBTEB_POINTER(PVOID) GdiThreadLocalInfo;

    PEBTEB_POINTER(ULONG_PTR) Win32ClientInfo[WIN32_CLIENT_INFO_LENGTH]; // User32 Client Info

    PEBTEB_POINTER(PVOID) glDispatchTable[233];     // OpenGL

    PEBTEB_POINTER(ULONG_PTR) glReserved1[29];      // OpenGL

    PEBTEB_POINTER(PVOID) glReserved2;              // OpenGL

    PEBTEB_POINTER(PVOID) glSectionInfo;            // OpenGL

    PEBTEB_POINTER(PVOID) glSection;                // OpenGL

    PEBTEB_POINTER(PVOID) glTable;                  // OpenGL

    PEBTEB_POINTER(PVOID) glCurrentRC;              // OpenGL

    PEBTEB_POINTER(PVOID) glContext;                // OpenGL

    ULONG LastStatusValue;

    PEBTEB_STRUCT(UNICODE_STRING) StaticUnicodeString;

    WCHAR StaticUnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH];

    PEBTEB_POINTER(PVOID) DeallocationStack;

    PEBTEB_POINTER(PVOID) TlsSlots[TLS_MINIMUM_AVAILABLE];

    PEBTEB_STRUCT(LIST_ENTRY) TlsLinks;

    PEBTEB_POINTER(PVOID) Vdm;

    PEBTEB_POINTER(PVOID) ReservedForNtRpc;

    PEBTEB_POINTER(PVOID) DbgSsReserved[2];

    ULONG HardErrorMode;

    PEBTEB_POINTER(PVOID) Instrumentation[14];

    PEBTEB_POINTER(PVOID) SubProcessTag;

    PEBTEB_POINTER(PVOID) EtwTraceData;

    PEBTEB_POINTER(PVOID) WinSockData;              // WinSock

    ULONG GdiBatchCount;

    BOOLEAN InDbgPrint;

    BOOLEAN FreeStackOnTermination;

    BOOLEAN HasFiberData;

    BOOLEAN IdealProcessor;

    ULONG GuaranteedStackBytes;

    PEBTEB_POINTER(PVOID) ReservedForPerf;

    PEBTEB_POINTER(PVOID) ReservedForOle;

    ULONG WaitingOnLoaderLock;

    PEBTEB_POINTER(ULONG_PTR) SparePointer1;

    PEBTEB_POINTER(ULONG_PTR) SoftPatchPtr1;

    PEBTEB_POINTER(ULONG_PTR) SoftPatchPtr2;   

    PEBTEB_POINTER(PPVOID) TlsExpansionSlots;

#if (defined(_WIN64) && !defined(PEBTEB_BITS)) /

    || ((defined(_WIN64) || defined(_X86_)) && defined(PEBTEB_BITS) && PEBTEB_BITS == 64)

    //

    // These are in native Win64 TEB, Win64 TEB64, and x86 TEB64.

    //

    PEBTEB_POINTER(PVOID) DeallocationBStore;

    PEBTEB_POINTER(PVOID) BStoreLimit;

#endif   

    LCID ImpersonationLocale;       // Current locale of impersonated user

    ULONG IsImpersonating;          // Thread impersonation status

    PEBTEB_POINTER(PVOID) NlsCache;                 // NLS thread cache

    PEBTEB_POINTER(PVOID) pShimData;                // Per thread data used in the shim

    ULONG HeapVirtualAffinity;

    PEBTEB_POINTER(HANDLE) CurrentTransactionHandle;// reserved for TxF transaction context

    PEBTEB_POINTER(PTEB_ACTIVE_FRAME) ActiveFrame;

    PEBTEB_POINTER(PVOID) FlsData;

    BOOLEAN SafeThunkCall;

    BOOLEAN BooleanSpare [3];

   

} PEBTEB_STRUCT(TEB), *PEBTEB_STRUCT(PTEB);

 

你可能感兴趣的:(thread,windows,exception,struct,user,64bit)