20199310 2019-2020-2 《网络攻防实践》第9周作业

作业课程: https://edu.cnblogs.com/campus/besti/19attackdefense
作业要求: https://edu.cnblogs.com/campus/besti/19attackdefense/homework/10695
课程目标: 学习《网络攻防技术与实践》教材第九章,并完成课后作业
本次作业实现目标: 学习恶意代码安全攻防

作业正文:

1 知识点梳理

1.1 恶意代码

恶意代码:使计算机按照攻击者的意图执行以达到恶意目标的指令集,不一定使二进制执行文件,也可以使脚本语言代码、宏代码,或者是寄生在其他代码或启动山区中的一段指令流。
恶意代码类型、特性及典型实例

恶意代码命名规则[恶意代码类型.]恶意代码家族名称[.变种号]
多维度标签的恶意代码技术形态分类方法
传播:病毒(寄生感染),蠕虫(网络传播),邮件蠕虫(邮件传播),特洛伊木马(伪装感染),网页木马(网页攻击感染)
控制:后门(一对一控制),僵尸程序(一对多控制)
隐藏:内核Rootkit(内核隐藏),用户Rootkit(应用隐藏)
攻击:DDoS工具(DDoS攻击),Spyware(信息窃取),ClickBot(单击欺诈)

计算机病毒

计算机病毒(Computer Virus):一种能够自我复制的代码,通过将自身嵌入其他程序进行感染,而感染过程通常需要人工干预才能完成。
三种可执行文件的感染方式前缀感染机制后缀感染机制插入感染机制
前缀感染机制:指的是病毒将自身复制到宿主程序的开始,当宿主程序被执行时,操作系统首先会运行病毒代码,大多数情况下,病毒在判断其触发条件是否满足后会将控制权转交给宿主程序,所以用户很难感觉到病毒的存在;
后缀感染机制:指的是病毒将自身复制到宿主程序的末端,然后通过修改宿主程序开始时的指令,加入一条跳转指令,使得在宿主程序执行时首先跳转到病毒代码,执行完病毒代码后再通过一条跳转指令继续执行宿主程序;
中间插入感染机制:指的是病毒在感染宿主程序时,能把它拦腰截断,把病毒代码放在宿主程序的中间。中间插入感染机制能够通过零长度插入技术等使得病毒更加隐蔽,但该机制需要阶段宿主程序时的位置要恰当,需要保证病毒能够首先获得控制权,而且病毒不能被卡死,宿主程序也不能因病毒的插入而不能正常工作,因此编写此类病毒需要高超的技巧。
计算机病毒的传播渠道:移动存储、电子邮件及下载、共享目录等。

网络蠕虫

蠕虫(Worm):自我复制机制与计算机病毒类似,但蠕虫是一类自主运行的恶意代码,并不需要将自身嵌入到其他宿主程序中。蠕虫通常通过修改操作系统相关配置,使其能够在系统启动时得以运行。蠕虫一般通过主动扫描和攻击网络服务的漏洞进行传播,一般不需要人工干预。
基本特性:网络蠕虫和计算机病毒都有感染和自我复制的特性,而且网络蠕虫通过网络的自主传播无需人为干预,计算机病毒特性在于感染宿主,包括可执行文件、数据文档或磁盘引导删去,蠕虫病毒没有必要感染宿主,大多数病毒则需要用户运行一个程序或浏览一个文件。

网络蠕虫的组成结构:类似导弹,弹头用来穿透目标,传播引擎驱动导弹飞向它的目标,目标选择算法和扫描引擎用来引导导弹发现和指向它的目标,有效在和仓中携带了执行真正破坏性攻击的恶性材料。

后门与木马:

后门(Backdoor):是指一类能够绕开正常的安全控制机制,从而为攻击者提供访问途径的一类恶意代码。攻击者可以通过使用后门工具对目标主机进行完全控制,著名的后门工具包括Netcat、Back Orifice、Linux Root Kit和我国自行开发的冰河等。
特洛伊木马(Trojan Horse):是一类伪装成有用的软件,但隐藏其恶意目标的恶意代码。后门和特洛伊木马两个概念经常混淆,后门仅为攻击者给出非法访问途径,而特洛伊木马的特征则在于伪装性。当然,许多工具融合了后门和特洛伊木马两者的特性,即攻击者将后门工具伪装成善意的软件,诱导用户安装从而为其给出访问权,此类工具可称为木马后门。

