论文阅读笔记——PathAFL:Path-Coverage Assisted Fuzzing
文章目录
- 前言
- PathAFL:Path-Coverage Assisted Fuzzing
- 1、解决的问题和目标
- 2、技术路线
- 2.1、如何识别 h − p a t h h-path h−path?
- 2.2、如何减少 h − p a t h h-path h−path的数量?
- 2.3、哪些h-path将被添加到种子队列?
- 2.4、种子选择算法
- 2.5、资源调度
- 3、达到的效果
- 3.1、一个简单例子的结果(RQ1)
- 3.2、代码覆盖率和崩溃测量(RQ2)
- 3.3、LAVA-M数据集(RQ3)的结果
- 3.4、发现现实世界中的漏洞(RQ3)
- 4、结论
- 总结
前言
此博客为PathAFL:Path-Coverage Assisted Fuzzing论文的阅读笔记,本篇论文提出了一种新的跟踪执行路径的方法、路径过滤算法和追踪执行路径的方法,以提高Fuzz的准确性以及Fuzz性能。本文将会从解决的问题和目标、技术路线、达到的效果和结论四个角度来分析本篇论文。以下就是本文的全部内容。
PathAFL:Path-Coverage Assisted Fuzzing
1、解决的问题和目标
现有的覆盖引导fuzzer通常使用所探索的基本块或边的数量来测量代码覆盖,路径覆盖可以提供比基本块和边缘覆盖更准确的覆盖信息。然而,路径的数量随着程序大小的增加而呈指数级增长,几乎不可能追踪真实世界应用程序的所有路径,这也是本文亟待解决的问题。针对此问题,本文完成了以下几个目标:
- 作者提出了一种新的跟踪执行路径的方法,并在跟踪路径覆盖粒度和fuzzing性能之间进行了权衡。研究发现,作者可以用很少的开销来追踪重要的路径
- 作者设计了一种路径过滤算法,它对新的路径做出了快速的判断。只有那些满足特定条件并具有高权重的路径才会添加到种子队列中
- 作者提出了一种追踪执行路径的新方法,并在追踪路径覆盖的细粒度和模糊性能之间进行了权衡。研究发现,作者可以在几乎没有额外开销的情况下追踪重要路径
- 作者开发了PathAFL的开源实现,并将其作为AFL的分支发布在Github上
2、技术路线
关于PathAFL的工作过程如下图所示(紫色的组件显示了作者对原始AFL的改进):
由上图可知,PathAFL是在AFL的基础上进行改进的,而AFL的整个工作流程如下所示:
- 对目标应用插桩
- 向种子队列提供初始输入
- 选择种子。AFL根据种子选择算法从种子队列中选择一个种子,该算法更喜欢更快、更小的种子。种子选择算法采用贪婪算法实现,如下图所示:
- 变异种子。该步骤使用多种变异算法对种子文件进行变异,并在循环中生成大量测试用例
- 测试和跟踪。此步骤以测试用例为输入,执行并跟踪插桩指令的目标应用程序
- 报告崩溃。如果发现崩溃,则可能触发了潜在的漏洞
- 识别种子。如果发现新的边缘覆盖状态,则将测试用例添加到下一个循环的种子队列中
- 如果该种子的fuzzing结束,则转到步骤(3),否则转到步骤(4)
需要注意的是,整个fuzzing处理过程是一个无限循环,只有在手动终止时才会结束循环。此外,因为AFL使用哈希计算来存储边缘覆盖信息(需要通过在每个BBL中插入一个BID随机数来进行哈希计算),不过这样会存在哈希冲突的问题(哈希冲突率通常在30%~70%范围内浮动)。为了解决这个问题,AFL又发展为了CollAFL,CollAFL使用新的哈希计算来存储边缘覆盖信息,这样可以让哈希冲突降低到接近0%(不过CollAFL只使用了边缘覆盖)。此外,CollAFL还遵循以下三个新的种子选择策略:
- 具有更多未受影响的相邻分支的种子将优先进行fuzzing处理
- 更喜欢有更多未受影响的邻居后代的种子
- 更喜欢具有更多内存访问操作的种子
现在我们对AFL和CollAFL已经有了较深的理解,不过上面提到的这两种技术的覆盖率信息又是什么东西呢?覆盖率信息可以看作是评判fuzzer的能力的一项指标,覆盖率越高,说明fuzzer探索到的路径越多,故越有可能发现漏洞;反之则说明覆盖率越低,说明fuzzer探索到的路径越少,故越没有可能发现漏洞。目前测量代码覆盖率的方法主要有三种:
- B B L BBL BBL覆盖率(基本块覆盖率): B B L BBL BBL是一个有一个入口和一个出口点的代码片段,BBL中的指令将按顺序执行,并且只执行一次。 B B L BBL BBL是程序执行的最小相干单元,可以通过第一条指令的地址来识别。通过代码插入和静态分析可以很容易地提取BBL信息。由于这些优点, B B L BBL BBL覆盖信息被fuzzer广泛使用。而典型的基于 B B L BBL BBL的覆盖引导fuzzer只跟踪每个块是否被击中,而不跟踪fuzzing过程中哪些块被击中的顺序,因此详细信息会丢失。如下图所示,在fuzzing过程中,如果首先执行程序路径 1 ( A , B , C , D ) 1(A,B,C,D) 1(A,B,C,D),则与程序路径 2 ( A , B , D ) 2(A,B,D) 2(A,B,D)相关联的测试用例将永远不会添加到种子队列中,因为路径 2 2 2没有命中新的 B B L BBL BBL,因此边缘 B D BD BD的信息将丢失。
- 边缘覆盖率:为了解决 B B L BBL BBL覆盖的缺点,边缘覆盖跟踪每条边缘是否被击中。在上图的例子中,如果首先执行程序路径 1 ( A , B , C , D ) 1(A,B,C,D) 1(A,B,C,D),fuzzer将记录边缘 A B AB AB、 B C BC BC和 C D CD CD,当执行路径 2 ( A 、 B 、 D ) 2(A、B、D) 2(A、B、D)时将记录新的边缘 B D BD BD,因此与路径 2 2 2相关的测试用例现在将添加到种子队列中。然而,边缘覆盖并不能追踪边缘被命中的顺序,因此一些详细信息可能会丢失。我们使用下图中的简单程序和其控制流图来说明这个问题,该程序以 8 8 8个字符作为输入。当输入为
abcd**‼
$或**cdef!!
时,程序将崩溃。
- 路径覆盖率:基于路径覆盖的方法跟踪整个执行路径,包括命中的顺序边缘,从而记录最丰富的信息。几乎不可能为真实世界的应用程序实现路径覆盖,因为程序中有太多的循环和条件,路径的数量会激增。海量路径将带来较大的运行时开销,并可能降低模糊处理的效率。为了克服这个问题,作者将新探索的路径分为两类:
- 对于之前未触及的边,作者将其表示为 e − p a t h e-path e−path。 “ e − ” “e-” “e−”表示路径有新的边
- 所有边都已接触的路径,作者将其表示为 h − p a t h h-path h−path。 “ h − ” “h-” “h−”表示路径有一个新的哈希
关键问题是如何处理大量的 h − p a t h h-path h−path,作者的解决方案是,不将所有的 h − p a t h h-path h−path添加到种子队列,而只将那些高权重的 h − p a t h h-path h−path增加到种子队列。这是一种效率和追踪粒度之间的权衡。
根据上文分析可以发现,目前主要的挑战是路径的数量随着程序大小的增加而呈指数级增长。因此,建议只向种子队列添加重要路径。根据这一思想,作者总结了路径覆盖辅助fuzzer的三个关键问题:
- 如何识别 h − p a t h h-path h−path?
- 如何减少 h − p a t h h-path h−path的数量?
- 哪些 h − p a t h h-path h−path将被添加到种子队列?
2.1、如何识别 h − p a t h h-path h−path?
静态插桩。AFL在编译时对目标程序进行插桩。插桩代码计算边缘哈希并更新边缘覆盖记录到共享内存中。PathAFL维护一个类似AFL的全局哈希表。表索引表示路径哈希,值表示路径是否被覆盖。PathAFL以类似的方式对目标程序进行插桩。它只在AFL原始插桩代码中插入了一小段代码来计算路径哈希。此外,PathAFL扩展了原始共享内存,以存储路径哈希值的4个字节。在程序执行期间,执行路径的哈希值会实时计算并追加到共享内存中。当程序运行完成时,执行路径哈希可用于确定是否已探索新路径。与AFL相比,PathAFL只在插入代码中添加了哈希计算函数,导致开销增加很少。
2.2、如何减少 h − p a t h h-path h−path的数量?
PathAFL采用两种方法来降低执行路径的跟踪粒度,以便模糊器可以限制新 h − p a t h h-path h−path的数量:
-
选择性插桩:AFL默认情况下对目标程序中的所有边缘进行检测,使我们能够跟踪几乎所有的执行路径。为了减少路径,PathAFL必须降低跟踪粒度,只检测部分 B B L BBL BBL并跟踪到达新BBL或触发新错误的概率更高的路径。为了实现这个目的,PathAFL仅对一些函数进行执行路径的插桩。提出以下四个策略来选择关键函数(根据以下策略,可以有效地减少新发现的 h − p a t h h-path h−path的数量):
- 插桩较大的函数,默认为最大的 20 20% 20。因此,可以找到许多通过这些函数的 h − p a t h h-path h−path
- 插桩具有内存操作的函数,例如函数名包含
alloc/free
的函数 - 忽略太小的函数。类似于第一个策略,函数越小,代码越少
- 对其他函数的 10 10% 10进行插桩
-
哈希算法:作者采用了一个非常简单的方案,直接使用全加运算作为路径哈希算法,并以粗粒度的方式区分执行路径。哈希算法如下:
p p p表示执行路径。 B S BS BS表示所有插桩的基本块的执行序列。只需在现有的插桩代码中插入一个add
汇编指令,对测试程序的运行效率几乎没有影响。哈希表的大小与AFL中的位图相同。请注意,此方法仅用于计算路径哈希,不影响 AFL 的原始边缘哈希计算。
2.3、哪些h-path将被添加到种子队列?
为了进一步减少添加到种子队列的 h − p a t h h-path h−path的数量,设计了一种策略来确定是否向种子队列添加 h − p a t h h-path h−path:
- 效率是一个关键因素
- e − p a t h e-path e−path比 h − p a t h h-path h−path更重要
- 应该选择变异后更有可能接触到新边缘的 h − p a t h h-path h−path
正如以下算法所示,作者设计了一种快速过滤算法来满足这些要求。
2.4、种子选择算法
在AFL的原始种子选择算法中存在一个小问题。它虽然确保 F F F(受青睐的种子集)覆盖所有探测到的边,但它并不能确保在一个fuzzing测试循环中测试的受青睐的种子涵盖所有已发现的边,此问题正如下面的算法所示。
针对此问题,作者提出了一个新的种子选择算法,如下图所示。它修复了上述提到的缺陷,确保在一个模糊测试周期中测试的受青睐的种子将覆盖所有已发现的边。
2.5、资源调度
PathAFL根据路径的权重实现新的资源调度,并将更多的资源分配给更高权重的路径。具体来说,它将所有路径按权重划分为六部分,每一部分都分配了不同的资源。
3、达到的效果
作者使用IDA进行静态分析。编写IDAPython脚本来自动分析程序结构,获得边缘信息,并为目标程序生成数据文件。该文件记录所有边缘信息,作为PathAFL的输入,以计算路径权重。下表展现了关于静态分析的时间开销。
3.1、一个简单例子的结果(RQ1)
此部分的实验用于回答RQ1,即“跟踪执行路径对于fuzzing是否可行?”。作者以第1.3节中讨论的例子作为测试用例,对其所有边进行了插装,以在使用PathAFL进行测试时计算路径哈希。结果显示在下表中。AFL和CollAFL-x在7天内未能触发崩溃,而PathAFL和PathAFL-np仅用了一个小时就触发了。此外,PathAFL和PathAFL-np分别在一天内触发了6次和8次崩溃。
这个实验表明,PathAFL能够有效地识别 h − p a t h h-path h−path,并且使用 h − p a t h h-path h−path引导模糊测试是可行的。
3.2、代码覆盖率和崩溃测量(RQ2)
此部分的实验用于回答RQ1,即“PathAFL的代码覆盖率有多好?”。在本次实验中,作者选择了如下几个流行的应用程序进行测试。
下表显示了四个模糊测试工具探索的路径和边的数量。
以上实验表明,PathAFL和PathAFL-np探索的路径数量几乎相同,但PathAFL探索的边的数量比PathAFL-np多。故认为PathAFL更好,可能触及更多的新代码分支。
下图显示了10个实验中不同fuzzer随时间的增长的代码覆盖率的增长。
这再次表明作者的解决方案是有效的。
下表统计了触发的唯一崩溃的平均数量。
此结果表明PathAFL在找到程序中存在的不同崩溃方面表现出色。
总之,PathAFL在路径和边缘发现方面优于AFL和CollAFL-x。而且最好使用资源调度。这些实验证明,所提出的解决方案可以帮助提高路径和边缘覆盖率,并引发更多的崩溃。
3.3、LAVA-M数据集(RQ3)的结果
此部分的实验用于回答RQ1,即“PathAFL的错误检测能力有多好?”。作者在LAVA-M数据集上对AFL和PathAFL进行了为期7天的评估。且对每个实验都进行了五次,并对所有发现的bug进行了计数。评估结果如下表所示。
结果表明,与AFL相比,PathAFL发现了更多的错误。具体来说,PathAFL发现了AFL发现的所有错误。此外,PathAFL发现了base64中注入的所有漏洞,甚至发现了LAVA-M的作者没有列出的四个新漏洞。
3.4、发现现实世界中的漏洞(RQ3)
作者选择了binutils、libav和libtiff进行实验,并使用PathAFL发现了许多严重的漏洞和几个bug(如下表所示)。
所有的错误和漏洞以前都没有报告,可能会带来一些安全风险。作者联系了这些工具的开发人员,并提交了错误详细信息。
4、结论
在本文中,作者辅助fuzzer进行路径覆盖,讨论了其中的一些挑战,并最终实现了一个名为PathAFL的新fuzzing系统。它采用了粗粒度的路径跟踪和快速过滤算法,可以有效地选择更高权重的 h − p a t h h-path h−path,大大增加了路径覆盖的数量。此外,作者还设计了一种基于路径权重的种子选择算法和资源调度。作者在几个不同的实验中对其进行了评估,结果证明 PathAFL 在改善边缘覆盖和发现更多唯一崩溃方面比AFL和CollAFL更为有效。在经过充分测试的程序中,PathAFL 发现了8个新的安全漏洞,分配了6个CVE编号。
总结
以上就是本篇论文阅读笔记的全部内容了,读完这篇论文后,相信各位读者朋友也会认为本篇论文写的相当不错,当然,有些地方笔者可能也理解不深,欢迎各位读者朋友与我积极讨论。后面如果有时间,我会分享阅读本篇论文的心得体会!
相关文章:

