Hey guys, so. Today, I will try to Demystify Windows Kernel Exploitation by Abusing GDI Objects. My name is Saif. I’m Egyptian and I work for Sensepost. That’s the Egyptian traditional dress over there. Now I want to start by saying why am I doing this so um, a year and a half ago I started getting into binary auditing and wanted to do static analysis and finding vulnerabilities. And I found CTF’s really enjoyable but as- at the same time they don’t really present real world scenarios. So I decided to go for patch diffing and finding 1 days. And the result was epic and I hope you guys like it through the talk. So what we will learn through this talk is first Abusing two types of GDI Objects, to gain ring zero exploit primitives. The next thing is analyzing two one days MS16-098, MS17-017 by using this techniques. Now the complex is pretty complex, um I will try to simplify it as much as possible; however, there is a full white paper um and the slides and the exploit code and everything that is up on GitHub at the moment. You can access it on that link. The first thing that I have to talk about before we get- get into the true stuff is the kernel pool. You can think of the kernel pool as the heap memory fo- that the Windows kernel uses. The first thing that the kernel pool that, is that any object that allocated to the pool will have a size a pool header attached to it. For 64 bit systems this headers is 8 bytes in size and for 86 bit systems this header is 8 bytes in size. The next thing is that small allocations, or allocations smaller than thousand bytes will be allocated to a pool page that has the size of one thousand bytes. So the kernel pool is effectively different mented into two thousand byte pages. And the allocation dynamics works as followings. SO the first allocation will be allocated from the beginning of the page. Subsequent allocations will be allocated by the end of the page. The next thing I want to talk about is kernel pool spraying. Why do we do kernel pool spraying or feng-shui in the exploit development? First of all it is used to get the pu- kernel pool memory in deterministic state. The way it does it is by doing a series of allocations and deallocations. The series of deallocations is used to create memory holes between that hopefully our vulnerable object will be allocated too. And thus having our vulnerable object allocated in a space between objects under our control that we can abuse to gain an extra exploit primitive or a- an extra access to the memory next to it. The next thing I want to follow through is kernel pool corruption. And we will focus about x86 integer overflows or integer overflows in general. So, the first equation to talk about is FFFFFF 80 plus 81 will result in 1. While that’s not really the truth behind it. The truth is that it actually results in a much larger number 01000001. But x86 registers can only hold up to 4 bytes in memory. So this number is larger than 4 bytes max int and the most significant byte or D word anything that is larger than four byte will then be truncated, thus equals to one. First part I want to address is linear overflows. And this can be a result of mem copies with a larger size than the located object or a memory copying group that is larger than the allocated object. So if an overflowed size will supply the location object it would result in a very small object being allocated and then a memory copying loop or a memory copying function will try to copy a large number of data to that small sized allocation. Effectively overflowing the next object in memory with the amount of bytes that it tries to copy. The next one is out of bounds writes. So if you think of an overflowed size that will allocate the smaller object and then the function expects that object to be of a certain size and tries to write to a certain offset of it, it will effectively write this object or this data in an out of bounds location from that location of the allocated size. Now both of these you will see how we can exploit them when we get to the exploitation part of the one days And now I want to talk about how I was able to gain exploitation primitives out of these type of com- pool corruptions. And one of the things that we I’m gonna focus about is actually the abuse of GDI objects. Now there are certain objects that are allocated to kernel memory that has some interesting characteristics that can give us some sort of memory reading writing primitives For example, if we want to get a relative number read and write. Which is basically reading and writing in the memory location adjacent or relative to the object location in memory. The object that can be abused has to have a size member that can be extended to be able to access out of bounds memory adjacent to it’s location. If you want to get arbitrary memory read and write the object has to have some sort of data point in memory that if you can corrupt or control its value you will be able to read and write from any location in memory of kernel read space. And if you look at the process of who this is done. If you consider that we have two objects that are allocated adjacent to each other and these objects both have a size member and a data pointer member We can use the first object or any pool corruption primitive to actually corrupt the size of the first object. Thus extending that, that amount of memory that it can read and basically go into the adjacents object’s memory and then use the first object as a manager to actually overwrite the address or the data pointer of the second object and use the second object as a worker to read and write from any point in memory. Now this exploitation technique can be used in kernel and is heavily used in browsers as well. The first of these objects that can be abused is the bitmaps. Now GDI bitmaps techniques have been there from 2015. So the first people who talked about it was Ski Team and it was later heavily detailed by eh Nico Kimono I hope I said this right and Diego Juarez. Um, the kernel, the bitmap is presented in memory by a surf object and has a pool tag of GH question mark 5 which represents a number that differs from one system to another. So this can be zero or one or two depending on the version of Windows or Gla5 when its allocated the look inside list which is outside of this talk. And uh this is how the surf object structure looks in kernel memory. So you notice that I highlighted a couple of numbers which are interesting to us. First of all is the sizlmitmap which represents the width and height of the bitmap. So if you can corrupt any of these numbers you’d be able to effectively extend the size and gain relative memory to read and write. The other number the pvScan0 which is a pointer to the bitmap data. The way you can allocate bitmaps to memory is by calling create bitmap user mode function. The- This takes the width, a height, the planes, bitsperpixel and bits of the bitmap and allocates a bitmap in memory. The way you can Free bitmaps is by calling delete object. The next point is the way you can read the bitmap memory is by using GetBitmapBits. These are all user mode functions, you can code them from any application. And the way you can write to bitmap memory is by using SetBitMapBits. So how do you exploit or abuse Bitmaps? Basically, if you consider that we have two bitmaps that are allocated adjacent to each other as a result of our kernel pool spray. You, if you have a pull corruption that allows you to overwrite the width or the height of a sizlBitmap; that effectively extends this bitmap to write into the adjacent Bitmap memory and then we can use that as a manager and overwrite the pvScan0 of the second bitmap and then we’re able to read and write from any point in memory. The next thing I want to discuss is an undisclosed technique that has not been discussed anymore, anywhere. Um, I just had that conversation with Scabi about it and he mentioned that they have seen some in the wild but it has not been documented anyway, so this is effectively sort of an 0hday technique. And the way we are, the way we address it, or the object that we use is actually color palettes. So color palettes are interesting objects they are presented in kernel memory by using the palette or the XEPAL object name and the have the PoolTag of Gh number 8 or Gla8. This is the x86 structure of the object. And this is the 64 bit structure of the object. Now, the members highlighted are in red are the interested, numb- interesting members to us. So you find that the cEntries member which represents the entries count of the palette can be overwritten or extended uh which allow, which gives us relative memory read and write primitive. And the second number that we can abuse is the pFirstColor pointer. So this is a pointer to the array of colors of that color palette which is highlighted in green and usually allocated by the end of the object. So, you can allocate GDI palettes by using the KA palette function that takes a logical palette structure that contains the palette entries as well as the palette ah, un, entry numbers and the palette version and the palette entries contain the RGB color value for each palette. You can free palette objects from kernel memory by using delete object. And you can read palette memory by using get palette memory get palette entries function from user mode and you have two functions to actually write to uh to palette memory in the kernel which are SetPaletteEntries and AnimatePalette and we will look at the difference- differences between them in a bit. So how do you exploit palettes? If we have a pool spray that results in two adjacent palettes be- allocated in memory and we have a pool corruption primitives that allows us to actually increase or extend the size or the number of entries of the specific palette that will give us relative read and write into the adjacent object which is another palette. We can abuse that by overwriting the pFirstcolor pointer and use the second palette to read and write from anywhere in kernel memory. So there are some technique restrictions in regards to using color palettes in exploitation. First of all the minimum palette allocation size for x86 system is 98 bytes and D8 bytes for x64 ones. So when you corrupt the c entries member it has to be larger than these values. The next restriction is related to setpaletteentries function when you try to write to palette memory using setpaletteentries if you clobber any of the fuc- the current member any of these members it will block the writing to memory which effectively will result in a blue screen of death or will result in erroring out without actually writing to kernel memory. So the first restriction in regards to SetPaletteEntries when you call SetPaletteEntries from user mode it will reach GRESetPaletteEntries and then it will call XEPAL object ulSetEntries and you see in the highlighted parts the palette is actually checking for the pTransCurrent and the pTransOld which are the transformations that happen on the specific color palette. If any of these members are set it will try to access this memory location and then will try to end the value in it by zero. So if these member notifications were set and not allocated it will error out without writing anything to memory. The next restriction is that when you call SetPaletteEntries and after the previous function was called it will actually try to access the hdcHead number which presents the owner context of the palette, if this value was set, it would try to get the owner of the palette to set its value in the device context. Now this will effectively result in a blue screen of death which will kill the whole system and not error out and not write anything. The second restriction I want to talk about is about AnimatePalette. So AnimatePalette has to have the pointer pointed to pFirstColor has to be of an odd value, the first byte of it, has to be an odd value. And we know the reason why, thank you MSDN, said specifically that AnimatePalette would only work on entries that has the PC_Reserved flag set and that flag is effectively one so that’s why you can see highlighted there that the function tries to test for one before writing. Now this didn’t really present any problems in eight- actually six systems since you could easily control where the palette is and control the first byte of the pulled memory to be an odd value, however in 64 bit systems it proved to be a bit of a problem set the first um part of the address since it’s always FF. [sighs] Now we need to move on to the next step of exploitation. What we need to do is we need to try to steal a system Eprocess Token and what this is is that each process that is running on the system is represented by an Eprocess structure in kernel memory, this structure contains very interested members. It contains a member such as an ImageName which is the exe name and it contains a token. The token is the most interesting part of it since this token represents the security permission that this process has. Also it has a member that is the ActiveProcessLinks which is a double link list that is actually pointing to the next Eprocess entry in kernel memory, and the UniqueProcessID which is the PID of the current process. The offsets to these members differs from one system to another, and specifically for this talk we’ll be covering Windows 8 point 1 64 bits, and Windows 7 SP1 at- for X86 Bits and these are the offsets to these members. And the game plan we have to actually exploit this or get the system token of the system process is first we need to get the address of the eprocess, or the system’s eprocess structure in memory. And the way we can do this is actually there’s an exported symbol called PSInitialSystemProcess, so if you load then TOS kernel into TOXE into your program’s memory and get its offset and subtract it from the base of the NTOS kernel memory, you’ll get an offset that this specific entry is located in the kernel and then you can easily leak the NTOS base kernel address from the drivers and then just add that this offset to it and successfully you clogged the system EProcess structure location from the kernel mode. Then we use the Arbitrary read primitive that we got to actually read the token of the system process and move on to iterating over the ActiveProcessLinks until the process current ID or the UniqueProcessID represents the CurrentProcessID and use the Arbitrary write primitive to just replace our Current Process Token with the system one effectively gaining an innovative type privileges. The first exploit I want to talk about is actually MS17-017 while I read of the death I don’t know if that’s true, um Microsoft has actually released it back in March um and that’s the patch that I reversed but it can be MS17-013 as well, but I am not very sure about it. It affects um all versions of Windows but um I found it very difficult to exploit it on 64 bit ones um so I was only able to exploit it on Windows Sp1 X86 and it tri- the function that is vulnerable is ENGRealizeBrush and the type of the vulnerability is an Integer overflow that leads to an Out Of Bounds Write. First of all, the first step that I took to analyze this kind of exploit is to actually diff the patch that was released. It was released back in March 2017. This is the function that is uh vulnerable which is ENGRealizeBrush and this is the patch. So it was very difficult to find out where the problem actually is as you can see there were many changes, all of the changes were related to some integral checking mechanisms, or integral checking functions um so I decided to look at the function itself, and the first step to do that is actually find a way to trigger that function from user mode. So if you look, the first function you need to call is CreatePatternBrush and this will create a brush using a specific bitmap that you supplied, and then use the function PatBlt which actually writes the brush pattern to a specific path in memory. And then this will lead effectively to that function. So the way you do it in code in C code is this, this is actually an expert of the exploit code so in the future any of that th- uh code that is between this uh tangle is actually expert from exploit code itself. And the above code will reach this following Ida snipped with a controlled value in edi. The first step that this code will do is actually get the value of edi, which is the bitmap width. And then it will get ecx and multiply it with this value, which is at the time is 20, and this can be controlled by the bitmap format, and then it will divide this value by 8, and then it will multiply both values, the width and the height after the formula calculations and then it will add 4- 44 to it, which obviously if you don’t have checking leading to that function you can easily overflow but what happens in the overflowed function? So when I overflow the integer what will happen later? Is the most important part. So if you notice- if you follow the instructions of what happened with this overflowed integer you notice that it will leach the following code snippet, or the code branch, which is actually an location function. So this overflowed integer ca- will be added to 40 again and then passed as the size value for our location function, so if you remember we said that if you’re able to influence the size of any location, and overflow the integer into a smaller size, then the location will result in a smooth location that is unexpected by the function itself, or by the system. So after that location happens. We can try to trigger this, a specific number of bytes that the object will actually allocate. So we need a 10 byte object to be allocated and we know why 10 bytes specifically in the late- next slide. So we know that the overflowed value is 1000000 10 and then we have to subtract 40 and 44 from it and we will reach the following number which is FFFFFF8C and then if you take the result and look at the factors of that result- the factors of that integer watch- which- presents- which two numbers when multiplied together will actually result in that value we’ll uh we’ll come out to 8C and 1D4 1D4 1. If we take 8C as the width and effectively reverse the calculations that happened in the previous slide by multiplying it by 8 and then dividing it by 20 will result in 23. So if I take this and carry the bitmap that will be used by the CreatePatternBrush by having the width of 23 and a height of 1D4 1D4 1, I will effectively leach that location function with the locator uh with the controlled value of 10 bytes. And then after the fe- uh the function allocates the object it assigns the address of the location to the esi and the next step it takes is actually try to re- to write to certain offsets of esi. So the function is expecting esi to be of a certain size, hopefully minimum of 84 since if you supplied zero it would be added to 40 and then 44 and it will become an 84 byte structure. So what happens when we overflow it with a 10- when we actually allocate a 10 byte structure is that the lost highlighted uh in blue value will actually write to an out of bounds offset of the object, so esi plus 3C is actually out of bounds, since that location size is 10 bytes and it gets added to a pool header of 8 bytes which makes it 18 bytes so esi plus 3c will actually write to the next object in memory. The problem is that this object actually is allocated at the end of the page uh this object gets freed at the end of the function which if you c- if you have it in the middle of a pool page it will effectively corrupt the next chunk’s header and that will be a problem when it gets freed at the end of the execution since it will de- di- the whole system will use screen with a bad pool header value. So why specifically 10 bytes object? If you look at the calculation, the allocated object size is 10, and then the bitmap pool header if it’s an adjacent bitmap is 8 bytes and then the bitmap or the surf object starts with a base object of 10 bytes and the offset to the bitmap height is 14 will result in 3C which is the same value that it application tries to write to. So now we have three options, we can use this extended size bitmap to actually override the address of an adjacent bitmap which is the old technique and gain the ability to read and write and it will work find uh and then we can gain system. We can use the extended bitmap to demonstrate the arbitrary read and write capability of a palette object or we can bi- do bit of work and this is what we are chose to go with and use the extended bitmap to actually extend an adjacent pallet to gain relative read and write and demo how the relative read and write impacts work and then use the extended palette to actually override the pFirstColor member of this next palette and gain arbitrary kernel read and write from there. The first thing is first so we need- as I mentioned the object is allocated in the perner eh- in if the object was allocated in the middle of a pool page, then when the object gets freed at the end of the function the system will blue screen of death. So how do we get over that is by allocating the object at the end of the page, so when the object gets freed there is not a next chunk header and the pool will not- pool checking functions will not be able to check the next pool header and thus the free will work normally and the application or the system will not crash. And the first thing we need to do is, we know that the pool pages are separated into 1000 bytes each and we need- we know that our object will be in total 18 bytes, 10 bytes for the object that we supply, and 8 bytes for the pool header So we allocate a bitmap of size FE8 which will leave. We allocate around 2000 of these til the puh- the pool memory becomes in a domestic state which will leave an 18 byte unallocated memory at the end of the pool. Then we use the window class memory uh menu name which is available for the page session pool to allocate 18 byte strings that will fill in the unallocated 18 bytes memory. Then we freed the bitmap that we just allocated and continue to allocate an adjacent bitmap or a next bitmap of size 7F8 and then allocate palettes of sizes 7e8 effectively filling the 1000 page- or the 1000 byte pool page with our controlled objects. Then we free some of the 18 byte menu names that we allocated and hopefully if everything worked we should find our object allocated at the end of the pool page as we see in front of you. So now the object is allocated in the end of the pool page, when the function frees the object, it will free it fine, and also we have an adjacent bitmap and if we remember the calculations that if it’s right with 3c when it has an adjacent bitmap it will actually extend the size of this bitmap. So the adjacent- when we look at the uh bitmap adjacent bitmap in memory we’ll notice that in the first part, or in the top part, the size is 18, 1A8 by 1 which is the width and height and after that overflow or the out of bounds rights happen we noticed that the size would be 1A8 and the height would be 6 effectively extending the size and it will effectively read past it’s bounds. So the next step to do is to actually extend that bitmap object to read and write to the next adjacent palette and change the c entries member from 1e3 which is the original size of the adjacent palette to FFFFFFFF effectively gaining relative read and write to 4 gigabytes of kernel memory. So how do we find this manager palette in the allocations? So we have two tho- around two thousand palettes that are being allocated in memory, how do I found the specific one that was extended? Is by roofing- looping over that get Palette entries function until one of the getpalette entries codes will result in the return value of a larger number than expected which is the size of 1e3 so until we find one that returns a number like larger than 388 that’s our manager palette, that will be used to actually overwrite the next palette in memory. So if we look at the next palette in memory, the top part is before we actually try to overwrite to and we will use SetPaletteEntries on the manager palette to actually set the pfirstColor and update it to our value under our control. So some of the data that we were reading using getpalette entries will contain actually some pool addresses. That will allow us to leak some pull addresses and calculate from it a header address from one of them which is the beginning of the pool page. So if we change the palette entries of one of the pool pages to the beginning of a pool page effectively pointing to the bitmap header, since we need to get this header to actually fix the bitmap object, because if we leave it as is, by the time we finish the execution that system will crash because there were pool headers that were corrupted. So the way we can find it is again by looping over our allocated palettes using getpalette entries, finding the first byte- the palette entry with the first byte of 35 which represents the number 5 and if you remember the bitmap object has a tag of GH5 which is part of the pool header, so the first byte of that object will be actually 5. So the first- then we can use an extended palette which we extended the size as a manager palette and use it to set the pFirstColor of the adjacent palette object, of the worker palette object, and then use the worker palette object to actually gain kernel- arbitrary kernel read and write. So the next step would be to use these primitives to actually read and change the current process token privileges. So we start by getting the initial system process and as I explained earlier calculating the address of this kernel system process and then using the arbitrary read to read the security token and then use a kernel writer replace our own and we will see now directly exactly how this happened. So we start by using a low privilege user. And I’ve put in the code some debug breaks so when we execute the code it will actually break on kernel memory, we just reload our symbols again. And we find our place. So on the right is our code, we trigger the overflow and break on the location functions to- to see where exactly if everything went right and you can see the pool layout went correct so we have our object allocated at the end and we have an extended palette and our bitmap and our manager palette and the worker palette in there. I’m sorry if it’s a bit fast, all the videos will be available on the GitHub page. And then I modified the gdi object dump window bug extension to actually dump this structure from a pointer, we can see the original bitmap size which was 1 and 1e3 and after the overwrite we can see that the height of the bitmap changed to 6. Next we view the palette object that is adjacent to this bitmap to see if what changes happen in memory. And we notice that it’s original size is 1e3 and then after we use SetPaletteEntries to actually overwrite its members we notice that the size will change from 1e3 to FFFFFF and now if we take a look at the next palette entry in memory we notice that the pFirstColor member value is the default value of the original value and after we overwrite the values using SetPaletteEntries, the value has changed pointing to a beginning of a page or a bitmap object. And if we dump the memory that is located at this location, now this is the updated pfirstColor and if we look at the memory that is in that location we’ll notice an original bit- this is the clobbered bitmap header and we already read the original bitmap header and after we write to it we have successfully modified the header to our fixed one, and this is going over the eprocess token stealing so if you look at the eprocess structure that is saved in our code and dump the image file name and token we see that this is actually a system process and that this token is the system token. If we move on to get our current process itself we notice that the process name is exactly our exploit name and the token is uh normal token or a no- low privileges user token. After we use the arbitrary read and arbitrary write to actually replace our- uh our current process token with a system one this means that we successfully actually got system privileges and when we continue execution and go back to our virtual machine when we’ll notice that we’re actually system now. So that’s the first exploit I want to talk about so from a low privilege user abusing gdi objects and abusing gdi palettes to effectively gain system privileges on a system basically doing a revision of privilege on- from a low privilege user. The next exploit is MS16-098 which is a region ob- affecting the region object and it’s an int- integer overflow leading to a pool overflow. If you look at the start by patch diffing we notice that the function UlongMulti is added to the fixed function which effectively checks if the 2 integers supplied will result in an overflowed value, and then it will pass this value back to our allocation function, that’s the patched version. The unpatched version though will multi- do some calculations on our register and then pass the value directly to our allocation function that will allocate that value. So again how we reach this function? If we look at the function sign ticks that is defined in Ida which is differ function we notice that it works on epath objects. So the way I did it was I just Googled for MSDN fill and path and I reached a function fillpath. So when I call fillpath from user memory and I take the example code out of Ida I look as if I’m not actually hitting the function that I’m supposed to hit, but instead I’m hitting the first function of the series which is EngFastFill. By analyzing this function I found out that it’s actually checking the type of the device context that I’m doing this fillpath in and turns out that it required a memory bitmap path ob- uh device context. And this is the code that is used to actually reach the vulnerable function. So the next step would be to control the location size. So we know that the value is that these instruction load effective address rax plus rax times 2 into ecx is effectively multiplying this value by 3 and then shifting the- this value by 4 or enable is act- effectively multiplying this value again by 16. So if we get the max end value and divide it by 3 and then add 1 to it so we can actually overflow it it will reshu- result in 5555555 6 and then to check if we multiply this value by 3 again we’ll notice that the value will be 100000 2, now that’s before the shifting, so after we shifted by 4 it will result in 10000000 20 and if you look at that value and you know that this exploit is actually affecting Windows 8 64bit then you notice that this value will not overflow at 64 bit register however I notice during my analysis of 2 exploits so far that if any- some of the allocation functions who end up getting called, the size is actually s- uh casted into a 32 bit register before the allocation effectively truncating its value. So this value will be 20 which will be supplied to the allocation. Now how can we actually control this allocation size? Well a fun to- uh book was by Nicholas Kimono which was great uh it was for MS16 039 um and the exploit code itself or the func- the vulnerable function looks to be exactly copy pasted from the current function I was analyzing and he pointed out that the number of points in a given path is what- what actually controls this allocation value. So how can I control the number of points in a path? By using the user mode function PolyLineTo and supplying a point array. Calling this function 156 times with 3 FE01 points will result in a controlled value being allocated in kernel memory so if you multiplied the two numbers it will result in 55555 6 now someone will tell me this is much smaller than the value that we discussed during the calculations, and you are right. And due to the shifting of 4, this value will actually the- result in 1000000 5 and after it gets shifted by enable this value will be 50 and the 1 will be truncated. We do our pool feng shui and the exact same thing as the last exploit so we cate- we allocated uh large size bitmap and you notice that this time I left an allocated space of 80, the reason being at that time I didn’t know a function that I can abuse like the menu name to actually allocate and deallocate small sized objects so I went uh with a weird way with the next step allocating 2 accelerator objects which have a fixed size of 40 bytes and then I allocate the bitmap and allocate a region object of size BC0, now this is just padding, we don’t actually need this object, but if we allocate the bitmap adjacent to our- our vulnerable object directly it will actually uh the overflow will not result in overwriting any of the interesting members that we find. And then we allocate the space that is left with 3C0 with our bitmap and free our accelerator tables and hopefully if everything went right, we should find the following pool layout which shows uh that our object is allocated at the end of a pool page so when the object is freed it will not crash the system and the bitmap and original object is adjacent to it. So we needed to control the overflow since if we overwrite this large number of points to a small allocation size it will actually blue screen of the system faster than we than we can do anything. The function responsible for copying points is bContructGET and it calls out addEdgeToGet, this function will actually cast the previous Point dot Y to R 10 and the current point dot Y to R 11. Then it will check the current point dot Y against a certain value which on my system was 1F0 and it proved to be working on all systems. Now this value is actually a shifted value by 4. So that current point dot Y will be shifted by 4 and then compared to this value, if the value was more than the- the comparison results in a value more than the 1F0 then it will not copy the point, if it’s less than it will copy the point, and this gives us a primitive to actually control how many points are copied to memory, thus controlling the overflow number. So the way we can control it is by actually setting in our point array, the third point to 20 decimal which is 14 hex shifted by 4 equals 1, 4, 0 which is less than 1F0 so until we hit a specific point of the pointing line to loop which is 1F iterations, that will copy exactly the number of points needed to overflow the bitmap height and width. So before the overflow on the top we can see that the system bitmap is actually um 1 and 52 and after the overflow happens the system bitmap is 1 and FFFF effectively extending its size and where this value comes from is actually the same function that copies the point will subtract the previous point dot Y from the current point dot Y and if it was signed- if it was unsigned it will write 1 to that offset, and if it was signed it will write FFFF to a second offset. We’ll again loop over GetBitmaps this time to find our worker and luckily enough the next hand in was the worker or the next bitmap in memory. And we get some of the addresses that are leaked using Get bit- GetBitmapbits and from them calculate the offsets or the addresses of the overflown objects so we can fix their headers and then we can use set bitmap bits on the manager to actually set the previous scan 0 of the worker and use the worker bitmap to write to anywhere in memory arbitrary read and write, and then we use this to fix the bitmap or- and the region object overflow headers and ultimately steal the system token and this is the video of it happening. So we again we’re using uh low privilege user and we have debugger breakpoints set in our exploit code, we run our exploit, then at this point I didn’t know so much SCR so we stay black like this [laughter] [clears throat] now we break at our debugger, we see that actually we are just before the the vulnerable function or triggering the integer overflow. So we break at the allocation and after the allocation, after the write, and we’ll continue execution, we’ll notice that at the allocation we control the value and we’ll be able to allocate a 50 byte object and try to copy around 5 gigs of points to it which will result in byte overflow but luckily we found a way to actually control the overflow as I explained earlier and if you look at the layout of the pool after the allocation we’ll notice that it’s the same layer that was shown previously and we have a allocated object, the manager bitmap, and the worker bitmap. And we use the gray GDI object uh dump extension after litigation to actually dump these bitmaps from memory so we can see the structures clearly we see that the manager bitmap, sizlbitmap was size is 1 and 52 and after the overflow or the point copying we find that the size is now 1 and FFFFFFFF effectively extending the bitmap reading or writing functionality to 4 gigs of kernel memory and then we continue execution and we can see that we can use this manager bitmap to actually override an adjacent bitmap objects pvscan0 this is the original pvscan0 of the worker bitmap and after we use the bitmap bits we’re able to overwrite it with a value that we control pointing to one of the clobbered headers of the bitmap or region objects and if we dump the memory we’ll see that this value of the header is actually clobbered and not a valid header and then we use the leak addresses and the read getbitmapbits to actually read a proper header and fix that object’s header and then if we continue execution we reach the part where we’re stealing the system’s token. And now we verify that it’s actually a system token and not an eprocess. And this is the token value, then we go into finding our current process, Eprocess structure in memory. And we use the arbitrary kernel memory read and write to actually overwrite this value with a system process token and we verify that our current process was actually overwritten by a system process token and we just continue execution [bumps microphone] And go back to our virtual machine to find that real system [applause] So the conclusions of this talk that we have not only 1 but a new dis- undisclosed technique to GDI objects that we can abuse to gain arbitrary kernel memory read and write. And abuse per- kernel pool corruptions we can identify hopefully and exploit the same type of vulnerabilities in kernel and any other objects and the tools used in this talk was Ida, BinDiff, WinDBg, and VMware and guys you can get ahold of me at that my email or my Twitter handle and if you have any questions, modifications, suggestions, or if you ever find Diego Juarez because I really would like to meet him uhm there’s not enough time to take questions on stage so I’ll be heading to the chill out lounge just next to this room if you guys have any questions or have any suggestions please um get me- catch me there, thank you! [applause]