基本特征:后门和木马是恶意代码中经常被混淆的两类技术形态,在实际的样本实例中也往往融合在一起使用。从定义特性上进行分析,后门是允许攻击者绕过系统常规安全控制机制的程序,能够按照攻击者自己的意图提供访问通道;而木马作为特洛伊木马的简称,是指类看起来具有某个有用或善意目的,但实际掩盖着一些隐藏恶意功能的程序。错误的观点是将后门和木马等同,将提供对受害计算机远程控制的任何程序或受害计算机上的远程命令行解释器均视为木马:而根据定义特性,它们应被视为后门,但如果将后门工具伪装成良性程序,这才具备真正的木马特征。欺骗用户或系统管理员安装特洛伊木马程序,这样木马程序就通过毫无戒备的用户进入到计算机系统中: 隐藏在计算机的正常程序中,将自己伪装成看起来属于该系统,使得用户和管理员不会觉察到它的存在,通常与后门工具结合,成为木马后门。

僵尸网络和程序:

僵尸网络(Botnet):是攻击者(称为botmaster)出于恶意目的,传播僵尸程序控制大量主机,并通过一对多的命令与控制信道所组成的攻击网络。僵尸网络区别于其他攻击方式的基本特性是使用一对多的命令与控制机制,此外也具有恶意性和网络传播特性。
僵尸程序(Bot):是用于构建僵尸网络以形成一对多控制攻击平台的恶意代码形态。内核套件(Rootkit)是在用户态通过替换或修改系统关键可执行文件,或者在内核态通过控制操作系统内核,用以获取并保持最高控制权(root access)的一类恶意代码,又分为用户态Rootkit和内核态Rootkit两种。
基本特征:僵尸程序通常也会携带渗透攻击“弹头”通过利用网络服务漏洞进行网络传播,但它与蠕虫的区别在于是否受控,蠕虫一般都是自主传播方式,而僵尸程序则是接受控制后进行攻击和传播;僵尸程序为了隐藏自身在受害主机上的存在,会采用--些伪装和欺骗机制,此时也具有特洛伊木马特性,但这并非僵尸程序必有的特征:与后门工具类似,僵尸程序也会为攻击者提供对受害主机的远程控制,如在受害主机上执行特定指令,或下载安装一些恶意程序,但它与后门工具的区别在于控制机制的差异,后门通常提供一对- -的控制,而僵尸程序能够为攻击者提供更灵活的一对多的控制机制。因此我们定义,僵尸网络是指攻击者(称为botmaster) 出于恶意目的,传播僵尸程序控制大量主机,并通过一对多的命令与控制信道所组成的网络。僵尸网络区别于其他攻击方式的基本特性是使用一-对多的命令与控制机制,另外,僵尸网络还具有恶意性和网络传播性。
僵尸程序的功能组成结构:

Rootkit:

Rootkit:是一种特殊的恶意软件,它的功能是在安装目标上隐藏自身及指定的文件、进程和网络链接等信息,比较多见到的是Rootkit一般都和木马、后门等其他恶意程序结合使用。
基本特征:正如Rootkit定义中所明确指出的,首先, 它属于特洛伊木马的范畴,它获取运行在目标计算机上与操作系统相关联的常规程序,并用恶意版本替换它们:恶意的Rootkit 程序将自身伪装成恰当且普通的程序,为的就是掩盖其真正的恶意目的,而这种伪装和隐藏机制正是特洛伊木马的定义特性;此外,Rootkit 还作为后门行使其职能,各种Rootkit通过后门口令、远程Shell或其他可能的后门]途径,为攻击者提供绕过正常机制的后门]访问通道,而这正是后门工具的定义特性。作为一类特殊形态的木 马后门工具,一个恶意代码之所以能够被称为Rookit,就必须具备替换或修改现有操作系统软件进行隐藏的特性,而这才是Rootkit的定义特性。

2 实验内容

2.1 代码分析

