走进Windows 2000 内部(二)
--Windows 源代码解读与发现
2 动态线程本地存储(TLS)
TEB(Thread Environment Block 线程环境块) 是另一个更为重要的与线程信息相关的数据结构,现在我只知道它的一部分信息。不过没有关系,有了SoftICE,我还是找到了与TLS相关的信息。在当前TEB后0x00000e10外,是当前线程TLS表,它的大小是0x40。
下面一段代码演示如何利用这个信息,对TLS进行操作。
PVOID GetCurrentTeb()
{
PTEB pTeb = NULL;
__asm
{
mov eax,fs:[00000018h]
mov pTeb , eax
}
return pTeb;
}
// 得到 TLS 值
PVOID WINAPI MyTlsGet(DWORD dwIndex)
{
if (dwIndex >= 0x40)
return FALSE;
DWORD* pTls = (DWORD* )GetCurrentTeb();
pTls = (DWORD *)((BYTE* )pTls + 0xe10);
return (PVOID)pTls[dwIndex];
}
// 设置 TLS值
BOOL WINAPI MyTlsSet(DWORD dwIndex , PVOID pValue)
{
if (dwIndex >= 0x40)
return FALSE;
DWORD* pTls = (DWORD* )GetCurrentTeb();
pTls = (DWORD *)((BYTE* )pTls + 0xe10);
pTls[dwIndex] = (DWORD)pValue;
return TRUE;
}
3 hotkey(热键)
毫无疑问,这个信息比上面那个更有用。因为Win32并没有提供对hotkey进行直接操作的接口。
在内部,这个管理是通过一个简单的链表来实现的,看下面的数据结构:
typedef struct tagHOTKEY {
PTHREADINFO pti; // 相关的线程信息,这个结构说过的
PWND spwnd; // 关联的窗口
WORD fsModifiers; // MOD_SHIFT, MOD_ALT, MOD_CONTROL, MOD_WIN
WORD wFlags; // MOD_SAS
UINT vk; // Virtual Key
int id; // ID
struct tagHOTKEY *phkNext; //支持链表的指针
} HOTKEY, *PHOTKEY;
加上注释就一目了然了。系统为我们维护一个这样的链表,在有键盘中断时,会对这个链表进行查询,在查询匹配时,将发送消息线指定的窗口。
现在的问题是找到链表的入口。这个入口是一个全局变量。利用SoftICE我找到了它在内存中的地址。不过在Windows的不同版本中这个值可能是不一样的。我使用的是 Windows 2000 Professional Sp4 (内部版本是 2195)。即使版本相同,如果你将你的系统设置成3GB的(不过在这个版本中,这样做没有任何好处,劝你不要这么做。),这个地址仍然会不同,现在我还没有找到好的办法解决这个问题。
下面的代码演示对hotkey的一些操作
// 定义了入口指针的地址
#define HOTKEY_LIST_HEAD (PHOTKEY* )(0xa01826c4)
typedef PHOTKEY HHOTKEY;
typedef struct tagHotKeyInfo
{
HWND hWnd;
WORD fsModifiers; // MOD_SHIFT, MOD_ALT, MOD_CONTROL, MOD_WIN
UINT vk;
int id;
}HotKeyInfo, *PHotKeyInfo;
// 得到入口地址
HHOTKEY WINAPI NtGetFirstHotKey()
{
PHOTKEY phk = NULL;
if (!ReadSysMemroy(&phk , HOTKEY_LIST_HEAD , sizeof(phk)))
return NULL;
return phk;
}
// 得到下一个入口
HHOTKEY WINAPI NtGetNextHotKey(HHOTKEY hHotKey)
{
PHOTKEY phk = NULL;
if (!ReadSysMemroy(&phk ,
memaddr(hHotKey , HOTKEY , phkNext) ,
sizeof(phk))
)
return NULL;
return phk;
}
// 得到完整的hotkeyinfo
BOOL WINAPI NtGetHotKeyInfo(HHOTKEY hHotKey , HotKeyInfo* hki)
{
HOTKEY hk;
if (!ReadSysMemroy(&hk , hHotKey , sizeof(hk)))
return FALSE;
HWND hwnd = NULL;
// WND 的信息还没有提供,不过hwnd在这个结构的0x0 处,你可以直接读取
if (!ReadSysMemroy(&hwnd , memaddr(hk.spwnd, WND, head.toh.head.h), sizeof(hwnd)))
hwnd = NULL;
hki->hWnd = hwnd;
hki->id = hk.id;
hki->fsModifiers = hk.fsModifiers;
hki->vk = hk.vk;
return TRUE;
}
// 搜索hotkey信息
PHOTKEY FindHotKey(HotKeyInfo* phki, BOOL bCheckK)
{
HotKeyInfo hki;
PHOTKEY phk;
phk = NtGetFirstHotKey();
while (phk)
{
if (!NtGetHotKeyInfo(phk , &hki))
break;
if (bCheckK)
{
if (hki.vk == phki->vk && hki.fsModifiers == phki->fsModifiers)
return phk;
}
else
{
if (hki.hWnd == phki->hWnd && hki.id == phki->id)
return phk;
}
phk = NtGetNextHotKey(phk);
}
return NULL;
}
// 设置hotkey信息
BOOL WINAPI NtSetHotKeyInfo(HotKeyInfo* phki)
{
PHOTKEY phk = FindHotKey(phki , TRUE);
if (phk)
return FALSE;
phk = FindHotKey(phki , FALSE);
if (!phk)
return FALSE;;
HOTKEY hk;
if (!ReadSysMemroy(&hk , phk , sizeof(hk)))
return FALSE;
hk.fsModifiers = phki->fsModifiers;
hk.vk = phki->vk;
return WriteSysMemroy(phk , &hk , sizeof(hk));
}
本文地址:http://com.8s8s.com/it/it1041.htm