Windows核心编程学习笔记(13)--浅谈线程上下文

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

你可能感兴趣的:(thread,数据结构,编程,windows,struct,extension)