终极指南:windows-defender-remover PowerShell模块开发与功能扩展
引言:你还在为Windows Defender残留问题困扰吗?
Windows Defender作为Windows系统默认的防病毒软件,虽然在安全性方面表现出色,但在某些特定场景下(如开发环境、专用服务器或性能优化需求),用户可能需要彻底移除它。然而,直接禁用或卸载Windows Defender往往会遇到系统保护机制的阻碍,导致残留服务继续占用资源、弹出烦人的安全警告,甚至影响其他安全软件的正常运行。
本文将带你深入了解windows-defender-remover项目的工作原理,并详细介绍如何扩展其PowerShell模块功能,实现更彻底、更灵活的Windows Defender移除方案。无论你是系统管理员、开发人员,还是对Windows系统优化有深入需求的高级用户,读完本文后,你都将能够:
- 理解Windows Defender在系统中的深层集成点
- 掌握windows-defender-remover的核心工作流程
- 学会开发自定义PowerShell函数扩展移除功能
- 构建模块化的注册表操作组件
- 实现系统级服务管理与任务调度控制
- 开发用户界面交互与反馈机制
一、项目架构与核心组件解析
1.1 项目目录结构与功能划分
windows-defender-remover项目采用模块化设计,主要包含以下关键目录和文件:
windows-defender-remover/
├── @Management/ # 管理工具目录
│ └── RegistryUnifier.ps1 # 注册表统一操作脚本
├── Remove_Defender/ # Defender移除核心组件
│ └── RemoveDefender.reg # Defender注册表移除项
├── Remove_SecurityComp/ # 安全组件移除
│ └── Remove_SecurityComp.reg # 安全组件注册表移除项
├── Remove_SecurityComp_moduled/ # 模块化安全组件移除
│ └── DisableUAC.reg # UAC禁用注册表项
├── Remove_defender_moduled/ # 模块化Defender移除
│ ├── DisableAntivirusProtection.reg # 禁用防病毒保护
│ ├── DisableDefenderPolicies.reg # 禁用Defender策略
│ └── ...(其他12个专项功能注册表文件)
├── defender_remover13.ps1 # 主移除脚本
├── RemoveSecHealthApp.ps1 # 安全健康应用移除脚本
├── Script_Run.bat # 批处理启动器
└── PowerRun.exe # 高级权限执行工具
1.2 核心功能模块分析
项目的核心功能通过以下几个关键模块实现:
1.2.1 主控制模块:defender_remover13.ps1
这是项目的主脚本,实现了用户交互、功能调度和核心逻辑控制。其主要结构包括:
# 版本定义
$defenderremoverver = "12.8.2"
# 参数处理与用户交互
if ($args[0] -eq "y" -or $args[0] -eq "Y") {
Remove-Defender
} elseif ($args[0] -eq "a" -or $args[0] -eq "A") {
Remove-Antivirus
} elseif ($args[0] -eq "S" -or $args[0] -eq "s") {
Disable-Mitigation
} else {
# 显示交互菜单...
}
# 核心功能函数
function RunAsTI { ... } # 高权限执行
function Remove-AppxPackages { ... } # Appx包移除
function Set-WindowsDefenderPolicies { ... } # 策略设置
function Disable-WindowsSecurityNotifications { ... } # 通知禁用
function Remove-WindowsDefenderTraces { ... } # 残留清除
function Disable-Mitigation { ... } # 安全缓解措施禁用
1.2.2 注册表操作模块
项目通过大量.reg文件和PowerShell注册表操作函数,实现对Windows Defender相关注册表项的修改。这些注册表项主要分布在:
HKLM:\SOFTWARE\Microsoft\Windows Defender- Defender主配置HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender- Defender策略HKLM:\SYSTEM\CurrentControlSet\Services- 系统服务配置HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache- 任务调度缓存
1.2.3 应用移除模块:RemoveSecHealthApp.ps1
该脚本专注于移除Windows安全健康应用(SecHealthUI),通过AppxProvisionedPackage和AppxPackage API实现彻底卸载:
$remove_appx = @("SecHealthUI")
$provisioned = get-appxprovisionedpackage -online
$appxpackage = get-appxpackage -allusers
$store = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore'
$users = @('S-1-5-18') # 系统账户SID
# 遍历用户并移除应用包
foreach ($choice in $remove_appx) {
foreach ($appx in $($provisioned | where {$_.PackageName -like "*$choice*"})) {
# 移除预安装包...
}
foreach ($appx in $($appxpackage | where {$_.PackageFullName -like "*$choice*"})) {
# 移除已安装包...
}
}
二、PowerShell模块开发基础
2.1 PowerShell函数设计规范
在扩展windows-defender-remover功能时,遵循一致的函数设计规范至关重要:
<#
.SYNOPSIS
简短描述:一句话说明函数功能
.DESCRIPTION
详细描述:函数的详细功能说明
.PARAMETER 参数名
参数描述:说明参数的用途、取值范围和默认值
.EXAMPLE
示例用法:展示函数的典型使用场景
.NOTES
注意事项:包含函数的作者、版本、依赖关系等信息
#>
function Function-Name {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param (
[Parameter(Mandatory=$true, HelpMessage="参数帮助信息")]
[ValidateNotNullOrEmpty()]
[string]$ParameterName
)
# 函数实现代码...
if ($PSCmdlet.ShouldProcess("目标对象", "操作描述")) {
# 执行可能有风险的操作...
}
}
2.2 注册表操作函数开发
Windows Defender的彻底移除需要对系统注册表进行深入操作。以下是一个通用的注册表操作函数示例:
<#
.SYNOPSIS
管理Windows注册表项,支持创建、修改和删除操作
.DESCRIPTION
提供安全的注册表项管理功能,包含错误处理和权限检查
#>
function Manage-RegistryEntry {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param (
[Parameter(Mandatory=$true)]
[string]$Path,
[Parameter(Mandatory=$false)]
[string]$Name,
[Parameter(Mandatory=$false)]
[ValidateSet('String', 'Binary', 'DWord', 'QWord', 'MultiString', 'ExpandString')]
[string]$Type,
[Parameter(Mandatory=$false)]
$Value,
[Parameter(Mandatory=$false)]
[switch]$Remove
)
# 检查路径是否存在,如果不存在则创建
if (-not (Test-Path -Path $Path)) {
if ($PSCmdlet.ShouldProcess($Path, "创建注册表路径")) {
try {
New-Item -Path $Path -Force -ErrorAction Stop | Out-Null
Write-Verbose "成功创建注册表路径: $Path"
} catch {
Write-Error "创建注册表路径失败: $_"
return $false
}
}
}
# 移除操作
if ($Remove) {
if ($PSCmdlet.ShouldProcess("$Path\$Name", "删除注册表项")) {
try {
if ($Name) {
# 删除特定值
Remove-ItemProperty -Path $Path -Name $Name -Force -ErrorAction Stop
Write-Verbose "成功删除注册表值: $Path\$Name"
} else {
# 删除整个键
Remove-Item -Path $Path -Recurse -Force -ErrorAction Stop
Write-Verbose "成功删除注册表键: $Path"
}
return $true
} catch {
Write-Error "删除注册表项失败: $_"
return $false
}
}
}
# 设置值操作
if ($PSBoundParameters.ContainsKey('Value')) {
if ($PSCmdlet.ShouldProcess("$Path\$Name", "设置注册表值")) {
try {
Set-ItemProperty -Path $Path -Name $Name -Type $Type -Value $Value -Force -ErrorAction Stop
Write-Verbose "成功设置注册表值: $Path\$Name = $Value"
return $true
} catch {
Write-Error "设置注册表值失败: $_"
return $false
}
}
}
return $true
}
2.3 服务控制函数开发
Windows Defender由多个系统服务组成,开发服务控制函数是扩展功能的关键:
<#
.SYNOPSIS
控制Windows系统服务,支持启动、停止和禁用操作
.DESCRIPTION
提供对系统服务的高级控制,包括设置启动类型和依赖关系管理
#>
function Manage-SystemService {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param (
[Parameter(Mandatory=$true)]
[string]$ServiceName,
[Parameter(Mandatory=$true)]
[ValidateSet('Start', 'Stop', 'Restart', 'Disable', 'Enable')]
[string]$Action,
[Parameter(Mandatory=$false)]
[ValidateSet('Automatic', 'Manual', 'Disabled', 'Automatic (Delayed Start)')]
[string]$StartupType
)
# 检查服务是否存在
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if (-not $service) {
Write-Warning "服务 $ServiceName 不存在"
return $false
}
# 执行服务操作
switch ($Action) {
'Start' {
if ($service.Status -ne 'Running') {
if ($PSCmdlet.ShouldProcess($ServiceName, "启动服务")) {
Start-Service -Name $ServiceName -ErrorAction Stop
Write-Verbose "服务 $ServiceName 已启动"
}
} else {
Write-Verbose "服务 $ServiceName 已经在运行中"
}
break
}
'Stop' {
if ($service.Status -ne 'Stopped') {
if ($PSCmdlet.ShouldProcess($ServiceName, "停止服务")) {
Stop-Service -Name $ServiceName -Force -ErrorAction Stop
Write-Verbose "服务 $ServiceName 已停止"
}
} else {
Write-Verbose "服务 $ServiceName 已经停止"
}
break
}
'Restart' {
if ($PSCmdlet.ShouldProcess($ServiceName, "重启服务")) {
Restart-Service -Name $ServiceName -Force -ErrorAction Stop
Write-Verbose "服务 $ServiceName 已重启"
}
break
}
'Disable' {
if ($PSCmdlet.ShouldProcess($ServiceName, "禁用服务")) {
$service | Set-Service -StartupType Disabled -ErrorAction Stop
Write-Verbose "服务 $ServiceName 已禁用"
# 如果服务正在运行,停止它
if ($service.Status -ne 'Stopped') {
Stop-Service -Name $ServiceName -Force -ErrorAction Stop
Write-Verbose "服务 $ServiceName 已停止"
}
}
break
}
'Enable' {
if ($PSCmdlet.ShouldProcess($ServiceName, "启用服务")) {
$startupType = if ($StartupType) { $StartupType } else { 'Manual' }
$service | Set-Service -StartupType $startupType -ErrorAction Stop
Write-Verbose "服务 $ServiceName 已启用,启动类型: $startupType"
}
break
}
}
return $true
}
三、高级功能扩展开发
3.1 模块化注册表操作组件
为提高代码复用性和可维护性,我们可以开发一个模块化的注册表操作组件,统一管理所有与注册表相关的操作:
# RegistryManager.psm1 - 注册表操作模块
<#
.SYNOPSIS
从.reg文件导入注册表设置
#>
function Import-RegistryFile {
[CmdletBinding(SupportsShouldProcess=$true)]
param (
[Parameter(Mandatory=$true)]
[ValidateScript({Test-Path $_ -PathType Leaf})]
[string]$FilePath
)
try {
if ($PSCmdlet.ShouldProcess($FilePath, "导入注册表文件")) {
$process = Start-Process -FilePath "reg.exe" -ArgumentList "import `"$FilePath`"" -Wait -PassThru -NoNewWindow
if ($process.ExitCode -eq 0) {
Write-Verbose "成功导入注册表文件: $FilePath"
return $true
} else {
Write-Error "注册表文件导入失败,退出代码: $($process.ExitCode)"
return $false
}
}
} catch {
Write-Error "导入注册表文件时出错: $_"
return $false
}
}
<#
.SYNOPSIS
批量应用注册表设置
#>
function Apply-RegistrySettings {
[CmdletBinding(SupportsShouldProcess=$true)]
param (
[Parameter(Mandatory=$true)]
[hashtable]$Settings
)
foreach ($path in $Settings.Keys) {
$regSettings = $Settings[$path]
# 确保路径存在
if (-not (Test-Path -Path $path)) {
if ($PSCmdlet.ShouldProcess($path, "创建注册表路径")) {
New-Item -Path $path -Force | Out-Null
}
}
# 应用每个设置
foreach ($name in $regSettings.Keys) {
$value = $regSettings[$name].Value
$type = $regSettings[$name].Type
if ($PSCmdlet.ShouldProcess("$path\$name", "设置注册表值 $value")) {
Set-ItemProperty -Path $path -Name $name -Value $value -Type $type -Force
Write-Verbose "设置注册表值: $path\$name = $value ($type)"
}
}
}
return $true
}
# 导出模块函数
Export-ModuleMember -Function Import-RegistryFile, Apply-RegistrySettings
使用示例:
# 导入注册表模块
Import-Module .\RegistryManager.psm1
# 定义Defender禁用设置
$defenderSettings = @{
"HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender" = @{
"DisableAntiSpyware" = @{ Value = 1; Type = "DWord" }
"DisableRoutinelyTakingAction" = @{ Value = 1; Type = "DWord" }
"ServiceKeepAlive" = @{ Value = 0; Type = "DWord" }
}
"HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection" = @{
"DisableRealtimeMonitoring" = @{ Value = 1; Type = "DWord" }
"DisableBehaviorMonitoring" = @{ Value = 1; Type = "DWord" }
"DisableOnAccessProtection" = @{ Value = 1; Type = "DWord" }
}
}
# 应用设置
Apply-RegistrySettings -Settings $defenderSettings
3.2 系统服务与任务调度管理
Windows Defender通过多个系统服务和计划任务实现持续运行,开发专用的服务和任务管理模块是彻底移除的关键:
<#
.SYNOPSIS
管理与Windows Defender相关的系统服务和计划任务
#>
function Remove-DefenderServicesAndTasks {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param ()
# 定义Defender相关服务列表
$defenderServices = @(
"WinDefend", # Windows Defender服务
"SecurityHealthService", # 安全健康服务
"wscsvc", # 安全中心服务
"WdNisDrv", # Windows Defender网络检查驱动
"WdNisSvc", # Windows Defender网络检查服务
"WdFilter", # Windows Defender筛选器驱动
"WdBoot", # Windows Defender启动驱动
"MsSecCore", # Microsoft安全核心服务
"SgrmAgent", # 系统防护代理
"SgrmBroker", # 系统防护代理
"MsSecFlt", # Microsoft安全筛选器
"MsSecWfp" # Microsoft安全WFP驱动
)
# 停止并禁用所有Defender服务
foreach ($service in $defenderServices) {
Manage-SystemService -ServiceName $service -Action Disable
}
# 定义Defender相关计划任务路径
$defenderTasks = @(
"\Microsoft\Windows\Windows Defender\",
"\Microsoft\Windows\WindowsUpdate\Automatic App Update",
"\Microsoft\Windows\WindowsUpdate\Scheduled Start"
)
# 禁用并删除计划任务
foreach ($taskPath in $defenderTasks) {
if ($PSCmdlet.ShouldProcess($taskPath, "删除计划任务")) {
try {
# 获取所有子任务
$tasks = Get-ScheduledTask -TaskPath $taskPath -ErrorAction SilentlyContinue
if ($tasks) {
foreach ($task in $tasks) {
# 禁用任务
Disable-ScheduledTask -TaskName $task.TaskName -TaskPath $taskPath -ErrorAction Stop
# 删除任务
Unregister-ScheduledTask -TaskName $task.TaskName -TaskPath $taskPath -Confirm:$false -ErrorAction Stop
Write-Verbose "已删除计划任务: $taskPath$($task.TaskName)"
}
}
} catch {
Write-Warning "处理计划任务 $taskPath 时出错: $_"
}
}
}
# 删除任务缓存中的残留项
$taskCachePaths = @(
"HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{0ACC9108-2000-46C0-8407-5FD9F89521E8}",
"HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{1D77BCC8-1D07-42D0-8C89-3A98674DFB6F}"
)
foreach ($path in $taskCachePaths) {
Manage-RegistryEntry -Path $path -Remove
}
return $true
}
3.3 交互式用户界面开发
为提升用户体验,可以开发一个基于PowerShell的交互式用户界面,提供直观的操作选项和状态反馈:
<#
.SYNOPSIS
显示交互式菜单界面
#>
function Show-InteractiveMenu {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$Title,
[Parameter(Mandatory=$true)]
[array]$MenuItems,
[int]$DefaultChoice = 0,
[int]$MenuWidth = 80
)
# 计算边框和标题位置
$titlePadding = [Math]::Max(0, ($MenuWidth - $Title.Length) / 2)
$titleLine = "=" * $MenuWidth
$titleFormatted = " " * [Math]::Floor($titlePadding) + $Title + " " * [Math]::Ceiling($titlePadding)
# 显示菜单
do {
Clear-Host
Write-Host $titleLine -ForegroundColor Cyan
Write-Host $titleFormatted -ForegroundColor Cyan
Write-Host $titleLine -ForegroundColor Cyan
Write-Host
# 显示菜单项
for ($i = 0; $i -lt $MenuItems.Count; $i++) {
$item = $MenuItems[$i]
$choiceNum = $i + 1
$choiceText = "[$choiceNum] $item"
# 突出显示默认选项
if ($i -eq $DefaultChoice) {
Write-Host $choiceText -ForegroundColor Green
} else {
Write-Host $choiceText
}
}
Write-Host
Write-Host $titleLine -ForegroundColor Cyan
Write-Host
# 获取用户输入
$inputKey = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# 处理数字键
if ($inputKey.VirtualKeyCode -ge 48 -and $inputKey.VirtualKeyCode -le 57) {
$choice = [int][char]$inputKey.Character - 1
if ($choice -ge 0 -and $choice -lt $MenuItems.Count) {
return $choice
}
}
# 处理箭头键和回车键
switch ($inputKey.VirtualKeyCode) {
13 { return $DefaultChoice } # Enter键
38 { $DefaultChoice = ($DefaultChoice - 1) % $MenuItems.Count } # 上箭头
40 { $DefaultChoice = ($DefaultChoice + 1) % $MenuItems.Count } # 下箭头
}
} while ($true)
}
# 使用示例
$menuItems = @(
"完全移除Windows Defender及所有组件 (需要重启)",
"仅移除Windows Defender,保留UAC",
"禁用所有安全缓解措施",
"自定义移除选项",
"恢复Windows Defender默认设置",
"退出"
)
$choice = Show-InteractiveMenu -Title "Windows Defender Remover v$defenderremoverver" -MenuItems $menuItems
# 根据用户选择执行相应操作
switch ($choice) {
0 { Remove-Defender }
1 { Remove-Antivirus }
2 { Disable-Mitigation }
3 { Show-CustomOptions }
4 { Restore-DefenderDefaults }
5 { exit }
}
3.4 系统状态检测与兼容性检查
开发系统状态检测功能,确保在执行移除操作前系统满足必要条件,并提供兼容性警告:
<#
.SYNOPSIS
执行系统兼容性检查
#>
function Test-SystemCompatibility {
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)]
[switch]$DetailedReport
)
$compatibility = @{
Compatible = $true
Issues = @()
Warnings = @()
SystemInfo = @()
}
# 获取系统信息
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
$compatibility.SystemInfo += @{
OSName = $osInfo.Caption
OSVersion = $osInfo.Version
BuildNumber = $osInfo.BuildNumber
ServicePack = $osInfo.ServicePackMajorVersion
Architecture = if ([Environment]::Is64BitOperatingSystem) { "64-bit" } else { "32-bit" }
Hypervisor = (Get-CimInstance -ClassName Win32_ComputerSystem).HypervisorPresent
}
# 检查Windows版本兼容性
$buildNumber = [int]$osInfo.BuildNumber
$supportedBuilds = @(
@{ Min = 9200; Max = 9600; Name = "Windows 8/8.1" }, # Windows 8/8.1
@{ Min = 14393; Max = 19045; Name = "Windows 10" }, # Windows 10
@{ Min = 22000; Max = 25999; Name = "Windows 11" } # Windows 11
)
$isSupported = $false
foreach ($build in $supportedBuilds) {
if ($buildNumber -ge $build.Min -and $buildNumber -le $build.Max) {
$isSupported = $true
break
}
}
if (-not $isSupported) {
$compatibility.Compatible = $false
$compatibility.Issues += "不支持的Windows版本 (内部版本号: $buildNumber)。支持的版本: Windows 8/8.1, Windows 10, Windows 11"
}
# 检查系统保护状态
$systemProtection = Get-CimInstance -ClassName Win32_ShadowCopy -ErrorAction SilentlyContinue
if ($systemProtection) {
$compatibility.Warnings += "系统保护(卷影复制)已启用,可能导致Defender文件无法完全删除"
}
# 检查Hypervisor状态
if ($compatibility.SystemInfo.Hypervisor) {
$compatibility.Warnings += "检测到虚拟机环境,部分安全功能可能无法完全禁用"
}
# 检查Windows更新状态
$wuStatus = Get-Service -Name wuauserv -ErrorAction SilentlyContinue
if ($wuStatus -and $wuStatus.Status -eq 'Running') {
$compatibility.Warnings += "Windows更新服务正在运行,可能导致Defender组件自动恢复"
}
# 检查是否已安装其他防病毒软件
$avProducts = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct -ErrorAction SilentlyContinue
if ($avProducts -and $avProducts.Count -gt 0) {
$otherAV = $avProducts | Where-Object { $_.displayName -notlike "*Windows Defender*" }
if ($otherAV) {
$compatibility.Warnings += "检测到其他防病毒软件: $($otherAV.displayName -join ', ').可能导致冲突"
}
}
# 显示详细报告
if ($DetailedReport) {
Show-CompatibilityReport -Compatibility $compatibility
}
return $compatibility
}
<#
.SYNOPSIS
显示系统兼容性报告
#>
function Show-CompatibilityReport {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[hashtable]$Compatibility
)
Write-Host "`n=== 系统兼容性报告 ===" -ForegroundColor Cyan
Write-Host "操作系统: $($Compatibility.SystemInfo.OSName) (内部版本 $($Compatibility.SystemInfo.BuildNumber))"
Write-Host "架构: $($Compatibility.SystemInfo.Architecture)"
Write-Host "虚拟化环境: $(if ($Compatibility.SystemInfo.Hypervisor) { '是' } else { '否' })"
if ($Compatibility.Issues.Count -gt 0) {
Write-Host "`n=== 兼容性问题 ===" -ForegroundColor Red
$Compatibility.Issues | ForEach-Object { Write-Host "- $_" }
}
if ($Compatibility.Warnings.Count -gt 0) {
Write-Host "`n=== 警告 ===" -ForegroundColor Yellow
$Compatibility.Warnings | ForEach-Object { Write-Host "- $_" }
}
if ($Compatibility.Compatible) {
Write-Host "`n=== 状态 ===" -ForegroundColor Green
Write-Host "系统兼容,可以继续执行操作"
} else {
Write-Host "`n=== 状态 ===" -ForegroundColor Red
Write-Host "系统不兼容,不建议继续执行操作"
}
Write-Host "`n======================`n" -ForegroundColor Cyan
}
四、高级功能实战:自定义移除模块开发
4.1 开发Web威胁防护移除模块
Windows Defender的Web威胁防护功能深度集成在系统中,我们可以开发一个专用模块来彻底移除它:
<#
.SYNOPSIS
彻底移除Windows Defender Web威胁防护组件
#>
function Remove-WebThreatDefense {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param ()
Write-Output "正在禁用WebThreatDefense及相关服务..."
# 1. 移除防火墙规则
$wtpFirewallRules = @(
"Windows Defender Web Protection",
"Windows Defender Web Protection (TCP-In)",
"Windows Defender Web Protection (UDP-In)"
)
foreach ($rule in $wtpFirewallRules) {
if ($PSCmdlet.ShouldProcess($rule, "删除防火墙规则")) {
try {
Remove-NetFirewallRule -DisplayName $rule -ErrorAction Stop
Write-Verbose "已删除防火墙规则: $rule"
} catch {
Write-Warning "删除防火墙规则失败 $rule : $_"
}
}
}
# 2. 移除Web威胁防护注册表项
$wtpRegistryPaths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-Windows Defender/Operational",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-Windows Defender/WHC",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels\Microsoft-Windows-Windows Defender/ThreatDetection",
"HKLM:\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\Microsoft.OneCore.WebThreatDefense.Service.UserSessionServiceManager",
"HKLM:\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\Microsoft.OneCore.WebThreatDefense.ThreatExperienceManager.ThreatExperienceManager",
"HKLM:\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\Microsoft.OneCore.WebThreatDefense.ThreatResponseEngine.ThreatDecisionEngine",
"HKLM:\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\Microsoft.OneCore.WebThreatDefense.Configuration.WTDUserSettings"
)
foreach ($path in $wtpRegistryPaths) {
Manage-RegistryEntry -Path $path -Remove
}
# 3. 移除相关文件和目录
$wtpFilePaths = @(
"$env:SystemRoot\System32\WdNisDrv.sys",
"$env:SystemRoot\System32\WdNisSvc.dll",
"$env:SystemRoot\System32\WdNisSvc.exe",
"$env:SystemRoot\System32\drivers\WdNisDrv.sys",
"$env:ProgramData\Microsoft\Windows Defender\Scans",
"$env:ProgramFiles\Windows Defender"
)
foreach ($path in $wtpFilePaths) {
if (Test-Path -Path $path) {
if ($PSCmdlet.ShouldProcess($path, "删除Web威胁防护文件/目录")) {
try {
# 获取文件所有权
Take-Ownership -Path $path
# 删除文件或目录
if (Test-Path -Path $path -PathType Container) {
Remove-Item -Path $path -Recurse -Force -ErrorAction Stop
} else {
Remove-Item -Path $path -Force -ErrorAction Stop
}
Write-Verbose "已删除: $path"
} catch {
Write-Warning "删除失败 $path : $_"
}
}
}
}
# 4. 清理浏览器集成
$browserIntegrationPaths = @(
"HKLM:\SOFTWARE\Microsoft\Internet Explorer\Extensions\{1FD49718-1D00-4B19-AF5F-070AF6D5D54C}",
"HKLM:\SOFTWARE\Mozilla\Firefox\Extensions\extension@windowsdefender.microsoft.com",
"HKLM:\SOFTWARE\Google\Chrome\Extensions\gfnfhpelfgechhkdofpfibihhbnibfbo"
)
foreach ($path in $browserIntegrationPaths) {
Manage-RegistryEntry -Path $path -Remove
}
Write-Output "Web威胁防护组件移除完成。需要重启系统以应用所有更改。"
return $true
}
<#
.SYNOPSIS
获取文件/目录所有权
#>
function Take-Ownership {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$Path
)
try {
# 使用icacls命令获取所有权
icacls $Path /grant Administrators:F /T /C /Q > $null
Write-Verbose "已获取 $Path 的所有权"
return $true
} catch {
Write-Warning "获取 $Path 所有权失败: $_"
return $false
}
}
4.2 开发系统还原点与备份模块
在执行系统级修改前创建还原点是一个重要的安全措施,我们可以开发一个专用的备份与还原模块:
<#
.SYNOPSIS
管理系统还原点
#>
function Manage-SystemRestorePoint {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
param (
[Parameter(Mandatory=$true)]
[ValidateSet('Create', 'List', 'Restore')]
[string]$Action,
[Parameter(Mandatory=$false)]
[string]$Description,
[Parameter(Mandatory=$false)]
[int]$RestorePointId
)
# 检查系统保护是否启用
$systemProtection = Get-CimInstance -ClassName Win32_ComputerSystem -Property SystemType
$protectionEnabled = $false
# 获取系统保护状态
$volumes = Get-Volume | Where-Object { $_.DriveType -eq 'Fixed' -and $_.DriveLetter }
foreach ($volume in $volumes) {
$protection = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore" -Name "RPSessionInterval" -ErrorAction SilentlyContinue
if ($protection) {
$protectionEnabled = $true
break
}
}
if (-not $protectionEnabled) {
Write-Warning "系统保护未启用,无法创建还原点"
return $false
}
switch ($Action) {
'Create' {
if (-not $Description) {
$Description = "Windows Defender Remover - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
}
if ($PSCmdlet.ShouldProcess("系统", "创建还原点: $Description")) {
try {
# 创建还原点
$restorePoint = Checkpoint-Computer -Description $Description -RestorePointType "MODIFY_SETTINGS" -ErrorAction Stop
Write-Host "成功创建还原点: $Description (ID: $($restorePoint.Id))" -ForegroundColor Green
return $restorePoint
} catch {
Write-Error "创建还原点失败: $_"
return $false
}
}
break
}
'List' {
Write-Host "`n=== 可用还原点 ===" -ForegroundColor Cyan
$restorePoints = Get-ComputerRestorePoint
$restorePoints | Format-Table -AutoSize -Property @(
@{Name='ID'; Expression={$_.SequenceNumber}},
@{Name='描述'; Expression={$_.Description}},
@{Name='创建时间'; Expression={$_.CreationTime}},
@{Name='类型'; Expression={$_.RestorePointType}}
)
Write-Host "`n==================`n" -ForegroundColor Cyan
return $restorePoints
}
'Restore' {
if (-not $RestorePointId) {
Write-Error "必须指定RestorePointId参数"
return $false
}
$restorePoint = Get-ComputerRestorePoint | Where-Object { $_.SequenceNumber -eq $RestorePointId }
if (-not $restorePoint) {
Write-Error "未找到ID为 $RestorePointId 的还原点"
return $false
}
if ($PSCmdlet.ShouldProcess("还原点 $RestorePointId", "还原系统")) {
Write-Warning "警告: 系统还原将把计算机恢复到 $($restorePoint.CreationTime) 的状态,此操作无法撤销!"
$confirm = Read-Host "确定要继续吗? (Y/N)"
if ($confirm -eq 'Y' -or $confirm -eq 'y') {
try {
# 启动系统还原(需要管理员权限)
Start-Process -FilePath "rstrui.exe" -ArgumentList "/offline:$(Get-Volume -DriveLetter $env:SystemDrive).DriveLetter`:\" -Wait
Write-Host "系统还原已启动,请按照系统还原向导操作" -ForegroundColor Green
return $true
} catch {
Write-Error "启动系统还原失败: $_"
return $false
}
} else {
Write-Host "系统还原操作已取消" -ForegroundColor Yellow
return $false
}
}
break
}
}
}
4.3 开发日志记录与调试模块
为便于开发和问题排查,实现一个详细的日志记录系统:
<#
.SYNOPSIS
日志记录模块
#>
function Initialize-Logger {
[CmdletBinding()]
param (
[Parameter(Mandatory=$false)]
[string]$LogPath = "$env:TEMP\WindowsDefenderRemover.log",
[Parameter(Mandatory=$false)]
[ValidateSet('Debug', 'Info', 'Warning', 'Error')]
[string]$LogLevel = 'Info'
)
# 创建日志目录
$logDir = Split-Path -Path $LogPath -Parent
if (-not (Test-Path -Path $logDir)) {
New-Item -Path $logDir -ItemType Directory -Force | Out-Null
}
# 定义日志级别数值
$script:logLevels = @{
Debug = 0
Info = 1
Warning = 2
Error = 3
}
# 设置当前日志级别
$script:currentLogLevel = $logLevels[$LogLevel]
$script:logFilePath = $LogPath
# 写入启动日志
Write-Log -Message "=== Windows Defender Remover 日志会话开始 ===" -Level Info
Write-Log -Message "日志路径: $LogPath" -Level Info
Write-Log -Message "日志级别: $LogLevel" -Level Info
Write-Log -Message "开始时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -Level Info
Write-Log -Message "===============================================" -Level Info
return $true
}
<#
.SYNOPSIS
写入日志消息
#>
function Write-Log {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]$Message,
[Parameter(Mandatory=$false)]
[ValidateSet('Debug', 'Info', 'Warning', 'Error')]
[string]$Level = 'Info',
[Parameter(Mandatory=$false)]
[switch]$ShowConsole
)
# 检查日志级别
if (-not $script:logLevels.ContainsKey($Level)) {
$Level = 'Info'
}
$levelNum = $script:logLevels[$Level]
if ($levelNum -lt $script:currentLogLevel) {
return # 不记录低于当前日志级别的消息
}
# 格式化日志消息
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff'
$logMessage = "[$timestamp] [$Level] $Message"
# 写入日志文件
try {
Add-Content -Path $script:logFilePath -Value $logMessage -Encoding UTF8 -ErrorAction Stop
} catch {
Write-Warning "写入日志失败: $_"
}
# 显示在控制台
if ($ShowConsole -or $Level -eq 'Error' -or ($Level -eq 'Warning' -and $script:currentLogLevel -le $logLevels['Warning'])) {
$color = switch ($Level) {
'Debug' { Gray }
'Info' { White }
'Warning' { Yellow }
'Error' { Red }
default { White }
}
Write-Host $logMessage -ForegroundColor $color
}
return $true
}
<#
.SYNOPSIS
生成操作报告
#>
function Generate-OperationReport {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[hashtable]$OperationResults,
[Parameter(Mandatory=$false)]
[string]$OutputPath = "$env:TEMP\WindowsDefenderRemover_Report.html"
)
# 创建HTML报告
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>Windows Defender Remover 操作报告</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
h2 { color: #3498db; margin-top: 20px; }
.section { margin-bottom: 30px; }
.status-success { color: #27ae60; }
.status-failed { color: #e74c3c; }
.status-warning { color: #f39c12; }
table { border-collapse: collapse; width: 100%; margin: 15px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.timestamp { color: #7f8c8d; font-size: 0.8em; }
</style>
</head>
<body>
<h1>Windows Defender Remover 操作报告</h1>
<p class="timestamp">生成时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')</p>
<div class="section">
<h2>系统信息</h2>
<table>
<tr><th>项目</th><th>值</th></tr>
<tr><td>操作系统</td><td>$($OperationResults.SystemInfo.OSName)</td></tr>
<tr><td>版本</td><td>$($OperationResults.SystemInfo.OSVersion) (内部版本 $($OperationResults.SystemInfo.BuildNumber))</td></tr>
<tr><td>架构</td><td>$($OperationResults.SystemInfo.Architecture)</td></tr>
<tr><td>用户名</td><td>$env:USERNAME</td></tr>
<tr><td>计算机名</td><td>$env:COMPUTERNAME</td></tr>
</table>
</div>
<div class="section">
<h2>操作摘要</h2>
<table>
<tr><th>操作</th><th>状态</th><th>详细信息</th></tr>
"@
# 添加操作结果
foreach ($operation in $OperationResults.Operations) {
$statusClass = switch ($operation.Status) {
'Success' { 'status-success' }
'Failed' { 'status-failed' }
'Warning' { 'status-warning' }
default { '' }
}
$html += @"
<tr>
<td>$($operation.Name)</td>
<td class="$statusClass">$($operation.Status)</td>
<td>$($operation.Details)</td>
</tr>
"@
}
# 完成HTML报告
$html += @"
</table>
</div>
<div class="section">
<h2>兼容性检查</h2>
<p>兼容状态: $(if ($OperationResults.Compatibility.Compatible) { '<span class="status-success">兼容</span>' } else { '<span class="status-failed">不兼容</span>' })</p>
"@
if ($OperationResults.Compatibility.Issues -and $OperationResults.Compatibility.Issues.Count -gt 0) {
$html += "<h3>问题:</h3><ul>"
foreach ($issue in $OperationResults.Compatibility.Issues) {
$html += "<li class='status-failed'>$issue</li>"
}
$html += "</ul>"
}
if ($OperationResults.Compatibility.Warnings -and $OperationResults.Compatibility.Warnings.Count -gt 0) {
$html += "<h3>警告:</h3><ul>"
foreach ($warning in $OperationResults.Compatibility.Warnings) {
$html += "<li class='status-warning'>$warning</li>"
}
$html += "</ul>"
}
$html += @"
</div>
<div class="section">
<h2>后续操作建议</h2>
<ul>
<li>建议重启系统以应用所有更改</li>
<li>重启后检查系统状态和安全软件功能</li>
<li>保留此报告以备将来参考</li>
</ul>
</div>
</body>
</html>
"@
# 保存报告
try {
$html | Out-File -Path $OutputPath -Encoding UTF8 -ErrorAction Stop
Write-Log -Message "操作报告已生成: $OutputPath" -Level Info
return $OutputPath
} catch {
Write-Error "生成报告失败: $_"
return $false
}
}
五、模块集成与部署
5.1 功能模块整合
将开发的所有模块整合到主脚本中,形成一个完整的解决方案:
# defender_remover_extended.ps1 - 扩展版主脚本
# 版本定义
$defenderremoverver = "13.0.0" # 升级版本号
# 初始化日志系统
Initialize-Logger -LogLevel Info
# 导入自定义模块
Write-Log -Message "导入自定义模块..." -Level Info
. .\RegistryManager.psm1
. .\ServiceManager.psm1
. .\RestorePointManager.psm1
. .\WebThreatDefenseRemover.psm1
. .\ReportGenerator.psm1
# 执行系统兼容性检查
Write-Log -Message "执行系统兼容性检查..." -Level Info
$compatibility = Test-SystemCompatibility -DetailedReport
# 如果系统不兼容,询问用户是否继续
if (-not $compatibility.Compatible) {
Write-Host "`n系统兼容性检查发现问题,不建议继续执行操作。" -ForegroundColor Red
$continue = Read-Host "是否仍要继续? (Y/N)"
if ($continue -ne 'Y' -and $continue -ne 'y') {
Write-Log -Message "用户取消了操作" -Level Info
exit 0
}
}
# 创建系统还原点
$restorePoint = $null
if ($PSCmdlet.ShouldProcess("系统", "创建还原点")) {
Write-Log -Message "创建系统还原点..." -Level Info
$restorePoint = Manage-SystemRestorePoint -Action Create -Description "Windows Defender Remover v$defenderremoverver"
if (-not $restorePoint) {
Write-Warning "创建还原点失败,继续执行操作但风险增加"
}
}
# 初始化操作结果跟踪
$operationResults = @{
SystemInfo = $compatibility.SystemInfo
Compatibility = $compatibility
Operations = @()
StartTime = Get-Date
}
# 显示交互式菜单
$menuItems = @(
"完全移除Windows Defender及所有组件 (需要重启)",
"仅移除Windows Defender,保留UAC",
"禁用所有安全缓解措施",
"自定义移除选项",
"恢复Windows Defender默认设置",
"退出"
)
$choice = Show-InteractiveMenu -Title "Windows Defender Remover v$defenderremoverver" -MenuItems $menuItems
# 根据用户选择执行相应操作
try {
switch ($choice) {
0 {
$result = Remove-Defender -OperationResults $operationResults
}
1 {
$result = Remove-Antivirus -OperationResults $operationResults
}
2 {
$result = Disable-Mitigation -OperationResults $operationResults
}
3 {
$result = Show-CustomOptions -OperationResults $operationResults
}
4 {
$result = Restore-DefenderDefaults -OperationResults $operationResults
}
5 {
Write-Log -Message "用户选择退出" -Level Info
exit 0
}
}
# 生成操作报告
$reportPath = Generate-OperationReport -OperationResults $operationResults
if ($reportPath) {
Write-Host "操作报告已保存至: $reportPath" -ForegroundColor Green
}
# 提示重启
if ($result -and $choice -ne 4) {
Write-Host "`n所有操作已完成。为使更改生效,系统需要重启。" -ForegroundColor Cyan
$reboot = Read-Host "是否立即重启? (Y/N)"
if ($reboot -eq 'Y' -or $reboot -eq 'y') {
Write-Log -Message "用户选择立即重启" -Level Info
Write-Host "系统将在10秒后重启..." -ForegroundColor Yellow
Start-Sleep -Seconds 10
Restart-Computer -Force
} else {
Write-Log -Message "用户选择稍后重启" -Level Info
Write-Host "请记住在方便时手动重启系统以应用所有更改。" -ForegroundColor Yellow
}
}
} catch {
Write-Log -Message "执行操作时发生错误: $_" -Level Error
Write-Host "操作失败: $_" -ForegroundColor Red
# 生成错误报告
$reportPath = Generate-OperationReport -OperationResults $operationResults
if ($reportPath) {
Write-Host "错误报告已保存至: $reportPath" -ForegroundColor Yellow
}
}
# 结束日志会话
Write-Log -Message "===============================================" -Level Info
Write-Log -Message "结束时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -Level Info
Write-Log -Message "=== Windows Defender Remover 日志会话结束 ===" -Level Info
5.2 部署与分发方案
为便于用户使用和分发,可以创建一个自包含的部署包:
@echo off
:: Script_Run_Extended.bat - 扩展版启动脚本
:: 检查管理员权限
NET SESSION >nul 2>&1
if %errorLevel% neq 0 (
echo 请求管理员权限...
powershell -Command "Start-Process '%0' -Verb RunAs"
exit /b
)
:: 设置工作目录
cd /d "%~dp0"
:: 检查PowerShell版本
powershell -Command "$psversiontable.PSVersion.Major" > psversion.tmp
set /p psversion= < psversion.tmp
del psversion.tmp
if %psversion% lss 5 (
echo 错误: 需要PowerShell 5.0或更高版本
pause
exit /b 1
)
:: 启动扩展版移除工具
echo 启动Windows Defender Remover v13.0.0 (扩展版)...
powershell -ExecutionPolicy Bypass -File "defender_remover_extended.ps1"
:: 检查执行结果
if %errorlevel% equ 0 (
echo 操作已完成
) else (
echo 操作失败,错误代码: %errorlevel%
)
pause
六、总结与后续开发路线图
6.1 项目扩展成果总结
通过本文介绍的扩展开发,我们为windows-defender-remover项目添加了以下关键功能:
-
模块化架构:将原有的单体脚本重构为多个功能明确的模块,提高了可维护性和可扩展性。
-
增强的用户交互:开发了交互式菜单系统,提供更友好的用户体验和更清晰的操作指引。
-
系统安全措施:添加了系统还原点创建功能,降低了操作风险。
-
完善的日志系统:实现了详细的日志记录和报告生成功能,便于问题排查和操作审计。
-
高级移除功能:开发了Web威胁防护专用移除模块,实现更彻底的组件清理。
-
兼容性检查:添加了全面的系统兼容性检测,减少在不支持环境下的操作风险。
6.2 后续开发路线图
未来可以考虑以下扩展方向,进一步提升项目功能:
6.2.1 短期开发计划(1-3个月)
-
图形用户界面(GUI):基于Windows Presentation Foundation (WPF) 或 Windows Forms开发图形界面,降低使用门槛。
-
多语言支持:实现中英文等多语言界面,扩大用户群体。
-
自动更新机制:添加模块自动更新功能,确保用户始终使用最新版本。
-
备份与恢复工具:开发专用的Defender配置备份与选择性恢复工具。
6.2.2 中期开发计划(3-6个月)
-
组策略集成:开发组策略模板,支持企业环境中的集中部署。
-
远程管理功能:添加PowerShell远程管理能力,支持多台计算机的批量操作。
-
自定义配置文件:实现可定制的移除配置文件,支持不同场景下的灵活部署。
-
实时监控功能:开发Defender组件活动监控工具,检测并阻止自动恢复行为。
6.2.3 长期开发计划(6个月以上)
-
驱动级防护:开发内核模式驱动,阻止Defender核心组件加载。
-
云管理平台:构建基于Web的远程管理平台,支持大规模部署和监控。
-
逆向兼容性:添加对旧版本Windows(如Windows 7)的支持。
-
开源社区建设:建立插件开发框架,鼓励社区贡献新功能模块。
6.3 最佳实践与注意事项
在扩展和使用windows-defender-remover时,应遵循以下最佳实践:
-
充分测试:在修改系统关键组件前,始终在非生产环境中充分测试。
-
创建备份:执行任何系统修改前,务必创建系统还原点或完整备份。
-
文档记录:详细记录所有修改,便于后续排查问题或恢复系统。
-
了解风险:认识到移除系统安全组件可能带来的安全风险,仅在必要场景下使用。
-
保持更新:定期更新移除工具,以应对Microsoft不断变化的系统保护机制。
-
法律合规:确保在适用法律法规允许的范围内使用此类工具,尊重软件许可协议。
结语
windows-defender-remover项目为需要彻底控制Windows系统安全组件的用户提供了强大工具。通过本文介绍的模块化扩展方法,开发者可以根据特定需求定制功能,实现更精细、更彻底的系统组件管理。
随着Microsoft不断加强Windows的安全性和系统集成度,移除工具的开发也将面临持续挑战。通过采用本文介绍的模块化架构和开发方法,项目可以保持灵活性和适应性,应对未来的系统变化。
无论你是系统管理员、开发人员还是高级用户,希望本文提供的知识和工具能帮助你更好地理解和控制Windows系统中的安全组件,打造更符合个人需求的计算环境。
最后,再次强调:修改系统安全组件可能带来安全风险,请谨慎评估需求和风险,仅在必要情况下使用此类工具。
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin07
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00