蓝队—反钓鱼的策略提供
字数 670 2025-08-22 12:23:25

蓝队反钓鱼策略详解

一、前言

本文提供了一套完整的蓝队反钓鱼策略,通过多种技术手段检测系统中的可疑进程和潜在威胁。主要思路是通过IP查找、特殊文件名检查、文件编译器验证和启动项检查来筛选可疑进程,最终以弹窗形式呈现结果。

二、总体思路

  1. 流量分析:获取所有进程的IP连接,筛选出可疑的外部连接
  2. 启动项检查:扫描系统启动目录和任务计划中的启动项
  3. 签名验证:检查进程的数字签名状态
  4. 行为分析:检测进程的异常行为模式
  5. 综合评估:结合以上信息判断进程风险等级

三、流量分析实现

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;
}

八、关键点总结

  1. 管理员权限检查:确保程序以管理员权限运行,才能获取完整的系统信息
  2. IP连接分析:获取所有进程的网络连接,过滤掉内网IP,重点关注外部连接
  3. 启动项检查:扫描系统启动目录和注册表启动项,检测异常启动程序
  4. 数字签名验证:使用WinVerifyTrust API验证进程签名状态
  5. 行为分析:检测进程是否伪装系统进程、是否有异常行为模式
  6. 综合评估:结合进程名称、路径、签名状态、网络连接和行为特征判断风险等级

这套策略可以有效检测常见的钓鱼攻击和恶意软件行为,特别是那些伪装成正常程序、试图建立外部连接或设置自启动的恶意进程。

蓝队反钓鱼策略详解 一、前言 本文提供了一套完整的蓝队反钓鱼策略,通过多种技术手段检测系统中的可疑进程和潜在威胁。主要思路是通过IP查找、特殊文件名检查、文件编译器验证和启动项检查来筛选可疑进程,最终以弹窗形式呈现结果。 二、总体思路 流量分析 :获取所有进程的IP连接,筛选出可疑的外部连接 启动项检查 :扫描系统启动目录和任务计划中的启动项 签名验证 :检查进程的数字签名状态 行为分析 :检测进程的异常行为模式 综合评估 :结合以上信息判断进程风险等级 三、流量分析实现 1. 获取所有进程的IP连接 2. IP地址过滤 四、启动项检查 1. 扫描启动目录 2. 检查任务计划启动项 五、签名验证 1. 检查进程签名状态 2. 检查启动目录中的无签名文件 六、行为分析与综合检测 1. 检测系统进程伪装 2. 检测高风险进程名称 3. 检测进程自启动 4. 综合监控进程 七、主程序逻辑 八、关键点总结 管理员权限检查 :确保程序以管理员权限运行,才能获取完整的系统信息 IP连接分析 :获取所有进程的网络连接,过滤掉内网IP,重点关注外部连接 启动项检查 :扫描系统启动目录和注册表启动项,检测异常启动程序 数字签名验证 :使用WinVerifyTrust API验证进程签名状态 行为分析 :检测进程是否伪装系统进程、是否有异常行为模式 综合评估 :结合进程名称、路径、签名状态、网络连接和行为特征判断风险等级 这套策略可以有效检测常见的钓鱼攻击和恶意软件行为,特别是那些伪装成正常程序、试图建立外部连接或设置自启动的恶意进程。