论文阅读笔记——PathAFL:Path-Coverage Assisted Fuzzing
文章目录 前言PathAFL:Path-Coverage Assisted Fuzzing1、解决的问题和目标2、技术路线2.1、如何识别 h − p a t h h-path h−path?2.2、如何减少 h − p a t h h-path h−path的数量?2.3、哪些h-path将被添加到种子队列?2.4、种…...
C语言中各种运算符用法
C语言中有许多不同的运算符,用于执行各种不同的操作。 以下是C语言中常见的运算符及其用法: 算术运算符: 加法运算符():用于将两个值相加。减法运算符(-):用于将一个值减…...

pythonJax小记(五):python: 使用Jax深度图像(正交投影和透视投影之间的转换)(持续更新,评论区可以补充)
python: 使用Jax深度图像(正交投影和透视投影之间的转换) 前言问题描述1. 透视投影2. 正交投影 直接上代码解释1. compute_projection_parameters 函数a. 参数解释b. 函数计算 2. ortho_to_persp 函数a. 计算投影参数:b. 生成像素坐标网格&am…...

web安全学习笔记【16】——信息打点(6)
信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等[1] #知识点: 1、业务资产-应用类型分类 2、Web单域名获取-接口查询 3、Web子域名获取-解析枚举 4、Web架构资产-平台指纹识别 ------------------------------------ 1、开源-C…...