恶意代码分析:按需求使用一定的规则、方法和工具对计算机程序进行分析,以推导出其程序结构、数据流程和程序行为的处理过程。利用一些列的程序分析技术方法、流程和工具,来识别恶意代码关键程序结构和行为特征的过程。
恶意代码分析的技术方法主要包括静态分析动态分析两大类。静态代码分析方法在不实际执行软件代码情况下对恶意代码进行自动化或辅助分析,通常包括使用反病毒引擎扫描识别已知的恶意代码家族和变种,逆向分析获取恶意代码的关键程序信息、模块构成、内部数据结构和关键控制流程,理解恶意代码的机理,并提取特征码用于检测。动态代码分析方法则通过在受控环境中执行待分析的目标恶意代码,并利用系统、网络、甚至指令层次上的监控技术手段,来获取目标代码的行为机理和运行结果。
静态分析主要手段:

动态分析主要手段:

动手实践:恶意代码文件类型识别、脱壳与字符串提取

实践任务:对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下。

(1)使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具。
首先使用file来是获取文件格式和运行平台,是基于80386型号的CPU,windows操作系统。

为了获取文件文本内容,这里可以直接使用strings rada.exe,但是这里发现是乱码,说明该文件有进行加壳处理:

还有一种获取文件文本内容的方法是先运行该程序,然后在process explorer上读取进程Strings信息:

(2)使用超级巡警脱壳机等脱壳软件,对rada恶意代码样本进行脱壳处理。
为了获取加壳信息,这里使用在C:FileDetectorPFiD下打开PEiD工具,这里可以看到加壳相关工具:

然后用脱壳器进行脱壳文件目录下会出现一个rada_unpacked.exe文件,也就是脱壳文件:

(3)使用字符串提取工具,对脱壳后的rada恶意代码样本进行分析,从中发现rada恶意代码的编写作者是谁?
这时再用PEiD打开发现当前编译工具使用时VB5.0/6.0:

我们在用上面讲的两种方法读取文本内容,可以看到文本内容已经没有乱码:

动手实践:分析Crackme程序

实践挑战:使用IDA Pro静态或动态分析crackme1.exe与crackme2.exe,寻找特定的输入,使其能够输出成功信息。
这里一共有两个需要破解程序,我们可以用file查看文件格式和运行平台:

首先要猜测需要输入的参数个数,这里我们从0个参数开始,依次测试不同参数个数的输出

然后我们使用IDA工具开始反编译,该程序在路径C:DisassembleIDA Freeidag.exe下:

这里先查看程序中明文字符串Strings window,可以发现前四个中有两项输出记录下来了,猜测第2条是密码,第四条是破解成功的提示语:

将窗口切换到汇编语言窗口IDA View-A,在菜单栏中View-Graphs-Function calls依次点开查看函数结构:

这里定位到sub_401280是主要的逻辑函数:

我们在Functions window中定位该函数:

然后看到具体的汇编内容:

这里主要推测的依据是不同逻辑判断后程序的提示语:

此时,我们可以推测输出正确输入应该为"I know the secret",由于是字符串变量,这里必须要加"

对于crackme2.exe采用相同的方法,首先测试其参数:

可以推测出正确参数个数为1,然后在IDA中打开,查看不同的字符串输出,这里一共有五种,1和3已经出现,剩下三条中应该是包括输入和输出的信息:

我们依据同样的分析方法打开函数结构图:

其中定位到比较关键的sub_401280函数:

以及它之后的判断分支:

根据分析,我们应该将原文件重命名为crackmeplease.exe,然后显示出Pardon?What did you say?,这说明我们已经离正确输出很近了,然后就是修改制定的密文为:I have the secret",就可以输出正确答案:

3.实践作业

样本分析实践:分析一个自制恶意代码样本rada,并撰写分析报告

本次实践作业的任务是分析一个自制的恶意代码样本,以提高对恶意代码逆向工程分析技术的认识,并提高逆向工程分析的方法、工具和技术。
关于这个二进制文件,我们创建它的目的是为了提高安全业界对恶意代码样本的认识, 并指出为对抗现在的恶意代码威胁发展更多防御技术的必要性。你作为一名安全事件处理者的任务(如果你接受的话)就是深入分析这个二进制文件,并获得尽可能多的信息,包括它是如何工作的,它的目的以及具有的能力,最为重要的,请展示你获取所有信息所采取的恶意代码分析技术。
待分析二进制文件位置:rada.zip警告这个二进制文件是一个恶意代码,因此你必须采用一些预防措施来保证业务系统不被感染,建议在一个封闭受控的系统或网络中处理这个未知的实验品。

