#windows #multithreading #seh
#Windows #многопоточность #seh
Вопрос:
Есть ли способ найти информационный блок потока (TIB) другого потока, запущенного в вашем процессе?
Мне нужно создать обработчик исключений для другого потока, но я не могу сделать это в самом потоке. Поэтому мне нужно найти его TIB и сконструировать его внутри другого потока. Как я могу этого добиться?
Комментарии:
1. Я не думаю, что вы можете изменить TIB какого-либо потока … вероятно, даже в режиме ядра.
2. Конечно, вы можете, это просто структура данных в памяти. Это ужасная идея сделать это, но это не волшебство — это в пользовательском режиме.
3. @Paul Betts, у вас также есть идея о том, как это сделать?
4. @Пол, ты всегда можешь изменить все, что пожелаешь, если действительно хочешь, но это не значит, что это хорошая идея. Я только говорил это от первого лица, что, как правило, не стоит возиться с этим.
5. Я согласен с ответом floyd73: вы можете использовать
GetThreadContext
для полученияFS
селектора и получить TIB. Однако я не совсем понимаю, что вы подразумеваете под «созданием обработчика исключений». Вы имеете в виду, что хотите явно добавить запись регистрации исключения SEH в цепочку с помощью вашего обработчика? Обратите внимание, что регистрационные записи AFAIK SEH должны поступать в порядке убывания памяти (это защита операционной системы от повреждения памяти). Обычно проблем не возникает, поскольку такие записи размещаются в стеке, но может возникнуть проблема с вашим подходом
Ответ №1:
Вы можете получить доступ к адресу TIB непосредственно из реестра FS (проверьте http://www.microsoft.com/msj/archive/S2CE.aspx ). Итак, чтобы получить TIB для другого потока, возможно, можно использовать GetThreadContext() для получения значения FS и, следовательно, адреса TIB? (просто предположение, я этого не пробовал!)
Комментарии:
1. Я попробую это, кажется, возможно получить регистр FS другого потока, используя этот API: DWORD SegGs; DWORD SegFs; DWORD SegEs;
Ответ №2:
void PrintTibAddress(DWORD thread_id) {
HANDLE thread_handle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, thread_id);
if (thread_handle == NULL) return;
SuspendThread(thread_handle);
CONTEXT context;
context.ContextFlags = CONTEXT_SEGMENTS;
if (!GetThreadContext(thread_handle, amp;context)) {
CloseHandle(thread_handle);
return;
}
LDT_ENTRY ldtSel;
if (!GetThreadSelectorEntry(thread_handle, context.SegFs, amp;ldtSel)) return;
ResumeThread(thread_handle);
DWORD fs_base = (ldtSel.HighWord.Bits.BaseHi << 24 ) | ( ldtSel.HighWord.Bits.BaseMid << 16 ) | ( ldtSel.BaseLow );
fwprintf(stdout, L"[i] FS:[0] (TIB) is @ 0xXn", fs_base);
}
Ссылки:
http://recxltd.blogspot.de/2012/02/from-archives-printing-seh-chain-from.html http://msdn.microsoft.com/en-us/library/windows/desktop/ms679362 (v = против 85).aspx
Полный пример программы:http://pastebin.com/gSTcPz1y
Ответ №3:
Это может не сработать, но попробуйте поставить APC пользовательского режима в очередь к целевому потоку, который настраивает ваш обработчик исключений.
Ответ №4:
Вы можете получить TIB потока, но я очень сомневаюсь, что вы сможете изменить его.
Как правильно указал Paul, это получает только TIB для потока, который его использовал, поэтому я предлагаю вызвать его в потоке, из которого вам нужны эти данные, а затем переместить их в поток, где вам нужно их использовать.
Чтобы получить его, вы можете использовать что-то вроде этого, описанного здесь:
// Microsoft C
void *getTib()
{
void *pTib;
__asm {
mov EAX, FS:[0x18]
mov [pTib], EAX
}
return pTib;
}