145.二叉树的后序遍历
// 定义一个名为Solution的类,用于解决二叉树的后序遍历问题 class Solution { // 定义一个公共方法,输入是一个二叉树的根节点,返回一个包含后序遍历结果的整数列表 public List<Integer> postorderTraversal(TreeNode root) { /…...
ssh远程连接免密码访问
我们在远程登录的时候,经常需要输入密码,密码往往比较复杂,输入比较耗费时间,这种情况下可以使用ssh免密码登录。 一般的教程是需要生成ssh密钥后,然后把密钥复制到server端完成配置,这里提供一个简单的方…...
Vue-Json-Schema-Form: 如何基于模板定制前端页面
本人从事的是工业物联网, 面对工业设备的通讯难题是各大设备都有各自的通讯协议, 如果想要用一款硬件去和所有设备做通讯的话, 就得面对怎么把自己想要采集的配置下发给自己的采集器的问题, 以前都是采用各种模型去尝试构建配置项, 但是因为配置可能会有深层次嵌套, 而且…...
保存Json对象到数据库
文章目录 背景实现方式1. 直接以 Json 对象保存到数据库2. 以 String 类型保存到数据库 背景 项目过程中可能需要保存 Json 对象到数据库中。 实现方式 有两种实现方式,一种是直接保存 Json 对象到数据库,这种方式在创建实体类以及编写 Mapper XML 脚本…...

