 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 address over there. Now I want to start by saying why am I doing this? So a year and a half ago I started getting into binary auditing and wanted to do static analysis and finding vulnerabilities and I found CTFs really enjoyable but at the same time they don't really represent three-word scenarios. So I decided to go for patch-diffing and finding one-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 I'm using two types of GDI objects to gain ring Z to exploit primitives. The next thing is analyzing two one-days MS-16098 and MS-17017 by using these techniques. Now the complex is pretty complex, I will try to simplify it as much as possible however there is a full white paper 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 into the juicy stuff is the kernel pool. You can think of the kernel pool as the heap memory that the Windows kernel uses. The first thing about the kernel pool is that any object allocated to the kernel pool will have a pool header attached to it. For 64-bit systems this header 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 1,000 bytes will be allocated to a pool page that has the size of 1,000 bytes so the kernel pool is effectively defragmented in 2,000 byte pages and the allocation dynamics work as following. 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 French way in the exploit development? First of all it is used to get the kernel pool memory in the deterministic state. The way it does it is by doing a series of allocations and the allocations. The series of the allocations is used to create memory holes that hopefully our vulnerable object will be allocated to as 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 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 integral overflows or integral overflows in general. So the first equation I want to talk about is ff ff ff 80 plus 81 will result in 1. Well that's not really the truth behind it. The truth is that it actually results in a much larger number 0 1 0 0 0 0 0 1. But x86 registers can only hold up to four bytes in memory. So this number is larger than four bytes max int and the most significant byte or d word or anything that is larger than four byte length will be truncated thus equals to one. The first part I want to address is linear overflows and this can be a result of mem copies with a larger size than the allocated object or a memory copying loop that is larger than the allocated object. So if an overflowed size was supplied to our location object it will 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 rights. So if you think of an overflowed size that will allocate a 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 the allocated object size. Now both of these 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 are we able to gain exploitation parameters out of these type of pool corruptions. And one of the things that I'm going to focus about is actually the abuse of GDI objects. Now there are certain objects that are allocated to current in memory that has some interesting characteristics that can give us some sort of memory reading and writing parameters. For example if we want to get a relative memory 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 this location. If we want to get arbitrary memory read and write the object has to have some sort of data pointer memory that if you can corrupt or control its value you'll be able to read and write from any location in memory of current in space. And if we look at the process of how this is done if we consider that we have two objects that are located 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 the amount of memory that it can read and basically going to the adjacent object's memory and then use the first object as a manager to actually overwrite the address of 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 expectation 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 scheme team and it was later heavily detailed by Nico Okonomo I hope I said that's right and Diego Juarez. The kernel the bitmap is represented in memory by a surf object and has a pool tag of GH question mark five 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 GLA five when it's allocated to the local side list which is outside of the stock and this is how the surf object structure looks in kernel memory so you'll notice that they're highlighted a couple of members which are interesting to us so first of all is the sizzle bitmap which represents the width and height of the bitmap so if you can corrupt any of these members you'll be able to effectively extend the size and gain relative memory read and write the other member is the PV scan zero which is a pointer to the bitmap data the way you can allocate bitmaps to memory is by calling create bitmap user mode function this takes a width a height the planes the bits per pixel and the 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 git bitmap bits these are all user mode functions you can call them from any application and the way you can write to bitmap memory is by using set bitmap bits so how do we exploit or abuse bitmaps basically if we 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 pool corruption that allows you to override the width of the height of the sizzle bitmap that effectively extends this bitmap to write into the adjacent bitmap memory and then we can use that as a manager and override the PV scan zero 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 I just had a conversation with KP 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 ODE technique and the way we address it or the object that we use is actually color pellets so color pellets are interesting objects they are presented in kernel memory by using the pellet or the XEPL object name and they have the pool tag of GH number eight or GLE eight 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 member interesting members to us so you find that the C entries member which represents the entries count of the pellet can be overwritten or extended which allow which gives us relative memory read and write primitive and the second member that we can abuse is the P first color pointer so this is a pointer to the array of colors of that color pellet which is highlighted in green and usually allocated by the end of the object so you can allocate GDI pellets by using the create pellet function that takes a logical pellet structure that contains the pellet entries as well as the pellet entry numbers and the pellet version and the pellet entries contain the RGB color value for each pellet you can free pellet objects from kernel memory by using the lead object and you can read pellet memory by using cat pellet memory cat pellet entries function from user mode and you have two functions to actually write to pellet memory in the kernel which are set pellet entries and animate pellet and we will look at the differences between them in a bit so how do you exploit pellets if we have a pool spray that results in two adjacent pellets 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 a specific pellet that will give us relative lead and write into the adjacent object which is another pellet we can abuse that by overwriting the P first color pointer and use the second pellet to lead and write from anywhere in kernel memory so there are some technical restrictions in regards to using color pellets in exploitation first of all the minimum pellet 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 set pellet entries function when you try to write to pellet memory using set pellet entries if you clover any of the current member any of these members it will block the writing to memory which effectively will result in either a blue screen of death or will result in arrowing out without actually writing to kernel memory so the first restriction in regards to set pellet entries when you call set pellet entries for user mode it will reach gre set pellet entries and then it will call xe pell object ul set entries as you see in the highlighted parts the pellet is actually checking for the P trans current and the P trans old which are the transformations that happen on that specific color pellet if any of these members are set it will try to access this memory location and then we'll try to end the value in it by zero so if these memory locations were set and not allocated it will arrow out without writing anything to memory the next restriction is that when you call set pellet entries and after the previous function was called it will actually try to access the HDC head member which presents the owner device context of the pellet if this value was set it will try to get the owner of the pellet 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 arrow out and not write anything the second restriction I want to talk about is about animate pellet so animate pellet has to have the pointer pointer 2 by P first color has to be of an odd value the first byte of it has to be of an odd value and we know the reason why thank you as dn said specifically animate pellet would only work on entries that has the pc reserve 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 represent any problems in x86 system since you can easily control where the pellet is and control the first byte of the pool memory to be an odd value however in 64 bit systems it proved to be a bit of a problem to set the first part of the address since it's always ff now we need to move on to the next step of exploitation what we need to do is we need to try to steal the system e process token and what this is is that each process that is running on your system is represented by an e process structure in kernel memory this structure contains very interesting members it contains a member such as an image name 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 active process links which is a double linked list that is actually pointing to the next e process entry in kernel memory and the unique process ID 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.164 bits and windows 7 sp1 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 a system process is first we need to get the address of the e process or the system's e process structure in memory and the way we can do this is actually there is an exported symbol called psrs system process so if you load the nto s kernel.exe into your program's memory and get its offset and subtract it from the base of the nto s kernel memory you'll get an offset that this specific entry is located in the kernel and then you can easily leak the nto s base kernel address from the drivers and then just add that this offset to it and you successfully got the system e process structure location from the kernel mode then we used the arbitrary read primitive that we got to actually read the token of the system process and move on to iterating over the active process links until the process current ID or the unique process ID represents the current process ID and use the arbitrary write primitive to just replace our current process token with the system one effectively gaining an elevated type privileges. The first exploit I want to talk about is actually ms17 or 17 well I really doubted that 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 or 13 as well but I'm 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 the function that is vulnerable is an unrealized brush and the type of the vulnerability is an integral overflow that leads to an out of bow right. 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 unrealized brush 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 integer checking mechanisms or integer checking functions um so I decided to look at the function itself at the first step to do that is to actually find a way to trigger that function from user mode so if you look the first function you need to call is create pattern brush and this will create a brush using a specific bitmap that you supply and then use a function petvlt 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 the code that is between this rectangle is actually expert from the exploit code itself and above code will reach this following Ida snippet 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 following calculations and then it will add 44 to it which obviously if you don't have checking leading to that function you can easily overflow but what happens on 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'll notice that it will leech the following code snippet or the code branch which is actually an allocation function so this overflowed integer can will be added to 40 again and then passed as the size value for an allocation function so if you remember we said that if you're able to influence the size of any allocation and overflow the integer into a smaller size then the allocation will result in a small allocation that is unexpected by the function itself or by the system so after the allocation happens we can try to trigger this a specific number of bytes that object will actually allocate so we need a 10 byte object to be allocated and we will know why 10 bytes specifically in the next slide so we know that the overflowed value is 1 0 0 0 0 0 0 10 and then we have to subtract 40 and 44 from it and we will reach the following number which is ff ff ff 8c and then if we take the result and look at the factors of that result the factors of that integer watch which represents which two numbers when multiplied together will actually result in that value we will 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 create the bitmap that will be used by the create pattern brush by having the width of 23 and a height of 1d4 1d4 1 I will effectively reach the allocation function with a controlled value of 10 bytes and then after the function allocates the object it assigns the address of the allocation to our ESI and the next step it takes is actually try to try 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 will 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 allocated 10 byte structure is that the last highlighted 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 the allocation 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 this object gets freed at the end of the function which if you could if you have it in the middle of a pool page it will effectively corrupt the next chunks header and that would be a problem when it gets freed at the end of the execution since it will the whole system will blue screen with a bad pool header value so why specifically 10 bytes object if you look at the calculation the located 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 asset to the bitmap height is 14 will result in 3c which is the same value that the 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 arbitrary read and write and it will work fine 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 do a bit of work and this is what we chose to go with and use the extended bitmap to actually extend an adjacent palette to gain relative read and write and demo how the relative read and write and pilots work and then use the extended palette to actually override the p-first color member of the asset and next palette and gain arbitrary corner read and write from there the first things is first so we need as I mentioned the object is allocated in the partner 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 that 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 an x 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 in 2000 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 till the pool memory becomes in a deterministic state which will leave an 18 byte unallocated memory at the end of the pool then we use the window class memory menu name which is available for this page session pool to allocate 18 byte strings that will fill in the unallocated 18 bytes memory then we freed our bitmap that we just allocated and continue to allocate an adjacent bitmap or a next bitmap of size 7f8 and then allocate pallets 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 you remember the calculations that if it tries to 3c when it has an adjacent bitmap it will actually extend the size of this bitmap so the adjacent when we look at the bitmap the adjacent bitmap in memory we'll notice that in the first part over the top part the size is 1a8 by 1 which is the width and height and after the overflow or the out of bound writes happened we notice that the size would be 1a8 and the height would be 6 effectively extending its size and it will effectively read past its bounds so the next step to do is to actually extend that bitmap object to read and write to the next adjacent pallet and change the c entries member from 1e3 which is the original size of the adjacent pallet to ff, ff, ff, ff effectively gaining relative read and write to 4 gigabytes of kernel memory so how do we find this manager pallet in the allocations so we have around 2000 pallets that are being allocated in memory how do I find the specific one that was extended is by looping looping over the get pallet entries function until one of the get pallet entries calls 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 pallet that will be used to actually overwrite the next pallet in memory so if we look at the next pallet in memory the top part is before we actually try to overwrite 2 and we will use set pallet entries on the manager pallet to actually set the p first color and update it to a value under our control so some of the data that we were reading using get pallet entries will contain actually some pool addresses that will allow us to leak some pool 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 pallet 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 or at 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 pallets using get pallet entries finding the first byte the pallet entry with the first byte of 35 which represents the number five 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 five so the first then we can use the extended pallet which we extended its size as a manager pallet and use it to set the p-first color of the adjacent pallet object of the worker pallet object and then use the worker pallet 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 this security token and then use a kernel write to 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 allocation functions to know to see where exactly if everything is 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 pallet bitmap and our manager pallet and the worker pallet in there I'm sorry if it's a bit fast all the videos would be available on the github page and then I modified the gdi object when debug extension to actually dump the structure from a pointer we can see the original bitmap size which was one and one a three and after the override we can see that the height of the bitmap changed to six next we view the pallet object that is adjacent to this bitmap to see if what changes happens in memory and we notice that its original size is one e three and then after we use set pallet entries to actually override its members we notice that the size will change from one e three to f f f f f and now if we take a look at the next pallet entry in memory we notice that the p first color member value is the default value or the original value and after we override the value using set pallet entries 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 p first color and if you look at the memory that is in that location we 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 successfully modified the header to a fixed one and this is going over the e process token stealing so if you look at the e process 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 a normal token or a low privileges user token after we use the arbitrary read and arbitrary write to actually replace our 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 will notice that we are actually system now so that's the first exploit I wanted to talk about so from a low privilege user I'm using gdi objects and I'm using gdi palettes to effectively gain system privileges on the system basically doing an elevation of privilege from a low privilege user the next exploit is ms 16 or 98 which is a region object affecting the region object and it's an integral overflows leading to a pool overflow if you look at the store by patch different we notice that the function you long multi is added to the fixed function which effectively checks if the two integral supply it will result in an overflowed value and then it will pass this value back to our location function that's the patched version the unpatched version though will multiply two some calculations on our register and then pass the value directly into our location function that will allocate that value so again how we reach this function if you look at that function syntax that is defined in Ida which is b-fill function we'll notice that it works on e-path objects so the way I did it was I just googled for msdm fill and path and I reached the function fill path so when I call fill path from user memory and I take the example code out of Ida I notice that 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 mj-fast-fill by analyzing this function I found out that it's actually checking the type of the device context that I'm doing this fill path in and turns out that it required a memory bitmap path of device context and this is the code that is used to actually reach the vulnerability function so the next step would be to control the location size so we know that the value is that these assembly instruction load effective address rix plus rx times 2 into acx is effectively multiplying this value by 3 and then shifting that this value by 4 or a nibble is effectively multiplying this value again by 60 so if we get the max int value and divide it by 3 and then add 1 to it so we can actually overflow it it will result in 5555556 and then to check if we multiply this value by 3 again we'll notice that the value will be 1 0 0 0 0 0 2 now that's before the shifting so after we shifted by 4 it will result in 1 0 0 0 0 0 0 20 and if you look at that value and you know that this exploit is actually affecting Windows 8 64 bit then you'll notice that this value will not overflow on 64 bit register however I noticed during my analysis of two exploits so far that if any some of the allocation functions when they're getting called the size is actually cast 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 I found a blog post by Nicholas Economo which was great it was for ms16 or 39 and the exploit code itself or the fun 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 polyline 2 and supplying a point array calling this function 156 times with 3f e01 points will result in a controlled value being allocated in kernel memory so if you multiply the two numbers it will result in 555556 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 10000005 and after it gets shifted by a nibble this value will be 50 and the one will be truncated we do our pool function and the exact same thing as the last exploit so we create we allocate a 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 of a function that I can abuse like the menu name to actually allocate and deallocate small size objects so I went with a weird way with the next step allocating two accelerator objects which have a thick size of 40 bytes and then unallocate the bitmap and allocate a region object of size bc0 now this is just padding we don't actually need this object but if you allocate the bitmap adjacent to our vulnerable object directly it will actually the overflow will not result in overwriting any of the interesting numbers 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 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 the region 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 can do anything the function responsible for copying points is bconstruct get and it goes add edge to get this function will actually cast the previous point dot y to r10 and the current point dot y to r11 then it will check the current point dot y against a certain value which on my system was one f0 and it proved to be working in all systems now this value is actually a shifted value by four so the current point dot y will be shifted by four and then compared to this value if the value was more than the comparison results in a value more than the one f0 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 decimals which is 14 hex if shifted by four equals one for zero which is less than one f0 so until we hit a specific point of the polyline two loop which is one f 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 sizzle bitmap is actually one and 52 and after the overflow happens the sizzle bitmap is one and f f f f effectively extending its size and where this value comes from is actually the same function that copies the point will subtract the previous point at y from the current point at y and if it was signed if it was unsigned it will write one to that offset and if it was signed it will write f f f f to a second offset we'll again loop over gitmap bits this time to find our worker and luckily enough the next handle was the worker or the next bitmap in memory and we get some of the addresses that are leaked using git bitmap bits and from them calculate the offsets or the addresses of the overflow in objects so we can fix their headers and then we can use set bitmap bits on the manager to actually set the previous can zero of the worker and use the worker bitmap to write to anywhere in memory arbitrary then write and then we use this to fix the bitmap and the region object overflow the headers and ultimately steal the system token and this is the video of it happening so we again we're using a no 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 ascii art so we stay black like this now we break at our debugger we see that actually we are just before the the vulnerable function or triggering the integral overflow so we break at location and after the location after the right and we continue execution we'll notice that at the location we control the value and we'll be able to allocate a 50 byte object and try to copy around five gigs of points to it which will result in direct overflow but luckily we found a way to actually control the overflow as explained earlier and if you look at the layout of the pool after the location we'll notice that it's the same layer that was shown previously and we have our allocated object the manager bitmap and the worker bitmap and we use the great gdi object uh dump extension after modification to actually dump these bitmaps from memory so we can see the structures clearly we see that the manager bitmap scissor bitmap was sizes one and 52 and after the overflow or the point copying we find that the size is now one and f f f f f effectively extending the bitmap reading or writing functionality to four 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 object pvscan0 this is the original pvscan0 of the worker bitmap and after we use set bitmap bits we're able to override it with the value that we control pointing to one of the clobbered headers of the bitmap origin 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 bitmap bits to actually read a proper header and fix the object's header and then if we continue execution we reach the part where we're stealing the system token and now we verify that it's actually a system token and not any process and this is the token value then we go into finding our current process e process structuring memory and we use the arbitrary kernel memory read and write to actually override 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 and go back to our virtual machine to find that we are system so the conclusions of this talk that we have not only one but i knew this undisclosed technique to gdi objects that we can abuse to gain arbitrary kernel memory read and write and abuse kernel pool corruptions we can identify hopefully and exploit the same type of vulnerabilities in kernel and in any other objects and the tools used in this talk was aida bindiff windebug and vmware and guys you can get a hold 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 there's not enough time to take questions on stage so i'll be heading to the chillout lounge just next to this room if you guys have any questions or have any suggestions please um i got me catching there thank you