经过相当多的谷歌搜索和here的一些提示后,我终于设法FS
段的find a layout(由windows用来存储TIB数据)。我特别感兴趣的是PSDK中提供的ArbitraryUserPointer
成员:
typedef struct _NT_TIB {
struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
PVOID StackBase;
PVOID StackLimit;
PVOID SubSystemTib;
union {
PVOID FiberData;
DWORD Version;
};
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self;
} NT_TIB;
使用此变量究竟有多安全(在Vista及以上)?它在x64上是否仍然存在?
次要的是访问此变量。我正在使用MSVC,因此我
可以访问__readfsdword
&但是,__readgsqword
内在函数MSDN由于某种原因将这些标记为特权指令:
这些内在函数仅在内核模式下可用,并且这些例程仅作为内在函数提供。
它们当然只是 不 内核,但为什么它们被标记为这样,只是不正确的文档? (我的离线VS 2008文档没有此条款)。
最后,通过单个ArbitraryUserPointer
直接访问__readfsdword(0x14)
是安全的还是首选通过线性TIB地址使用它? (仍然需要从FS
读取。)
答案 0 :(得分:5)
ArbitraryUserPointer
是一个不常用的内部字段。操作系统在内部使用它,如果你覆盖它,你将破坏东西。我承认它名字很差。
答案 1 :(得分:0)
如果您还在寻找答案,我也遇到了同样的问题并发布了我的问题,与您的问题类似:
Thread-local storage in kernel mode?
我需要内核模式驱动程序中的TLS等效项。确切地说,我有一个深层函数调用树,它起源于某个点(例如驱动程序的调度例程),我需要传递上下文信息。
在我的特定情况下,问题是我不需要持久性存储,我只需要一个特定于线程的占位符来处理单个顶级函数调用。因此,我决定在TLS数组中使用任意条目进行函数调用,并在完成后 - 恢复其原始值。
您可以通过以下方式获取TLS阵列:
DWORD* get_Tls()
{
return (DWORD*) (__readfsdword(0x18) + 0xe10);
}
BTW我不知道为什么通常通过阅读fs:[0x18]
的内容来访问TIB。它只是由fs
选择器指出。但这就是所有MS代码访问它的方式,因此我决定也这样做。
接下来,您选择任意TLS索引,例如0。
const DWORD g_dwMyTlsIndex = 0;
void MyTopLevelFunc()
{
// prolog
DWORD dwOrgVal = get_Tls()[g_dwMyTlsIndex];
get_Tls()[g_dwMyTlsIndex] = dwMyContextValue;
DoSomething();
// epilog
get_Tls()[g_dwMyTlsIndex] = dwOrgVal;
}
void DoSomething()
{
DWORD dwMyContext = get_Tls()[g_dwMyTlsIndex];
}