【问题标题】:Finding another thread's Thread Information Block查找另一个线程的线程信息块
【发布时间】:2011-05-11 15:35:53
【问题描述】:

有没有办法找到在您的进程中运行的另一个线程的线程信息块 (TIB)?

我需要为另一个线程构建一个异常处理程序,但我不能在线程本身中执行它。因此我需要找到它的 TIB 并从另一个线程中构建它。我怎样才能做到这一点?

【问题讨论】:

  • 我不认为你可以改变任何线程的 TIB ......可能甚至在内核模式下也不能。
  • 当然可以,它只是一个内存数据结构。这样做是个糟糕的主意,但它不是魔法——它处于用户模式。
  • @Paul Betts,你也知道怎么做吗?
  • @Paul,如果您真的愿意,您可以随时更改您想要的任何内容,但这并不是说这是一个好主意。我只是从 POV 说的,一般来说,摆弄它不是一个好主意。
  • 我同意 floyd73 的回答:您可以使用GetThreadContext 获取FS 选择器并获取TIB。但是我不完全理解“构造异常处理程序”的意思。你的意思是你想用你的处理程序显式地添加一个 SEH 异常注册 record 到链中吗?请注意,AFAIK SEH 注册记录必须按内存降序排列(这是针对内存损坏的操作系统保护)。通常没有问题,因为此类记录是在堆栈上分配的,但您的方法可能存在问题

标签: windows multithreading seh


【解决方案1】:

您可以直接从 FS 寄存器访问 TIB 的地址(检查 http://www.microsoft.com/msj/archive/S2CE.aspx)。 因此,要获取另一个线程的 TIB,也许可以使用 GetThreadContext() 来获取 FS 的值,从而获取 TIB 的地址? (只是猜测,我没有尝试过!)

【讨论】:

  • 我试试这个,似乎可以使用这个 API 检索另一个线程的 FS 寄存器:DWORD SegGs;双字分段;双字分段;
【解决方案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, &context)) {
    CloseHandle(thread_handle);
    return;
  }

  LDT_ENTRY ldtSel;
  if (!GetThreadSelectorEntry(thread_handle, context.SegFs, &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 @ 0x%08X\n", 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=vs.85).aspx

完整的示例程序:http://pastebin.com/gSTcPz1y

【讨论】:

    【解决方案3】:

    这可能行不通,但请尝试queueing a user-mode APC 到设置您的异常处理程序的目标线程。

    【讨论】:

      【解决方案4】:

      你可以得到一个线程的 TIB,但是改变它我很怀疑你能做到。

      正如 Paul 正确指出的那样,这只会获取它使用它的线程的 TIB,因此我建议在您需要此数据的线程中调用它,然后将其移动到您需要使用它的线程。

      要获得它,您可以使用类似的东西,描述为here

      // Microsoft C
      void *getTib()
      {
          void *pTib;
          __asm {
              mov EAX, FS:[0x18]
              mov [pTib], EAX
          }
          return pTib;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-10-19
        • 2016-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多