文件分析
打开wireshark和已经脱壳的rada_unpacked.exe,在进程探测器中点击运行的进程,可以看到该二进制文件的编码字符串内容,当恶意程序打开后或以http协议与目标地址10.10.10.10RaDa_commands.html进行连接,在本机目录下会新建tmpbin两个文件夹,注册表也会有改变:

wireshark上发现大量发现10.10.10.10TCP数据包:

但是追踪上述TCP数据包并没有发现内容,推测这里开启DDoS拒绝服务远程攻击,在注册表编辑器中,增加了bin/目录下的RaDa.exe,说明该程序已经成为自动启动项:

IDA对脱壳后的二进制文件进行反编译,首先查找它的string,这里需要把type改成unicode

这里显示调用了很多命令行参数,参考了其他同学的博客内容,大概整理了有以下这些:

参数 作用
--verbose 显示Starting DDoS Smurf remote attack
--visible 决定在获取html文件时,IE窗口是否可见
--server 指定命令文件控制服务器的ip地址、访问协议及目录等,默认是http://.10/RaDa
--commands 指定命令文件,默认是RaDa_commands.html
--cgipath 指定服务器上cgi文件的根目录,默认是cgi-bin
--cgiget 指定负责文件上传的cgi脚本,默认是upload.cgi
--cgiput 指定负责文件下载的cgi脚本,默认是download.cgi
--tmpdir 指定临时文件夹的位置,默认是C:RaDa mp
--period 指定两次向服务器请求命令文件的时间间隔,默认是60秒
--cycles 指定多少次向服务器请求命令文件后退出,默认是0(没有限制)
--help 输出版权信息
--gui 使用该参数会使样本出现一个GUI窗口
--installdir 指定样本的安装路径,默认是C:RaDain
--noinstall 使用该参数,样本将不会安装、也不会添加注册表
--uninstall 卸载样本
--authors 如果确认不是在VMware的虚拟机中运行,则显示样本的作者;否则显示参数不存在

然后往下找,发现三个网段,10开头的网段让我想到了目标IP地址10.10.10.10,这里应该是确保本地连接至目标IP网段内网,然后获取一些指令:

常用获取的指令有exe, getputscreenshotsleep等,其中exe在宿主主机中执行指定的命令,put将宿主主机中的指定文件上传到服务器。get将服务器中的指定文件下载到宿主主机中,screenshot截取宿主主机的屏幕并保存到tmp文件夹,sleep停止活动一段时间:

回答问题
1.提供对这个二进制文件的摘要,包括可以帮助识别同一样本的基本信息。
MD5摘要信息

PE格式

可以运行在Windows系统上运行,支持的cpu型号是80386,32位,根据之前的静态分析的内容,该二进制文件进行了加壳处理。

2.找出并解释这个二进制文件的目的。
这个二进制文件通过连接互联网与攻击机取得会话连接,然后进行攻击,不具备自主传播,可以排除是蠕虫或者病毒,推测是后门程序或者僵尸程序。

3.识别并说明这个二进制文件所具有的不同特性。
RaDa.exe被执行时,将在该目录下新建bintmp文件,其中bin目录下的二进制文件修改注册表,自动随虚拟机开启,然后从指定的目标服务器请求web页面,获取指令和参数。

4.识别并解释这个二进制文件中所采用的防止被分析或逆向工程的技术。
通过脱壳前后的字符串对比,确定这个文件采取了UPX加壳,不经过脱壳处理无法解析反编译,因为产生的都是乱码。

5.对这个恶意代码样本进行分类(病毒、蠕虫等),并给出你的理由。
该程序并未进行自我复制和传播,不符合蠕虫和病毒的特征,也没有伪装成其他形式的文件,也不是木马,所以可能是一个后门程序或者僵尸程序。

6.给出过去已有的具有相似功能的其他工具。
类似的比如上周实验中使用的用msfvenom命令生成后门文件,通过写入攻击机IP和端口的二进制文件,靶机可以直接被攻击机通过multi/handler模块直接连接。

奖励问题:
7.可能调查出这个二进制文件的开发作者吗?如果可以,在什么样的环境和什么样的限定条件下?
可以找到该二进制文件的开发者,必须对该二进制文件脱壳,然后通过process explorer进行进程查看,其中字符串内容中有显示开发者:

