WinXP SP2 user32.dll ValidateHandle(HWND h)
/****************************************
tEST jS
WinXP SP2 user32.dll ValidateHandle(HWND h)
OK, 你如果看到这篇文章,你现在把她当草稿吧。
*****************************************/
ValidateHandleMacro(pci, pobj, h, bType); /* 这是一个宏函数定义在 wow.c 中。 详细实现
#define ValidateHandleMacro(pci, pobj, h, bType) /
StartValidateHandleMacro(h) /
BeginAliveValidateHandleMacro() /
BeginTypeValidateHandleMacro(pobj, bType) /
DESKTOPVALIDATE(pci, pobj) /
EndTypeValidateHandleMacro /
EndAliveValidateHandleMacro() /
EndValidateHandleMacro
注意以上宏的次序不可更换,这是由于他们的实现方式使然。
接着开始逐个分析。
*/
以下是 用IDA 解析的 user32.dll 中相关的源代码片断。
.text:77D18520 mov eax, large fs:18h ; eax = TEB
.text:77D18526 mov ecx, dword_77D70080 ; ecx = gpsi
.text:77D1852C lea ebx, [eax+6CCh] ; ebx = TEB.Win32ClientInfo;
关于fs:18 在许多帖子上有解释,它是TEB的地址。
关于TEB的结构不同版本的windows各有不小的差距。如果你在任何帖子看到一些所谓的TEB的结构,并且所给出的结构没有类似 #if VER_PRODUCTBUILD>xxxx 这样对不同版本分类,那么千万不要太当真。 毕竟,我曾经看过好多帖子,上面的TEB+6CCh 是存在于 GDI_TEB_BATCH GdiTebBatch; 这个大成员中。 把我迷惑了好久........>_< 害人不浅。我推荐看这里的: http://www.acc.umu.se/~bosse/ntifs.h <-这个是ReactOS中的TEB结构。这里是 TEB.Win32ClientInfo. 也就是宏函数中的pci。(pci: pointer of ClientInfo)
gpsi 是一个全局变量,类型为PSERVERINFO,她的地址存在于77D70080 。 定义在globals.h中。gpsi中的一个成员变量cHandlesEntries是句柄入口的个数。在ValidateHandleMacro中检查句柄有重要作用。
{
PHE phe;
DWORD dwIndex;
WORD uniq;
dwIndex = HMIndexFromHandle(h);
if ( dwIndex < gpsi->cHandleEntries) {
phe = &gSharedInfo.aheList[dwIndex ];
uniq = HMUniqFromHandle(h);
if ( uniq == phe->wUniq || uniq == 0 || uniq == HMUNIQBITS )
{
/* Macro End */
/*
mov eax, edi ; eax = hWnd
and eax, 0FFFFh ; dwIndex = eax = HMIndexFromHandle(hWnd);
;以上代码就是 */
dwIndex = HMIndexFromHandle(h);
/*
cmp eax, [ecx+8]
jnb short loc_77D1858B ; dwIndex >= gpsi->cHandleEntries ?
; goto 77D1858B
;以上代码就是 */
if ( dwIndex < gpsi->cHandleEntries)
{
/*接着就是:
mov ecx, dword_77D700A4 ; 77D700A4 = &gSharedInfo.aheList ;
lea eax, [eax+eax*2] ;因为aheList的大小是3个DWORD, 这条语句用lea
;完成了eax*3的操作,这里不用乘法语句是因为用
;lea 短小。应该是聪明的编译器的功劳:-)
lea ecx, [ecx+eax*4] ; phe = &gSharedInfo.aheList[dwIndex];
; ECX = phe = aheList + sizeof(HANDLEENTRY)*dwIndex;
;以上代码就是 */
phe = &gSharedInfo.aheList[dwIndex ];
mov eax, edi ; eax = hWnd;
shr eax, 10h ; uniq = EAX = (HIWORD)hWnd
;以上代码就是 */
uniq = HMUniqFromHandle(h);
/*
cmp ax, [ecx+0Ah] ; cmp uniq phe.wUniq
jnz loc_77D1E5D0 ; if( uniq != phe.wUniq )
goto 77D1E5D0
........
.text:77D1E5D0 test ax, ax ; if( ax == 0 )
jz loc_77D18559; goto 77D18559
cmp ax, 0FFFFh;if( ax!= 0xFFFF )
jnz loc_77D1858B;goto 77D1858B
jmp loc_77D18559
;以上代码就是 */
if ( uniq == phe->wUniq || uniq == 0 || uniq == HMUNIQBITS )
{
以上就是StartValidateHandleMacro(h)的源代码。从源代码可以知道为什么这些宏不能改变次序了。
接着我们看看
BeginAliveValidateHandleMacro()
/*
test byte ptr [ecx+9], 1 ; if( phe.bFlags != HANDLEF_DESTROY )
jnz short loc_77D1858B ; goto 77D1858B;
;以上代码就是*/
if (!(phe->bFlags & HANDLEF_DESTROY))
{
这是一个非常简单的宏函数。
下面展示的是
BeginTypeValidateHandleMacro(pobj, bType)
/*
mov al, [ecx+8] ; al = phe.bType;
cmp al, dl ; if( phe.bType != bType ){
jnz loc_77D1DB7F ; goto 77D1DB7F;
;以上代码就是*/
if ((phe->bType == bTypeTest) || /
(bTypeTest == TYPE_GENERIC && phe->bType != TYPE_FREE)) { /
/
/* /
* Instead of try/except we use the heap range check /
* mechanism to verify that the given 'pwnd' belongs to /
* the default desktop. We also have to do a Win 3.1 like /
* check to make sure the window is not deleted /
* See NT bug 12242 Kitchen app. Also 6479 /
* /
* TESTDESKOP returns the handle if the handle is valid /
* in the current desktop /
*/ /
pobj = phe->phead; /
{
{
NIT nit;
.......
W32CLIENTINFO clientInfo;
......
}TEB;
WORD wRIPFlags; // RIPF_ flags
WORD wSRVIFlags; // SRVIF_ flags
WORD wRIPPID; //PID of process to apply RIP flags to (zero means all)
WORD wRIPError; // Error to break on (zero means all errors are treated equal)
KERNEL_ULONG_PTR cHandleEntries; // count of handle entries in array /*0x08*/
........
}SERVERINFO;
.text:77D18559 test byte ptr [ecx+9], 1 ; if( phe.bFlags != HANDLEF_DESTROY ){
.text:77D1855D jnz short loc_77D1858B ; goto 77D1858B;
.text:77D1855D ; }
.text:77D1855F mov al, [ecx+8] ; al = phe.bType;
.text:77D18562 cmp al, dl ; if( phe.bType != bType ){
.text:77D18564 jnz loc_77D1DB7F ; goto 77D1DB7F;
.text:77D18564 ; }
typedef struct tagSHAREDINFO {
PSERVERINFO psi;
PHE aheList; /* handle table pointer ......
}SHAREDINFO, *PSHA