今天看到了 線程的上下文 context 就覺得一件很有意思的事情 ,破解外掛的時候會遇到一件神奇的事情當外掛發現調試器 這個程序自己不知怎么了自己崩潰(通常說EIP 尋址錯誤啥額 或者內存不能讀寫 .......)
這個C++線程上下文 就是當你線程 掛起的時候 系統肯定要記錄這些寄存器以及eip的值 此時你可以讀取里面的值並且修改 當線程再次得到處理機 里面的值被隨便改了 肯定 會出錯 ....當然這里也可以hook 自己沒學到以后說
自己寫了一個簡單的異常函數
VOID SetiExcepTion() { //#define random(a,b) (rand()%(b-a)+a) 要定義它 CONTEXT cont; cont.ContextFlags = CONTEXT_CONTROL; HANDLE pseudoHandle = GetCurrentThread(); ::SuspendThread(pseudoHandle); BOOL ok = ::GetThreadContext(pseudoHandle, &cont); if (ok) { cont.Ebp = random(10000, 99999); cont.Esp = random(10000, 99999); cont.Eip = random(10000, 99999); SetThreadContext(pseudoHandle, &cont); ::ResumeThread(pseudoHandle);
CloseHandle(pseudoHandle); } }
或者直接內聯匯編
_asm
{
mov eax, 0
mov [eax], 1
}
程序也就崩潰了方式很多種
以下 來自滴水中級課件 總結不錯 作為本人筆記
每個線程在執行的時候,都會獨自占用一個CPU,當系統中的線程數量 > CPU的數量時,就會存在多個線程共用一個CPU
的情況。但CPU每次只能運行一個線程,Windows每隔20毫秒會進行線程的切換,那比如線程A執行到地址:0x2345678
eax:1 ecx:2 edx:3 ebx:4...還有eflag標志寄存器中的值等等。。。
此時,線程執行時間到了,被切換到了線程B。。。。當線程B的時間片也到了,再切換會線程A時,系統是如何知道該
從哪個地址開始執行呢?被切換前用到的各種寄存器的值該如何恢復呢?
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.
//
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.
//
FLOATING_SAVE_AREA FloatSave;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//
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.
//
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
//
BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;
獲取線程CONTEXT結構:
//掛起線程
SuspendThread(線程句柄);
CONTEXT context
//設置要獲取的類型
context.ContextFlags = CONTEXT_CONTROL;
//獲取
BOOL ok = ::GetThreadContext(hThread,&context);
//設置
context.Eip = 0x401000;
SetThreadContext(hThread,&context);