- Currently it’s known that we can create PALETTE objects in the large session pool, and we can leak their address.
- We can allocate two PALETTE objects, one after the other, and even without spraying, they will be close enough (<0x1000000 bytes far) to each other - this came from my testing, and running this many times
- If we have a write - where vulnerability (where we can't control what we write), we can use that to modify the size of the PALETTE object by modifying 1 byte in the cEntries field, the only requirement is that we can precisely set the location, and it should be something other than 0. We will target the location marked with ** below:
- Luckily the 7 bytes before and 8 bytes after that field are not so important, so if we smash them we will not cause a BSOD and we can continue to use the object. Essentially the following fields marked with red (also in the above memdump) in the PALETTE structure won't cause an issue if we overwrite them (anything before or after will cause a BSOD):
- With modifying that byte to anything other then 0, we increased the size of our PALETTE to > 4 * 0x1000000, which means that if we have another one nearby (and as we saw at step 2 we can have), we can write to it with out-of-bound writes
- We overwrite the pFirstColor pointer of the 2nd PALETTE to point to our original PALETTE’s pFirstColor memory location, thus achieving a classic GDI read / write primitive —> We achieved arbitrary kernel read / write
0: kd> dd fffff8cc44dc4000
fffff8cc`44dc4000 fe0809ec ffffffff 00000000 00000000
fffff8cc`44dc4010 26986580 ffffd687 00000501 **0003de
fffff8cc`44dc4020 0096f8aa 00000000 00000000 00000000
fffff8cc`44dc4030 00000000 00000000 00000000 00000000
fffff8cc`44dc4040 00000000 00000000 00000000 00000000
fffff8cc`44dc4050 00000000 00000000 00000000 00000000
fffff8cc`44dc4060 00000002 00000001 00000000 00000000
fffff8cc`44dc4070 00000000 00000000 44dc4088 fffff8cc
BASEOBJECT64 BaseObject; // 0x00
FLONG flPal; // 0x18
ULONG32 cEntries; // 0x1C
ULONG32 ulTime; // 0x20
HDC hdcHead; // 0x24
ULONG64 hSelected; // 0x28,
FLONG flPal; // 0x18
ULONG32 cEntries; // 0x1C
ULONG32 ulTime; // 0x20
HDC hdcHead; // 0x24
ULONG64 hSelected; // 0x28,
This will also work if we have another type of vulnerability where we can decrement / increment a value at a memory location of our choice, we can achieve the same. We locate the byte above (**) as a target for decrementing or incrementing, we achieved the same.
Limitations:
Limitations:
- The PALETTE itself, it won't work beyond Win10 RS3
- If the write what we don't control is larger than 0x10 bytes, this can't be used as we overwrite other fields that will cause a BSOD