首页
社区
课程
招聘
[原创]Win10 tagWnd & 内核枚举窗口
发表于: 2019-5-7 11:55 14968

[原创]Win10 tagWnd & 内核枚举窗口

2019-5-7 11:55
14968

tagWnd在win7是公开的 在windbg中输入dt tagWnd是可以看到完整结构体的.

So,这个就不讨论win7了.虽然win10 win32k大改了,但是还是参考的.


先看下win7的结构体

可以看到,大部分的信息都可以直接看到的.

好的,那定一个目标,最后实现的结果是什么样的?

1.支持win10 14393-win10 17763 x64 只弄下x64,    x86原理一致

2.获取窗口的句柄,tagWnd,窗口标题,窗口类名信息,下一个窗口,上一个窗口,父窗口,RECT,以及样式

Ojbk!开整!

回想一下,5*16*16+2*16+2=1282+32=1314,522是16进制的1314,黑客情人节啊!

额...不好意思,突然脑抽想到了这个.正经的

第一步:

我们需要得到所有的tagWnd.嗯 year.怎么得到tagWnd呢?

稍微了解一点子系统的小哥哥小姐姐就知道win32k!ValidateHwndEx返回tagWnd. So,We need to see see it!

怎么得到所有的tagWnd呢?啊哈哈哈哈哈哈哈.see later.

第二步:

得到偏移,取值

得到了tagWnd,就是找偏移,取值了,这些偏移怎么搞到?

想一下:5*16*16+2*16+2=1282+32=1314,522是16进制的1314,黑客情人节啊!

.....额...看win32k相关api的实现啊.

就两步呗,那ojbk啊.

First,We need IDA!打开我从某解下载的泄露版ida !O shit,i love ida.

先从简单的搞起,看下7601 win32k!ValidateHwnd:


为什么说[rdi+0x10]可以看出rdi就是tagWnd呢?

看下公开的结构体就知道了,都对的上,标题,RECT,句柄,啥的都是ojbk的.

Ojbk!

So,总结一下:

Win7的tagWnd计算公式:

[hwnd->cx*[gSharedInfo+0x10]] + [gSharedInfo+0x8]]

到这里,我们可以猜想,如何枚举所有窗口的tagWnd呢?

1.公式的唯一变数就是hwnd的低16位,那么0~0xffff就是所有的啦

2.tagWnd中记录了上一个窗口和下一个窗口,并且打开彗星小助手或者spy++,会发现总窗口(最大的那个窗口hwnd是固定的,就是0x10010),通过把0x10010转换为tagWnd,然后通过下一个窗口遍历即可.

Ojbk!

搞win10!

先搞一个14393的!

ida打开win32kbase!ValidateHwndEx

大概看下 公式也没变,只是部分偏移改变了

So,

14393:[hwnd->cx*[gSharedInfo+0x10]] + [gSharedInfo+0x8]]

鉴于篇幅,还有写此文章时的电脑并非调试机,就简单说下

Win10:

14393的计算公式同win7

>= 15063 的计算公式都改变了

上面说过了>=15063的公式是改变的

下面就选择16299的win32kbase.sys来看

同样的,也是看win32kbase!ValidateHwndEx

只是基数不同

So,总结一下:

7601:[hwnd->cx*[gSharedInfo+0x10]] + [gSharedInfo+0x8]]

14393:同7601

15063:[[gpKernelHandleTable] + 0x10 * ((hwnd->cx * [gSharedInfo+0x10]) >> 5)]

16299:[[gpKernelHandleTable] + 0x18 * ((hwnd->cx * [gSharedInfo+0x10]) >> 5)]

17134:[[gpKernelHandleTable] + 0x18 * ((hwnd->cx * [gSharedInfo+0x10]) >> 5)]

17763:[[gpKernelHandleTable] + 0x18 * ((hwnd->cx * [gSharedInfo+0x10]) >> 5)]

Win10中的gpKernelHandleTable和gSharedInfo是导出的.So


到这里,我们已经可以得到所有tagWnd了(1903还没看),那么下面就是去tagWnd获取信息了.

我们需要以下信息:

1.窗口hwnd(好废话)

2.窗口标题

3.窗口类名

4.窗口RECT

5.窗口的样式

6.窗口的进程信息

7.窗口的关系

提一下:应用层与驱动层都有tagWnd结构,在7601-16299 结构体是相同的

但>16299是不同的,也就是说在>16299的win10中有两个tagWnd,一个是用户层的,一个是内核的,虽然名字一样(看符号),但是内容不一样,用户层获取用户层的tagWnd最简单的就是调用一下NtUserCallOneParam(hwnd, xxx),这个xxx不同的build都不同,最后都是调用到内核的MapDesktopObject.

鉴于不可抗拒的原因,这里只列出内核的tagWnd


这个是最简单的,tagWnd的前8个字节就是hwnd.

联想一下:5*16*16+2*16+2=1282+32........

好的,继续,窗口标题,看下win32kfull!NtUserFindWindowEx

鉴于篇幅,这里只看下14393的,其他一样.

NtUserFindWindowEx->_FindWindow

其中0xe0就是偏移(wchar*) 其实d8就是一个UNICODE_STRING

Ojbk,其他的这里总结下:

