[2024]简单分析一下火绒为什么误报explorer.exe huoji 火绒,360 2024-02-19 690 次浏览 1 次点赞 ### 免责声明 刚收假回来,花了五分钟看的, 没细看,说的不一定对,需要等待后续报告。 ### 前言 在win10 20h2的一次更新中。火绒误杀了windows的explorer组件: ![](https://key08.com/usr/uploads/2024/02/2000824865.jpg) 本来不想蹭这个热度的,但是热度太高 ,刚收假回来,准备练练手。 这个是误报的explorer: https://www.virustotal.com/gui/file/06d066fe672f18faba41dd5787dbfc3991744dc4c17a3bb3d8154aceadbd66fb/detection 火绒的规则报的是avkiller,根据本人第一直觉,应该是匹配到了杀毒软件字符串,所以我们打开IDA,把有问题的explorer拖进去 ### IsHijackingProcessRunning -被杀的根源 在IsHijackingProcessRunning这个函数中,发现了一些绿球的字符串: ![](https://key08.com/usr/uploads/2024/02/1769447761.png) 这个函数的作用就是检测360在不在: ``` __int64 __fastcall ShellFeedsCampaignHelper::IsHijackingProcessRunning( ShellFeedsCampaignHelper *this, unsigned __int8 *a2) { const unsigned __int16 *v3; // r8 HANDLE v4; // rbx signed int LastError; // eax unsigned int v6; // ebx unsigned int v7; // edi __int64 *v8; // rsi HANDLE Toolhelp32Snapshot; // [rsp+20h] [rbp-48h] BYREF __int64 v11[5]; // [rsp+28h] [rbp-40h] BYREF *(_BYTE *)this = 0; v11[0] = (__int64)L"360leakfixer.exe"; v11[1] = (__int64)L"360safe.exe"; v11[2] = (__int64)L"360PatchMgr64.exe"; v11[3] = (__int64)L"360Tray.exe"; v11[4] = (__int64)L"ZhuDongFangYu.exe"; Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0); v4 = Toolhelp32Snapshot; if ( Toolhelp32Snapshot == (HANDLE)-1i64 ) { LastError = GetLastError(); v6 = LastError; if ( LastError > 0 ) v6 = (unsigned __int16)LastError | 0x80070000; } else { v7 = 0; v8 = v11; while ( !ShellFeedsCampaignHelper::IsProcessRunning(Toolhelp32Snapshot, (void *)*v8, v3) ) { ++v7; ++v8; if ( v7 >= 5 ) goto LABEL_9; } *(_BYTE *)this = 1; LABEL_9: CloseHandle(v4); v6 = 0; } wil::unique_any_t>>::~unique_any_t>>(&Toolhelp32Snapshot); return v6; } ``` 其中匹配到这些,就代表绿球在: ``` v11[0] = (__int64)L"360leakfixer.exe"; v11[1] = (__int64)L"360safe.exe"; v11[2] = (__int64)L"360PatchMgr64.exe"; v11[3] = (__int64)L"360Tray.exe"; v11[4] = (__int64)L"ZhuDongFangYu.exe"; ``` **火绒应该是杀了这些字符串** ### CheckCampaignAvailability 好,我们知道微软在搜索这些字符串,那么目的是什么呢?是要劫持绿球吗? 查看交叉引用,我们发现是这个CheckCampaignAvailability调用它的 ![](https://key08.com/usr/uploads/2024/02/3328002639.png) 这个代码非常复杂,我给出简化版的代码: ![](https://key08.com/usr/uploads/2024/02/1147340473.png) 代码如下: ``` __int64 __fastcall ShellFeedsCampaignHelper::CheckCampaignAvailability(_QWORD *a1, char *a2, __int64 a3) { unsigned int v6; // ebx _QWORD *v7; // rcx unsigned __int8 *v8; // rdx int IsFeedsAvailable; // eax unsigned int *v10; // r8 char v11; // cl bool v12; // al __int64 v13; // r8 const wchar_t *v14; // rdx unsigned __int8 *v15; // rdx unsigned int *v16; // r8 char v17; // cl int IsDeviceInDmaRegion; // eax int v19; // eax char v20; // cl int ShellFeedsRegKey; // eax int v22; // ecx char v23; // cl char v24; // al int IsHijackingProcessRunning; // eax char v26; // cl int v27; // eax unsigned __int8 *v28; // rdx char v29; // cl int v30; // eax char v31; // cl char v33[4]; // [rsp+20h] [rbp-20h] BYREF unsigned __int16 v34[2]; // [rsp+24h] [rbp-1Ch] BYREF _QWORD *v35; // [rsp+28h] [rbp-18h] v35 = a1; v6 = 0; *a2 = 0; std::wstring::assign(a3, &Class, 0i64); v7 = a1; if ( a1[3] >= 8ui64 ) v7 = (_QWORD *)*a1; if ( (unsigned __int8)std::_Traits_equal>(v7, a1[2], L"feeds-reclaim", 13i64) ) { v33[0] = 0; IsFeedsAvailable = ShellFeedsExperienceHelpers::IsFeedsAvailable((ShellFeedsExperienceHelpers *)v33, v8); v11 = v33[0]; *a2 = v33[0]; if ( IsFeedsAvailable < 0 || !v11 ) { v13 = 16i64; v14 = L"FeedsUnavailable"; goto LABEL_40; } *(_DWORD *)v34 = 0; v12 = (int)ShellFeedsExperienceHelpers::GetShellFeedsRegKey( (ShellFeedsExperienceHelpers *)L"ShellFeedsTaskbarViewMode", v34, v10) >= 0 && *(_DWORD *)v34 == 2; *a2 = v12; if ( !v12 ) { v13 = 9i64; v14 = L"PinStatus"; LABEL_40: *a2 = 0; std::wstring::assign(a3, v14, v13); std::wstring::_Tidy_deallocate(a1); return 0i64; } if ( (unsigned __int8)wil::details::FeatureImpl<__WilFeatureTraits_Feature_Feeds_DmaCompliance>::__private_IsEnabled(&`wil::Feature<__WilFeatureTraits_Feature_Feeds_DmaCompliance>::GetImpl'::`2'::impl) ) { v33[0] = 1; IsDeviceInDmaRegion = ShellFeedsDMAHelpers::IsDeviceInDmaRegion((ShellFeedsDMAHelpers *)v33, v15); v17 = v33[0] == 0; *a2 = v33[0] == 0; if ( IsDeviceInDmaRegion < 0 || v33[0] ) { v13 = 3i64; v14 = L"DMA"; goto LABEL_40; } } else { v17 = *a2; } if ( v17 ) { v33[0] = 0; v19 = ShellFeedsCampaignHelper::IsInCampaignEnabledRegion((ShellFeedsCampaignHelper *)v33, v15); v20 = v33[0]; *a2 = v33[0]; if ( v19 < 0 || !v20 ) { v13 = 6i64; v14 = L"Region"; goto LABEL_40; } } if ( *a2 ) { *(_DWORD *)v34 = 0; ShellFeedsRegKey = ShellFeedsExperienceHelpers::GetShellFeedsRegKey( (ShellFeedsExperienceHelpers *)L"IsEnterpriseDevice", v34, v16); v22 = *(_DWORD *)v34; if ( ShellFeedsRegKey < 0 ) v22 = 1; if ( v22 ) { v23 = 1; v24 = 0; } else { v23 = 0; v24 = 1; } *a2 = v24; if ( v23 ) { v13 = 10i64; v14 = L"Enterprise"; goto LABEL_40; } if ( v24 ) { v33[0] = 0; IsHijackingProcessRunning = ShellFeedsCampaignHelper::IsHijackingProcessRunning( (ShellFeedsCampaignHelper *)v33, v15); v26 = v33[0]; *a2 = v33[0]; if ( IsHijackingProcessRunning < 0 || !v26 ) { v13 = 0x16i64; v14 = L"HijackingProcessNotRun"; goto LABEL_40; } } } if ( *a2 ) { v33[0] = 0; v27 = ShellFeedsCampaignHelper::CheckAvailability_UserUnpinDate((ShellFeedsCampaignHelper *)v33, v15); v29 = v33[0]; *a2 = v33[0]; if ( v27 < 0 || !v29 ) { v13 = 17i64; v14 = L"LastUserUnpinDate"; goto LABEL_40; } v33[0] = 0; v30 = ShellFeedsCampaignHelper::CheckAvailability_LastCampaignRunDate((ShellFeedsCampaignHelper *)v33, v28); v31 = v33[0]; *a2 = v33[0]; if ( v30 < 0 || !v31 ) { v13 = 19i64; v14 = L"LastCampaignRunDate"; goto LABEL_40; } } } else { std::wstring::assign(a3, L"Campaign ID error", 17i64); v6 = 0x80070490; } std::wstring::_Tidy_deallocate(a1); return v6; } ``` 注意看这一段: ``` if ( v24 ) { v33[0] = 0; IsHijackingProcessRunning = ShellFeedsCampaignHelper::IsHijackingProcessRunning( (ShellFeedsCampaignHelper *)v33, v15); v26 = v33[0]; *a2 = v33[0]; if ( IsHijackingProcessRunning < 0 || !v26 ) { v13 = 0x16i64; v14 = L"HijackingProcessNotRun"; goto LABEL_40; } } ... LABEL_40: *a2 = 0; std::wstring::assign(a3, v14, v13); std::wstring::_Tidy_deallocate(a1); return 0i64; ``` 这里很明显返回的是否是错误码,判断是否能启动Campaign 对应后面的RunFeedsCampaign调用部分 ``` if ( (int)ShellFeedsCampaignHelper::CheckCampaignAvailability(v5, v18, (__int64)v24) >= 0 && v18[0] ) { v6 = v21; if ( v22 >= 8 ) v6 = (__int64 *)v21[0]; if ( (unsigned __int8)std::_Traits_equal>(v6, v21[2], L"feeds-reclaim", 13i64) ) { v8 = ShellFeedsCampaignHelper::CampaignAction_Reclaim(this, v7); LODWORD(v20) = v8; v9 = v21; if ( v22 >= 8 ) v9 = (__int64 *)v21[0]; *(_QWORD *)&v19[1] = v9; FeedsTelemetry::ShellFeedsCampaign_RunResult(&v20, &v19[1]); GetSystemTime(&SystemTime); wMonth = SystemTime.wMonth; if ( (int)StringCchPrintfW((wchar_t *)Buffer, 0x28ui64, L"%02hu-%02hu-%4huT%02hu-%02hu-%02hu", SystemTime.wDay) >= 0 ) SHRegSetString( HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Feeds", L"LastCampaignRunDate", (const unsigned __int16 *)Buffer); } ``` **如果返回0 则就启动** 关于这个campaign: > 在Windows 10系统中,"Campaign"通常指的是一系列由操作系统或应用程序发起的推广活动,旨在提升用户体验、推广新功能、提供教育内容、或者鼓励用户进行某些操作。例如,微软可能会通过Campaign来推广Windows更新、新的安全特性、用户调研、或者其他产品和服务。 在您提供的代码上下文中,ShellFeedsCampaignHelper::RunFeedsCampaign函数可能是用来管理和执行这些推广活动的。这些活动可能与用户的动态内容订阅服务(Feeds)相关,例如新闻、通知、提示等。CampaignAction_Reclaim这样的函数可能是活动的一部分,用于执行特定的操作,比如回收资源、更新内容或其他与活动相关的任务。 总的来说,"Campaign"在这里可能是指Windows 10系统中的一种用户互动活动,用于推广系统的特定功能或服务。 应该是它自己的推广相关的 ### RunFeedsCampaign 这个函数的目的是执行一个名为“Feeds Campaign”的活动。它首先检查注册表中的“CampaignState”键值是否为2,这表示活动可能是激活状态。然后,它会检查注册表中的“Campaign”键值,以获取活动的具体信息。 如果活动状态和信息都有效,函数会继续检查活动是否可用。这涉及到调用CheckCampaignAvailability函数,该函数会进行一系列检查,如前所述。如果活动可用,函数会执行CampaignAction_Reclaim方法,这可能是一个恢复或回收资源的操作。执行后,它会记录活动的结果,并更新注册表中的“LastCampaignRunDate”键值,以记录活动的最后运行日期。 如果活动不可用,或者在检查过程中发现任何问题,函数会记录相应的结果,并设置适当的状态码。 最后,函数会尝试更新注册表中的“CampaignState”键值,以反映活动的最新状态。如果更新失败,它会记录错误信息。 总的来说,这个函数的目的是管理和执行一个Shell应用程序中的活动,确保所有必要的条件都满足,活动可以顺利进行,并记录活动的状态和结果。 ``` void __fastcall ShellFeedsCampaignHelper::RunFeedsCampaign( ShellFeedsCampaignHelper *this, struct Feeds::FeedsDynamicContent *a2, unsigned int *a3) { unsigned __int16 *v4; // r9 _QWORD *v5; // rax __int64 *v6; // rcx struct Feeds::FeedsDynamicContent *v7; // rdx int v8; // ebx __int64 *v9; // rcx __int64 *v10; // rax int v11; // eax __int64 *v12; // rax __int64 *v13; // rax unsigned int v14; // er8 unsigned int v15; // er9 int v16; // eax int wMonth; // [rsp+20h] [rbp-E0h] char v18[4]; // [rsp+50h] [rbp-B0h] BYREF _DWORD v19[3]; // [rsp+54h] [rbp-ACh] BYREF __int64 *v20; // [rsp+60h] [rbp-A0h] BYREF __int64 v21[3]; // [rsp+68h] [rbp-98h] BYREF unsigned __int64 v22; // [rsp+80h] [rbp-80h] struct _SYSTEMTIME SystemTime; // [rsp+88h] [rbp-78h] BYREF __int64 v24[2]; // [rsp+A8h] [rbp-58h] BYREF __m128i si128; // [rsp+B8h] [rbp-48h] unsigned int v26[4]; // [rsp+C8h] [rbp-38h] BYREF __int128 v27; // [rsp+D8h] [rbp-28h] __int64 v28; // [rsp+E8h] [rbp-18h] __int16 Buffer[20]; // [rsp+F0h] [rbp-10h] BYREF wil::details::in1diag3 *retaddr; // [rsp+128h] [rbp+28h] *(_OWORD *)v26 = 0i64; v27 = 0i64; v28 = 0i64; if ( (int)ShellFeedsExperienceHelpers::GetShellFeedsRegKey( (ShellFeedsExperienceHelpers *)L"CampaignState", (const unsigned __int16 *)v19, a3) >= 0 && v19[0] == 2 && (int)ShellFeedsExperienceHelpers::GetShellFeedsRegKey( L"Campaign", (const unsigned __int16 *)0x14, (unsigned int)v26, v4) >= 0 && LOWORD(v26[0]) ) { std::wstring::wstring(v21, v26); v18[0] = 0; si128 = _mm_load_si128((const __m128i *)&_xmm); LOWORD(v24[0]) = 0; v5 = (_QWORD *)std::wstring::wstring(&SystemTime, v21); if ( (int)ShellFeedsCampaignHelper::CheckCampaignAvailability(v5, v18, (__int64)v24) >= 0 && v18[0] ) { v6 = v21; if ( v22 >= 8 ) v6 = (__int64 *)v21[0]; if ( (unsigned __int8)std::_Traits_equal>(v6, v21[2], L"feeds-reclaim", 13i64) ) { v8 = ShellFeedsCampaignHelper::CampaignAction_Reclaim(this, v7); LODWORD(v20) = v8; v9 = v21; if ( v22 >= 8 ) v9 = (__int64 *)v21[0]; *(_QWORD *)&v19[1] = v9; FeedsTelemetry::ShellFeedsCampaign_RunResult(&v20, &v19[1]); GetSystemTime(&SystemTime); wMonth = SystemTime.wMonth; if ( (int)StringCchPrintfW((wchar_t *)Buffer, 0x28ui64, L"%02hu-%02hu-%4huT%02hu-%02hu-%02hu", SystemTime.wDay) >= 0 ) SHRegSetString( HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Feeds", L"LastCampaignRunDate", (const unsigned __int16 *)Buffer); } else { v8 = 0x80070057; LODWORD(v20) = 0x80070057; v10 = v21; if ( v22 >= 8 ) v10 = (__int64 *)v21[0]; *(_QWORD *)&v19[1] = v10; FeedsTelemetry::ShellFeedsCampaign_RunResult(&v20, &v19[1]); } v11 = 6; if ( v8 >= 0 ) v11 = 3; v19[0] = v11; } else { v19[0] = 5; v12 = v24; if ( si128.m128i_i64[1] >= 8ui64 ) v12 = (__int64 *)v24[0]; *(_QWORD *)&v19[1] = v12; v13 = v21; if ( v22 >= 8 ) v13 = (__int64 *)v21[0]; v20 = v13; FeedsTelemetry::ShellFeedsCampaign_NotAvailable(&v20, &v19[1]); } std::wstring::_Tidy_deallocate(v24); std::wstring::_Tidy_deallocate(v21); } else { v19[0] = 1; FeedsTelemetry::ShellFeedsCampaign_SettingsUnavailable(v19, v26); } v16 = ShellFeedsExperienceHelpers::SetShellFeedsRegKey( (ShellFeedsExperienceHelpers *)L"CampaignState", (const unsigned __int16 *)v19[0], v14, v15); if ( v16 < 0 ) wil::details::in1diag3::_Log_Hr( retaddr, (void *)0xD2, (unsigned int)"pcshell\\shell\\explorer\\helpers\\shellfeedscampaignhelper.cpp", (const char *)(unsigned int)v16, wMonth); } ``` `RunFeedsCampaign`函数的目的是在Windows 10系统中执行和管理一个名为“Feeds Campaign”的活动。这个活动可能与用户的动态内容订阅服务相关,例如新闻、天气、股票信息或其他实时更新。具体来说,这个函数可能会执行以下操作: 1. 检查注册表中的“CampaignState”键值,确定活动是否已经被激活。 2. 如果活动已激活,函数会进一步检查活动的详细信息,如活动名称和相关参数。 3. 确认活动信息后,函数会调用`CheckCampaignAvailability`来检查活动是否满足所有运行条件。 4. 如果活动可用,函数可能会执行特定的活动操作,如`CampaignAction_Reclaim`,这可能涉及更新用户的订阅内容或执行其他相关任务。 5. 活动执行完毕后,函数会记录活动的结果,并更新系统注册表中的“LastCampaignRunDate”键值,记录活动的最后运行日期。 6. 最后,函数会更新注册表中的“CampaignState”键值,以反映活动的最新状态,并记录任何错误或状态更改。 总之,`RunFeedsCampaign`函数的目的是确保“Feeds Campaign”活动按照预定的条件和流程顺利执行,并且记录活动的状态和结果,以便系统或用户可以跟踪活动的进展。 ### 结论 嗯破案了,微软看有没有360在,如果不在就推推广比如新闻天气等,可能之前发现跟绿球有冲突,所以才这样做的。 **而火绒可能依靠字符串查杀不小心把这个给查杀了。** 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 1
还不快抢沙发