Поиск информационного блока другого потока

#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;
}