strName:

7601:0xe0

14393:0xe0

15063:0xf0

16299:0xf0

17134:0xa8

17763:0xa8

窗口类名并没有直接保存在tagWNd,而是通过索引去查Atom表

这里就只说下索引

看win32kfull!NtUserGetClassName(15063)


或者

窗口标题那张图的上一句

在调试过程中并没有走到v12!=0x19里面

其中Index就是索引

总结一下:

14393:WORD[[tagWnd+0x98] + 0xA]

15063:WORD[[tagWnd+0xA8] + 0xA]

16299:WORD[[tagWnd+0xA8] + 0xA]

17134:WORD[[[tagWnd+0x70] + 8] + 2]

17763:WORD[[[tagWnd+0x70] + 8] + 2]

有两个RECT,一个是RcWindow,一个是Rcclient

是一个tagRect结构

RcClient的上8个字节就是RcWindow

看下win32kfull!xxxGetUpdateRect(15063)

0x90指向一个tagRect结构,而0x90-8则指向RcWindow

RcClient:

14393:[tagWnd+0x80] hrgnUpdate=0xA0

15063:[tagWnd+0x90] hrgnUpdate=0xB0

16299:[tagWnd+0x90] hrgnUpdate=0xB0

17134:[[tagWnd+0x28]+0x68] hrgnUpdate=[[tagWnd+0x28]+0x88]

17763:[[tagWnd+0x28]+0x68] hrgnUpdate=[[tagWnd+0x28]+0x88]

RcWindow:

偏移-8

17134:[[tagWnd+0x28]+0x60] hrgnUpdate=[[tagWnd+0x28]+0x88]

17763:[[tagWnd+0x28]+0x60] hrgnUpdate=[[tagWnd+0x28]+0x88]

内核中共有3个样式

1. Style

2. ExStyle

3. ExStyle2

怎么找?

Win32kfull!xxxSetWindowStyle(15063)


ExStyle2往下找UnsetLayeredWindow的上一句

这里的样式并不是用户层spy++或者彗星小助手显示的样式格式,需要转换,这里就不进行转换了.

14393:

Style:0x34 DWORD

ExStyle:0x30 DWORD

ExStyle2:0x120 DWORD

15063:

Style:0x44 DWORD

ExStyle:0x40 DWORD

ExStyle2:0x130 DWORD


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 6
支持
分享
最新回复 (14)
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
需要符号表吧
2019-5-7 11:58
0
雪    币: 4006
活跃值: (716)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
yy虫子yy 需要符号表吧
不需要,符号都木有了
2019-5-7 12:02
0
雪    币: 9626
活跃值: (1838)
能力值: ( LV5,RANK:73 )
在线值:
发帖
回帖
粉丝
4
给力嗷
2019-5-7 12:46
0
雪    币: 1176
活跃值: (1264)
能力值: ( LV12,RANK:380 )
在线值:
发帖
回帖
粉丝
5
2019-5-7 13:32
0
雪    币: 914
活跃值: (2458)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
6
然而R3可以做到的事,为什么要R0去做
2019-5-8 08:36
0
雪    币: 4006
活跃值: (716)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
万剑归宗 然而R3可以做到的事,为什么要R0去做
纯属无聊....
2019-5-8 10:17
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
666666
2019-5-8 11:35
0
雪    币: 6497
活跃值: (2372)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
9
前几天刚好逆完相关结构体的偏移,准备发上来,被楼主抢先一步了,哈哈哈!
最后于 2019-5-8 17:11 被yirucandy编辑 ,原因:
2019-5-8 17:09
0
雪    币: 954
活跃值: (123)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
大半夜看到此等好帖,睡意全无,LZ牛逼!!!
2019-5-9 02:55
0
雪    币: 4006
活跃值: (716)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
yirucandy 前几天刚好逆完相关结构体的偏移,准备发上来,被楼主抢先一步了,哈哈哈!
发啊
2019-5-9 10:29
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
感谢分享!
2019-5-24 00:19
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
抖机灵,实测无效
2020-5-25 11:56
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
牛逼,顶一个,能否再总结下x64各版本tagwnd结构的总大小
2020-7-15 12:20
0
雪    币: 21
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15

其实不需要硬编码和分析各系统偏移也能拿到tagWnd,这里我就分享一下吧:

NTSTATUS ALIEN_WindowKrnl(__int64 Hwnd)
{
    NTSTATUS status = STATUS_SUCCESS;
    CHAR* szFuncName = "ValidateHwnd";
    DriverInfo data = { 0 };
    status = Utils_GetDriverBaseInfo("win32kbase.sys", &data);
    if (!NT_SUCCESS(status))
    {
        return status;
    }
    ULONG64 pFunAddress = (ULONG64)RtlFindExportedRoutineByName((PVOID)data.ulDriverBaseAddr, szFuncName);
    if (pFunAddress > 0)
    {
        t_ValidateHwnd ValidateHwnd = (t_ValidateHwnd)pFunAddress;
        PVOID tagWnd = ValidateHwnd(Hwnd);
        DPRINT("tagWnd:%p", tagWnd);
    }
    return status;
}


2023-1-26 01:19
1
游客
登录 | 注册 方可回帖
返回
//