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
                                                                注意以上宏的次序不可更换,这是由于他们的实现方式使然。
                                                                接着开始逐个分析。
                                                                 */

/* 首先解释一下pci, pobj, h, bType 这些变量的来源。
    以下是 用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中检查句柄有重要作用。
        


#define StartValidateHandleMacro(h)     /                                   
{                                                                          
            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()

#define 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)

#define BeginTypeValidateHandleMacro(pobj, bTypeTest) /
            /*
             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;                                          /
                {                        

 

typdef _TEB
{
NIT   nit;
.......
W32CLIENTINFO    clientInfo;
......
}TEB;



 

typedef struct tagSERVERINFO {       // si
      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;

 

test

 

test2


.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

posted on 2006-07-30 22:53  norsd  阅读(381)  评论(0编辑  收藏  举报

导航