В докладе рассказывается о новом механизме управления хендлами gdi объектов, появившимся в сентябрьском обновлении Windows 10, и его отличиях от старого менеджмента хендлов. А также о влиянии данных изменений на эксплуатацию уязвимостей LPE.
Call Girls In Defence Colony Delhi 💯Call Us 🔝8264348440🔝
Дроздов Юрий и Дроздова Людмила - Windows 10: Последние изменения в управлении хендлами gdi объектов и их влияние на процесс эксплуатации уязвимостей
1. Center of vulnerability research
Yurii Drozdov Liudmila Drozdova
DCG#7812
Saint-Petersburg
2016
WINDOWS 10 ANNIVERSARY UPDATE:
GDI HANDLE MANAGEMENT AND
VULNERABILITY EXPLOITATION
2. GDI HANDLE MANAGEMENT BEFORE WINDOWS
10 ANNIVERSARY UPDATE
• Win32k.sys contains gdi handle manager (win32kbase.sys for Windows 10),
functions with Hmg* prefix are responsible for handle management.
• HmgInsertObject inserts every gdi object (Bitmap, Brush, Font, Pen ….) into handle
table after allocation in kernel mode.
• Handle table is mapping to address space of every gui process. Pointer to mapped
table is located in the PEB.GdiSharedHandleTable field.
3. GDI HANDLE MANAGEMENT BEFORE WINDOWS
10 ANNIVERSARY UPDATE
Every object in handle table described by following structure
typedef struct {
PVOID64 pKernelAddress;
USHORT wProcessId;
USHORT wCount;
USHORT wUpper;
USHORT wType;
PVOID64 pUserAddress;
} GDICELL64;
So, we can get kernel address of gdi object from usermode.
4. OLD HMGINSERTOBJECT
Every object must be added to handle table after creation. Handle table pointer saved in win32k variable gpentHmgr (its pointer is
located in PEB.GdiSharedHandleTable in usermode).
HmgInsertObject function inserts object into handle table and contains following code
HmgInsertObject(_BASEOBJECT *ObjectKernelAddress,
unsigned __int16 flags,
unsigned __int8 objtype) {
...
Handle = hGetFreeHandle(objtype);
ENTRYOBJ::vSetup(
(gpentHmgr + 24i64 * LOWORD(Handle)),
ObjectKernelAddress,
objtype,
flags,
LOWORD(Handle));
...
}
ENTRYOBJ::vSetup function is filling GDICELL64 structure with given parameters.
5. WHY DO WE NEED GDI KERNEL OBJECT
ADDRESS DURING EXPLOITATION?
• To make exploit more stable:
• 1) we can check if object was allocated on the right place after spray.
• 2) we can change memory layout as we want.
• Sometimes it is important part of exploitation.
• 1) We can change Bitmap (SURFOBJ) fields and gain arbitrary read and write when we
know its address.
• We can use gdi objects for exploitation even if we have vulnerability in different (not
win32k) system component.
• SURFOBJ is one of the popular ways to achieve privilege escalation, which is working
from Vista to 10.
6. WINDOWS 10 ANNIVERSARY UPDATE
• Gdi handle management was changed a lot after update of Windows 10.
• PEB.GdiSharedHandleTable doesn’t contain kernel addresses anymore.
• New handle management classes and functions were added in win32kbase.sys.
• This update was introduced for Windows 10 only, but other systems can be affected soon.
7. WIN32KBASE.SYS CHANGES
• New Hmg* functions were added. The most interesting – HmgPentryFromPobj, because it
references new class GdiHandleManager.
• New handle management classes were added – GdiHandleManager,
GdiHandleEntryDirectory, GdiHandleEntryTable, EntryDataLookupTable.
• HmgCreate creates and initializes handle table (like in old version).
• We can easily track all changes via HmgInserObject function.
12. WHAT PEB.GDISHAREDHANDLETABLE
CONTAINS?
• Handle entry size wasn’t changed, it is like old GDICELL64 size – 0x18
typedef struct {
PVOID64 pKernelAddress;
USHORT wProcessId;
USHORT wCount;
USHORT wUpper;
USHORT wType;
PVOID64 pUserAddress;
} GDICELL64;
• The main change – pKernelAddress contains value 0xffffffffff000000 | dword_index, where dword_index =
[zero_byte][unused_table_index][lookup_entry_address_index]|[lookup_entry_index]
• no kernel addresses anymore.
13. HOW TO GET GDI OBJECT ADDRESS BY HANDLE
(X64) ?
Before updates Windbg command looked like this (handle in this case - 0x3c05096a)
• dq poi(poi(win32kbase!gpentHmgr) + 0x18*(0x3c05096a & 0xffff))
After changes (handle in this case - 0x1f0509e)
• dq poi(poi(poi(poi(poi((poi(poi(win32kbase!gpHandleManager)+0x10) + 8 + 0*8)) +
0x18)) + ((0x1f0509ea & 0xffff) / 0x100) * 8) + (0x1f0509ea & 0xff)*0x10 + 8)
15. CHANGES SUMMARY
• Object metadata (pid, object type …) and object address were saved
together in GDICELL structure before update and both were mapped to
userspace.
• Now, only object metadata is mapping, kernel addresses are located in
kernel pool inaccessible from usermode.
16. LPE VULNERABILITIES EXPLOITATION AFTER
UPDATES
• All this changes made exploitation more difficult. But there are few possible solutions. Gdi
is good, but not only exploitation approach.
• We still have user objects (window, cursor, menu etc) and we can still get their addresses!
i.e. we can use user objects in some exploits instead of gdi objects.
• Theoretically we can still use gdi objects (SURFOBJ): we can try to predict location of
object via spray.
• We can find additional vulnerability which will allow us to get gdi object address (we have
few ideas, but need some time to check them).