Drecik学习经验分享
转载请注明出处:http://blog.csdn.net/drecik__/article/details/8095311
系统使用CONTEXT对象来记住线程的状态,这样线程在下一次获得CPU可以运行时,就可以从上次停止处继续,WinNT.h的头文件中给出了CONTEXT的数据结构,但是需要注意的是,成员的具体情况取决于Windows运行在什么CPU上。下面给出CONTEXT的结构:
typedef struct _CONTEXT { // // The flags values within this flag control the contents of // a CONTEXT record. // // If the context record is used as an input parameter, then // for each portion of the context record controlled by a flag // whose value is set, it is assumed that that portion of the // context record contains valid context. If the context record // is being used to modify a threads context, then only that // portion of the threads context will be modified. // // If the context record is used as an IN OUT parameter to capture // the context of a thread, then only those portions of the thread's // context corresponding to set flags will be returned. // // The context record is never used as an OUT only parameter. // DWORD ContextFlags; // 标志,用来标志该结构体哪些结构可用; // // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT // included in CONTEXT_FULL. // // 标识CPU的调试寄存器; DWORD Dr0; DWORD Dr1; DWORD Dr2; DWORD Dr3; DWORD Dr6; DWORD Dr7; // // This section is specified/returned if the // ContextFlags word contians the flag CONTEXT_FLOATING_POINT. // // 标识CPU的浮点寄存器; FLOATING_SAVE_AREA FloatSave; // // This section is specified/returned if the // ContextFlags word contians the flag CONTEXT_SEGMENTS. // // 标识CPU的段寄存器; DWORD SegGs; DWORD SegFs; DWORD SegEs; DWORD SegDs; // // This section is specified/returned if the // ContextFlags word contians the flag CONTEXT_INTEGER. // // 标识CPU的整数寄存器; DWORD Edi; DWORD Esi; DWORD Ebx; DWORD Edx; DWORD Ecx; DWORD Eax; // // This section is specified/returned if the // ContextFlags word contians the flag CONTEXT_CONTROL. // // 标识CPU的控制寄存器; DWORD Ebp; DWORD Eip; DWORD SegCs; // MUST BE SANITIZED DWORD EFlags; // MUST BE SANITIZED DWORD Esp; DWORD SegSs; // // This section is specified/returned if the ContextFlags word // contains the flag CONTEXT_EXTENDED_REGISTERS. // The format and contexts are processor specific // // 标识CPU的扩展寄存器; BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; } CONTEXT;程序可以通过调用函数GetThreadContext来获取线程的上下文,但需要在线程挂起的时候调用,否则返回信息就不一致了:
BOOL GetThreadContext( HANDLE hThread, // 线程句柄; LPCONTEXT lpContext // 上下文指针; );调用这个函数之前先分配一个CONTEXT结构,并在ContextFlags成员中使用标志需要获取的寄存器的值,多种可以使用异或,例如下面代码:
// 获取hThread线程的控制寄存器和浮点寄存器; CONTEXT Context; Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT; GetThreadContext( hThread, &Context );
需要再次强调下,获得的各个成员所代表的寄存器是依赖于CPU的
既然可以获取CONTEXT的值,也可以设置CONTEXT的值,调用SetThreadContext即可,调用之前还是需要挂起线程,否则结果无法预料:
BOOL SetThreadContext( HANDLE hThread, // 线程句柄; CONST LPCONTEXT lpContext // 上下文指针; );首先还是要分配一个CONTEXT对象, 并在ContextFlags成员中使用标志需要设置的寄存器的值,多种可以使用异或,例如下面代码:
// 设置hThread线程的Eip寄存器; CONTEXT Context; Context.ContextFlags = CONTEXT_CONTROL; GetThreadContext( hThread, &Context ); Context.Eip = 0x00010000; Context.ContextFlags = CONTEXT_CONTROL; SetThreadContext( hThread, &Context );上面代码可能会早晨远程线程的访问违规,系统会向用户显示一个异常的消息框,然后终止远程进程(注意,是远程进程),在我们自己继续正常执行的同时,可以成功使另一个进程崩溃。