解析Windows NT/2000窗口对象的组织(http://webcrazy.yeah.net/)

SSDTHook实现进程保护 SSDTHook实现进程保护:http://blog.csdn.net/php_fly/article/details/9202379 立即下载
解析Windows NT/2000窗口对象的组织 
                      WebCrazy( http://webcrazy.yeah.net/)

   Microsoft Visual Studio提供的Microsoft Spy对Windows的窗口组织有非常直观的表现,在Windows视图下的Window Properties可以显示窗口的很多内容或属性。本文将从Windows NT/2000内核出发,说明这些重要的结构在Windows NT/2000中的最底层的组织。
   先从窗口组织说起,大家知道枚举窗口可以通过EnumWindows、EnumDesktopWindows或EnumChildWindows等这些API来实现。我想真正理解Windows NT/2000实现这些API的细节后,应该可以发现很多Windows NT/2000的内部执行情况,于是我认真的研究了这些API,下面我以Windows 2000 Server Build 2195下EnumWindows API的分析步骤叙述如下:

    1.user32.dll下的EnumWindows首先调用user32.dll下的InternalEnumWindows,然后InternalEnumWindows又调用BuildHwndList(user32.dll).
    2.BuildHwndList调用NtUserBuildHwndList,而这个函数也位于user32.dll模块中。
    3.NtUserBuildHwndList只是调用int 2e指令,然后使用ID为0x112e的System Service,即win32k.sys模块中的NtUserBuildHwndList,请参阅《 Windows 2000 System Services列表 》。从这开始也就从用户态进入了核心态。
    4.win32k.sys中的NtUserBuildHwndList继续调用win32k.sys中的BuildHwndList,应该注意的是这两个例程与上面User32.dll中的相应例程同名,这也是我一直强调模块名的原因。BuildHwndList最后调用InternalBuildHwndList(win32k.sys),这个例程才是我们真正感兴趣的地方。InternalBuildHwndList在特定参数下(如EnumDestopWindows API调用,EnumDestopWindows最终也会调用InternalBuildHwndList)是一个递归例程以实现窗口的枚举。

    这个分析只是说明了EnumWindows等API的执行流程,真正的细节还是要看一看代码了。Windows NT/2000下窗口是与特定线程相关联的,即每个线程都可以拥有窗口,最典型的例子是Windows  Explorer(Windows资源管理器),在每打开一个Explorer窗口,explorer进程都会建立线程与这些窗口关联。由于这个原因,Microsoft在内核态的ETHREAD(KTEB)中存储窗口结构(Windows NT早期版本Win32子系统位于用户态,我这未加以说明),这些结构由ETHREAD中的Win32Thread成员指定。Win32Thread在ETHREAD的位置可由Windbg的以下命令找出:

    > !kdex2x86.ethread
    Structure ETHREAD (Size:0x240) member offsets:
    +0000    Tcb(KTHREAD struct)
    +0000      Header(DISPATCHER_HEADER struct)
             .
             .
             .
    +0124      Win32Thread
             .
             .
             .

    要指出一点的是,Win32Thread成员在SoftICE 4.05 for Windows NT中显示为Service Table。为便于用户态代码更容易获得Win32Thread的值,Windows NT/2000也在线程的TEB中存取了Win32Thread指针,在Windows 2000 Server Build 2195其位置位于TEB的后0x40处。user32.dll由下列函数获得Win32Thread的值(i386kd输出):

    kd> x user32!PtiCurrent
    77df3686 user32!PtiCurrent

    kd> u user32!PtiCurrent
    USER32!PtiCurrent: 
    77df3686 64a118000000  mov eax,fs:[00000018] 
    77df368c 83784000      cmp dword ptr [eax+0x40],0x0 
    77df3690 0f8492700200  je USER32!PtiCurrent+0xc (77e1a728) 
    77df3696 64a118000000  mov eax,fs:[00000018]
    77df369c 8b4040        mov eax,[eax+0x40]
    77df369f c3            ret 

    下面是我实现枚举特定线程拥有的窗口的代码实现(我从KTEB中获得Win32Thread):


    //------------------------------------------------------------
    //
    // BuildHwndList--Enum Thread Windows(SoftICE hwnd Command)
    // Only test on Windows 2000 Server Build 2195 Chinese Edition 
    // Build 2195(Free)!Programmed By WebCrazy
    // ( tsu00@263.net  ) on 11-25-2000!
    // Welcome to  http://webcrazy.yeah.net  to get more information
    //
    //------------------------------------------------------------

    #define WIN32THREAD_OFFSET    0x124
    #define HWNDLIST_OFFSET       0xb8
    #define HWNDHANDLE_OFFSET     0x0
    #define HWNDNEXT_OFFSET       0x2c
    #define HWNDPARENT_OFFSET     0x30
    #define HWNDRECT_OFFSET       0x3c
    #define HWNDPROC_OFFSET       0x5c

    //RECT:copied from windef.h
    typedef struct tagRECT
    {
        LONG    left;
        LONG    top;
        LONG    right;
        LONG    bottom;
    } RECT, *PRECT;

    typedef struct tagHWNDRECT{
       RECT WindowRect;
       RECT ClientRect;
    }HWNDRECT,*PHWNDRECT;

    void BuildHwndList(void *kteb)
    {
       PVOID Win32Thread;
       PVOID HwndList;
       PHWNDRECT pHwndRect;

       if(((USHORT)NtBuildNumber)!=2195){
           DbgPrint("Only test on Windows 2000 Server Build 2195!/n");
           return;
       }
       
       Win32Thread=(PVOID)(*(PULONG)((char *)kteb+WIN32THREAD_OFFSET));
       if(!Win32Thread){
          DbgPrint("kteb:%08X isn't a win32 thread!/n",kteb);
          return;
       }

       HwndList=(PVOID)(*(PULONG)((char *)Win32Thread+HWNDLIST_OFFSET));
       if(!HwndList){
          DbgPrint("kteb:%08X isn't a hwnd list!/n",kteb);
          return;
       }
   
       DbgPrint("@kteb %08X first HwndList at %08X/n",kteb,HwndList);
       DbgPrint("HwndList  HWND      PARENT    Window Proc  Window(Client) Rect/n");
       DbgPrint("--------  --------  --------  -----------  -------------------/n");

       do{
          pHwndRect=(PHWNDRECT)((char *)HwndList+HWNDRECT_OFFSET);
          DbgPrint("%08X  %08X  %08X  %08X     %d,%d,%d,%d(%d,%d,%d,%d)/n",
                   HwndList,
                   *(PULONG)((char *)HwndList+HWNDHANDLE_OFFSET),
                   *(PULONG)(*(PULONG)((char *)HwndList+HWNDPARENT_OFFSET)),
                   *(PULONG)((char *)HwndList+HWNDPROC_OFFSET),
                   pHwndRect->WindowRect.left,pHwndRect->WindowRect.top,
                   pHwndRect->WindowRect.right,pHwndRect->WindowRect.bottom,
                   pHwndRect->ClientRect.left,pHwndRect->ClientRect.top,
                   pHwndRect->ClientRect.right,pHwndRect->ClientRect.bottom);

          HwndList=(PVOID)(*(PULONG)((char *)HwndList+HWNDNEXT_OFFSET));
      }while(HwndList);
    }

    运行一个实例,输出内容大概如下:

    @kteb FF7BB020 first HwndList at A0312DA8
    HwndList  HWND      PARENT    Window Proc  Window(Client) Rect
    --------  --------  --------  -----------  -------------------
    A0312DA8  0001002A  0001000C  77DFF0DF     0,0,0,0(0,0,0,0)
    A0310D50  00010022  0001000C  775331C4     0,0,112,27(4,23,108,23)
    A03176B8  0002004A  0001000C  77DFF0DF     0,0,0,0(0,0,0,0)
    A031A500  00010082  0001000C  76621AC6     44,44,812,581(48,67,808,577)
    A0318FA8  00010062  0001000C  775676F4     0,0,1024,768(0,0,1024,768)

    下面我再讲讲Window Class吧。谈到Class,真的可以想到很多东西,如C++的类等等。至于Window Class我觉的还是引用Microsoft文档的解释吧:

    A window class is a set of attributes that the system uses as a template to create a window. Every 
window is a member of a window class. All window classes are process specific. 

    从上的说明也可以看出Window Class是与特定进程相关联的。窗口与线程关联,所以其结构存于ETHREAD(KTEB)中,相应的Windows Class的结构则存于EPROCESS(KPEB)中。窗口结构由Win32Thread指定,Window Class则由Win32Process中指定。Win32Process在EPROCESS中的位置也可由windbg看出:

    > !kdextx86.processfields
     EPROCESS structure offsets:
             .
             .
             .
        Win32Process:                      0x214
             .
             .
             .

    下面是实现枚举特定进程的Window Class的代码:

    //----------------------------------------------------------------------
    //
    // BuildWindowClassList--Enum Process Window Class(SoftICE class Command)
    // Only test on Windows 2000 Server Build 2195 Chinese Edition 
    // Build 2195(Free)!Programmed By WebCrazy(tsu00@263.net ) on 11-25-2000!
    // Welcome to http://webcrazy.yeah.net to get more information
    //
    //----------------------------------------------------------------------

    #define WIN32PROCESS_OFFSET       0x214
    #define WINPRIVATECLASS_OFFSET    0x38
    #define WINGLOBALCLASS_OFFSET     0x3c

    #define CLASS_CLASSSTYLE_OFFSET   0x2c
    #define CLASS_WINDOWPROC_OFFSET   0x30
    #define CLASS_MODULEBASE_OFFSET   0x3c
    #define CLASS_CLASSNAME_OFFSET    0x50

    void BuildWindowClassList(void *kpeb)
    {
        PSINGLE_LIST_ENTRY pPrivateClassList,pGlobalClassList;
        PVOID Win32Process;
        PCHAR pClassName;

        Win32Process=(PVOID)(*(PULONG)((char *)kpeb+WIN32PROCESS_OFFSET));
        if(!Win32Process){
            DbgPrint("kpeb:%08X isn't a win32 process!/n",kpeb);
            return;
        }

        pPrivateClassList=(PSINGLE_LIST_ENTRY)(*(PULONG)((char *)Win32Process+WINPRIVATECLASS_OFFSET));
        if(pPrivateClassList){
            DbgPrint("Application(kpeb:%08X) Private Class List:/n",kpeb);
            DbgPrint("%-35sHandle    ModBase   WinProc   Styles/n","Class Name");
            DbgPrint("%-35s--------  --------  --------  --------/n","----------");

            do{

               pClassName=(PCHAR)(*(PULONG)((char *)pPrivateClassList+CLASS_CLASSNAME_OFFSET));
               DbgPrint("%-35s%08X  %08X  %08X  %08X/n",pClassName,pPrivateClassList,
                       *(PULONG)((char *)pPrivateClassList+CLASS_MODULEBASE_OFFSET),
                       *(PULONG)((char *)pPrivateClassList+CLASS_WINDOWPROC_OFFSET),
                       *(PULONG)((char *)pPrivateClassList+CLASS_CLASSSTYLE_OFFSET));

               pPrivateClassList=pPrivateClassList->Next;
            }while(pPrivateClassList);
        }

        pGlobalClassList=(PSINGLE_LIST_ENTRY)(*(PULONG)((char *)Win32Process+WINGLOBALCLASS_OFFSET));
        if(pGlobalClassList){
            DbgPrint("Application(kpeb:%08X) Global Class List:/n",kpeb);
            DbgPrint("%-35sHandle    ModBase   WinProc   Styles/n","Class Name");
            DbgPrint("%-35s--------  --------  --------  --------/n","----------");

            do{

               pClassName=(PCHAR)(*(PULONG)((char *)pGlobalClassList+CLASS_CLASSNAME_OFFSET));
               DbgPrint("%-35s%08X  %08X  %08X  %08X/n",pClassName,pGlobalClassList,
                       *(PULONG)((char *)pGlobalClassList+CLASS_MODULEBASE_OFFSET),
                       *(PULONG)((char *)pGlobalClassList+CLASS_WINDOWPROC_OFFSET),
                       *(PULONG)((char *)pGlobalClassList+CLASS_CLASSSTYLE_OFFSET));

               pGlobalClassList=pGlobalClassList->Next;
            }while(pGlobalClassList);
        }
    }

    照例是一个运行实例的结果:

    Application(kpeb:FF5BA3C0) Private Class List:
    Class Name                         Handle    ModBase   WinProc   Styles
    ----------                         --------  --------  --------  --------
    ConsoleIMEClass                    A031F938  01000000  0100152E  00000000
    DDEMLUnicodeServer                 A031F8A8  77DF0000  77E2E2F9  00000000
    DDEMLAnsiServer                    A031F820  77DF0000  77E2E2F9  00000000
    DDEMLUnicodeClient                 A031F790  77DF0000  77E2E14D  00000000
    DDEMLAnsiClient                    A031F708  77DF0000  77E2E14D  00000000
    DDEMLMom                           A031F688  77DF0000  77DFD316  00000000
    Application(kpeb:FF5BA3C0) Global Class List:
    Class Name                         Handle    ModBase   WinProc   Styles
    ----------                         --------  --------  --------  --------
    Static                             A031F610  77DF0000  77E000F9  00004088
    IME                                A031F5A0  77DF0000  77DFF0DF  00004000
             .
             .
             .

    上面我给出的两个代码段,分别实现了SoftICE中的hwnd与class命令的功能。在分析了这两个命令后,也就可以进一步分析Windows NT/2000内部消息机制,这是Windows GUI实现的基础。可以继续挖掘的东西看来还越来越多了。

参考资料:
      1.David Solomom《Inside Windows NT,2nd Edition》
MODIS 遥感数据批量下载(使用Cygwin) MODIS 遥感数据批量下载(使用Cygwin)包含Cygwin的下载教程 阅读详情

相关推荐

强化学习环境Gym库的介绍

Gym是一个用于进行强化学习实验的开源库,它提供了一个仿真环境,内置了多种仿真游戏,例如出租车游戏、悬崖游戏等,不同的游戏所用的网格、规则、奖励(reward)都不一样,适合为强化学习做测试。(1) 多种环境:Gym库内置了上百种实验环境,包括算法环境、简单文本环境、经典控制环境、Atari游戏环境、MuJoCo环境和机械控制环境等。(2) Gym提供多种环境供我们使用,这里以一个简单的CartPole-v0为例,首先导入gym库,然后创建一个CartPole-v0环境,通过调用gym.make方法实现。

ahah12345678的博客 2148

使用NtUserBuildHwndList遍历窗口_win7x64

在我的上一篇文章中讲到 http://blog.csdn.net/zhuhuibeishadiao/article/details/51604788 枚举窗口 使用EnumWinodws是调用内核中NtUserBuildHwndList 这个函数最后2个参数必须是R3的地址 不然会返回0xC0000008错误,并且如果使用控制台窗口测试,这时ETHREAD下的win32Thr

zhuhuibeishadiao 6479

HDLBits答案汇总

前言 该博客为本人做HDLBits习题时的心得记录总结,欢迎大家一起交流进步。 HDLBits网站链接 Verilog Language Basics Vectors Modules:Hierarchy Procedures More Verilog Features Circuits Combinational Logic Basic gates Multiplexers Arithmetic Circuits Karnaugh Map to Circuit Sequential Logic Latche

谦豫 9万+

转Hook Shadow SSDT

网上很多文章都有关于SSDT的完整的实现,但是没有关于Shadow SSDT的完整实现,目前最好的文章是《shadow ssdt学习笔记 by zhuwg》,我这里的程序也很多参考了他的文章,在这里谢谢了。我这里给出一个hook shadow ssdt的完整实现的驱动和3层的代码。 这里主要是hook 了 NtUserFindWindowEx,NtUserBuildHwndList,NtUse

Tommy(凌飞)的专栏 1844

C语言面试,8道一定会遇到的----关于指针的笔试题详解

C语言面试,8道一定会遇到的----关于指针的笔试题详解

m0_55322924的博客 463

2、通过mos管构成的逻辑门电路

一、总结 mos管 是构成 逻辑门电路 的最基本单元。 各个逻辑门电路的真值表如下: 二、各种门 1、非门 NOT 2、与门 AND 3、与非门 把上面与门电路 右边的 非门电路 去掉 NAND 4、或门 OR 5、或非门 NOR 把或门右边的非门电路去掉 6、异或门 XOR 两个输入相异为1,相同为0。 7、同或门 XNOR 两个输入相同为1,相异为0。 ...

engineer0的博客 4万+

调用 NtUserXXX 引发系统 BSOD 的问题分析

这篇文章通过一次在 Windows XP 和 Windows 7 操作系统内核中分别调用同一个 NtUserXxx 系统调用产生不同现象的问题,对其做了简单分析。最近在驱动中需要实现在一些 HOOK 处理函数中调用如 NtUserBuildHwndList 这样的 API 对目标样本进程的窗口状态(是否存在窗口等)进行判定。实现代码在 Windows 7 下一切正常,但在 Windows XP 中的部分进程上下文中调用时会产生的偶发 BSOD 异常。为了解决该问题,通过内核调试进行分析。

qq_44005305的博客 383

CAN信号定义避坑指南:Kvaser Database Editor里Byteorder和Bitpos设置的那些‘坑’

本文详细解析了在Kvaser Database Editor中配置CAN信号时,字节序(Byteorder)和起始位(Bitpos)设置的常见错误及解决方案。通过实际案例和验证技巧,帮助工程师避免DBC文件配置中的陷阱,确保车载电子系统的稳定通信。

weixin_28678831的博客 360

(转)HOOK SHADOW SSDT

http://www.vcfans.com/2010/04/hook-shadow-ssdt.html 作 者: sislcb原 文:http://bbs.pediy.com/showthread.php?t=65931 网上很多文章都有关于SSDT的完整的实现,但是没有关于Shadow SSDT的完整实现,目前最好的文章是《shadow ssdt学习笔记 by zhuwg》,我这里...

weixin_30414635的博客 221

67、全球导航卫星系统授时弹性分析与建议

本文分析了全球导航卫星系统(GNSS)在授时过程中面临的问题,包括系统自身异常和外部干扰欺骗,并探讨了提升授时弹性的关键技术与解决方案。文章介绍了美国、欧洲及中国在弹性授时系统建设方面的进展,重点剖析了高精度原子钟、时间同步、干扰检测与识别等核心技术,提出了GNSS与其他授时系统互补的集成化发展路径。最后展望了未来授时系统向更高精度、更强弹性、更广应用的发展趋势,为构建安全可靠的国家授时体系提供参考。

corn8的博客 185

17.6 LangSmith 私有化部署实战指南:企业级AI应用的安全基石

LangSmith 私有化部署, 企业级AI开发平台, 数据隐私合规, 混合云架构, 模型监控与审计。

yonggeit的博客 3777

【旧文章搬运】关于NtUserBuildHwndList的一点记录~

原文发表于百度空间,2011-04-07========================================================================== 该函数与ring3的枚举窗口函数有关,原型如下: NTSTATUS APIENTRY NtUserBuildHwndList( HDESK hDesktop, HWND hwndPare...

weixin_30287169的博客 662

【WorkBuddy专栏】完结篇暨付费专栏总目录(内容继续更新中)

【WorkBuddy专栏】完结篇和付费内容总目录

AI人人懂 908

程序防多开之二:程序窗口检测

通过循环调用NtUserFindWindowEx()来获取窗口句柄,并通过窗口句柄获取PID,实现多开检测.

RitMan的博客 2490

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

搞定QQ游戏系列(寻仙,DNF等等)驱动保护TesSafe.sys

1.用RKU看一下SSDT和SSDTShadow,发现SSDT并没有被HOOK,SSDTShadow HOOK了5个调用:NtUserBuildHwndListNtUserFindWindowExNtUserGetDCNtUserGetDCExNtUserGetForegroundWindow想也不用想,肯定是为了防止其他软件找到他的窗口。解决方法:在TesSafe加载前先加载自己的驱动,备份这5

老裴 3798

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

简单实现了下SSDT SHADOW HOOK

介绍: SSDT SHADOW HOOK可用于安全软件窗口保护、安全输入、截屏保护等。例如:挂钩NtUserFindWindowEx、NtUserGetForegroundWindow、NtUserBuildHwndList、NtUserQueryWindow、NtUserWindowFromPoint、NtUserSetParent、NtUserPostMessage、NtUserMes...

huobengle 842

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Hook Shadow SSDT

作 者: sislcb时 间: 2008-06-02,23:21链 接: http://bbs.pediy.com/showthread.php?t=65931网上很多文章都有关于SSDT的完整的实现,但是没有关于Shadow SSDT的完整实现,目前最好的文章是《shadow ssdt学习笔记 by zhuwg》,我这里的程序也很多参考了他的文章,在这里谢谢了。我这里给出一个hook shado

1478

驱动编程:注册表回调,进程回调,文件回调,进程隐藏断链,窗口保护

#include "struct.h" #define debug_pott_offset 0x298 //#define debug_pott_offset 0x1f0 DWORD changge_size_NtClose = 0; //NtClose被修改了N字节 PUCHAR ori_head_NtClose = NULL; //NtClose的前N字节数组 PVOID ori_addr_NtClose = NULL; //NtCl..

追逐光芒,追随内心 2712

关于Win7 x64 Shadow SSDT 的探索和 Inline HOOK

http://bbs.pediy.com/thread-210481.htm 来看雪一年了,在这里面学到了很多知识,非常感谢各位前辈对知识的分享和不懈的研究,也非常感谢各位大神对我们这些小白的照顾,特别要感谢MaMy、hksoobe、luolinlove等大神的指导。我也一直非常希望能为看雪贡献一点什么,但是小白的理解估计大神也看不上,这次也是注册看雪一周年,冲着这个也来发表一点自己的理

fyfy 4472

ARK之杀进程这点小事-有线程补充

A.NtTerminateProcess B.涂改内存    //内存清0 C.卸载模块 //free ntdll.dll或主模块 D.窗口攻击 //发close quit 洪水 或 SetParant 这里演示SetParant R3 如果要这么做的话最好在内核中使用更底层的函数 这里提一下枚举窗口 使用EnumWinodws是调用内核中NtUserBuildHwndList 这个函数

zhuhuibeishadiao 3291

StrongOD hook的API

好久没写东西了~~: >SSDT State NtClose Actual Address 0xF0389268 Hooked by: C:\OllyDBG\plugin\whlsod.sys NtCreateProcess Actual Address 0xF0

井底之蛙 4721
上一篇: 分析Windows NT/2000堆内存与虚拟内存组织(http://webcrazy.yeah.net)
下一篇: Windows 2000内核KPEB/KTEB详细结构(http://webcrazy.yeah.net/)
freexploit
博客等级 码龄22年 315粉丝 778原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值