DATAONLY PWNING MICROSOFT WINDOWS KERNEL EXPLOITATION OF KERNEL

  • Slides: 54
Download presentation
DATA-ONLY PWNING MICROSOFT WINDOWS KERNEL: EXPLOITATION OF KERNEL POOL OVERFLOWS ON MICROSOFT WINDOWS 8.

DATA-ONLY PWNING MICROSOFT WINDOWS KERNEL: EXPLOITATION OF KERNEL POOL OVERFLOWS ON MICROSOFT WINDOWS 8. 1 Nikita Tarakanov, Moscow, Russia Zero. Nights 2014 14 st of November 2014

Agenda • Introduction • Pool super basics • Previous attacks • New idea •

Agenda • Introduction • Pool super basics • Previous attacks • New idea • Mitigations • Q&A

Introduction • Ring 3(IE, Adobe Reader, Flash player, MS Office etc) applications as first

Introduction • Ring 3(IE, Adobe Reader, Flash player, MS Office etc) applications as first attack vector • Not privileged level • Sandboxes (IE EPM, Reader sandbox, Chrome sandbox etc) • Need to get Ring 0 to have ability to make fancy stuff • So, Elevation of Privileges (R 3 ->R 0) Exploits/Vulnerabilities are critical • Good examples: pwn 2 own 2013/2014 IE EPM sandbox escapes via kernel exploit

Pool basics • Following 5 slides are copy-paste from work of mighty Tarjei Mandt

Pool basics • Following 5 slides are copy-paste from work of mighty Tarjei Mandt

Pool Header 32 -bits • • • kd> dt nt!_POOL_HEADER +0 x 000 Previous.

Pool Header 32 -bits • • • kd> dt nt!_POOL_HEADER +0 x 000 Previous. Size : Pos 0, 9 Bits +0 x 000 Pool. Index : Pos 9, 7 Bits +0 x 002 Block. Size : Pos 0, 9 Bits +0 x 002 Pool. Type : Pos 9, 7 Bits +0 x 004 Pool. Tag : Uint 4 B Previous. Size: Block. Size of the preceding chunk Pool. Index: Index into the associated pool descriptor array Block. Size: (Number. Of. Bytes+0 x. F) >> 3 Pool. Type: Free=0, Allocated=(Pool. Type|2) Pool. Tag: 4 printable characters identifying the code responsible for the allocation

Pool Header 64 -bits kd> dt nt!_POOL_HEADER +0 x 000 Previous. Size : Pos

Pool Header 64 -bits kd> dt nt!_POOL_HEADER +0 x 000 Previous. Size : Pos 0, 8 Bits +0 x 000 Pool. Index : Pos 8, 8 Bits +0 x 000 Block. Size : Pos 16, 8 Bits +0 x 000 Pool. Type : Pos 24, 8 Bits +0 x 004 Pool. Tag : Uint 4 B +0 x 008 Process. Billed : Ptr 64 _EPROCESS Block. Size: (Number. Of. Bytes+0 x 1 F) >> 4 ( 256 List. Heads entries due to 16 byte block size ) • Process. Billed: Pointer to process object charged for the pool allocation (used in quota management) • •

Free Chunks • If a pool chunk is freed to a pool descriptor List.

Free Chunks • If a pool chunk is freed to a pool descriptor List. Heads list, the header is followed by a LINK_ENTRY structure • Pointed to by the List. Heads doubly-linked list • kd> dt nt!_LIST_ENTRY • +0 x 000 Flink : Ptr 32 _LIST_ENTRY • +0 x 004 Blink : Ptr 32 _LIST_ENTRY

Allocation order

Allocation order

Merging Pool Chunks

Merging Pool Chunks

Previous attacks • Pool metadata corruption - out of scope • Object metadata corruption

Previous attacks • Pool metadata corruption - out of scope • Object metadata corruption (DKOHM)

Object Metadata POOL_HEADER • OBJECT_HEADER • Optional headers Optional Headers OBJECT_HEADER Object

Object Metadata POOL_HEADER • OBJECT_HEADER • Optional headers Optional Headers OBJECT_HEADER Object

