소스 설명
- process id 를 가지고 snapshot 을 얻는다.
- snapshot 에서 thread id 를 얻는다.
- thread id 를 이용해서 handle 을 얻는다.
- 이 handle 을 이용해서 context 를 얻는다.
source from : Gray hat python
edited by namh
edited by namh
thread_entry = THREADENTRY32() thread_list = [] # http://msdn.microsoft.com/en-us/library/windows/desktop/ms682489(v=vs.85).aspx snapshot = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, self.pid) if snapshot is not None: thread_entry.dwSize = sizeof(thread_entry) success = kernel32.Thread32First(snapshot, byref(thread_entry)) while success: if thread_entry.th32OwnerProcessID == self.pid: thread_id = thread_entry.th32ThreadID thread_list.append(thread_entry.th32ThreadID) # Get a thread context context = CONTEXT() context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS, None, thread_id) if kernel32.GetThreadContext(h_thread, byref(context)): kernel32.CloseHandle(h_thread) return context else: return False success = kernel32.Thread32Next(snapshot, byref(thread_entry)) kernel32.CloseHandle(snapshot) return thread_list else: return False
Process
CreateProcess()
을 입힌 parameter 가 우리가 관심을 가져야 할 녀석들이다.BOOL WINAPI CreateProcess( _In_opt_ LPCTSTR lpApplicationName, _Inout_opt_ LPTSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCTSTR lpCurrentDirectory, _In_ LPSTARTUPINFO lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation );
- lpApplicationName : 실행할 application, 즉, 실행될 녀석의 path
- lpCommandLine : 실행할 command line
- dwCreateionFlags : 이 flag 로 priority class 와 process 의 생성을 control 할 수 있다.
이 flag로 실행할 process 를 debugged process 로 설정할 수 있다.(DEBUG_PROCESS 0x00000001)
OpenProcess
HANDLE WINAPI OpenProcess( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwProcessId );
OpenProcess 는 이미 존재하고 있는 process 에 특정권한으로 접근하겠다고 요청하면 그에 해당하는 handle 를 돌려준다.
- dwDesiredAccess : 열려고 하는 process 에 대해서 얻고 싶은 권한을 명시해 주면 된다.
debugging 을 위해서는 PROCESS_ALL_ACCESS 로 설정해야 한다. - dwProcessId : 우리가 handle을 얻고 싶어하는 process 의 PID
handle 은 WinNT.h 에 아래와 같이 정의되어 있다.[ref. 3]
typedef PVOID HANDLE;
thread
Traversing the Thread List 을 보면 아래 함수들을 어떻게 사용하는지에 대해 이해가 쉬울 것이다.ThreadCotext 얻기
- thread_id 얻기 : thread 을 traversing 하면서 thread_id 를 얻을 수 있다.
- thread_handle 얻기 : 여기서 얻은 thread_id 를 가지고 OpenThread 를 하면, thread 의 handle 을 얻을 수 있다.
- context 얻기 : 이 handle 을 가지고 GetThreadContext() 를 이용해서 Thread 와 관련된 값들(register 값들) 을 얻을 수 있다.
OpenThread
HANDLE WINAPI OpenThread( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwThreadId );
CreateToolhelp32Snapshot function
HANDLE WINAPI CreateToolhelp32Snapshot( _In_ DWORD dwFlags, _In_ DWORD th32ProcessID );
dwFlags 를 TH32CS_SNAPTHREAD(0x00000004) 로 하면 등록된 thread 의 snapshot 의 handle을 얻게 된다. 이 handle 이 Thread32First() 에 parameter 로 쓰인다.
아래 flag 에서만 th32ProcessID 가 사용된다. th32ProcessID 는 thread 를 가지고 있는 process 의 ID 를 적어준다.
- TH32CS_SNAPMODULE
- TH32CS_SNAPMODULE32
- TH32CS_SNAPHEAPLIST
- TH32CS_SNAPALL
Thread32First()
BOOL WINAPI Thread32First( _In_ HANDLE hSnapshot, _Inout_ LPTHREADENTRY32 lpte );
thread 를 열거할 때 쓰이는 함수이다.(enumerate)
lpte 는 함수가 성공적으로 수행되면 값이 할당된다.
THREADENTRY32
typedef struct tagTHREADENTRY32 { DWORD dwSize; DWORD cntUsage; DWORD th32ThreadID; DWORD th32OwnerProcessID; LONG tpBasePri; LONG tpDeltaPri; DWORD dwFlags; } THREADENTRY32, *PTHREADENTRY32;
parameters
- dwSize : Thread32First() 를 수행하기 전에 sizeof(THREADENTRY32) 로 초기화 해야 한다.
- th32ThreadID : thread 의 ID OpenThread() 로 얻은 thread 의 ID 를 사용하면 된다.
- th32OwnerProcessID : thread 가 있는 process 의 ID
GetThreadContext
BOOL WINAPI GetThreadContext( _In_ HANDLE hThread, _Inout_ LPCONTEXT lpContext );
SetThreadContext
BOOL WINAPI SetThreadContext( _In_ HANDLE hThread, _In_ const CONTEXT *lpContext );
Context structure
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;
References
- Windows Data Types, MSDN
- OpenThread function, MSDN
댓글 없음:
댓글 쓰기