
researcher pen test and basically I'm a big kids who likes playing with stuff I should say that this thing feeds when you jumped on sort of played a musical note and anyone who walks past that without jumping on they got something wrong with them okay so what I'm going to talk about today I briefly explained what I mean by object-orientated exploitation and then I'm going to look at kind of a specific area of that which is object corruption and how that relates to some of the various mitigations that Microsoft would have introduced in Windows to try and prevent exploits from succeeding I'm going to talk through to new techniques which bypass two of these mitigations
and but first I'm going to talk about the theory behind those techniques and then sort of putting them all together into a proof-of-concept exploit okay so object-orientated exploitation what do I mean by that I'm sure hopefully lots of you have heard of object injection you know there's been quite a lot of activity in both PHP and Java recently with with you know these vulnerabilities and also there's another area which is quite closely associated which I've called object corruption which happens within sort of native C++ applications and until recently it was incredibly easy to exploit so we wouldn't really talk much about it but an object comes becomes corrupted in sort of one of several scenarios so you
get type confusion vulnerabilities where basically the application becomes confused about what type and object is or use after free which is when you free an object and replace it with some other object or data and also the vast majority of exploits at least until recently would essentially target object corruption as a way to gain code execution so I guess the main difference between objects injection and object corruption is that in objects injection you're injecting a new object into the process or application whereas in object corruption you're corrupting an existing object there's a number of sand Rio's basically where we don't you know corrupt the object completely we might only you know partially corrupt it so in
order to understand this issue we need to understand what an object looks like in memory so an object is basically a set of properties but the first property which is essentially a hidden property is a pointer to a table of methods and each of those methods has a pointer associated there with it which is basically where the instruction pointer is going to be sent and before control-flow guard this is what the invocation of our virtual method would look like sort of both in assembly and I've put some shorthand there because you know you can't really put read assembly that well and so basically what it's doing is it's getting a pointer to the object it's
grabbing that vtable pointer and looking up what method is going to be calling within that so in order to gain a code execution before some of these mitigations basically what we're after is the method that's going to be invoked you know we point that to what we want to run in reality this function table would normally exist within a dll or some area of memory that might be hard to overwrite but it's the vtable pointer that's easy to overwrite and you know we simply basically point that so in that method invoked our shell code and would run our shell code back a long time ago there's a really nice paper called heap feng-shui and kind of a
precursor to a lot of the stuff we'll be looking at you know he mentioned you could sort of if we jump back and the ACX gets set to the V table pointer we could just jump to ECX that's you know from some fixed address and we'd be running our shell code so in 2009 Microsoft introduced a mitigation called data execution prevention you know they kind of I guess like I have in this talk they take a you know ronnie'll does what it says on the tin approach it prevents you from executing data and the solution to this was return orientated program so the first step of a return orientated exploit would essentially be to pivot the static so if
we've got these virtual calls because we can't just put some code that we're going to run what we need to do is hijack the stack and we do that essentially by taking control of the stack pointer rather than the instruction pointer and you'd find a stack pivot gadget essentially you know a tiny set of bytes so if we've got a big set of code it's quite easy to find that sequence of bytes even though that might not be the intended instruction to hijack the stack pointer and pointee our code and then our exploit would look something like this so we'd pivot the stack run a series of rock and that rock would probably point into our shellcode and
start executing that in 2012 they introduced another mitigation called BT guard or virtual table guard which is basically a bit like a cookie or canary within the virtual table that was a value that's checked this kind of mitigation is looking fairly dated and I've only mentioned it because we'll see it and I didn't want to sort of used to say what on earth is he talking about VC guard for also in 2012 a SLR was introduced I think in about 2006 but there was a whole bunch of dll's that didn't opt into it and so the way to get around it was to you know cause the application to load one of these dll's and then we
could build a rope chain based on code at a known location there's a really really good paper called the info leak error on software exploitation and this is kind of once a SLR became effective the general opinion was that you had to find an information leak to leak out the address of a dll in order to execute code and in 2014 they introduced further mitigation called control flow guard which essentially means that all these pointers within the function table can no longer sort of point to some arbitrary piece of executable code they must point to a valid function and there's not been a great deal of work on how we might get past this by corrupting
so what I wanted to do was take a quick look at what virtual method in vacations look like now this mitigations been introduced and they're slightly different on 32-bit and 64-bit and actually it was the way one of the issues they'd have to address they've had to address on 32-bit that started giving me some of the ideas that we're going to be talking about further so on 32-bit it calls out to a routine that's going to check if it's a valid function that we're trying to call so I'm not going to go into loads of the implementation details but basically Windows keeps a big bitmap you know of ones and zeros for every kind of entry
point in an application is this a method you know the start of a method a valid entry point to a method but as well as that on 32-bit there's a little check after the function has been invoked to check that the stack point is still where it was before the function is invoked and the reason for this is that what you could do for instance if you call cause the application to call a function that was expecting one argument but sent it like four arguments it's going to only pop one off the stack and leave the stack in an undesirable state afterwards so for instance if we could manipulate one of these arguments to point to some code it might get
interpreted as a return address and then we'd have defeated control flow guard on 64-bit it doesn't have any check like that basically because the caller pops the arguments off the stack for rather than the function that's called so it's impossible for it to become D synchronized okay so let's start taking a look at these techniques I was talking about okay so firstly there'd been a number of attacks or bypasses on control flow guard I've got whole load of references at the end of the paper I don't have time to sort of go into all the details of these previous attacks but by and large they'd make heavy use of a sort of gaining full read/write access to the
process base and starting to manipulate things most of them have been mitigated but one that aligns quite well with what we're doing hasn't been which is overwriting return addresses on the stack okay so control flow gadgets basically what we're going to be looking at is you know they've been a number of sort of code reuse attacks they Rock and rep to Lipsy being the most well known one what we're going to do is use these valid functions as gadgets and see if we can chain them together to cause interesting things to happen where with return orientated programming the focus is the stack so we talked about pivoting the stack to an area under our control
in control flow gadgets the focus will be like the current this object or the object of focus okay so an early approach I sort of looking at this is well just like we do an object injection can we essentially chain together to get to a useful function so we do things like try and get it to load a library from a UNC path now obviously you'll see here you'd have to control for instance a number of the properties of the object and find a useful gadget that started using those those properties and called a method on one of those properties and so on and so forth Microsoft have obviously kind of cottoned on to this type of approach and
I've started closing off all the functions that might be useful but in they recently spoke about these mitigations a couple of weeks ago and there's one thing that they mention as a known limitation and well-known limitations and limitations just as much as unknown limitations are so we're going to be using this and that's basically that yes you can overwrite return the dresses on the stack in the not-too-distant future they've worked with Intel on our hardware mitigation for this and that they're basically moving the return addresses to a shadow stack that hopefully you can't corrupt okay so how can we look at overwriting a return address on the stack kind of from an from an object
perspective well what we could think about is basically mismatching the arguments between a function that invokes another and what that function is expecting so you know if you've looked at any reasonable amount of code obviously local vary are often used and they're stored on the stack so if we could get a function to pass a local variable off to another function and then that functions treating it in an unexpected way for instance as an object basically we may be able to overwrite the return address by setting the appropriate property on our object now I guess sort of that sounds nice in theory but you know can we find these these kind of functions because the proof of
concept that I'm going to go through later is all 32-bit because the second technique I'm going to talk about is only 32-bit I thought I'd show you some examples of the 64-bit versions of the gadget so here's a tiny valid function from Ms HTML 64-bit when actually it turns out I was a bit online Bish's tonight and you're trying to overwrite one property there's a whole load of these functions that basically grab a load of properties and overwrite them you know onto another object and so the the gadget we have to Mack match with that is one which uses local variables and here's just such a gadget again within MS HTML a slight difference from this from the
gadget we were kind of theorizing might exist is if we look closely this is basically before it invokes a method it's pivoting to a property of that object so a property of that object which will also be an object is becoming the focus okay so that this is basically where we are now and this will get us past control flow guards so we've got one object we set one of its properties to what what we want to use is a stack pivot and then we use this pair of gadgets to overwrite that stack pivot as the return address and then we'll hopefully be able to execute our return orientated code and jump to the shell
code or whatever because we want to make this technique as generic as possible sort of one of the first questions we should ask yourself is what if we can't control that property that we want to use to overwrite a value on the stack well one of the most obvious things to do would be to simply pivot to a property of the object that we partially control and you know these what I've written there is a pivots a property gadget if you can imagine there's a whole ton of functions that the first thing they do is call a method on on a property of the object so these are really easy to find and that would mean if we controlled any
property that we could find a corresponding gadget for we could also control the stack pointer but again trying to be as generic as possible the question we should ask yourself is what if we don't control any properties of the objects because looking at the the way this previously worked it was sufficient to just overwrite the vtable pointer well if we could somehow basically make the you know make the code treat the function table as if it was an object it certainly isn't and there's no legitimate code that would do that but then we would have solved our problem and we would be able to continue so before I talked about mismatched arguments the next thing I want to think
about is unintended arguments so when I talked about that stack desynchronisation attack there was the fact that the you know we're allowed to call any valid function and it doesn't have to have the expected number of arguments so if we call a function that's expecting four arguments but we only supply at one where are the other arguments going to come from and basically the idea is well maybe we could get that vtable pointer to happen to be one of the arguments here our approach has to split slightly between 32-bit and 64-bit essentially because they have different calling conventions so the way arguments are passed to a function differs between the two on 32-bit most of the arguments
are placed on the stack so we'll need to place a be table pointer on the stack and interpret it as an argument and on 64-bit the first four arguments are passed by a register so what we want to do is try and set one of those registers to point to our V table pointer so again that sounds nice in theory off we go to see if we can find a gadget that does there and lo and behold there there is one now this it calls one virtual method which we can easily sort of stub out you know set to the simplest gadget we can find something that will return cleanly and then it will set r9 which is the
register used for the fourth argument of an invocation to the V table pointer and call into another gadget and obviously we need to find a corresponding gadget which is going to use that register and set that as the object to focus and call a call a method on it and there's a gadget that does just that so it turns out we can pivot the V table pointer and if we sort of squash things together we're pretty much back where we were before controlled flow guards so we have to chuck a bunch of stuff into the function table set up a few pointers to sort of point to each other but that is essentially control flow guard bypassed
okay so the second technique we're going to look at is an attack on a SLR but it's specific to 32 bits though because the address space on 64 bit is much larger than 32 bit the approach we take care is invalid have a very brief look at how a SLR alert works for the address that code is loaded into the system so basically you know it's a randomized address Microsoft will generally state that there's 8 bits of entropy and the address that this is loaded actually if we're trying to make a practical exploit it turns out there's a little bit more entropy it's important to note that the dll's based address is well aligned so
essentially it's only these two highest bytes that will ever be randomized and it's the one I've colored slightly darker Green that will take you know will be completely random and the other other value will be in a fairly fixed range and the main attack technique that we're going to use is something called heap spraying which has been around for a long long time and we're not just going to spray data which is what people generally do but certainly there's other people who sprayed pointers which is what we're going to do and within heap spraying again well known that basically if you make large enough allocations your your data or pointers that you've sprayed will be
placed in a 64 kilobyte alignment okay so what is a shifted pointer basically we just find a normal pointer and we're addressing it from a slight offset now the important thing is looking at this what I've called a shifted pointer it still contains all the entropy from the deity you know the randomness of the dll's loaded address but we can point it in to data that we control so what we do is we spray with a bunch of these shifted pointers so that we get one at a fixed address and then we have that point into our payload and our payload will have 256 exploits say in this case and essentially the action of triggering the vulnerability will select
the appropriate payload based on the base address of the dll as I mentioned before to actually do this practically we need to try and go beyond those eight bits of entropy which it's fairly obvious how we can exploit but what we can do is basically set up a series of shifted pointers now we're not going to know which one is at some fixed address but because we place the payload directly after these allocations if you imagine sorry you know we've got these shifted pointers and we've got our payload whichever one is active at a fixed address also would determine kind of the alignment of our payload in those terms if we were very careful with the
way we select values we can basically overlay a bunch of different payloads on top of each other and you know effectively bypass a SLR so let's move on to the proof of concept okay so I've picked out a CVE which basically someone else has taken a good look at if you want kind of the details of you know what the vulnerability is and why it works etc go and go and read his article it'll explain it a lot better than I could for our purposes is base a simple type confusion vulnerability that gives us control of an object pointer so this is what the code that triggers that vulnerability looks like I guess in in
simple terms there's a there's a function within VB script that's expecting to be passed an array what it's not expecting to be passed is a byte array that we control completely but all the tests it does to check that it's the right type of object a byte array passes and as long as we set the type correctly basically we can overwrite an object pointer and I've just highlighted sort of the two places that will end up so it's both the the pointer that's dereference to look up the entry in the V table and it's also the first argument that's passed to the function that's invoked okay so how are we going to exploit this well first we have to create the shifted
pointers that I talked about and this is a fairly simple way to create those shifted pointers within ie and I think it still works in edge as well basically we we create Dom elements and we can give them an arbitrary number of attributes so we keep adding attributes until we've got something that's representation in memory takes a whole 64k chunk and essentially we you know spank the memory with these and we'll end up with this pattern in memory now as I mentioned we can't you know this isn't a known alignment it could be at one of four alignment so only one of these gifted pointers will be active at a fixed address that the address we're going to
use is two eight zero zero zero zero one five okay so now we've got we know we can place a shifted pointer at a fixed location in memory and that's going to in turn point to a V table oh I forgot something right I put a note there that kind of an interesting detail where I've put the star that ruins our initial plan was that is going to invoke the first entry in the V table so if we want this V table to be an object and a V table it's vtable pointer is already taken so if we can't really use it as a fake object is the way we get past it it's fairly easy we pivot to a project
property of that object before it's vtable is ever used so this is what we use for the vtable pivot I haven't given the sort of full source code of the gadgets you can go off and look at them or you can trust me I guess basically so the first gadget whose purpose is to just incidentally set the EDI register so it happens to set EDI to the vtable pointer and then doesn't use it for anything else afterwards but also doesn't reset it then the second gadget that we use pushes this EDI pushes the pointer onto the stack as the first argument now the reason we can sort of do this so simply is because there's two
different calling conventions in 32-bit there's one where you would have ECX set as that this pointer and one where it's the first argument on the stack so what we're doing is we've found somewhere where it's expecting to invoke a function with ECX pointing to the object to focus but we're going to invoke a function that's going to pull the first argument off the stack and use that as the list pointer and this incidentally pushes EDI on it's just it's actually just intending to preserve EDI so it's going to push it on and pop it off when it's finished the function and finally as I mentioned because the vtable pointer for this object that doesn't actually exist would be taken by that
first gadget we have to pivot away from it nice and quickly before the v table pointer ever gets used right so we've got this set up and we've got the four shifted pointers and we don't know which one's active sort of both the addresses of these or the layout the required layout shown here and the shifted pointers used have been carefully selected so that we can overlay for different exploits on top of each other without interfering with each other so one for each possible align so now we've got that we can attempt to overwrite return address on the stack so we need the stack overwrite gadgets that I was talking about so this first gadget here
sets a local variable and invokes another function and the second function just overwrites the load of stuff around that local variable so it starts to get a little bit like a jigsaw basically we have to fit those you know we can these are pointed to by this p2p so that's sort of phase to point so if we think of this the vtable pivot has phase one and overwriting the stack addresses phase two we're now basically we can point those anywhere so we have to set up these further gadgets and rather the first one shown here there needs to be one copy for each alignment but the second one shown here is kind of independent of the alignment it only
points to things within the DLL so we only need one copy of that as it turns out we actually need to because it kind of well I need to show you two in a in a 256 byte section because it it uses you know it goes on to the next 256 byte section right so we've done that we've got a little bit of space left we've got to fit some stuff in so we want to do the wrap as quickly as you know as short as we can so we've got basically a nice small piece of rock that's going to call virtual protect which basically is going to mark our shellcode as executable and because
we're running out of space we need sort of a small piece of shell code that's going to assemble the big shell code that we're going to run at the end and this is what the section of the full payload basically looks like so we've you know we fit the rock and the shell code into the gaps that are available so now I'm going to demonstrate this exploit I'm afraid it's not particularly exciting because I haven't sort of weaponized the exploit but I thought it would be more interesting to look at if I've got a mouse pointer I'm gonna try and pray to the demo gods and basically debug the exploit as it runs if I can get out Oh PowerPoint
so everything went a bit pear-shaped before the presentation so I've rebooted the computer and I don't know if it's going to be one of the rare cases where it won't work given how things go I'm sure it will be but let's try oh and I need to start a web server to me
so I've set the exploit to run when I click a button obviously in real life you know you've set it to load as soon as as the webpage is loaded but this makes it a lot easier to debug so we're going to attach a debugger and I'm gonna remember to set this symbol file path because otherwise everything will be
ok
so I was doing some testing before the presentation and got really confused why it wasn't working it's because I hadn't said that that's not right and then extra character someone sorry
so this breakpoint is basically you know almost the entry to the vulnerability this is where we should hopefully see let's take a few seconds doing the the pointer spray and then the heap tray that we talked about right we've hit our breakpoint and sorry one second remember the font size up
okay so two eight zero zero five which is where it's loading the object pointer from that's the pointer to our shifted pointer and three eight five F blah blah blah is the shifted pointer so that should mean you know this these bytes basically indicate where the DLL that's been loaded to and let's see how it works I think hope interesting to me and hopefully interesting to you thing to look at will be the call stack as this as the vulnerability proceeds as long as it works so and I think what we might do if we've got time probably don't have timers so we'll watch this as it goes through basically well better okay so it's loaded the pointer
to the shifted pointer it's getting the address of the function that we're going to call from our fake vtable pointer it's going to load that in this is basically mostly you know irrelevant to us okay this is where it's checking if that's a valid function obviously we've set it to a valid function so we're going to get through that fine and now we're going to call our first gadget so this is the first gadget and if you remember the purpose of this one was to set a DI to the pointer the pointer to the vtable pointer so we can pivot to it so eventually after it's done some stuff EDI has been set somewhere I missed it
was set just there purchases
so EBX is the pointer to the shifted pointer EDI is been loaded from EBX to to set the set the shifted pointer and that's all we wanted this gadget to do with set EDI and then invoke the next gadget so again we can agree get through all this stuff skip over that it is a valid function and off it goes to our next gadget now write what was the purpose of this one yeah so this the purpose of this is to push EDI onto the stack as the first argument and then invoke another function so we step through it that there's EDI getting pushed onto the stack nothing else gets pushed on after it it's going to
eventually load our next gadget it's a valid function so we passed that check and the purpose of this gadget was to quickly pivot away because the current object of focus doesn't have a valid V table pointer because we had to use it for something else
and there we are to the next gadget I said the purpose of this gadget is to use a local variable this is where we're going to try and overwrite the return address
so sorry I actually haven't hardly mentioned VT God but this is you know the VT guard check its turn because the value of VT guard is only based on the base address if we're defeating a SLR we're going to know the value of VT guard in a way so that's fine we won't get caught there sorry just the the function I just passed was loading ECX with a local variable so something near the stack you see X now points into the stack checking if it's a valid function is on to the next function now the purpose of this one is to start overwriting the return address so if we watch the current call stack as we pass
through this start overwriting values and somewhere suddenly it should Oh the call stacks been corrupted so we have to return out of this function as I mentioned in 32-bit it's going to do a check that we haven't desynchronized the stack pointer we called an argument with expected one argument with one argument we're fine just going to skip over the nasty error it was a thrown
basically eventually we're going to return from this function and now we're into our first prop gadget and we've set a EBP so the frame pointer to point out our rock code now the stack is basically completely under our control we're running our rock code we're gonna pop EPA X and we're going to jump to X and that's basically been set up as a pointer intervertebral takes it stub so there's a bit of junk to go through if I press the right key here you won't have to watch me go through the whole event and now it's returned in our code which has been marked as executable so now essentially we're running our shell code and it was that short section of code
that I talked about so we should see just underneath that jne jump if not equal we should start changing the code because we're copying over and there you go I'm afraid that the shell code at the moment is basically just set as a breakpoint and a bunch of arbitrary you know a bunch of junk that will go on for ages so if I just hit go but you should see that we've got plenty plenty of room for you know I've just filled it with a AAA BBB CCC or whatever but we can put whatever shell code we want it there and yet I'm afraid that's the end of the demo I know there wasn't a big shell
[Applause] just a couple more things to say take a minute to read them
well load up eventually okay so in summary essentially we looked at an object orientated by parts of control flow guard as far as I can tell that should be usable in just about any situation that you would encounter control flow guard obviously we need to have the gadgets that we use you know existing in the memory space and then shifted pointers was an object orientated bypass of 32-bit a SLR it's only usable basically when we're over writing an object pointer obviously in the same way that we talked about object corruption being targeted by any other kind of memory manipulation vulnerability that it this would be a perfectly valid target to bypass both a SLR and control flow guard on 32-bit by
deliberately over writing or corrupting an object pointer and and I think very important fact is that if you generally at you know the way these experts are going that bypass these these mitigations generally now everyone takes a read/write approach so they manipulate memory I was talking to Adam earlier so a common technique is for instance to cause an array to exist at some fixed address in memory and corrupt the length of that array you know if you've got the type of expert that allows you to write to an arbitrary address or or corrupt that length value essentially then you can convert that into a read/write primitive and read and write beyond the bounds that you're supposed to be but
obviously that relies on having a scripting language or something in the application that you're targeting whereas this approach all we needed to do was cause the application to make a series of memory allocations and if you think about I don't know you know network protocols or anything that's processing a file stream or you know decrypting some kind of file format it might well be possible to do that in situations where we've got no chance of gaining kind of arbitrary read write or get you know getting any feedback from the application as to the address of the DLL so the conclusions are basically that control flow guard in its current state is ineffective against object corruption you know
provided we can find these gadgets and we look to two very simple gadgets that allow us to overwrite the stack and I would kind of hypothesize that they probably existed in just about everything the vtable pivot gadgets may be less common that kind of waits waits to be seen and 32-bit SLR is ineffective against object pointer corruption in its current form in the presence of sufficient memory allocation if we can point to spray or heap spray we can get past it this is really boring but this is how I would fix it or at least begin to address it so the three table pivot worked by using unintended arguments I think Microsoft should segregate the
functions by the number of arguments that they're called with so if you're calling a function that's expecting two arguments you should only be allowed you know if you're supplying two arguments you should only be allowed to call a function that expects two arguments and there's basically you could put a lot of the work on the compiler to do that rather than at runtime this would be a nice efficient way to do it static protection obviously Microsoft's position is that there's this nice Hardware mitigation coming that will hopefully stop that we could think about in the way that sort of stack Canaries are used on a function that has local variables that might be overflowed we could say
well this only happens when we're invoking a function with a local variable so let's target those and check the frame pointer and stack points or after we've called a function the problem with this would be that you'd then probably just aim further down the stack you know you'd find a gadget to overwrite the return address of it of a different gadget further down and bt guard basically kind of isn't fit for purpose as it stands it's really silly to have it depend entirely on the DLL base address wherever we encountered it it could have caused us a lot of problems if it was a pseudo-random number for instance that we didn't have access to for shifted pointers as far as I know
any pointer kind of any object pointer created through normal means should be well aligned so you know only every four four bytes what we could do is enforce that alignment by simply handing the pointer with the value there and like VT guard is used to target virtual tables that they would thought were highly likely to be attempt for us to attempt to corrupt they could use a similar mitigation for objects that they thought we might target to corrupt the object pointer URI unfinished any questions
I basically just sort of predict what byte sequences might be in them and look for them if that makes sense obviously so I mentioned and it's in the references I think it's it's in there somewhere it should be yeah so number eight is a very detailed academic paper and they were really so what was different that they were looking at from what I was looking at was they're only looking at if you control the object completely and they were never leaving kind of that realm of executing valid methods and they kind of proved that in a lot of applications it's cheering complete and stuff like that but there's loads of details in there about them using a much more advanced
method to search for gadgets and stuff any other questions
[Applause]