取证分析实践: Windows 2000系统被攻陷并加入僵尸网络

案例分析挑战内容:
在2003年3月初,Azusa Pacific大学蜜网项目组部署了一个未打任何补丁的Windows2000蜜罐主机,并且设置了一个空的管理员密码。在运营的第-一个星期内,这台蜜罐主机就频繁地被攻击者和蠕虫通过利用几个不同的安全漏洞攻陷。在一次成功的攻击之后,蜜罐主机加入到一个庞大的僵尸网络中,在蜜罐主机运营期间,共发现了15164个不同主机加入了这个僵尸网络。这次案例分析的数据源是用Snort工具收集的该蜜罐主机5天的网络流日志,并通过编辑去除了一些不相关的流量并将其组合到了单独的一个二进制网络日志文件中,同时IP地址和一些其他的特定敏感信息都已经被混淆以隐藏蜜罐主机的实际身份和位置。你的任务是分析这个日志文件并回答以下给出的问题。.

1.IRC是什么?当IRC客户端申请加入一个IRC网络时将发送哪个消息? IRC一般使用哪些TCP端口?
IRC:因特网中继聊天(Internet Relay Chat),一般称为互联网中继聊天。IRC的工作原理非常简单,您只要在自己的PC上运行客户端软件,然后通过因特网以IRC协议连接到一台IRC服务器上即可。它的特点是速度非常之快,聊天时几乎没有延迟的现象,并且只占用很小的带宽资源。所有用户可以在一个被称为"Channel"(频道)的地方就某一话题进行交谈或密谈。每个IRC的使用者都有一个Nickname(昵称)。
申请加入一个IRC网络时会发送服务器的域名,TCP申请端口和昵称,一般端口号为6667,或者6660-6669范围的端口,该端口为明文传输,SSL加密传输在6697端口。

2.僵尸网络是什么?僵尸网络通常用于什么?
僵尸网络:攻击者通过各种途径传播僵尸程序感染互联网上的大量主机,而被感染的主机将通过一个控制信道接收攻击者的指令,组成一个僵尸网络。众多的计算机在不知不觉中如同僵尸群一样被人驱赶和指挥着,成为被人利用的一种工具,常见的僵尸网络攻击如分布式拒绝服务攻击(DDoS)、海量邮件垃圾等,黑客还可以控制和利用这些网络中主机所保存的信息。

3.蜜罐主机(IP地址: 172.16.134.191) 与哪些IRC服务器进行了通信?
已知蜜罐主机IPIRC服务的常用端口6667,我们通过ip.src == 172.16.134.191 && tcp.dstport == 6667来查找目标服务器IP地址,主要有63.241.174.144,217.199.175.10,209.126.161.29,66.33.65.58,209.196.44.172

4.在这段观察期间,多少不同的主机访问了以209.196.44.172为服务器的僵尸网络?
这里需要用到tcpflow这个命令,首先有关apt-get install tcpflow进行安装,然后执行tcpflow -r botnet_pcap_file.dat 'host 209.196.44.172 and port 6667',会生成172.016.134.191.01152-209.196.044.172.06667,209.196.044.172.06667-172.016.134.191.01152report.xml三个文件,在report.xml文件中显示了:

<configuration>
    <fileobject>
      <filename>209.196.044.172.06667-172.016.134.191.01152</filename>
      <filesize>1082018</filesize>
      <tcpflow startime='2003-03-06T04:23:18.829879Z' endtime='2003-03-06T08:27:57.736205Z' mac_daddr='00:05:69:00:01:e2' mac_saddr='00:e0:b6:05:ce:0a' family='2' src_ipn='209.196.44.172' dst_ipn='172.16.134.191' srcport='6667' dstport='1152' packets='9798' out_of_order_count='223' len='1630694' />
    </fileobject>
    <fileobject>
      <filename>172.016.134.191.01152-209.196.044.172.06667</filename>
      <filesize>1046</filesize>
      <tcpflow startime='2003-03-06T04:23:18.775202Z' endtime='2003-03-06T08:27:57.867166Z' mac_daddr='00:e0:b6:05:ce:0a' mac_saddr='00:05:69:00:01:e2' family='2' src_ipn='172.16.134.191' dst_ipn='209.196.44.172' srcport='1152' dstport='6667' packets='8902' len='536112' />
    </fileobject>
  </configuration>

