Пытаюсь заполучить кол-стек через StackWalk64 и сотоварищи. Как не бйус апстену, а все что я получаю, это только: KiFastSystemCallRet SymFunctionTableAccess64 И все Может чего-то нехватает? Какой-то дополнительной инициализации чего-нибудь еще?
Почти разобрался. Осталась последняя проблема... Код (Text): SymInitialize(GetCurrentProcess(), 0, TRUE); SymSetOptions(SYMOPT_LOAD_LINES); CONTEXT context = CONTEXT(); RtlCaptureContext(&context); IMAGEHLP_MODULE64 module = IMAGEHLP_MODULE64(); module.SizeOfStruct = sizeof(module); SymGetModuleInfo64(GetCurrentProcess(), context.Eip, &module); // Возвращает FALSE :'-( Почему-то не удается получить инфу о модуле по виртуальному адресу в нем В чем может быть дело?
1. а ты уверен что context.Eip 64 бита? Код (Text): BOOL WINAPI SymGetModuleInfo64( __in HANDLE hProcess, __in [b]DWORD64[/b] dwAddr, __out PIMAGEHLP_MODULE64 ModuleInfo ); 2. попробуй обнулить IMAGEHLP_MODULE64. 3. в msdn о SymInitialize написанно:
Songoku 1. Не понял? Там же все функции 64. 2. IMAGEHLP_MODULE64 module = IMAGEHLP_MODULE64(); // Это и есть обнуление module. 3. Не работает при обычном запуске, не под дебагом.
1. А шо говорит GetLastError() ? 2. А context.Eip вообще содержит валидный адрес? (я-то понимаю, что должен, но всякое бывает )
Ursus 1. ERROR_INVALID_PARAMETER = 87 = The parameter is incorrect. 2. Нужно пологать что валидный, поскольку вся остальная инфа (имя функции, строка и т.д.) по нему резолвится корректно.
Сейчас вопрос вот в чем. Если для получения контекста потока делать RtlCaptureContext, то все работает, стек прекрасно снимается. Если же контекст получать через GetThreadContext, то ничего не работает :-( В чем же разница? Весь отстой в том, что RtlCaptureContext работает только для вызывающего потока, а мне надо научиться получать стек произвольного потока, на который есть права. PS. SuspendThread / ResumeThread делаю.
Clerk GetThreadContext-то отрабатывает нормально! Просто StackWalk64 не раскручивает стек по этим данным. Вот код: Код (Text): HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION, 0, process_id); HANDLE thread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT, 0, thread_id); SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); SymInitialize(process, 0, TRUE); CONTEXT context = {0}; context.ContextFlags = CONTEXT_FULL; GetThreadContext(thread, &context); STACKFRAME64 stackFrame = {0}; stackFrame.AddrPC.Offset = context.Eip; stackFrame.AddrPC.Mode = AddrModeFlat; stackFrame.AddrStack.Offset = context.Esp; stackFrame.AddrStack.Mode = AddrModeFlat; stackFrame.AddrFrame.Offset = context.Ebp; stackFrame.AddrFrame.Mode = AddrModeFlat; StackWalk64(IMAGE_FILE_MACHINE_I386, process, thread, &stackFrame, 0, 0, SymFunctionTableAccess64, SymGetModuleBase64, 0); SymGetModuleInfo64(process, stackFrame.AddrPC.Offset, &module); // Вот тут уже лажа, // а повторный StackWalk64 скажет что мол все, стек закончился. // Если же взять RtlCaptureContext, то все раскручивается нормально. // Но мне нужен сторонний поток, а не вызывающий :-(
Clerk Как их получить средствами WinAPI и C++ (без кернелмода и ассемблера)? Great esp и ebp они отличаются, поэтому и StackWalk64 себя по-разному ведет. А почему они отличаются, я не понимаю. Кроме того, GetThreadContext на вызывающем потоке вроде как нельзя юзать, потому что для получения контекста нужно предварительно заюзать SuspendThread, что, очевидно, для вызывающего потока не канает. Видимо поэтому и есть RtlCaptureContext.
Сравнил контексты. Т.к. нас интересуют только eip, ebp и esp, то сравнивать остальное нет смысла. Код (Text): CONTEXT context = {0}; context.ContextFlags = CONTEXT_FULL; GetThreadContext(thread, &context); RtlCaptureContext(&context); // ........................................ GetThreadContext RtlCaptureContext Eip: 0x7c90eb94 0x004120f6 Esp: 0x0012ee9c 0x0012fddc Ebp: 0x0012eeac 0x0012ff68 Объясните пожалуйста, откуда берется такая разница?
Да RtlCaptureContext выполняет примитивную инициализация структуры CONTEXT и всё. Вот как определяется Eip: mov eax,dword ptr ss:[ebp+4], причём сама функция регистр Ebp не изменяет. Ну уж если ты память средствами WinAPI и C++ прочитать не можешь, то что говорить..
Clerk Я не верю, что получение кол-стека не возможно без ассемблерных вставок. Я умею "читать память средствами WinAPI и C++". Дело вот в чем. MSDN: Такими вещами я никогда не пользуюсь. Если уж без нее никак, то просто подскажи откуда мне эту TEB можно вынуть.