OBJECT_HEADER • • • • kd> dt nt!_OBJECT_HEADER • +0 x 000 Pointer. Count

OBJECT_HEADER • • • • kd> dt nt!_OBJECT_HEADER • +0 x 000 Pointer. Count : Int 4 B • +0 x 004 Handle. Count : Int 4 B • +0 x 004 Next. To. Free : Ptr 32 Void • +0 x 008 Lock : _EX_PUSH_LOCK • +0 x 00 c Type. Index : UChar <- Index of pointer to OBJECT_TYPE structure in Ob. Type. Index. Table • +0 x 00 d Trace. Flags : UChar • +0 x 00 d Dbg. Ref. Trace : Pos 0, 1 Bit • +0 x 00 d Dbg. Trace. Permanent : Pos 1, 1 Bit • +0 x 00 e Info. Mask : UChar • +0 x 00 f Flags : UChar • +0 x 010 Object. Create. Info : Ptr 32 _OBJECT_CREATE_INFORMATION • +0 x 010 Quota. Block. Charged : Ptr 32 Void • +0 x 014 Security. Descriptor : Ptr 32 Void • +0 x 018 Body : _QUAD

Ob. Type. Index. Table • • • • kd> dd nt!Ob. Type. Index. Table

Ob. Type. Index. Table • • • • kd> dd nt!Ob. Type. Index. Table L 40 • 81 a 3 edc 0 0000 bad 0 b 0 b 0 8499 c 040 849 aa 390 • 81 a 3 edd 0 84964 f 70 8499 b 4 c 0 84979500 84999618 • 81 a 3 ede 0 84974868 849783 c 8 8499 bf 70 84970 b 40 • 81 a 3 edf 0 849 a 8888 84979340 849 aaf 70 849 a 6 a 38 • 81 a 3 ee 00 8496 df 70 8495 b 040 8498 cf 70 84930 a 50 • 81 a 3 ee 10 8495 af 70 8497 ff 70 84985040 84999 e 78 • 81 a 3 ee 20 84997 f 70 8496 c 040 849646 e 0 84978 f 70 • 81 a 3 ee 30 8497 aec 0 84972608 849 a 0040 849 a 9750 • 81 a 3 ee 40 849586 d 8 84984 f 70 8499 d 578 849 ab 040 • 81 a 3 ee 50 84958938 84974 a 58 84967168 84967098 • 81 a 3 ee 60 8496 ddd 0 849 a 5140 8497 ce 40 849 aa 138 • 81 a 3 ee 70 84 a 6 c 058 84969 c 58 8497 e 720 85 c 62 a 28 • 81 a 3 ee 80 85 c 625 f 0 00000000

OBJECT_TYPE • kd> dt nt!_OBJECT_TYPE • +0 x 000 Type. List : _LIST_ENTRY •

OBJECT_TYPE • kd> dt nt!_OBJECT_TYPE • +0 x 000 Type. List : _LIST_ENTRY • +0 x 008 Name : _UNICODE_STRING • +0 x 010 Default. Object : Ptr 32 Void • +0 x 014 Index : UChar • +0 x 018 Total. Number. Of. Objects : Uint 4 B • +0 x 01 c Total. Number. Of. Handles : Uint 4 B • +0 x 020 High. Water. Number. Of. Objects : Uint 4 B • +0 x 024 High. Water. Number. Of. Handles : Uint 4 B • +0 x 028 Type. Info : _OBJECT_TYPE_INITIALIZER • +0 x 080 Type. Lock : _EX_PUSH_LOCK • +0 x 084 Key : Uint 4 B • +0 x 088 Callback. List : _LIST_ENTRY

Procedures • • • kd> dt nt!_OBJECT_TYPE_INITIALIZER [. . ] +0 x 030 Dump.

Procedures • • • kd> dt nt!_OBJECT_TYPE_INITIALIZER [. . ] +0 x 030 Dump. Procedure : Ptr 32 void +0 x 034 Open. Procedure : Ptr 32 long +0 x 038 Close. Procedure : Ptr 32 void +0 x 03 c Delete. Procedure : Ptr 32 void +0 x 040 Parse. Procedure : Ptr 32 long +0 x 044 Security. Procedure : Ptr 32 long +0 x 048 Query. Name. Procedure : Ptr 32 long +0 x 04 c Okay. To. Close. Procedure : Ptr 32 unsigned char