《Docker 简易速速上手小册》第3章 Dockerfile 与镜像构建(2024 最新版)
文章目录 3.1 编写 Dockerfile3.1.1 重点基础知识3.1.2 重点案例:创建简单 Python 应用的 Docker 镜像3.1.3 拓展案例 1:Dockerfile 优化3.1.4 拓展案例 2:多阶段构建 3.2 构建流程深入解析3.2.1 重点基础知识3.2.2 重点案例:构建…...

【Python笔记-设计模式】适配器模式
一、说明 适配器模式是一种结构型模式,它使接口不兼容的对象能够相互合作 (一) 解决问题 主要解决接口不兼容问题 (二) 使用场景 当系统需要使用现有的类,但类的接口不符合需求时当需要一个统一的输出接口,但输入类型不可预知时当需要创…...

二分算法(c++版)
二分的本质是什么? 很多人会认为单调性是二分的本质,但其实其本质并非单调性,只是说,有单调性的可以进行二分,但是有些题目没有单调性我们也可以进行二分。其本质其实是一个边界问题,给定一个条件…...

【C#】用于基于 UV DLP 的 3D 打印机的切片软件源码解析(一)DLP原理 GUI
0. 原理 基于 UV DLP 的 3D 打印机的工作原理是这样的: UV DLP 是一种使用数字光处理(Digital Light Processing)技术的 3D 打印方法,它利用紫外光(UV)来固化液态树脂,从而形成实体物体。UV DLP…...

