 We can start. We are in time. Inderazine will show us in his session something about memory corruption, memory analysis. I think it's a hardware. Heck, I don't know exactly. I'm interested in this, so I stand here. And let's start. Thank you, mate. Before we start, I will actually ask you to give a big clap to the organizers, because I think they're doing an amazing job, and like, I'm very happy to be here with you today. All right, so we're going to talk today about memory corruption bugs and how to automate the process. To be fully honest with you, we released the tool like three months back, and we got more than ten thousand downloads, and every single question I got was regarding remote stack-over-flows, which is something the tool was not meant to do, like the tool was meant to automate exploitation of invalid memory rights, and not at all, I mean stack-over-flows, which I thought, you know, it's pretty well understood, like, come on, it's the first class of bugs, which was disclosed, which actually deals with memory corruptions, if you Google for memory corruption bugs, like, everybody in his brother wrote a paper about stack-over-flows, so I was kind of bored about stack-over-flows, and I thought, like, ah, come on. And then I thought a bit about it, and, you know, eventually there are actually quite a few new security mechanisms, like 45, or PIE, Position Independent Executables, which actually worth a look. So if you guys agree, I'm gonna start with this, and then we'll switch to the meat, which is autofine, and auto-automate atomic, or not so atomic, so like, overwrite, in any other section of the binary. You may see by now that I'm not a native speaker, and I'm pretty sick today. I'm actually coming from Australia. I mean, anybody's coming from New Zealand? All right, so I'm the one coming from the opposite side of Earth, and I got pretty sick in the plane, so if at any point in time you don't understand what I'm saying, please interrupt me, like you can scream or wave around and stuff, and I'd be very happy to, you know, rephrase my wording or reword what I'm saying. Let's do it. Anybody wrote anybody read the white paper? Yeah, man. You guys have any idea how much time I spend on that stuff, and there is one dude who actually read it, and come on. At least lie to me. Tell me everybody wrote it. Yeah. Thank you so much. That's some love. I love you, too. All right. So, well, that's not really important. The only point which is actually relevant to me that I'm very happy to be here, and we're trying to create a small security conference in Paris. It's called Akito Agasson. It's not too far, and it's pretty, it has some quality. So if you like, if you guys like my talk, please submit, please come. We'd be very happy to see you guys in Paris. All right. Why doing binary stuff? Because to be fully honest with you, in my daily job, I don't enjoy web applications that much. It's super repetitive, and I think the world binary thing is a lot more complex and more exciting and more that's a meat. Agenda. So, I go back to a few basics. If it's too easy, you please raise your hands and I'll be very happy to skip the basics and go to the meat. I have like 95 slides. There is no way it's gonna fit in one hour. Yeah, I'm gonna be late. Sorry guys. So if it's too easy, let me know. I'll be more than happy to skip. In a nutshell, the tool is available. It's free software. So the address is PMCMA.org. Yeah, I know the name is pretty strange, but whatever. It was available. Surprisingly. It's published under the Apache 2 license. So it's free as in free software. We also have a repository on GitHub, and people actually do submit patches. So if you want to improve the tool yourself and add new checks and stuff like that, feel free to do so. We're very happy to merge new patches. If you do that, please use the GitHub. It's a lot easier for us in terms of maintenance. So like I mentioned earlier, we got 10,000 downloads for a tool which is actually helping reverse engineering on Linux. So either some guy is psychic or is using a bot to download it all day long, or the tool is actually interesting. This is like way more than we actually expected. So what is the tool supposed to do? The tool is actually a debugger. It's pinterest-based, so much like JDB. But it does all the stuff that JDB cannot do for you. And in particular, whenever you can trigger a bug, say you've been doing some fuzzing session or something, you've got plenty of crashes and you'd like to analyze which one are actually exploitable and which one is irrelevant. The tool is here too, so it's not writing an exploit for you, but it's showing you exploitation strategies, what we call exploitation scenarios. I'm going to start with a demo because like, so we'll all be on the same page. So any questions so far? Okay. Okay, so I'm starting as a tool. I cheated a bit. I created a small script. What it does is just starting Perl and filling it poc1.pl, which actually triggers a null pointer to the reference. Yeah, full size. Yeah, doable. Font size. Font size, doable, doable. Is that more sexy? Yeah, kinda. Everybody can read. Okay. So this is just a small null pointer inside Perl, but at least, yeah, any question? No? Okay. So at least we'll be on the same page on what the tool does and how it works and stuff. So you have different ways to invoke it, like much like GDB, you can attach to a running process or you can start a new process and start debugging it. So it shows you a bunch of stuff, blah, blah, blah, like the command line, which you can retrieve from the stack. Like which instruction it failed on, the state of registers, that's not too exciting. Then, okay, what really starts to be exciting is that it does, it tries to analyze the root calls of the bug by looking at the registers, looking at the instruction and the state of the stack. Basically, if you can walk back the stack, you know the stack is not mangled, so it's not a stack overflow. You received signal 11, so you know it's like, you know, some kind of invalid memory de-reference and by looking at the registers, it's pretty easy here to say that it's a read operation because it's only comparing and not writing anywhere in memory. And it's actually failing because ebx, which is worth thing zero at this time, is actually pointing to invalid memory. Do you have any kind of laser pointer or something? If anybody does, that'd be sweet, no, okay. So the ebx plus 8, if you have ebx worth in zero, pretty obviously it's gonna try to read from the first page, which is never mapped, and the Linux. Thing is, if you don't know assembly, if you don't know all that stuff, the tool tells it for you in human language. So that's pretty sweet. It's much like, you know, being exploitable for Microsoft or whatever. Then it looks at a bunch of binary properties like, was it combined with PIE? I get back to this. Stack Cookies, Fortify, you know, a bunch of properties like, is it a C++ binary, for instance? It's kind of relevant because like, if you have a C++ binary, you expect to find EPS of function pointers. Why? Well, because every class is basically, I mean, when you invoke a class in C++, what you actually do is calling a function pointer, right? So, well, it's pretty interesting to notice. Okay, then the real thing. It checks. All right, ASLR is tough. It's when we're actually writing exploit, repeatability is a problem. And so ASLR is, you know, at the core of the defense mechanism in the Linux. How do you check ASLR? The idea is that the tool is gonna respawn the very same application 100 times, and look if the mapping of every section differs from a run to the other one. All right. You could say, hey, I'm gonna do that with static analysis by, you know, looking at the binaries, PIE or whatever. If it's not, you expect the main binary to be made, to be mapped, always at the same address. And you can make a wild guess regarding shared libraries. It's actually much easier to just re-execute the binary and check in practice if it works or not. I got some surprises, like on some pretty old kernels, the libc, for instance, would be mapped 10% of the time at the same address. So, 10% is a lot. I mean, if you're doing a, if you can attack it at will, meaning you can you're attacking a server and it's forking, so you can, you can, you can trigger the bug as much as you want. In 10 times, you sure to get a shell. That's a lot, so you want to see it. So it's interesting to see it in practice. All right. Okay. Then we check much like um Pax test, the regression test for the geosecurity and packs inside geosecurity kernel. We check like, is this stack executable? Is the heap executable? This is entirely dependent on your kernel only and not the application you're attacking, but it's worth noting and it's always something you get a check before writing a proper exploit. So here I'm using a random latest Ubuntu machine or something. So like by default, the mappings are not executable. I mean, what's writable is not executable, but if you call in protect, then you can. Is it always a case? Of course not. If you use geosecurity kernel, for instance, you can have a hardened configuration which is going to prevent you from executing anything on the stack, even if you try to unprotect it. Basically the call train protect is going to fail. But Ubuntu is like not that good. Okay, then what the tool does is trying to get is basically passing every writable section and looking for function pointers. If we go back to the definition of a function pointer, it's something which is going to be on a writable section and it's something which is pointing to executable memory. So by passing all the writable memory, we can actually get us a short list of all the possible function pointers inside the application, even if they're stored, say, in shared libraries. And people tell me, oh, but I do that manually. You know what? Bullshit. You're never going to find a function pointer in, say, the data section of libcrypt. Right? And even if you do it statically, some tools are here to do this, like monad.py, anybody is using this? It's a cool tool from the guy from Coreland. The thing is it's only static. And there is a massive difference between a function pointer being somewhere in the other space and from a given point in time, this particular function pointer being called, and this is what I'm interested on. I don't care about finding function pointers which are not called during the normal flow of execution. Any questions so far too easy? Yeah? Okay, he's asking me if monad.py is available on Linux. No, it's not available on Linux. Yeah. But it's like the state of the art. So it's a good benchmark. Then we try to see if, basically, the tool is checking if, after the crash, we're getting back to the same instruction. This is pretty relevant. Why? Yeah? All right. The main idea. All right. So for those not in the room, they're saying that the probability is high to be in a loop. Actually, it depends. So in the case of my comparison here, are you going to get back to the very same instruction with the very same set of registers? It's hard to predict. Like, you know, basically arbitrary computation may happen. And I have no idea. The thing is, if we want to distinguish between an atomic right which failed and another right which failed, if I can overwrite multiple time, like overwrite an entire section, it's a lot more interesting to me than a single atomic right somewhere. Because if, for instance, if I can overwrite the whole heap with content I control, it's a lot more interesting to me that writing, say, four bytes somewhere in the heap, especially in case of SLR. I get back to this. All right. And then from then, what the tool does is basically looking for function pointers. Okay. In this case, it did not find any. Wow. That was a cool demo, right? Okay. So people asked me about Stack Overflows. So I'll do the Stack Overflow stuff. If it gets boring, please, we'll get back to the meat. Boring. Yeah, I know. But like, I got questions. Now, there is actually some pretty cool stuff to say. Anybody know how to bypass position independent executable, for instance? Okay. Position independent executable is the fact of having full randomization. Let's see that. Okay. So basically Stack Overflow, blah, blah, blah. So you have a bunch of possible, I mean, compared to the very first articles like Aleph 1 and stuff like this, we got non-executable bits. We got Stack Cookies. We got SLR, Position Independent Code. Possibly Static Guards. And Ask Your Moring. The real point why I'm saying it's not that interesting is that you can do the whole analysis and write to exploit statically. You don't need a debugger to do that. And I'm going to prove it to you. SSP. So that's the main difficulty when writing remote Stack Overflows. This guy, Ben Oaks, is a really, really sharp guy, in addition to being nice and being Australian. Yeah, tough life. So he showed that this conference in Australia, which I really recommend to you, which is called Rockscan, he showed that basically when you develop a server under Unix for, to make the whole design more robust, what we do instead of using threads, because we could use pthreads, much like those Windows morons, now what we do is actually forking, because it creates another process. And like, we want to have two threads trying to, you know, write in the same memory, triggering rest conditions or whatever. So what we do is actually creating a replica of the parent process by calling fork. When you do this, the forking process is going to inherit is stack cookie from its parent, because you're not calling exact VE, which is the only system call, which is setting the stack cookie for you. So every single fork is going to have the same mapping. In terms of ASL, it's going to be the exact same mapping. And the stack cookie is going to be the same. So what Ben said is that, hey, you know what? I'm going to overwrite byte per byte the stack cookie in different threads. So like, I create a new connection. I send the amount of data to fill in my buffer, my stack buffer. And then I'm reaching my cannery. I'm overwriting only the first byte. I have 256 tries, and after 256 tries, one of them is actually going to succeed. And that's going to give me the first byte. So byte per byte, you have four bytes, assuming a 32-bit architecture. So in 1024 tries, you can actually brute force the stack cookie. Yep. That's pretty bad. All right, the second production, honestly, stack cookie was the absolute nightmare for everybody until pretty recently. 45 is like a new compiler enhancement. Basically, at compilation time, they're trying to replace, say, mem copy, which could be vulnerable when writing to a stack buffer to a stack overflow. So they're going to replace mem copy by mem copy underscore chk, which takes an additional argument. And the additional argument is the maximum size of the buffer, assuming it can be known at compilation time. And it's going to check at runtime that you're not trying to copy past the end of the buffer. If you look at the implementation of, say, mem check underscore chk under Apple, it's scary. It completely sucks. What it does is verifying that the length you're giving at runtime is smaller than the actual size of the buffer. But it's not verifying that the copy is starting from the start of the buffer. Saying that if you have a buffer of 20 and you're starting the copy in the middle of the buffer of a size of 20, it's actually going to say, hey, it's all right, man. Let me show you something really cool about 45. I love it. I call it 40 fail. All right. Anybody can see what's the problem with this code here? Well, it's pretty legit. If I ask GCC to compile it, so I'm going to use the 45 flag, I'm going to ask you guys a favor. Can anybody bring me a beer? Is this drinkable water? It's only water. All right. I shall survive. Right. So depending on the exact version of your compiler, 45 may be applied by default if you use optimization of at least two. If you use optimization greater than two, you bang stupid because it's not supported by GCC anyway. So if I do this, GCC gives me a warning, but it does compile the thing. And if we look at the dynamic symbols inside the newly created binary, there is no memcopy underscore CHK whatsoever. So here, 45 actually failed, and it did so because it could not find the definition of memcopy. This is super bad because if you take a binary like SSH, you will find both memcopy and memcopy underscore CHK, which is actually expected because 45 cannot protect every single call to memcopy. It only protects those who actually copy to a static buffer with a known size in the stack. So if you copy that in the heap, or if the size of the buffer is not known in advance, then it's totally unable to protect the binary. The thing is, in SSHD, imaging that one of the objects is actually using memcopy to call, I mean, to copy data to a static buffer in the stack. If one of the objects actually failed to include string.h, like in my previous example, you're totally unable to see it. Thank you, man. I love you. All right. So the problem here was actually that my definition of memcopy was missing because string.h was not, well, was missing from my demo example here. But, you know, is it happening in SSH? Well, hard to say. All right. How is that? Okay. So he's asking me if memcopy here has length checking. So in the example I compiled, not at all. Like, it completely failed. Like, if you look at the symbols inside the binary I did compile, if it had this additional length check, you would have memcopy underscore chk. All right. A little bit more what? Larger. Larger. Yeah, sure. I can do that. I didn't get you. Excuse me. Yeah. Yeah. So I'm not saying that SSH is actually available to anything. I'm just saying that it's impossible to verify that Fortify has been applied to every object which has been used to create the big SSH executable. And if you look at, you know, if you compile every single network dmin available in Linux, you will probably find ips of vulnerabilities of that kind. I mean, missing checks like this. And you can credit me for your advisory. No, I'm kidding. I totally don't care. All right. So the big thing is PIE, which stands for four pi. Come on. No. Yeah. Position independent executable. The main idea that even though we have ASLR normally, your main binary, unless you compile it with these new fancy flags, is not actually going to be randomized. Meaning, your shell libraries may be randomized. Your heap and your stack are going to be randomized. But because at compile time, the compiler is assuming that the base address of the main binary is going to be static, it's going to hot code all the references to other sections like to data sections, to BSS sections, and internal sections in the binary. And therefore, you cannot change the base address of, well, the main executable, which is pretty bad. Even if you have randomization, and you don't have PIE, you have a lot in case of stack overflows, you can find a raw gadget, for instance, inside the main executable, because the PLT is going to be at a static location in just a second. So if you want to do return to PLT, or if you want to do ROP, you can find your gadgets at normal locations. Yes. What with 11.10? Yeah, it's going to work with 11.10. But my version is 10.10. It's usually, you know, if it works on, if you have this feature on 10.10, yeah, it's going to be on the next versions, too. Good question. Thank you much. So if you look at public exploit, I honestly could not find a real exploit for PIE. Well, he wrote one, but he failed at the compilation phase. You want to come on stage and discuss this? No, okay. All right. So thing is, if you compare it with PIE, the main executable is going to be compared much like a shared library, and it can be mapped at any address. So it can be randomized, too. And then exploitation becomes a problem. Yes, it does. Because even if you can, even if you have an exploitable stack of a flow and you can return anywhere, you control the stack and whatever, what do you return? You have no idea. Good news is I found something for you. The main idea that, okay, if we keep in mind the layout of the stack, so you're going to have like the buffer you're going to fill, then you have your stack cookie that we know how to brute force. Then we have the saved EBP, and then we have the saved EIP. The saved EBP is not that relevant, but the saved EIP is like, if I get to know the saved EIP, basically I win. Why? Because the saved EIP is going to be the return address, which can be either in one library, and if I get the mapping of that library, I can find rub gadgets or whatever inside that library entirely, not to mention that usually in the Linux library are only translated one from each other, meaning that if you have the base address of one library, you usually have the base address of all the libraries, so in particular as a Libc, so in particular in Protect, so I can call in Protect. Or your main or your return address, if it's not in a shared library, it's going to be in your main binary, and if I find this return address, I get the base address of the main binary, and if I get the main address of the main binary, I have the PLT of the main binary, the world executable of the main binary, and I'm back to what we know how to do read to PLT or rob. Enough bullshit, let's have a demo. Okay, I'm going to show you something really cool here. I'm pretty proud of it, to be honest. Yeah, a larger font. Chill out. Fuck. Yeah, I try control plus plus, it doesn't work for some reason, so all right. Let's first verify that I'm not bullshitting you and that the binary is actually compared with in the state of the art. So there is Takuki and X is enabled, come on, and X is enabled, and the binary is actually compared with PIE. What is this four arrow thing here? Four relocation means that so it means two things. First off, your destructors are before the data section. We don't really give a fuck, but like in terms of, I mean, it's pretty standard when you have a BSS overflow to have a write also the detour section and to have a write the pointer in the detour section to point to your shell code. In the case of a stack overflow, it's irrelevant, and it also means another thing, which is that your global of set table is actually going to be solved by the dynamic linker. At the very moment, you execute the binary, so no lazy-biting. It's a bit costly in terms of performance, but then your global of set table, instead of being writable, is remapped as read-only. So you cannot, like we often do when using Rop, you cannot patch the global of set table. All right, so let me run this server here. Okay, and I'm going to run my cool exploit. Okay, so it's attacking my stuff here. All right, it brute-forced the stack cookie, then it brute-forced the saved EIP. Therefore, it finds the base address of the text. When we have this, honestly, it's game over. We could use we could use, say, read to PLT or Rop, and we would not need any kind of brute-forcing, but my exploit is much cooler. Yeah, man. Let me explain you why. Let me explain you why. I actually do brute-force a bit, see, because my exploit is going to work against any binary, and not just that one. If I write a payload using Rop, it's going to be very specific to one application. Here, the exploit I have can target, well, assuming you can reach the available buffer, it's going to be pretty universal. So I'm going to use another server. So the one I run here was serverDemon or something. We have another server here, which is serverNoPie, which is not combined with PIE. So it's definitely not the same binary. The security properties are different. We don't have PIE. We don't have this full-rare-row thing. Well, actually, partial-rare-row means that the destructure section is before the BSS, but we don't have a static got. We still have cookies. So let me run this application here, and I'm going to use the same exploit, again, that one. To spice this stuff a bit, I'm going to run it as root. Why not? I like root shells. No PIE. So I'm going to use the same exploit against a different binary. So it found a cookie. Then it found that it was not combined with PIE, so my exploit is pretty smart. And I got my root shell. Thank you. All right. So as you can see, remote stack overflows are not that interesting, and this is why the original tool, what we're getting back to, is actually not targeting stack overflows. Any question? Too easy. All right. Let's go to the meat. So what I'm really interested on, to be fully honest, is not stack overflows because, I mean, when you do security research and stuff, you don't find that many stack overflows anymore. What you get a lot is invalid reads and invalid writes. Like if you first any kind of servers or whatever, or even local stuff, you get ips of that stuff, like the lame pearl bug I showed you, like this compare something with nine, and the compare stuff is reading from the first page. If this exploitable, how to say? So this is why we took the time to write a debugger. Dude, you don't like my talk? You're bringing me beer. I love you. All right. The basics. You already care about the basics? Yeah? All right. So quick. The basics. Why do application crash? All right. They can crash in many different ways. Basically, you can eat an assert and like it's going to abort and end up with a signal six. You can get a stack corruption. And if it's combined with SSP, it's going to be coked by the handling routine of the libc. Or more interestingly, you can have an invalid memory access, which can be of three different types. You can try to execute a memory location you're not supposed to execute. What's the probability that this is going to be exploitable? Your application is dying and it's trying to execute something which is not supposed to be executed. No idea. We say that this is very unlikely to be executed, to be exploitable. Yeah? One person? Two people? Three? All right. Who says it's like 50-50? All right. Who says it's super likely to be exploitable? Well, the thing is, it depends if you can actually control the location, right? But if you control the location, I mean, if the application is trying to execute a memory location, it's not supposed to. And you can control this location. You make it point to some data you control in this game over, right? I have slides to explain this. All right. Just why do bugs happen? All right. We don't really care. I mean, there are so many ways you can fuck up, like, variable misuse, blame my French, heap overflows, you know, overflows in any kind of section. I'm especially interested in those. Like, if stack overflows are very well understood, and there is some literature on heap overflows, there is kind of little which is currently usable for, say, BSS overflows, especially because of what I just mentioned. Like, if you have your destructors, which are before the BSS section, then in case you have a proper BSS overflow, you need to have a write something in this very section to achieve remote execution. And this something you're going to have a write in the BSS section and we're looking for is actually called a function pointer. Same thing for heap overflows. Like, in theory, you can have a write heap metadata. I'm assuming you have a, you know, a recent PT malloc memory management. We're not in 2000 anymore. I mean, we have safe and linking and stuff like this. So by overwriting only heap metadata, I know in theory it does exist, but you need to be able to, like, allocate thousands of chunks with arbitrary size and arbitrary content to achieve an arbitrary for write. This is total bullshit in real life. The real way we do exploit heap overflows is basically you find function pointer in your heap, you override the heap. I love you finally. You override the function pointer and you make the function pointer point to data you control. And this is how we achieve arbitrary code execution. There's no poison in it, right? All right. Obviously, NX is going to be a problem, but I'm going to discover this. I have 51 minutes left. All right. So back to the exact thing. Imagine I have call EAX and I have a segmentation fault in that stuff. I mean, come on. If I control EAX, this is cheesy. You make EAX point to data you control and that's it. It's going to be executed. Or you make it point to an interesting routine inside the application. Invalid memory reads, that's pretty unlikely, actually, to be executable. There are some cases where it is. For instance, imagine this comparison is supposed to be true 99% of the time and you can make it fail. It's going to take another branch and execute code it was not supposed to. And that's pretty bad. Yeah. Question? Nope. Oh, good. Another example of an invalid memory, right? Invalid memory, sorry, is this one. This is kind of unlikely to recognize. FLD, it's like a floating point instruction. So if you're not super fluent in assembly, it's not immediately obvious that this is actually a read. And PMCMA, so the tool is going to find it for you. All right. We don't care. We don't care. I'm going to skip to the demos. We have only 15 minutes left. Any questions? If you like the job, buy me beers. Yep. You're asking me the destructure. The actual distribution. Detour is read only. Detour is read only. So it depends, like detours. So the detour section, which is a section which contains an array of function pointers to be called when you basically call exit. When you have what we call partial relocation, yes, it's remapped before the data segment. So yeah, it's going to be remapped as readable. But it really depends on how you compile your binary. And actually, if you're smart, you can produce a binary which has no destruct, destruct, which has no detour section at all. Like you can produce a custom linker script which removes the section entirely or which puts the detour section between two read only section and is going to be mapped as read only, which effectively means it's not going to be used at all. Good question. Thank you. Any other questions? All right. So let's do this cool stuff. I'm going to do a bunch of demos here. Please give your hand to your neighbor. Yeah, do it. We're going to pray together. We're going to pray the demo lords because it never works in real life. All right. I'm going to start with a few videos. And if we have some time, I run PMCMA on SSH, which is like the cool stuff. All right. Let's start with I'm not too sure how much time I have left. So I'm going to start with that one. Yeah, it's fake. It's a movie, but I'm going to do the right thing after men. Just to show you how it works. So the idea that because I've been asked, yeah, I'm on a school, I know. We're using the tool to prototype the exploit and not to exploit. I'm saying this because like I've been asked previously, I mean, some people, dude. Yeah, I mean, it's pretty obvious that if you can pitrace attach to SSH, you're root already. So like PMCMA is of no help to you. PMCMA is fine to prototype the exploit and we don't actually use it during the real exploitation stage, right? I'm just mentioning because some people got confused previously. All right. Here we go. Sorry. Here we go. So we're going to attack sudo. So stopping sudo during its execution, I'm copying its pit, which is 2120 or something. And I'm attaching to this pit 2120, asking PMCMA to list only function pointers. And if it finds one, you actually exploit it. So here it's finding me a bunch on the left. It's telling me A, I found function pointers which are actually called and the mapping of this function pointer is repeatable with 100%, which means this function pointer, despite of SLR, is going to be at the very same location all the time. What does it mean? Game over. If I overwrite one of those and I make it point to my shell code, it's going to work. People who followed should be like, what? There is one problem actually. It's NX. Like if you did introduce some shell code, yeah, it should be in a writable zone and it should not be executable. I go back to this after the video. Well, here it's a debugger, so obviously it's kind of working. The cool thing here is that at the end of the video, yeah, here, it should create, it should open a port on 666 and bind a shell to it. And since we are taking sudo, it's going to be run with root privileges. So let's run netcat on port 666 and we root. Yeah, that was a video, but that was pretty cool. So you could upload, I think. Thank you. I'm going to show you why I rolled this whole tool entirely. I actually found a cool bug in Opera. So I need to do some voodoo here. I'm going to explain the voodoo. Hey, no cheating. Come on. Now, like under Ubuntu, you cannot debug your own applications. Like, yeah, I know. You need to set this particular key in the procfs file system. So I'm just going to run this as root. Now I can debug my own applications and I'm just going to run the stuff on Opera. All right. So I'm starting Opera with PMCMA. It's fast, hey. All right. Here we go. And I'm going to trigger the bug, yeah, that one, Opera POC minus the size of the proof of concept. It's ridiculously small anyway. So Opera started and it's crashing on this instruction. Does this look exploitable? Hey, it looks pretty good. It's a rightable instruction. It's a right instruction. So maybe I can write anywhere in memory. Turns out I can. Yes, I can write anywhere in memory. Problem is EAX is actually always null. So I can write zero on four byte aligned memory anywhere I want. Is that exploitable? Writing zero anywhere? No, it doesn't look good at all. But it's not impossible. So let's see. Let's see. All right. So it's doing my SLR test. I'm just showing you here that the tool can actually scale to an application to the size of Opera, even though the last stuff, yeah. So here it's going to take forever. Why? Because basically it's going to pass the heap, which is several hundreds of megabytes big. So this stuff is going to take like one hour or something. And it's going to find zero exploitation pointer. Because if I find exploitation pointer, all I can do, all function pointer in your binary are going to be four byte aligned for compiler performance, basically. Your compiler is going to make sure that all your function pointer are four byte aligned. And if you can write zero on four byte aligned binary, all you can do is basically zero one function pointer and you cannot trunk it one, which sucks. So plan B. Yeah, five minutes. Thank you. Is it cheesy? No worries. No, I'm not going to restart Opera. So what's plan B? Okay, even if I find function pointers, I cannot override them to hijack them and I can only write zeros. So I felt like, hey, you know what? But I can still write pretty much anywhere I want in memory and that's pretty cool. So what we're going to do is use PMCMA to do something I find pretty amazing, which is tracing all the unaligned memory reads and writes. We do this by basically, I let you look at the demo and which is going to trace SSH and I'm going to explain you how it works. Basically, we're going to set one flag in the, it's called the aligned flag in the eflag register. So like an Intel architecture, you have this special register, which is called eflags. There is this special flag, which nobody ever uses, which is called the unaligned flag. When you set the unaligned flag, every time your application is going to read or write from unaligned memory, it's going to trigger a signal seven, a sick bus. So PMCMA is going to catch the sick bus and set back the trace flag. And effectively, I'm going to trace all the memory reads and writes inside the application. I don't know any other way to do it. And what's cool about it is that sorry, here in SSH, you can see that I find a bunch of XOR, a word register. I'm using a 64-bit architecture just to show off and show you that it works on 64-bit architecture. And if you want to port it on BSD, you're the most welcome. Basically, here, the read is unaligned with that because of the three here. And here, because of the one, right? If you take any value, you multiply it by eight, you add another register and you add one. It's very likely to be unaligned. So this way, we can list all the reads of variables into registers which are unaligned. So if I can only write zero into a memory, what I want to do is write at this location. Why? Because I'm going to find a variable. I can truncate it. And maybe I'm going to trigger a secondary bug inside the application. Wow. All right. One last thing, and I'm done. Hey, that's cool, eh? All right. Okay, so two things. I'm sorry, I'm going to be a bit late. The inner working of the process is, so it doesn't work at all like GDB. What GDB does is basically you have GDB and it's retracing another process. And that's it. Yeah. My debugger, what it does is you have the debugger. It's debugging its debugged process. And it's going to force it to fork. So it's going to create a replica of the very same in terms of mapping, state of variable, stack of key, whatever, any interesting property. It's going to create a clone, if you will, of the debugging process in memory. So you can repeat that wheel. The thing is, how do I find all the function pointers in memory? Basically, in the first offspring I'm creating, I'm overwriting the first possible variable in writable memory. In the second fork, I'm overwriting a different variable, et cetera, et cetera, et cetera. And I can do it end times. So the process is actually not super costly and it is exhaustive. So that's pretty cool. I'm skipping you all the gory details. If you're interested, please go to the white paper. The last thing when I told you I bullshitted you was the NX thing, which should be... Yeah, come on. Oh, that's really interesting too. No, okay. Hey, next year you tell them to give me two slots. Yeah, that's the thing. Stack desynchronization. I thought I was a genius when I found that. And I got an email from Nergale who told me, hey, that was in my frack white paper five years ago. But yeah, that was a cool white paper reward. And I thought even smarter because that guy is just a genius. Anyway, the idea is that, okay, NX is a problem. So instead, even if you manage to find a function pointer and overwrite it, you cannot point directly to your shell code because the shell code you're going to load is going to be in writable memory and it's not going to be executable if you have writable X or executable. So how do you move around this? Well, the idea is that if you somehow control a big buffer in the stack, what you do is instead of returning to the normal function prologue, which has a given size, you return to a different function prologue. And what you're going to do is desynchronize the stack. If the stack expected to be, for instance, to pop 10 variables, 10 bytes before returning, and you pop 200, well, you're desynchronizing the stack. And what you can do from here is actually create a fake stack frame inside the stack itself. Wow. And that's really cool. And you can actually do that remotely. So the idea is that, statically, we can very, very well find, assuming you control a big buffer somewhere, just a sec, assuming you control a big buffer somewhere in the stack, you try to find a function prologue which actually allows you to shift the function pointer being in the middle of the buffer you control. And from there, you can actually put a bunch of ret, I mean, pointers to ret, which is going to act exactly like an obsolete. And then you put your fake stack frame, which is going to call and protect, much like Rob, and copy the proper shell code in a writable zone, call and protect and make it executable. Yep. How do you do pop and push on the stack? Because normally it won't execute. So if you have a stack segment, so it won't execute because it's a joke in this thing. You don't want to have executable stack. So you have a buffer in the stack and you can write a push instruction or a pop instruction, but it won't execute this. Yeah, you missed the point. I'm not doing any pop or push. I'm returning because I control, if I overwrite a function pointer, I control the next instruction to be executed. I can return to say sub ESP, whatever, a very big value, pop or pret. So what I do is pointing to this different epilogue from the normal epilogue. And this is going to return in the middle of a big buffer. And if I control the big buffer, then I create my fake stack frame over there. Yeah. Yeah. Any other question? Yep. Will there show examples, including the sources to be downloaded? And if yes, where? Anybody got the question? I missed it then. Oh, sorry. I'm going to get back to the address. Hey, thank you for helping me doing my auto promotion, buddy. Here we go. So the source code can be downloaded on PMCMA.org. Okay. And the slides are over there too. So, and there's another question. It means, is there a possibility to brutally force the stack cookie without having heaps of forks of the program? So this is not about PMCMA, right? It's about the stack corruption thing. Basically, if your application is not forking, so if it's using thread, or even if it's simply not a network daemon, you're doing like local exploitation, so you're attacking studio. Any time you're going to execute the binary, the cookie is going to be different. All right. So there is no way to brute force it. I mean, you can brute force it in the sense, you can try to find 32-bit value, but that's really big. Like doing it in 1000 tries is a lot smaller. This is what we do. Effectively, say in Ubuntu, the first bit, the first byte is always zero. So the size of the stack cookie under 32-bit is actually 24-bits. There is 24-bits randomness. That's really big. I mean, it's in millions. So you need to execute to exploit millions of time in the hope to get one working stuff. If you're attacking BSD, the cookie is always the same. It's called a null terminator, and if you're lucky, like if you can copy zeros, you actually know what the cookie is going to be. So there is zero randomness, and you can actually write a reliable exploit without any kind of brute forcing. But that's just because the way they implement stack cookies is pretty lame compared to the Linux ones. Any other questions? Thank you, mate. All right. Thank you so much.