Ob. Type. Index. Table & Object Type Ob. Type. Index. Table Object Header Type.

Ob. Type. Index. Table & Object Type Ob. Type. Index. Table Object Header Type. Index OBJECT_TYPE Pointer to OBJECT_TYPE Object’s dispatch func Pointers to various procedures

Object Type Index Table (x 86)

Object Type Index Table (x 86)

Object Type Index Table (x 64)

Object Type Index Table (x 64)

Object metadata corruption (DKOHM) POOL_HEADER overflow Optional Headers 0 x 0000 0 x. BAD

Object metadata corruption (DKOHM) POOL_HEADER overflow Optional Headers 0 x 0000 0 x. BAD 0 B 0 B 0 Fake OBJECT_TYPE OBJECT_HEADER Ob. Type. Index. Table Object Shellcode

Windows 8. 1 • 0 x. BAD 0 B 0 B 0 has gone

Windows 8. 1 • 0 x. BAD 0 B 0 B 0 has gone

New idea • Object data corruption (DKOHM + DKOM) • Object type confusion

New idea • Object data corruption (DKOHM + DKOM) • Object type confusion

Object data corruption (DKOHM + DKOM) • Set Type. Index value to different object

Object data corruption (DKOHM + DKOM) • Set Type. Index value to different object type (object type confusion) • Object Manager is fooled (before it was Type A, not it’s Type B) • Craft malicious object’s data (counters, pointers) • Invoke system service(s) to trigger access to malicious object • Profit

Object data corruption (DKOHM + DKOM) FILE OBJECT_TYPE Object Header Ob. Type. Index. Table

Object data corruption (DKOHM + DKOM) FILE OBJECT_TYPE Object Header Ob. Type. Index. Table Object Data ALPC OBJECT_TYPE

Object data corruption (DKOHM+DKOM) Object Header FILE_OBJECT After overwrite -> type confusion Object Header

Object data corruption (DKOHM+DKOM) Object Header FILE_OBJECT After overwrite -> type confusion Object Header ALPC_OBJECT(all data is under control) Invoke system service trigger access to object exploit Different scenarios

OBJECT_TYPE_INITIALIZER Procedures • +0 x 030 Dump. Procedure : (null) • +0 x 038

OBJECT_TYPE_INITIALIZER Procedures • +0 x 030 Dump. Procedure : (null) • +0 x 038 Open. Procedure : (null) • +0 x 040 Close. Procedure : 0 xfffff 801`5 b 913 b 44 void nt!Obp. Close. Directory. Object+0 • +0 x 048 Delete. Procedure : 0 xfffff 801`5 b 92743 c void nt!Obp. Delete. Directory. Object+0 • +0 x 050 Parse. Procedure : (null) • +0 x 058 Security. Procedure : 0 xfffff 801`5 b 848 e 54 long nt!Se. Default. Object. Method+0 • +0 x 060 Query. Name. Procedure : (null) • +0 x 068 Okay. To. Close. Procedure : (null)

OBJECT_TYPE_INITIALIZER Procedures • • +0 x 030 Dump. Procedure : (null) +0 x 038

OBJECT_TYPE_INITIALIZER Procedures • • +0 x 030 Dump. Procedure : (null) +0 x 038 Open. Procedure : (null) +0 x 040 Close. Procedure : (null) +0 x 048 Delete. Procedure : 0 xfffff 801`5 b 9250 fc void nt!Iop. Delete. Device+0 +0 x 050 Parse. Procedure : 0 xfffff 801`5 b 86 dde 0 long nt!Iop. Parse. Device+0 +0 x 058 Security. Procedure : 0 xfffff 801`5 b 842028 long nt!Iop. Get. Security. Object+0 +0 x 060 Query. Name. Procedure : (null) +0 x 068 Okay. To. Close. Procedure : (null)

Type Confusion Object Header Event Object nt!Se. Default. Object. Method After overwrite -> type