这里一部分是从目标服务器发送出来的,一部分是从其他主机发送到目标主机的,统计得到主机个数为3457:

5.哪些IP地址被用于攻击蜜罐主机?
首先,我们利用tcpdump指定IP地址收集被攻击的端口写入1.txt,然后执行tcpdump -n -nn -r botnet_pcap_file.dat 'dst host 172.16.134.191' | grep -v 'reply' | cut -d '.' -f 10 | cut -d ':' -f 1 | sort | uniq | more >1.txt; wc -l 1.txt统计个数:


我们通过snort获取所有可能链接的主机IP地址,将内容输出到2.txt,可以看到一共有165行共计165个:
tcpdump -n -nn -r botnet_pcap_file.dat 'dst host 172.16.134.191' | awk -F " " '{print $3}' | cut -d '.' -f 1-4 | sort | uniq | more > 2.txt;wc -l 2.txt:

6.攻击者尝试攻击了哪些安全漏洞?
首先用snort统计一下网络流量包分布情况:

以上可以看出大部分为tcp数据包,少部分为udp数据包,然后我们分别筛选这两种端口:



输出可以看到 TCP 响应端口为135(rpc)139(netbios-ssn)25(smtp)445(smb)4899(radmin)80(http)。将协议部分改为udp,可以筛选出udp端口137(netbios-ns)
下面依次分析这些端口:TCP135端口,只是进行了连接,没有数据内容交换,很有可能是对这个端点进行了connect扫描:

TCP25端口,与135端口相似,也没有进行数据内容的交换,猜测攻击机对其进行了connect扫描:

TCP139端口,这里大部分连接也没有传递具体会话内容,主要也是SMB查点:

TCP445端口,这里发现有一个PSEXESVC.EXE的文件,这个二进制文件主要是一种Dv1dr32蠕虫,这种蠕虫通过IRC进行通信。

然后该源IP地址与蜜罐主机建立了会话,攻击成功,这里Windowssvcctl MSRPC接口用于同SCM(服务控制管理器)通讯,svcctl漏洞允许匿名用户连接到SCM,然后就可以枚举所安装的或正在运行的服务。

TCP4899端口,这里上查了一些资料,4899其实是一个远程控制软百件所开启的服务端端口,由于这些控制软件功能强大,所以经常被黑客用来控制被自己控制的远程电脑,而且这类问软件一般不会被杀毒软件查杀,比后门还要安全。

TCP80端口,这里主要通过该端口使用脚本攻击IIS服务器的漏洞,从而获取系统权限。

210.22.204.101访问了80端口,攻击者通过缓冲区溢出获得命令行:

这里访问的是218.25.147.83,这里会看到c: otworm,是一个蠕虫攻击:


其余对80端口攻击,蜜罐主机均以IIS服务器的默认页面作为回应,这些攻击均失败了:

UDP137端口,网络基本输入/输出系统 (NetBIOS) 名称服务器 (NBNS) 协议是 TCP/IP 上的 NetBIOS (NetBT) 协议族的一部分,它在基于 NetBIOS 名称访问的网络上提供主机名和地址映射方法,在局域网中提供计算机的IP地址查询服务,处于自动开放状态,所以访问这个端口肯定就是 NetBIOS 查点了。

7.哪些攻击成功了?是如何成功的?
通过上面的分析,SVCCTL服务漏洞攻击成功,PSEXESVC蠕虫攻击成功。

4.学习中遇到的问题及解决

  • 问题1:程序动态分析
    问题1解决方案:这里主要用脱壳工具先对程序脱壳,然后用IDA工具对程序文件进行反编译,一般简答的程序可以通过String windows来查看定位关键函数,而一般的程序则需要分析函数结构图,这里其实还可以显示单个函数的汇编流程,需要现在Function window选中函数,然后才可以从View菜单栏中的Graph显示。

5.学习感悟和思考

本次实验涉及到恶意代码的分析,尤其是涉及取证分析,面对海量数据无从下手,很多知识内容还有待掌握。

参考资料

原文地址:https://www.cnblogs.com/louhao-20199310/p/12789892.html