蓝队—反钓鱼的策略提供
字数 670 2025-08-22 12:23:25
蓝队反钓鱼策略详解
一、前言
本文提供了一套完整的蓝队反钓鱼策略,通过多种技术手段检测系统中的可疑进程和潜在威胁。主要思路是通过IP查找、特殊文件名检查、文件编译器验证和启动项检查来筛选可疑进程,最终以弹窗形式呈现结果。
二、总体思路
- 流量分析:获取所有进程的IP连接,筛选出可疑的外部连接
- 启动项检查:扫描系统启动目录和任务计划中的启动项
- 签名验证:检查进程的数字签名状态
- 行为分析:检测进程的异常行为模式
- 综合评估:结合以上信息判断进程风险等级
三、流量分析实现
1. 获取所有进程的IP连接
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <winsock2.h>
#include <iphlpapi.h>
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <ws2tcpip.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "advapi32.lib")
// 获取进程名称
std::wstring getProcessName(DWORD pid) {
wchar_t processName[MAX_PATH] = L"<未知>";
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess != NULL) {
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
GetModuleBaseNameW(hProcess, hMod, processName, sizeof(processName) / sizeof(wchar_t));
}
CloseHandle(hProcess);
}
return std::wstring(processName);
}
// 获取进程路径
std::wstring getProcessPath(DWORD pid) {
wchar_t processPath[MAX_PATH] = L"<未知>";
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess != NULL) {
GetModuleFileNameExW(hProcess, NULL, processPath, sizeof(processPath) / sizeof(wchar_t));
CloseHandle(hProcess);
}
return std::wstring(processPath);
}
// 枚举所有网络连接
void enumerateConnections() {
PMIB_TCPTABLE2 tcpTable;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
tcpTable = (MIB_TCPTABLE2*)malloc(sizeof(MIB_TCPTABLE2));
if (tcpTable == NULL) {
std::cerr << "分配内存时出错" << std::endl;
return;
}
dwSize = sizeof(MIB_TCPTABLE2);
if ((dwRetVal = GetTcpTable2(tcpTable, &dwSize, TRUE)) == ERROR_INSUFFICIENT_BUFFER) {
free(tcpTable);
tcpTable = (MIB_TCPTABLE2*)malloc(dwSize);
if (tcpTable == NULL) {
std::cerr << "分配内存时出错" << std::endl;
return;
}
}
if ((dwRetVal = GetTcpTable2(tcpTable, &dwSize, TRUE)) == NO_ERROR) {
char ipStringBuffer[INET_ADDRSTRLEN];
std::wstring output;
for (int i = 0; i < (int)tcpTable->dwNumEntries; i++) {
inet_ntop(AF_INET, &tcpTable->table[i].dwRemoteAddr, ipStringBuffer, INET_ADDRSTRLEN);
std::string remoteIp(ipStringBuffer);
DWORD pid = tcpTable->table[i].dwOwningPid;
std::wstring processName = getProcessName(pid);
std::wstring processPath = getProcessPath(pid);
output += L"程序名称: " + processName + L"\n连接的IP: " +
std::wstring(remoteIp.begin(), remoteIp.end()) +
L"\n程序路径: " + processPath + L"\n--\n";
}
if (!output.empty()) {
MessageBoxW(NULL, output.c_str(), L"IP 和进程监控", MB_OK);
} else {
MessageBoxW(NULL, L"未找到任何连接信息。", L"IP 和进程监控", MB_OK);
}
}
if (tcpTable != NULL) {
free(tcpTable);
}
}
2. IP地址过滤
// 检查IP是否为公网IP
bool isPublicIP(const std::string& ip) {
unsigned int octet1, octet2, octet3, octet4;
if (sscanf_s(ip.c_str(), "%u.%u.%u.%u", &octet1, &octet2, &octet3, &octet4) != 4) {
return false;
}
// 排除私有IP范围
if ((octet1 == 10) || // 10.0.0.0/8
(octet1 == 127) || // 127.0.0.0/8 (环回地址)
(octet1 == 192 && octet2 == 168) || // 192.168.0.0/16
(octet1 == 172 && (octet2 >= 16 && octet2 <= 31)) || // 172.16.0.0/12
(octet1 == 0) || // 0.0.0.0 (无效地址)
(octet1 == 169 && octet2 == 254)) { // 169.254.0.0/16 (APIPA)
return false;
}
return true;
}
四、启动项检查
1. 扫描启动目录
// 获取目录中的所有文件
std::vector<std::wstring> getFilesInDirectory(const std::wstring& directoryPath) {
std::vector<std::wstring> filePaths;
WIN32_FIND_DATA findFileData;
HANDLE hFind = FindFirstFile((directoryPath + L"\\*").c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE) {
return filePaths;
}
do {
const std::wstring fileOrDirName = findFileData.cFileName;
if (fileOrDirName != L"." && fileOrDirName != L"..") {
const std::wstring fullPath = directoryPath + L"\\" + fileOrDirName;
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
filePaths.push_back(fullPath);
}
}
} while (FindNextFile(hFind, &findFileData) != 0);
FindClose(hFind);
return filePaths;
}
// 检查启动目录
void checkStartupDirectories() {
wchar_t* userName = nullptr;
size_t len = 0;
_wdupenv_s(&userName, &len, L"USERNAME");
// 常见启动目录
std::wstring startupDirectories[] = {
L"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup",
L"C:\\Users\\" + std::wstring(userName) + L"\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup",
L"C:\\Users\\" + std::wstring(userName) + L"\\AppData\\Local\\Microsoft\\Windows\\Startup",
L"C:\\Users\\" + std::wstring(userName) + L"\\AppData\\Roaming\\Microsoft\\Windows\\Startup"
};
free(userName);
std::wstring message = L"";
for (const auto& directory : startupDirectories) {
std::vector<std::wstring> files = getFilesInDirectory(directory);
if (!files.empty()) {
message += L"在目录 " + directory + L" 中找到以下启动项:\n";
for (const auto& file : files) {
message += L" - " + file + L"\n";
}
message += L"\n";
}
}
if (!message.empty()) {
MessageBoxW(NULL, message.c_str(), L"启动项检查", MB_OK | MB_ICONINFORMATION);
} else {
MessageBoxW(NULL, L"未检测到各启动目录中的启动项文件。", L"启动项检查", MB_OK | MB_ICONINFORMATION);
}
}
2. 检查任务计划启动项
void checkTaskSchedulerStartupItems() {
std::wstring command = L"schtasks /query /fo LIST /v";
std::wstring result = L"";
FILE* pipe = _wpopen(command.c_str(), L"r");
if (!pipe) {
MessageBoxW(NULL, L"无法执行任务计划程序查询命令!", L"错误", MB_OK | MB_ICONERROR);
return;
}
wchar_t buffer[1024];
while (fgetws(buffer, sizeof(buffer) / sizeof(wchar_t), pipe) != NULL) {
result += buffer;
}
_pclose(pipe);
if (!result.empty()) {
MessageBoxW(NULL, result.c_str(), L"任务计划启动项", MB_OK | MB_ICONINFORMATION);
} else {
MessageBoxW(NULL, L"未检测到任务计划中的启动项。", L"任务计划启动项", MB_OK | MB_ICONINFORMATION);
}
}
五、签名验证
1. 检查进程签名状态
enum ProcessSignatureStatus {
SIGNED_AND_TRUSTED,
SIGNED_BUT_NOT_TRUSTED,
NOT_SIGNED
};
ProcessSignatureStatus checkProcessSignature(const std::wstring& processPath) {
WINTRUST_FILE_INFO fileInfo = { 0 };
fileInfo.cbStruct = sizeof(fileInfo);
fileInfo.pcwszFilePath = processPath.c_str();
WINTRUST_DATA winTrustData = { 0 };
winTrustData.cbStruct = sizeof(winTrustData);
winTrustData.dwUIChoice = WTD_UI_NONE;
winTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
winTrustData.dwUnionChoice = WTD_CHOICE_FILE;
winTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
winTrustData.pFile = &fileInfo;
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
LONG status = WinVerifyTrust(NULL, &policyGUID, &winTrustData);
winTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(NULL, &policyGUID, &winTrustData);
if (status == ERROR_SUCCESS) {
return SIGNED_AND_TRUSTED;
} else if (status == TRUST_E_NOSIGNATURE) {
return NOT_SIGNED;
} else {
return SIGNED_BUT_NOT_TRUSTED;
}
}
2. 检查启动目录中的无签名文件
void checkStartupDirectoriesForUnsignedFiles() {
wchar_t* userName = nullptr;
size_t len = 0;
_wdupenv_s(&userName, &len, L"USERNAME");
std::wstring startupDirectories[] = {
L"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup",
L"C:\\Users\\" + std::wstring(userName) + L"\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"
};
free(userName);
std::wstring message = L"";
for (const auto& directory : startupDirectories) {
std::vector<std::wstring> files = getFilesInDirectory(directory);
for (const auto& file : files) {
if (checkProcessSignature(file) == NOT_SIGNED) {
message += L"无签名文件: " + file + L"\n";
}
}
}
if (!message.empty()) {
MessageBoxW(NULL, message.c_str(), L"无签名启动项", MB_OK | MB_ICONWARNING);
} else {
MessageBoxW(NULL, L"未检测到启动目录中存在无签名文件。", L"无签名启动项", MB_OK | MB_ICONINFORMATION);
}
}
六、行为分析与综合检测
1. 检测系统进程伪装
bool isSystemProcess(HANDLE hProcess) {
HANDLE hToken = NULL;
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
return false;
}
DWORD dwSize = 0;
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
PTOKEN_USER pTokenUser = (PTOKEN_USER)malloc(dwSize);
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) {
free(pTokenUser);
CloseHandle(hToken);
return false;
}
WCHAR szName[MAX_PATH];
WCHAR szDomain[MAX_PATH];
DWORD dwNameSize = MAX_PATH;
DWORD dwDomainSize = MAX_PATH;
SID_NAME_USE sidType;
if (LookupAccountSidW(NULL, pTokenUser->User.Sid, szName, &dwNameSize, szDomain, &dwDomainSize, &sidType)) {
if (wcscmp(szName, L"SYSTEM") == 0) {
free(pTokenUser);
CloseHandle(hToken);
return true;
}
}
free(pTokenUser);
CloseHandle(hToken);
return false;
}
2. 检测高风险进程名称
bool isHighRiskProcess(const std::wstring& processName, const std::wstring& processPath) {
std::vector<std::wstring> keywords = {
L"PC", L"财务", L"CW", L"2024", L"2023",
L"工资", L"报表", L"调整"
};
std::wregex extensionPattern(L".*\\.(com|exe|bat)", std::regex_constants::icase);
for (const auto& keyword : keywords) {
if (processName.find(keyword) != std::wstring::npos &&
std::regex_match(processPath, extensionPattern)) {
return true;
}
}
return false;
}
3. 检测进程自启动
bool isProcessInAutostart(const std::wstring& processPath) {
HKEY hKey;
LPCWSTR runKeys[] = {
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run",
L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
L"SYSTEM\\CurrentControlSet\\Services"
};
for (int i = 0; i < sizeof(runKeys) / sizeof(runKeys[0]); i++) {
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, runKeys[i], 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
DWORD index = 0;
wchar_t valueName[MAX_PATH];
wchar_t data[MAX_PATH];
DWORD valueNameSize = MAX_PATH;
DWORD dataSize = sizeof(data);
while (RegEnumValue(hKey, index, valueName, &valueNameSize, NULL, NULL,
(LPBYTE)data, &dataSize) == ERROR_SUCCESS) {
std::wstring dataStr(data);
if (dataStr.find(processPath) != std::wstring::npos) {
RegCloseKey(hKey);
return true;
}
index++;
valueNameSize = MAX_PATH;
dataSize = sizeof(data);
}
RegCloseKey(hKey);
}
}
return false;
}
4. 综合监控进程
void monitorProcesses() {
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
return;
}
if (!Process32First(hProcessSnap, &pe32)) {
CloseHandle(hProcessSnap);
return;
}
std::wstring message = L"";
do {
DWORD pid = pe32.th32ProcessID;
if (pid == 0) continue;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if (hProcess == NULL) continue;
std::wstring processPath = getProcessPath(pid);
if (processPath.find(L"C:\\Windows") != std::wstring::npos) {
CloseHandle(hProcess);
continue;
}
std::wstring processName = getProcessName(pid);
bool isHighRisk = isHighRiskProcess(processName, processPath);
ProcessSignatureStatus signatureStatus = checkProcessSignature(processPath);
if (signatureStatus == SIGNED_AND_TRUSTED) {
CloseHandle(hProcess);
continue;
}
std::vector<std::wstring> externalIPs = getExternalIPs(pid);
if (externalIPs.empty()) {
CloseHandle(hProcess);
continue;
}
bool hasSuspiciousBehavior = detectTrojanBehavior(pid, processPath);
bool inAutostart = isProcessInAutostart(processPath);
CloseHandle(hProcess);
std::wstring processInfo;
if (isHighRisk) {
processInfo = L"名称伪造高危进程: " + processName + L" (PID: " +
std::to_wstring(pid) + L")\n路径: " + processPath + L"\n";
} else if (signatureStatus == SIGNED_BUT_NOT_TRUSTED) {
processInfo = L"签名伪造高危进程: " + processName + L" (PID: " +
std::to_wstring(pid) + L")\n路径: " + processPath + L"\n";
} else if (signatureStatus == NOT_SIGNED) {
processInfo = L"无签名高危进程: " + processName + L" (PID: " +
std::to_wstring(pid) + L")\n路径: " + processPath + L"\n";
} else {
processInfo = L"进程: " + processName + L" (PID: " +
std::to_wstring(pid) + L")\n路径: " + processPath + L"\n";
}
processInfo += L" - 检测到外部IP连接:\n";
for (const auto& ip : externalIPs) {
processInfo += L" " + ip + L"\n";
}
if (hasSuspiciousBehavior) {
processInfo += L" - 检测到异常行为\n";
}
if (inAutostart) {
processInfo += L" - 已加启动\n";
} else {
processInfo += L" - 未发现自启动\n";
}
message += processInfo + L"\n";
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
if (!message.empty()) {
MessageBoxW(NULL, message.c_str(), L"高危进程监控", MB_OK | MB_ICONWARNING);
} else {
MessageBoxW(NULL, L"未检测到可疑进程。", L"高危进程监控", MB_OK | MB_ICONINFORMATION);
}
}
七、主程序逻辑
int main() {
// 检查管理员权限
if (!isRunningAsAdmin()) {
restartAsAdmin();
}
// 监控进程
monitorProcesses();
// 检查启动目录中的无签名文件
checkStartupDirectoriesForUnsignedFiles();
return 0;
}
八、关键点总结
- 管理员权限检查:确保程序以管理员权限运行,才能获取完整的系统信息
- IP连接分析:获取所有进程的网络连接,过滤掉内网IP,重点关注外部连接
- 启动项检查:扫描系统启动目录和注册表启动项,检测异常启动程序
- 数字签名验证:使用WinVerifyTrust API验证进程签名状态
- 行为分析:检测进程是否伪装系统进程、是否有异常行为模式
- 综合评估:结合进程名称、路径、签名状态、网络连接和行为特征判断风险等级
这套策略可以有效检测常见的钓鱼攻击和恶意软件行为,特别是那些伪装成正常程序、试图建立外部连接或设置自启动的恶意进程。