Type Confusion Object Header Event Object nt!Se. Default. Object. Method After overwrite -> type confusion Object Header FILE_OBJECT(all data is under control) Nt. Query. Security. Object exploit nt!Iop. Get. Security. Object

Security. Procedure vector • For most object types: nt!Se. Default. Object. Method • Wmi.

Security. Procedure vector • For most object types: nt!Se. Default. Object. Method • Wmi. Guid object type: nt!Wmip. Security. Method • File/Device object type: nt!Iop. Get. Security. Object • Key object type: nt!Cmp. Security. Method

nt!Iop. Get. Security. Object • FILE_OBJECT > -> DEVICE_OBJECT MAJOR_ROUTINE -> -> DRIVER_OBJECT attacker’s

nt!Iop. Get. Security. Object • FILE_OBJECT > -> DEVICE_OBJECT MAJOR_ROUTINE -> -> DRIVER_OBJECT attacker’s shellcode • Execution Hijack by three consequent dereferences!!!! -

nt!Iop. Get. Security. Object

nt!Iop. Get. Security. Object

nt!Iop. Get. Security. Object chain • 0: kd> dt nt!_FILE_OBJECT • +0 x 000

nt!Iop. Get. Security. Object chain • 0: kd> dt nt!_FILE_OBJECT • +0 x 000 Type : Int 2 B • +0 x 002 Size : Int 2 B • +0 x 008 Device. Object : Ptr 64 _DEVICE_OBJECT • 0: kd> dt nt!_DEVICE_OBJECT • +0 x 000 Type : Int 2 B • +0 x 002 Size : Uint 2 B • +0 x 004 Reference. Count : Int 4 B • +0 x 008 Driver. Object : Ptr 64 _DRIVER_OBJECT

nt!Iop. Get. Security. Object chain • 0: kd> dt nt!_DRIVER_OBJECT • +0 x 000

nt!Iop. Get. Security. Object chain • 0: kd> dt nt!_DRIVER_OBJECT • +0 x 000 Type : Int 2 B • +0 x 002 Size • +0 x 008 Device. Object • +0 x 010 Flags • +0 x 018 Driver. Start : Ptr 64 Void • +0 x 020 Driver. Size : Uint 4 B • +0 x 028 Driver. Section : Ptr 64 Void • +0 x 030 Driver. Extension : Ptr 64 _DRIVER_EXTENSION • +0 x 038 Driver. Name • +0 x 048 Hardware. Database : Ptr 64 _UNICODE_STRING • +0 x 050 Fast. Io. Dispatch : Ptr 64 _FAST_IO_DISPATCH • +0 x 058 Driver. Init • +0 x 060 Driver. Start. Io : Ptr 64 • +0 x 068 Driver. Unload • +0 x 070 Major. Function : [28] Ptr 64 : Int 2 B : Ptr 64 _DEVICE_OBJECT : Uint 4 B : _UNICODE_STRING : Ptr 64 long : Ptr 64 void long

Close/Delete Procedure vector • Huge amount of different execution flows: 56 functions • Mostly

Close/Delete Procedure vector • Huge amount of different execution flows: 56 functions • Mostly arbitrary memory overwrite • Some adjacent read/write • Some hijack of execution flow

Other Procedures • Dump. Procedure, Open. Procedure, Parse. Procedure, Query. Name. Procedure, Okay. To.

Other Procedures • Dump. Procedure, Open. Procedure, Parse. Procedure, Query. Name. Procedure, Okay. To. Close. Procedure • Are rare – no interest in here

Object’s body vector (DKOM) • There are several typical OOP interfaces • Constructor –

Object’s body vector (DKOM) • There are several typical OOP interfaces • Constructor – Nt. Create* (Nt. Create. File) • Destructor – Nt. Close • Getter – Nt. Query. Information* (Nt. Query. Information. Worker. Factory) • Setter – Nt. Set. Information* (Nt. Set. Information. Key) • Object Type specific: Nt. Clear. Event, Nt. Alpc. Accept. Connect. Port, Nt. Enumerate. Value. Key, Nt. Recover. Resource. Manager etc

DKOHM+DKOM restrictions • Unfortunately you cant freely use Getter/Specific when you change type of

