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 );
上面代码可能会早晨远程线程的访问违规,系统会向用户显示一个异常的消息框,然后终止远程进程(注意,是远程进程),在我们自己继续正常执行的同时,可以成功使另一个进程崩溃。