using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;
namespace DirectoryGuardPro
{
class Program
{
// 配置区
private static readonly string[] AllowedProcesses = { "TrustedApp.exe", "BackupTool.exe" }; // 白名单程序
private static readonly string ProtectedDirectory = @"C:\MissionCritical"; // 受保护目录
// 内核API声明
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
FileShare dwShareMode,
IntPtr lpSecurityAttributes,
FileMode dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
static void Main()
{
if (!IsAdmin())
{
Console.WriteLine("[错误] 必须使用管理员权限运行!");
return;
}
// 启动实时监控线程
Thread monitorThread = new Thread(FileAccessMonitor);
monitorThread.IsBackground = true;
monitorThread.Start();
Console.WriteLine($"防护已启用,保护目录:{ProtectedDirectory}");
Console.WriteLine("白名单程序:" + string.Join(", ", AllowedProcesses));
Console.WriteLine("按 Ctrl+C 退出...");
while (true) Thread.Sleep(1000);
}
// 核心监控逻辑
private static void FileAccessMonitor()
{
using (var watcher = new FileSystemWatcher(ProtectedDirectory))
{
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName
| NotifyFilters.Size | NotifyFilters.LastWrite;
watcher.IncludeSubdirectories = true;
// 绑定事件(使用高优先级响应)
watcher.Created += (sender, e) => ValidateProcess(e.FullPath);
watcher.Changed += (sender, e) => ValidateProcess(e.FullPath);
watcher.Renamed += (sender, e) => ValidateProcess(e.FullPath);
watcher.Deleted += (sender, e) => ValidateProcess(e.FullPath);
watcher.EnableRaisingEvents = true;
while (true) Thread.Sleep(10); // 保持线程活跃
}
}
// 验证进程合法性
private static void ValidateProcess(string filePath)
{
int processId = GetFileLockingProcessId(filePath);
if (processId == -1) return;
var process = Process.GetProcessById(processId);
string processName = process.ProcessName.ToLower();
bool isAllowed = AllowedProcesses.Any(p =>
p.Equals(processName, StringComparison.OrdinalIgnoreCase));
if (!isAllowed)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"[拦截] 非法访问!进程:{processName} (PID: {processId}) 文件:{filePath}");
Console.ResetColor();
try
{
process.Kill();
BlockFurtherAccess(filePath); // 阻止残留操作
}
catch (Exception ex)
{
Console.WriteLine($"[警告] 终止进程失败:{ex.Message}");
}
}
}
// 使用内核句柄检测文件锁定进程
private static int GetFileLockingProcessId(string filePath)
{
IntPtr handle = CreateFile(
filePath,
0x80000000, // GENERIC_READ
FileShare.ReadWrite,
IntPtr.Zero,
FileMode.Open,
0x80, // FILE_FLAG_BACKUP_SEMANTICS
IntPtr.Zero);
if (handle.ToInt32() == -1)
{
int errorCode = Marshal.GetLastWin32Error();
// 错误码 32 表示文件被占用
return (errorCode == 32) ? QueryProcessUsingHandle(filePath) : -1;
}
CloseHandle(handle);
return -1;
}
// 调用系统命令查询进程ID
private static int QueryProcessUsingHandle(string filePath)
{
var cmd = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "handle64.exe", // 需提前部署Sysinternals Handle工具
Arguments = $"/accepteula -nobanner \"{filePath}\"",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
cmd.Start();
string output = cmd.StandardOutput.ReadToEnd();
cmd.WaitForExit();
// 解析输出,例如:"wininit.exe pid: 508 type: File"
var line = output.Split('\n').FirstOrDefault(l => l.Contains("pid:"));
if (line != null && int.TryParse(line.Split(' ')[3], out int pid))
return pid;
return -1;
}
// 强制解除文件锁定
private static void BlockFurtherAccess(string filePath)
{
try
{
using (var fs = new FileStream(filePath, FileMode.Open,
FileAccess.ReadWrite, FileShare.None))
{
fs.Lock(0, fs.Length); // 独占锁定文件
}
}
catch { /* 无需处理 */ }
}
// 管理员权限检查
private static bool IsAdmin() =>
new WindowsPrincipal(WindowsIdentity.GetCurrent())
.IsInRole(WindowsBuiltInRole.Administrator);
}
}