DKOHM+DKOM restrictions • Unfortunately you cant freely use Getter/Specific when you change type of an object – caused by Valid. Access. Mask field • +0 x 010 Name : _UNICODE_STRING "Window. Station“ • +0 x 01 c Valid. Access. Mask : 0 xf 037 f • +0 x 010 Name : _UNICODE_STRING "Directory“ • +0 x 01 c Valid. Access. Mask : 0 xf 000 f • But you can still smash object’s data without changing object type

DKOHM+DKOM restrictions • Some Object Types have same Valid. Access. Mask • +0 x

DKOHM+DKOM restrictions • Some Object Types have same Valid. Access. Mask • +0 x 010 Name : _UNICODE_STRING "Section“ • +0 x 01 c Valid. Access. Mask : 0 x 1 f 001 f • +0 x 010 Name : _UNICODE_STRING "Job“ • +0 x 01 c Valid. Access. Mask : 0 x 1 f 001 f • So technique using Getter/Specific is possible, but limited

Symbolic Link: Getter vector Nt. Query. Symbolic. Link. Object

Symbolic Link: Getter vector Nt. Query. Symbolic. Link. Object

Directory Object: Getter vector Nt. Query. Directory. Object • Up-to 0 x 25 times

Directory Object: Getter vector Nt. Query. Directory. Object • Up-to 0 x 25 times of reading arbitrary memory

Worker. Factory object Getter: Nt. Query. Information. Worker. Factory

Worker. Factory object Getter: Nt. Query. Information. Worker. Factory

Worker. Factory object Setter: Nt. Set. Information. Worker. Factory

Worker. Factory object Setter: Nt. Set. Information. Worker. Factory

Redirection to Ring 0 Shellcode • Jump to Ring 3 address? • Nah, SMEP

Redirection to Ring 0 Shellcode • Jump to Ring 3 address? • Nah, SMEP

SMEP bypass techniques • ROP : Ex. Allocate. Pool. With. Tag (Non. Paged. Exec)

SMEP bypass techniques • ROP : Ex. Allocate. Pool. With. Tag (Non. Paged. Exec) + memcpy+jmp • ROP : clear SMEP flag in cr 4 • Jump to executable Ring 0 memory (Artem’s Shishkin technique) • Set Owner flag of PTE to 0 (MI_PTE_OWNER_KERNEL)

Typical Payload in Eo. P exploits • Copy token of SYSTEM process to attacker’s

Typical Payload in Eo. P exploits • Copy token of SYSTEM process to attacker’s process • Basically, its just copying data from memory addr A to addr B

Data-only PWNING!!! • We DON’T need to execute external instructions or use ROP •

Data-only PWNING!!! • We DON’T need to execute external instructions or use ROP • So it’s just manipulation with data and executing ABSOLUTE legitimate code (this is NOT ROP/JOP!!!) • GAME OVER

Mitigations • Hardware perspective • Microsoft’s perspective

Mitigations • Hardware perspective • Microsoft’s perspective

Hardware perspective • SMAP – prevent dereference of R 3 memory • Just raise

Hardware perspective • SMAP – prevent dereference of R 3 memory • Just raise the bar (attacker has to craft object(s) in r 0 memory)

Microsoft’s perspective • OBJECT_HEADER hardening – cookie? • Randomize Type. Index of Object Types

Microsoft’s perspective • OBJECT_HEADER hardening – cookie? • Randomize Type. Index of Object Types during boot • Isolated Pools

Conclusion

Conclusion

WTFuzz aka Peter VREUGDENHIL • Heapsprays are for the 99%

WTFuzz aka Peter VREUGDENHIL • Heapsprays are for the 99%

Tombkeeper aka Yang Yu • ROPs are for the 99%

Tombkeeper aka Yang Yu • ROPs are for the 99%

Nikita Tarakanov • Code execution is for the 99%

Nikita Tarakanov • Code execution is for the 99%

Q&A

Q&A

References • Tarjei Mandt BH US 2012 • Nikita Tarakanov HITB AMS 2013

References • Tarjei Mandt BH US 2012 • Nikita Tarakanov HITB AMS 2013