Javase补充-Arrays类的常用方法汇总
文章目录 一 . 排序方法二 . 查找方法三 . 判断是否相等的方法四 . 拷贝方法五 . 填充方法 一 . 排序方法 我们第一个要介绍的就是sort方法 这个排序实现的底层逻辑应该是十分复杂的,以我们目前的水平体系应该无法理解,我们今天尝试用我们可以理解的一种排序算法,插入排序来模…...
微信小程序-人脸检测-眨眼驱动ESP32蓝牙设备灯
前面2篇文章已经写了具体的人脸检测和蓝牙 这里直接结合,只列js 代码,剩下的其他代码在另外文章里面 https://blog.csdn.net/walle167/article/details/136261993 https://blog.csdn.net/walle167/article/details/136261919 上代码 import bleBehavior …...

怎么在wifi中实现手机和电脑文件互传
有时我们想手机电脑文件互传,数据线却不在身边,这时我们可以用MiXplorer来实现wifi中手机和电脑互相访问文件。 MiXplorer是一款来自著名安卓开发者论坛XDA的作品,免费且功能强大,被很多人誉为是“全能文件管理器”。 1.在手机上…...

07 STL 简介
目录 什么是STLSTL的版本STL的六大组件STL的重要性如何学习STLSTL的缺陷 1. 什么是STL c标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构和算法的软件框架 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee在惠普实验室的…...
unity学习(39)——创建(create)角色脚本(panel)——静态(static)
1.发现一个非常实用的功能,点击unity中console的输出项,可以直接跳转到vs的代码页! 2.static类(变量)有三个特点: (1)独一份(2)无法实例化。(3&…...

MacOS环境下用powerline配置Terminal终端
Powerline 简介及安装配置 Powerline 是一个 stateless 状态栏,也就是一个全局状态/提示栏。你可以将其配置到你的 bash、Terminal、iTerm2 或 VIM 中,效果会如下所示: 你的 Mac 终端提示栏将会呈现如下图所示: 你的 VIM 状态…...

liunx单机项目部署
文章目录 1.liunx简介2.liunx的jdk安装2.liunx的tomcat安装3.liunx的mysql安装4.单机项目部署 1.liunx简介 Linux,一般指GNU/Linux(单独的Linux内核并不可直接使用,一般搭配GNU套件,故得此称呼),是一种免费…...

SQL 中如何实现多表关联查询?
阅读本文之前请参阅----MySQL 数据库安装教程详解(linux系统和windows系统) 在SQL中,多表关联查询是通过使用JOIN操作来实现的,它允许你从两个或多个表中根据相关列的值来检索数据。以下是几种常见的JOIN类型: …...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...