线程控制

实验

零基础逆向工程34_Win32_08_线程控制_CONTEXT结构-LMLPHP

挂起线程

::SuspendThread(hThread);

恢复线程

::ResumeThread(hThread);

终止线程 (这里讲了同步调用与异步调用)

方式一:	此方法结束线程会自动清理堆栈

::ExitThread(DWORD dwExitCode);

方式二:

线程函数返回

方式三:	而此方法结束线程不会自动清理堆栈

::TerminateThread(hThread,2);
::WaitForSingleObject(hThread,INFINITE);

判断线程是否结束

BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);

STILL_ACTIVE 正在运行

参数:
hThread: 要结束的线程句柄
dwExitCode: 指定线程的退出代码。可以通过GetExitCodeThread来查看一个线程的退出代码

线程:CONTEXT结构

起因

每个线程在执行的时候,都会独自占用一个CPU,当系统中的线程数量 > CPU的数量时,就会存在多个线程共用一个CPU的情况。但CPU每次只能运行一个线程,Windows每隔20毫秒会进行线程的切换,那比如线程A执行到地址:0x2345678eax:1 ecx:2 edx:3 ebx:4...还有eflag标志寄存器中的值等等。此时,线程执行时间到了,被切换到了线程B。当线程B的时间片也到了,再切换会线程A时,系统是如何知道该从哪个地址开始执行呢?被切换前用到的各种寄存器的值该如何恢复呢?

那么就用到了CONTEXT结构

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);

这段代码有什么安全隐患?什么原因导致的?

HWND hEdit ;
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
TCHAR szBuffer[10];
DWORD dwIndex = 0;
DWORD dwCount; while(dwIndex<10)
{
GetWindowText(hEdit,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit,szBuffer);
dwIndex++;
} return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
TCHAR szBuffer[10];
DWORD dwIndex = 0;
DWORD dwCount; while(dwIndex<10)
{
GetWindowText(hEdit,szBuffer,10);
sscanf( szBuffer, "%d", &dwCount );
dwCount++;
memset(szBuffer,0,10);
sprintf(szBuffer,"%d",dwCount);
SetWindowText(hEdit,szBuffer);
dwIndex++;
} return 0;
} BOOL CALLBACK MainDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
BOOL bRet = FALSE; switch(uMsg)
{
case WM_CLOSE:
{
EndDialog(hDlg,0);
break;
}
case WM_INITDIALOG:
{
hEdit = GetDlgItem(hDlg,IDC_EDIT1);
SetWindowText(hEdit,"0"); break;
}
case WM_COMMAND: switch (LOWORD (wParam))
{
case IDC_BUTTON_T1:
{
HANDLE hThread1 = ::CreateThread(NULL, 0, ThreadProc1,
NULL, 0, NULL); ::CloseHandle(hThread1);
return TRUE;
}
case IDC_BUTTON_T2:
{
HANDLE hThread2 = ::CreateThread(NULL, 0, ThreadProc2,
NULL, 0, NULL); ::CloseHandle(hThread2);
return TRUE;
}
}
break ;
} return bRet;
} int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here. DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDlgProc); return 0;
}
05-28 19:54