滥用DComposition在外部窗口上渲染
2012年,微软推出了“ DirectComposition”技术,该技术可极大地帮助改善位图绘图和合成的性能,其工作方式是利用图形硬件来合成和渲染对象,这意味着它除了可以独立运行之外,还可以独立运行。主UI线程。
因此,可以推断出必须有一层交互作用,或者一种将组合物应用到所需窗口或目标上的方法,而滥用这一层交互作用是当今文章的主要目标。
DirectCompositions使用的交互层是称为“目标”和“视觉对象”的对象,每个IDCompositionTarget将由依赖于窗口句柄的相应API函数创建,并且每个目标都将依赖于IDCompositionVisual,后者包含表示的视觉内容屏幕上。
如果您认为可以轻松地创建一个窗口,然后通过非所有权过程在另一个窗口的顶部进行构图,那么您错了。这将导致错误,并且不会创建合成。
逆转
打开win32kfull,它是DWM,GDI和其他Windows功能的内核模式组件,然后搜索“ DComposition”将产生多个结果:
NtUserCreateDCompositionHwndTarget
根据它的原型__int64 (HWND a1, int a2, _QWORD *a3)
,我们感兴趣的是:,我们可以得出这仅仅是just IDCompositionDevice::CreateTargetForHwnd
,而参数是:(HWND hwnd, BOOL topmost, IDCompositionTarget** target)
。
在此功能的最开始,有一个测试检查您是否可以为此合成创建目标:
last_status = TestWindowForCompositionTarget(window_handle, top_most);
这是该功能的简化形式:
NTSTATUS TestWindowForCompositionTarget(HWND window_handle, BOOL top_most)
{
tagWND* window_instance = ValidateHwnd(window_handle);
if (!window_instance
|| !window_instance->thread_info)
return STATUS_INVALID_PARAMETER;
// some checks here to verify that DCompositions are supported, and available
PEPROCESS calling_process = IoGetCurrentProcess();
PEPROCESS owning_process = PsGetThreadProcess(window_instance->thread_info->owning_thread); // tagWnd*->tagTHREADINFO*->KTHREAD*
if (calling_process != owning_process)
return STATUS_ACCESS_DENIED;
CHwndTargetProp target_properties{};
if (CWindowProp::GetProp<CHwndTargetProp>(window_instance, &target_properties))
{
bool unk_error = false;
if (top_most)
unk_error = !(target_properties.top_most_handle == nullptr);
else
unk_error = !(target_properties.active_bg_handle == nullptr);
if (unk_error)
return (NTSTATUS)0x803e0006; // unique error code, i don't know what it's supposed to resemble
}
return STATUS_SUCCESS;
}
导致失败的检查为if (calling_process != owning_process)
,它将调用者的进程与窗口的所有者进程进行比较,如果此检查失败,则它们返回STATUS_ACCESS_DENIED错误。
他们通过调用来检索窗口的所有者进程ValidateHwnd
,这是win32k中到处使用的函数:
此函数将返回一个指向类型struct的指针tagWND
,然后tagTHREADINFO
在+ 0x10(window_instance-> thread_info)访问类型的成员,然后在+ 0x0(thread_info-> owning_thread)访问实际的线程指针。
规避这些检查的一种方法是将进程窗口的拥有线程临时交换到我们的窗口,在其上组成我们的目标,然后很快将其交换回去,这就是PoC的基础。
概念证明
我做了一个PoC,它将通过类名劫持一个窗口,然后在其中心渲染一个矩形。您可以在此处访问代码。
- Hadoop通过HCatalog编写Mapreduce任务访问hive库中schema数据
- 伪排练:NLP灾难性遗忘的解决方案
- java优雅的使用elasticsearch api
- springboot mybatis优雅的添加多数据源
- java通过shield链接Elasticsearch
- 使用LSTM预测比特币价格
- Redis密码设置与访问限制(网络安全)
- Elasticsearch-sql 用SQL查询Elasticsearch
- python使用装饰器@函数式化django开发
- python 设计模式,“多”例模式
- 怎样把微信聊天记录导出备份到电脑【微信公众平台技巧】
- zookeeper curator选主(Leader)
- zookeeper curator使用caches实现各种监听
- python apschedule安装使用与源码分析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP实现的多进程控制demo示例
- 你可能不知道的一些linux文件权限管理办法
- Laravel框架路由与MVC实例详解
- python实现学生管理系统开发
- 使用 chkconfig 和 systemctl 命令启用或禁用 Linux 服务的办法
- PHP defined()函数的使用图文详解
- 详解在Linux中清空或删除大文件内容的5种办法
- php和redis实现秒杀活动的流程
- CentOS 7中搭建NFS文件共享存储服务的完整步骤
- PHP检测一个数组有没有定义的方法步骤
- Yii2.0框架模型多表关联查询示例
- Yii2.0框架模型添加/修改/删除数据操作示例
- thinkphp5.1框架容器与依赖注入实例分析
- 在CentOS VPS上通过SSH安装 MySQL的办法图解
- 详解PHP 7.4 中数组延展操作符语法知识点