MSDN.WhiteKnight - Stack Overflow answers
Ответ на "базовый адрес потока"
Answer 830885
Можно использовать NtQueryInformationThread:
#include <stdio.h> #include <windows.h> #include <Winternl.h> LPVOID GetThreadAddress(DWORD thid){ HANDLE thread = OpenThread(THREAD_ALL_ACCESS,FALSE,thid); if(thread == NULL || thread == INVALID_HANDLE_VALUE) {wprintf(L"OpenThread failed");return NULL;} HMODULE hm=LoadLibrary(L"ntdll.dll"); if(hm == NULL){ wprintf (L"LoadLibrary failed\n"); return NULL;} NTSTATUS (__stdcall *NtQueryInformationThread ) (IN HANDLE , IN THREADINFOCLASS , OUT PVOID, IN ULONG, OUT PULONG OPTIONAL ) = (NTSTATUS (__stdcall *) (IN HANDLE , IN THREADINFOCLASS , OUT PVOID , IN ULONG , OUT PULONG OPTIONAL)) GetProcAddress(hm,"NtQueryInformationThread"); if(NtQueryInformationThread == NULL){ wprintf (L"GetProcAddress failed\n"); return NULL;} LPVOID info=NULL; NTSTATUS ntstatus = NtQueryInformationThread(thread,(THREADINFOCLASS)9 ,&info,sizeof(info),NULL); if(ntstatus != 0) {wprintf (L"NtQueryInformationThread NTSTATUS 0x%x\n",(UINT)ntstatus); return NULL;} else return info; }
При наличии отладочных символов также можно получить стек с помощью DbgHelp и пройти его до тех пор, пока не встретится системная функция создания потока (BaseThreadInitThunk):
#include <stdlib.h> #include <stdio.h> #include <windows.h> #include <process.h> #include "DbgHelp.h" #pragma comment(lib, "Dbghelp.lib") const int MaxNameLen = 256; LPVOID GetThreadAddress2( DWORD thid ) { BOOL result; HANDLE process; HANDLE thread = OpenThread(THREAD_ALL_ACCESS,FALSE,thid); if(thread == NULL || thread == INVALID_HANDLE_VALUE) {printf("OpenThread failed");return 0;} CONTEXT cont={0}; cont.ContextFlags = CONTEXT_DEBUG_REGISTERS|CONTEXT_INTEGER|CONTEXT_CONTROL; SuspendThread(thread); result = GetThreadContext(thread,&cont); if(result == FALSE) {printf("GetThreadContext failed\n");return 0;} ResumeThread(thread); STACKFRAME64 stack; ULONG frame; DWORD64 displacement; char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; char name[ MaxNameLen ]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; ULONG64 prevaddr = 0; char prevname[MaxNameLen]; memset( &stack, 0, sizeof( STACKFRAME64 ) ); process = GetCurrentProcess(); displacement = 0; #if !defined(_M_AMD64) stack.AddrPC.Offset = (cont).Eip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrStack.Offset = (cont).Esp; stack.AddrStack.Mode = AddrModeFlat; stack.AddrFrame.Offset = (cont).Ebp; stack.AddrFrame.Mode = AddrModeFlat; #endif result = SymInitialize( process, NULL, TRUE ); //загружаем символы if(result == FALSE) {printf("SymInitialize failed\n"); return 0;} for( frame = 0; ; frame++ ) { //получаем следующий вызов из стека result = StackWalk64 ( #if defined(_M_AMD64) IMAGE_FILE_MACHINE_AMD64 #else IMAGE_FILE_MACHINE_I386 #endif , process, thread, &stack, &cont, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL ); if( !result ) break; //получаем имя символа для адреса pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; result = SymFromAddr(process, ( ULONG64 )stack.AddrPC.Offset, &displacement, pSymbol); if(result == FALSE) {printf("SymFromAddr failed");continue;} if(lstrcmpA(pSymbol->Name,"BaseThreadInitThunk") == 0){ break; } lstrcpyA(prevname,pSymbol->Name); prevaddr = ( ULONG64 )pSymbol->Address; } return (LPVOID)prevaddr; }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.