
1. 从一次真实的蓝队困境说起先讲个我亲身经历的场景。某次授权攻防演练红队丢上来一个体积不到 200KB 的载荷过掉了我们当时全套的EDR。当时我们终端上跑着主流的商业杀软加EDR策略开到了严格模式但对方就靠一个白名单进程的DLL劫持把C2流量藏在HTTPS证书里整整三天我们没看到任何告警。后来复盘的时候发现不是我们日志没采全是采集到的行为序列根本没有命中任何一条规则——因为对方把每个动作都拆散穿插在正常的业务请求里单看每一条都人畜无害。那次之后我花了很长时间整理手头的免杀对抗笔记后来发现很多防御侧的同学对免杀的理解还停留在“特征码查杀”和“加壳混淆”这个层面觉得这是攻击队才需要研究的东西。这个认知偏差其实很要命——不了解对抗手法就根本没法设计出有效的检测策略。这篇笔记我不打算谈具体工具怎么用、Shellcode怎么生成那些东西在授权攻防之外没有任何意义。我只想从防御者的视角把这场对抗中攻击侧常用的思路、我们防守侧应该重点关注的行为特征以及我在实战中总结出来的排查套路完整梳理一遍。内容会覆盖PE文件的静态层面、运行时的行为层面、以及内存层面三条主线每一条都会给出我实测过的检测思路和踩坑记录。无论你是刚入门的安全运维还是已经写了几年检测规则的蓝队老兵这篇笔记应该都能给你一些可复用的东西。2. 免杀对抗的基本盘攻击者到底在绕什么2.1 杀软和EDR检测体系的三个层次要搞清楚免杀对抗先得明白对面在绕什么。现在主流的终端安全产品检测体系大致分三层这三层各有各的弱点攻击者的免杀手段基本都是冲着这三层去的。第一层是静态扫描引擎。这层靠的是特征库匹配杀软把已知恶意样本的字节片段、哈希、加壳特征提取成特征码扫描时把文件拆开逐一比对。优点是速度快、不占资源缺点是规则永远滞后于新样本而且特征提取本身就有规律可循——只要改变样本中特征码所在位置的几个字节或者换一种方式压缩壳特征就失效了这就是最早期的免杀手法。第二层是行为监控与沙箱。这层不再只看文件长得什么样而是看它运行起来干什么事。常见的手段包括挂钩关键API比如WriteProcessMemory、VirtualAlloc、CreateThread、监控注册表敏感位置变更、拦截可疑的进程注入行为等等。行为检测比静态扫描强不少但它有个天然的痛点——误报率高。企业环境里正常的软件安装、更新、加载驱动本身就会触发大量敏感API调用EDR厂商为了不影响业务不得不把行为规则放到一个相对保守的阈值上这就给攻击者留下了大量的检测盲区。第三层是关联分析东西向。这是最进阶的一层也是目前各大EDR主打的卖点。它会把单台主机上的行为事件聚合成图看的是攻击链而不是单点行为。比如一台机器上先有Office进程启动PowerShellPowerShell又访问了内网SMB共享接着另一个IP开始横向探测——这套序列组合起来明显是攻击行为。这类检测的难点在于时序和语义分析攻击者只要把动作拆散、拉长间隔、混入正常流量就能把攻击链打碎成一片看不出关联的事件。2.2 免杀的本质信息不对称下的规则对抗网上很多文章把免杀讲得很玄乎其实拆穿了就一句话攻击者利用检测规则对“变异”和“上下文语义”的感知盲区让恶意行为在检测模型里看起来没有恶意属性。这里有两个关键词需要展开说一下。第一个是“变异”。任何静态规则都基于已知样本抽象而来意味着规则只能覆盖它见过的变体空间。攻击者做的就是在这个变体空间里不断偏移——换编译方式、换壳、换加密算法、改变资源结构、打乱导入表顺序。这本质上是一个搜索问题攻击者在找一个点让样本落在这个点上的时候能避开所有已知规则的覆盖范围。第二个是“上下文语义”。行为检测规则的误报率高所以规则引擎里大量检测逻辑是带条件的比如“某个进程在访问LSASS进程内存时必须满足特定条件才会告警”。攻击者正是利用这种条件判断故意让恶意行为出现在“看似合理”的上下文里。比如有的白程序本身就会加载第三方DLL攻击者把恶意DLL伪装成这个白程序的合法插件往旁边一放行为监控一看“加载DLL”这个动作是合法进程触发的就放行了。理解这两点之后防守思路就清晰了。如果还只盯着“发现病毒”这个维度那你永远在和攻击者的变体赛跑累死也追不上。真正有效的防守是把关注点从“样本是不是恶意”转移到“行为是否符合这台主机/这个用户的正常基线”上这就是后面要讲的异常行为建模的核心逻辑。3. 攻击链视角下的免杀对抗拆解3.1 载荷投递从文件落地到白名单利用攻击者的免杀思路是贯穿整个攻击链的不只是最后那个Payload本身。从载荷投递阶段就开始设计了。主流的方式分几类我按频率从高到低排一下。第一类是宏文档与脚本型。Office宏、VBS、PowerShell、LNK文件这些都是攻击者的老朋友。这类载荷的免杀难点不在PE文件结构而在脚本内容本身。杀软对脚本内容的检测通常依赖正则和模糊哈希攻击者通过字符串拼接混淆、编码转换、拆段执行就能绕过。防守侧对应的检测思路很明确——监控Office进程创建子进程尤其是PowerShell、Cmd、监控脚本宿主进程的异常命令行参数、对脚本内容做行为沙箱模拟执行。第二类是白名单进程利用。这是目前攻防演练中最难防的一类。攻击者会寻找目标环境里已装好的签名软件利用它们的合法功能做坏事。比如用MSBuild.exe执行C#代码、用Regsvr32远程加载SCT脚本、用DllHost加载恶意COM对象、用Msiexec执行远程MSI。这类执行方式的共同点是父进程是可信签名程序子进程行为在外人看来完全正常EDR即使监控到执行链也不会触发规则。防守策略只有一个对这些“可以执行任意代码的合法工具”重点监控并且关注它们在你这台机器上是否“符合使用预期”——比如一台业务服务器上平时没人用MSBuild突然有人用它编译项目这本身就是强告警信号。第三类是无文件攻击。这个术语被用烂了实际情况里更准确的说法是“载荷不落盘”——从网络侧直接注入内存或者从注册表键值、WMI仓库里读取然后在内存中展开执行。检测无文件攻击的思路要从前端主机转移到网络侧和内存侧流量侧抓取可疑的下载响应内容、主机侧检测特定进程的不正常内存区域可写可执行这是后话第四章会展开讲。3.2 执行阶段行为拆解隐蔽术投递只是第一步真正决定成败的是执行阶段的隐蔽程度。攻击者在执行阶段最常用的手法是把恶意行为拆成独立小步骤然后混入正常业务动作流。举个例子。获取代码执行后攻击者需要把后续的Shellcode加载到内存并运行。经典的恶意操作序列是这样的申请内存VirtualAlloc、将解密后的Shellcode写入内存WriteProcessMemory或memcpy、修改内存页权限VirtualProtect、创建线程执行CreateThread。这套序列太经典了经典到每一个EDR都有对应的行为检测规则。攻击者怎么绕拆开来看。第一步“申请内存”任意程序运行过程都会申请内存这条无法拦。第二步“写入数据”函数调用拷贝数据进缓冲区是合法操作监控到一个线程往自己的内存里写东西正常得不能再正常。第三步“修改权限”这个动作有一定的告警价值但很多商业软件运行时也会动态修改内存页权限JIT编译器就这么干误报率控制不下来。第四步“创建线程”这就更没法拦了程序创建线程是操作系统层级最基础的操作。攻击者只要把这些步骤用合法的API包装起来、中间间隔随机化、在不同线程里执行行为规则的命中率就大幅下降。再配合“回调式执行”这种把线程创建包装进异步操作的手段传统的顺序匹配检测基本就失效了。防守侧的对策是把单个动作的告警阈值放低转而在更高维度做执行链分析——不是说看到VirtualAlloc就告警而是看“某个进程在一段时间内是否累积出现了符合恶意内存操作特征的动作组合”。我和团队在实践中发现基于时序窗口的特征工程比单点规则有效得多哪怕这个窗口只设成几秒钟也能把大量“拆散执行”的手法兜住。3.3 权限维持与痕迹清理防守侧最容易漏掉的一环绝大部分防守方的注意力都在“初始执行”这个阶段结果就是中了之后没发现。实际上攻击者执行完初始载荷后还有大量对检测有影响的动作这个阶段往往被我方防守人员忽视。权限维持方面攻击者常做的是注册表自启动项、创建计划任务、WMI事件订阅、替换常用程序的DLL。其中WMI事件订阅是隐蔽性极高的一种因为它存活在WMI仓库里常规的启动项扫描根本看不到而且通过WMI筛选器可以做到特定条件下才触发比如系统启动后延迟N分钟这要求防守方必须主动检查WMI活动。痕迹清理方面攻击者会清理事件日志、删除最近打开的文件记录、清空临时目录、移除攻击过程中产生的临时文件、关闭自身进程的审计标志。很多EDR告警链会因为日志被清而断裂后续溯源难度大幅增加。针对这两类行为防守方的工作重心其实是确保数据源的完整性和不可篡改性——日志要实时外发到集中式日志平台、终端上的安全Agent要有自保护机制防止被恶意停止或卸载、关键注册表键和文件系统目录要配置对象级的审计策略。这一步没有太多花活纯粹是基本功但做好了能显著降低攻击者的“留存”成功率。4. 核心对抗面分析静态、行为与内存4.1 静态对抗特征绕过与检测策略静态对抗是最“古老”的对抗形式但攻击者从未放弃过这个层面因为静态扫描仍然是最快、覆盖范围最广的检测手段。攻击者做静态免杀通常会用到这几种思路。花指令与熵值欺骗在样本的入口点之前插入大量无意义的跳转指令序列让扫描器的模拟执行引擎走到错误路径上或者识别不到有效的入口逻辑。更进阶的玩法是控制恶意代码段的熵值——把加密后的载荷伪造成正常数据流比如一张合法的图片、正常编译的库文件人为降低恶意代码段的熵值让“高熵分段”这种检测逻辑失效。检测端的应对思路是不要依赖单一特征重点检查导入表与导出表的异常组合、数字签名的有效性、资源段里藏的数据与文件声称的类型是否一致比如一个声称是PDF的文件资源段里却有个可执行节。已知签名白名单滥用目前最流行的静态度过一次是把恶意代码编译成微软签名的“LOLBIN”格式或者使用签名版的白程序外壳加载Payload。这种文件静态扫描时数字签名验证是合法有效的扫描器默认跳过签名为可信的文件。这个手法的关键在“文件功能与声明的身份不符”所以检测思路要覆盖到——监控签名的可执行文件是否执行了与其正常功能不匹配的行为。内存Shellcode与文件分离静态扫描能扫到的是“落盘”的文件本身攻击者只要把真正的恶意代码放到网络侧或者在运行时动态解密静态扫描对“分离式载荷”就完全没有感知了。这也是现在攻防演练里最主流的载荷落地方式。应对方法是把静态检测和大数据关联做打通——内网流量侧抓取到了可疑的二进制下载终端侧出现了对应进程的可疑行为两侧关联起来才能打中。4.2 行为对抗从单一行为到上下文检测行为检测的对抗核心在上下文语义的攻防。攻击者努力让自己的行为贴近“正常软件的操作习惯”防守者努力在行为序列里找出“正常软件不会那么做”的细节。以进程注入为例攻击者常用的方式有远程进程注入最常见OpenProcess拿句柄、VirtualAllocEx在目标进程申请内存、WriteProcessMemory写入数据、CreateRemoteThread执行这一套下来攻击者的代码就跑进别的进程里了。防御上重点要看的是“一个低权限进程是否获取了高权限进程的句柄”以及“目标进程是否存在调试权限标志”。APC注入用QueueUserAPC把shellcode排队到目标线程的异步过程调用里等目标线程下次被调度时执行。这种注入方式不创建远程线程行为特征比CreateRemoteThread隐蔽得多。检测思路是看进程内部是否出现了异常的执行权限切换。线程劫持挂起一个现有线程修改其上下文寄存器环境把执行流引向恶意代码再恢复线程。这类手法最隐蔽因为不申请新内存、不创建新线程纯靠修改线程上下文EDR对单个线程的上下文频繁切换通常没有监控。防守重点是设置对NtSetContextThread等API的敏感度告警并关联线程上下文切换频率的异常指标。行为检测的进阶玩法是用户实体行为分析UEBA。常规行为规则是“做了一套组合动作就报警”UEBA是做基线——每台主机先学一段时间正常行为然后检测偏离。比如机器A平时从来不访问某个IP突然开始持续访问机器A平时登录时间是白天凌晨3点突然有进程网络请求这些偏离基线本身就是强信号。这种检测方式对“拆散执行”、“慢速攻击”这类手法有天然优势因为无论攻击链怎么拆最后总要产生偏离基线的行为。4.3 内存对抗EDR扫描盲区与攻防焦点内存对抗是目前免杀对抗中技术含量最高的领域也是很多EDR产品的薄弱环节。攻击者在内存里做的事情本质上是在“不让EDR看到恶意代码在内存中的真实形态”。业界最常见的两种内存检测技术是内存扫描周期性地扫描进程内存空间查找shellcode特征。绕过方式很直接shellcode在内存中是加密状态的只有到执行前一刻才解密。攻击者可以做到“边执行边解密执行完立刻清理”内存扫描就抓不到。行为监控监控关键API调用序列。绕过思路就是前面讲的API拆散、合法API包装、回调式调用等等。比较高阶的对抗发生在可执行内存页的权限转换上。攻击者先申请可读写的内存页RW写入shellcode然后改成可读可执行RX最后执行。这种RW→RX的权限转换是内存中shellcode落地的必经之路。检测思路已经很成熟了就是开启**Arbitrary Code GuardACG**这类功能强制阻止内存页的可执行权限动态分配。Windows 10以上系统自带这个机制EDR可以调用它。很多企业环境没有开启这个策略这是个非常大的防守盲区。另外一个内存对抗焦点是远程线程的上下文状态。EDR通过遍历线程栈可以判断线程当前执行的内存取源自哪里如果发现一个线程的执行流跳转到了没有镜像文件对应的内存区域也就是没有模块名这就是典型的代码注入特征。攻击者为了规避这种检测会把shellcode藏进合法模块的代码缝隙里也就是Engage/Doppelgänging这类“模块种植”技术让线程栈显示执行流属于某个合法模块。防侧的策略调整为不只检查“执行流是否来自合法模块”还要检查“执行流的偏移是否在合法模块的正常代码段范围内”。5. 实战排查技巧与检测策略落地5.1 检测策略设计的三个核心原则看了前面的对抗面分析很多同学可能会问那到底怎么把这些思路变成真正能落地的检测策略我总结出三条核心原则这三条原则贯穿了所有有效检测方案在此分享给大家。原则一聚合。单个行为事件的信号量永远不够必须把多个弱信号聚合成强信号。比如“某进程调用了VirtualAlloc WriteProcessMemory CreateRemoteThread”这个组合每个动作单独看都正常但组合在一起且发生在同一个进程的一次运行周期内就是极强信号。工程实现上要注意聚合的窗口期设置窗口太短漏报太长误报爆炸一般建议从秒级别开始调参。原则二上下文。检测规则不要只写“进程做了什么”还要写“进程的身份和它的行为是否匹配”。示例powershell.exe执行脚本内容是正常行为但powershell.exe从网络下载文件然后执行是异常行为。具体到规则层面就是把执行链上下文加到检测逻辑里——父进程、命令行、网络连接的远端地址、文件路径层级这些元数据都是“上下文”。原则三不追求通杀追求兜底。很多检测工程师犯的错误是试图用一个规则覆盖这种攻击手法所有变体结果就是规则因为误报太高被调成静默。正确的思路是放弃“一条规则识别所有变体”的幻想把精度做高针对每个具体变体写对应的原子规则再在更高层的关联引擎里做聚合。宁可少而准不可多而废。5.2 常用排查命令与日志源对照实战排查中手里有一份“命令—日志源”对照表会省非常多的时间。我把日常应急响应最常用到的排查项整理成表方便大家直接抄作业。排查目标关键命令/工具需要看重的日志源进程链异常PowerShell: Get-Process | Select ProcessName,ParentProcessId,PathC:\Windows\System32\wmic.exe process getEDR的进程树事件流、Sysmon EventID 4688进程创建网络连接外联netstat -ano配合进程PID关联防火墙日志、EDR的网络连接事件、DNS日志自启动与计划任务reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Runschtasks /query /fo LIST /vSysmon EventID 1进程创建、EventID 12-14注册表变更WMI持久化wmic /namespace:\root\subscription path __EventConsumerBindingGet-WmiObject -Namespace root\subscription -Class CommandLineEventConsumerWMI活动日志、Sysmon EventID 19-21WMI事件内存可疑区域使用Volatility内存取证、Process Hacker查看进程内存模块EDR的内存扫描采集结果这里特别提醒一下日志外发的问题。很多企业都装了EDR但日志只留在终端本地攻击者清理日志后我们就彻底瞎了。一定要把EDR的原始事件流实时转发到集中式日志平台SEIM或自建的数据管道并且保证这个转发通道的可靠性。我见过太多应急响应案例最后卡就卡在日志不全攻击者把关键环节一清整个攻击链就拼不回去了。5.3 从告警到处置一个完整的检测响应流程实例理论和命令都讲完了我给一个真实的检测响应流程实例方便大家串起来理解。场景设定某天下午安全运营平台弹出一条告警——一台内网Windows服务器上的msbuild.exe进程创建了PowerShell子进程并且该PowerShell进程随后访问了外部IP。第一步告警分级。这条告警包含三个关键信号msbuild.exe创建PowerShell子进程执行链异常、PowerShell发起外部连接数据外带或C2通信迹象、外部IP在内网黑名单之外未知威胁。综合判断为高危告警立即进入应急响应流程。第二步快速研判。登录终端抓取当前进程快照确认msbuild.exe进程的完整命令行。仔细查看发现命令里有一个指向内网共享路径的XML文件路径这符合MSBuild执行C#代码的特征。同时查看PowerShell进程的网络连接确认确实在向外部IP的443端口发送数据。第三步阻断与隔离。立即断开该终端的外联网络在防火墙上封锁该终端IP和外部IP的通信通过EDR隔离终端阻止msbuild.exe和PowerShell进程继续运行。同时对样本文件那个XML做哈希提取在全网范围内搜索是否有其他终端存在相同文件。第四步溯源与清除。通过进程创建事件链回溯发现msbuild.exe是由outlook.exe启动的——攻击者通过邮件投递了带有恶意附件的钓鱼邮件附件被打开后释放XML文件到内网共享路径随后通过MSBuild执行了代码。清除工作包括删除恶意XML、清理注册表Run键里的痕迹、检查WMI持久化发现了一条计划任务、重置受感染账号的密码。第五步复盘改进。事后梳理发现两个防守缺口EDR对msbuild.exe创建PowerShell子进程的告警阈值设置过高因为测试期间出现过大量误报以及邮件网关对这类“附件中带脚本”的检测存在规则盲区。修复动作是把进程链告警的阈值调低同时联动沙箱对附件中的脚本类文件做深度模拟执行分析。这个实例里的每个环节对应着检测策略里面的一个重要点第一条就是告警来源的可靠性和上下文补齐能力没有好的日志和事件流再好的规则也发挥不出来。6. 常见问题与踩坑记录6.1 检测策略踩过的坑与调整方案我把自己和团队在实际项目中踩过的坑整理成清单按频率从高到低排列每个坑都附上我们最终怎么调整的。坑一误报率压不住规则被业务方投诉之后调成静默。这是最常见的坑几乎每个安全团队都会经历。原因通常是规则写得不够精确上下文信息用得太少。调整方案把单条规则拆成“原子规则聚合规则”两层原子规则负责捕获单一行为但只记录日志不弹告警聚合规则在原子规则的基础上加条件比如同一进程短时间内命中N条原子规则、或者关键进程是系统进程才触发告警。这样误报率能降一个数量级。坑二日志采集不全导致溯源断链。常见表现是进程创建有日志但命令行参数被过滤了因为某些EDR默认不记录、或者网络连接只有四元组没有进程关联。这种坑通常不是技术原因是部署时为了性能把很多字段给裁剪了。调整方案宁可少采几台机器的全量数据不要图快把关键字段砍掉。尤其关注命令行参数、父进程PID、文件哈希、网络连接四元组加进程ID这四个字段缺一个溯源能力就掉一个台阶。坑三只关注单点告警不做攻击链聚合。团队里规则写了一堆但全是“ISOLATED”的单点规则没有一个场景化的攻击链规则。结果就是攻击者把攻击链路拉长拆散告警分布到三天里没有一个单点事件能触发告警。调整方案专门安排人员做“攻击链剧本”梳理把常见攻击路径固化成“剧本”每个剧本对应一组关联查询规则一旦某个节点命中就自动回溯关联查询其他节点形成攻击链视图。6.2 检测盲区哪些场景目前很难覆盖说点大实话。即便技术和制度都做到位仍然有几个场景是当前行业内公认的检测盲区这需要从业者心里有数。盲区一内存中的无文件载荷。攻击者把shellcode完全放在内存中不申请可执行内存通过修改现有可读内存的权限实现不创建线程而是去劫持一个现有的等待线程。这种手法在技术上完全可行现在的主流EDR很难检测到。应对思路只能是加强内存取证能力——部署内存扫描agent定期对关键进程做内存采样分析并保留采样结果以便事后取证这种扫描有性能开销需要配合合理的调度策略。盲区二合法管理工具被滥用。攻击者使用与运维团队相同的管理工具比如企业内部用的PDQ、Lansweeper这类软件对运维人员来说这些工具是日常对攻击者来说这些是免杀的“合法外衣”。EDR大量规则会把这类工具的行为加入白名单攻击者就会利用白名单。应对思路是不要直接白名单而是建立“工具使用者时间窗口操作对象”的复合白名单比如“允许王工在工作时间通过PDQ给指定分组推补丁”超出任何一部分就告警。盲区三供应链级投毒。攻击者不是直接打终端而是污染攻击者的业务软件升级包或第三方依赖库。这种路线完全绕开终端侧的检测防线攻击行为看起来就是一次正常的软件升级。防守思路从终端转移到资产和软件供应链管理——锁版本、校验软件包哈希、对升级通道做记录审计追踪。这条线在中小型企业里基本是空白。6.3 加固清单防御侧提升检测能力的关键动作最后给一份可以照着做的加固清单不追求面面俱到都是我实测下来性价比最高的动作。全面开启SysmonSysmon是Windows平台上最强的进程行为和网络行为审计工具免费且微软签名部署成本极低。重点配置EventID 1进程创建、3网络连接、7镜像加载、11文件创建、12-14注册表变更、23文件删除。启用Windows Defender Credential Guard和ACG这两个Windows原生安全功能能阻断一大类内存攻击手法。Credential Guard防哈希传递和票据窃取ACG防内存页动态可执行权限变化。建立安全基线差异化告警阈值给不同类型的主机分配不同的检测策略级别。域控、备份服务器、财务系统要上严格策略普通终端可以宽松一些。一刀切的策略优化不了误报率。日志集中和长期保存至少保证90天以上的全量原始日志留存别只存告警日志。溯源阶段需要的是原始事件流而不是已经聚合过的告警数据。定期做红蓝演练每季度做一次内部攻防演练让攻击队用主流手法打一遍自己检测自己规则的盲区和误报率。复盘报告要落实到规则调整和流程改进不然演练就是走过场。7. 写在最后的个人体会翻来覆去讲了很多技术点最后落回我个人的体会。免杀对抗这件事本质上不是“谁的工具更先进”的比赛而是“谁对攻击手法的理解更深入、对自身环境的感知更敏锐”的较量。我见过太多团队花大价钱买了顶配EDR然后寄希望于厂商的规则库能覆盖所有威胁自己团队只需要“看告警、点处置”结果在攻防演练里被打得毫无还手之力。也见过资源有限的团队用Sysmon加自研日志分析管道配合所有人对攻击手法的持续学习把检测能力做得非常扎实。差距不在预算在思维方式和基本功。国内很多防守方同行容易陷入“追新工具、买新平台”的循环忽略了最根本的东西把已有的日志和数据用起来、把检测思路从“找特征”升级到“找异常”、把安全运营从“事件驱动”升级到“持续对抗”。这三件事任何团队都能做不需要预算堆砌需要的是持续投入和耐心打磨。如果你看完这篇笔记有收获建议从Sysmon部署和日志集中这两件事开始动手。先把数据源头做扎实后面的检测策略设计才有真正可靠的抓手。对抗永无止境但每一次规则和工具的进步都会让对手的免杀之路更难走一点——这就是我们做防御的最大意义。