← All talks

From Chaos to Control: A Modern Approach to UAF Attack Detection

BSides Seattle · 202633:42162 viewsPublished 2026-03Watch on YouTube ↗
Speakers
Tags
About this talk
Nader Ammari presents a three-year research project on detecting use-after-free (UAF) vulnerabilities, a critical memory safety issue that remains difficult to detect despite extensive industry effort. The talk covers the state of UAF attacks, introduces a novel detection method that instruments binaries to hook memory-free operations and scan for dangling pointers, and demonstrates a tool that scales to thousands of symbols in real-world applications like Chromium. Current work explores leveraging angr for data-flow analysis to reduce false positives by tracking pointer ownership transfers.
Show original YouTube description
Bsides Seattle February 27-27, 2026 lecture Presenter(s): Nader Ammari
Show transcript [en]

Thank you so much for attending the presentation. Uh it's a big pleasure and honor to be with you today. Uh fascinated by the scale and the quality of the event. My first besides and definitely not the last one. Uh so yeah, let's get started. So the presentation is about um use after free one of the most exciting at least for me one of the most exciting vulnerabilities. Uh anyone who's familiar with the term? Okay, good, good, amazing. So, it's a uh three years um research project that I have been trying to work on uh and uh I decided to uh share this with the uh community because I'm facing a few challenges, limitations as we're going

to see and I'm seeking your help uh and uh let's hope that we going to uh learn new stuff uh by the end of the presentation. uh the ones who doesn't know what is a use after free I think it's going to be maybe uh clearer and uh yeah so let's get started all right so the presentation is uh structured like next a quick introduction and background state-of-the-art this is where I'm going to explain what academia and industry try to do to address this problem uh and u session number three is mainly where we're going to discuss what I've proposed to solve the Uh and then u section number four is where we going to have a little bit of

fun with the tools uh and the demos. And then section number five I'm going to cover maybe advanced use cases. We're going to play with the chromium. Uh I need to be careful what I share here because I don't want to disclose uh uh publicly some CVS and go straight to Jane after this presentation. Uh okay. So yeah uh about me nam Mari uh I work currently with Microsoft doing a lot of uh product security uh research co director in University of Montreal previously worked on a lot of cyber physical system nuclear reactors smart grids aircrafts and so on and uh yeah I've been doing a lot of research recently uh what is used after freed so as the

name indicate it's so simple like using an object after being freed as simple as that So what is user after free? Simply as we as the name indicates using an object after being freed. Okay. Um so why it's interesting for me at least it's because uh academia and industry are struggling to solve the problem. We'll see that there has been a lot of solutions proposed and we still see a lot of instances being uh reported and exploited. Um and also um it's because uh it's one of the most exciting uh I would say code viability where you don't need to inject any code and like code injection attacks or code reuse attacks and that's why actually it's hard to

detect. Uh we can go to the next slide. This is where I'm going to cover the uh concept. Uh so as I mentioned yeah so you just use an object after being freed. Now why why it's dangerous? Why freeing or using an object after being freed is dangerous? Basically if we go to the next slide I put an example on how to exploit this and I tried to put a very simple example. Imagine if you have an object simply pointing to a variable called is notification on. Right? So you just go to your setting and set on and off your notification parameters. If this object is freed and then later allocated to another object called is admin right and you

still have a pointer pointing to this uh freed object simply by switching your notification on and off you are escalating your privilege basically. So this is a prof example maybe high level example on how you can exploit those type of attacks. So the memory would be allocated to another object in the future and you still have a dangling pointer that will allow playing with the uh freed object. Now if we go to the next slide uh I'm going to explain quickly why it's hard to detect. So as I mentioned you don't need to inject code unlike return oriented programming regular buffer flow uh red to lipy you don't need any malicious payload basically just play uh

with the behavior. um it can be time dependent and state dependent. So it's really hard to detect it like when we scan and at which state um the use and the free might be in different threads. So which one to monitor plus and this is what nearly give me a a lot of hard time. It's because also there are a lot of symbols to free an object. Like if you look at chromium, you might find more than 46,000 function that could trigger the free behavior at the end. Even the free itself as like the same symbol could have different definitions in different DNS and you might be loading all of them, right? So it's really hard to

detect. Oops. Okay. No, no worries. Uh okay so that's from higher perspective the challenges if we go to the next slide um I included um some slides of the u reward in the bug bounty just to give you an idea about the real word value uh so the screenshot is from u chromium bug tracker and I will admit it it's not a good example but here by just copy pasting a crush report for years after free uh the reward was 10,000 I've seen examples with hundreds of thousands uh so it's a 3D interesting attack at least for several technology providers including uh chromium team the next slide also providing another example 17,000 uh for a use after free uh crush report

now the state-of-the-art this is where I'm going to try to go quick uh it's 55 minute we have a lot of uh substance to discuss so the first approach tried by academia is dynamic detection approach right this is where you basically fuzz the software. I don't know if you heard about u Microsoft one fuzz. It's a planet skate fuzzer or Google cluster fuzz. Anyone heard about it? Okay, perfect. So this is what we this is what the main approach that we are leveraging today in order to detect after free in combination with asan address sanitizer. But uh this is the first approach. So the limitation in the next slide is mainly it's about the concept itself. you need

to trigger the use after free in order to find the use after free right doesn't make sense I mean uh and the proof is that we have a lot of u use after free are being missed and missed and uh fuzzers are not able to cover all the use cases uh the next um the next uh slide also will cover the address sanitizer for me to be honest I don't know if you're familiar with asan but asan is not a detection method it's more a good debugging method that would print all the information like which function used the object, which function feed it, which address and so on. So this is why as being used in combination with

fuzzing, right? So it's not a detection method. Uh next slide, we will also cover uh the uh hardware assisted sanitizers. Same thing. I mean it's uh one of the most uh drawbacks of this method. It's uh uh basically it's probabilistic and plus as we said it's it's like as it's more uh also providing uh good information. There is a limitation about the architecture here also for Windows and x86 uh user land. Yeah. The next approach in the next slide is static analysis. So yes we do use SAS to detect use after free but the detection is limited to the simple use case like where it's very obvious. Hey we did the free here we did the use

here. uh I don't know you can think about code or other solutions basically uh you can also scan the intermediate representation not necessarily the codebase but same thing uh it's still limited to a very simple use cases and it's not enough uh to stop the problem once for all uh in the next slides I put some examples yeah SAS we covered this uh uh prevention via safer abstraction security by design and I like the concept because indeed it does reflect what we mean by security by design The problem is good luck rewriting all Chromium codebase. I don't I don't quick question. Um if we compare Chromium codebase with Linux kernel, which one is bigger? >> It it's Chromium is bigger. I mean Linux

kernel was believed to be the most complicated project on the planet, but Chromium is much much bigger than that. And I'll be honest, like uh the challenge is so big. It's a planet skate challenge like nearly the entire planet are using browsers and chromium is being used to u build other browsers as you know edge and and chrome. So it's it's a planet scale problem. Uh yeah so but prevention via safe uh safer abstraction basically you just use smart pointers right I don't know if you heard about it but uh you just try to implement what we call security by design but again the drawback is good luck rewriting the entire codebase that's one good luck

convincing the third party providers to write their code also right because I mean if if you're secure and your providers are not I mean it's it's useless uh so that's yeah that's pretty much it about the safer uh abstraction Okay. So now we spoke about the problem. No, we defined the problem. We spoke about the solutions. What academia and industry try to do. Um so what are we proposing to solve the problem? Um the plan was or still is six steps uh pipeline. This is the idea that I had three years ago. And I remember it was on a Saturday. I called my father. I said, "Hey papa, we're going to be rich. I'm going to build the software. They're

going to find use after fee instance. I'm going to report them automatically to Google and each one might work between 10 10,000 to 100. Uh my father didn't understand anything but he said it's also like a good plan and since then he's calling me every Saturday checking out the project. He's he's my PMO team basically. Uh anyway uh so six u sixstep plan. Yeah. So first we just instrument the binary that we want to uh monitor or analyze. Uh then I need to use the instrumentation code to hook what I call the disallocators. It could be free delete class distractors any function that will lead to the uh to freeing an object basically. And then uh the third step is to scan

all the stacks and yes there is an s because for each thread there is a different stack and the plan was to hook the free all these allocators and then scan all the stacks and try to identify dangling pointers. So basically I'm going to grab the address that was sent as a parameter to the free and then I would try to locate it in the stack. uh I was struggling with the concept of what I call non-stable use after free condition because sometimes you would find the address in the stack but it would disappear after a few milliseconds right so that's why I said okay let's simplify the problem and I'm going to scan again after a few seconds and

confirm that the pointers still exist in the stack this is what I call stable use after free condition um so step number four is just confirming that the pointers are still there step number Five. So we find the dong pointers pointing to the object that was freed. Right? Step number four is to unwind the stack. Try to understand which function own those pointers. Right? I had to write my own stack and winding. We can discuss it after. Um and uh this is where I had to take a decision about not covering uh 64-bit architecture because there's literally one document on the planet discussing the this for Windows and I mean I'm a Microsoft employee I have

access to the internet information but I want to be to use only publicly available information. So 32 uh the stack and wind my stack and winder I need to say why because it's very similar concept but it's working good uh but 64 um I cannot cover it basically at least for windows um and then final step is to find a way to execute that function that hold the pointer to this object. So this is how I'm gonna trig that was my plan to trigger the use after fee. So first hook the free grab the address identify which function are holding those pointers using stack and winding algorithm and then call those functions right find the method to call

them that was the plan um you will see that I made a very critical assumption here and please try to identify it uh you have seven slides to find it but uh we're going to discuss it later but it was I mean it took me two years to like to see it. I don't know why to be honest. That's very obvious. But anyway, so that that was it for the plan. So let's summarize. Instrument the binary, hook the free, grab the address of the object that is being freed, identify the dangling pointers like similar address in the stacks and then unwind the stack to know which function is owning those pointers and then find a

way to trigger them. And we can just ask L&Ms like hey I have this function in chromium how to trigger it or hey this is my source code how to trigger this function. So basically that was the plan. Uh if we go to the next slide uh and all of them were implemented successfully by the way. Uh I used the green to say this but anyway uh I was able to instrument hook the free scan the stacks uh confirm that this is table use after free and then unwind the stack and then find a way to trigger those like it worked well but I'm not rich yet. So my father was calling me and he

was saying hey like what's gonna so I I made a very critical assumption the functions holding the pointers when the free was called are not necessarily the one that would dreference the pointer later like the ownership could be transferred to other functions right that was my like it took me two years to see this and I was happy because it worked on the test binaries and like my father was doing the math for his deaths and all the But um it it is so the only false the only true positives that we get from this is when the logic that we dreference the dangling pointer already has a frame in the stack when the free was called. This is the only

two positives that I got so far. Um but uh we do have a plan uh to cover the other use cases the ownership transfer. If we go to the next slide. So the 1 million question has become okay will the ownership of those dangling pointers be transferred data to later logics right and which one and the good news is that we know a framework that can do this it's called anger basically I don't know do anyone familiar with the platform people from anger here okay we need to connect okay now the only correct me if I'm wrong but the only problem with anger is that it doesn't support loading or attaching process right okay I'm rewriting the

core technology I mean no seriously I mean if we can do it and then confirm or deny the existence of an execution path starting from the state where the free was called right it's not a hunting problem because we're not doing this for all inputs right we have a very known state uh a function was called we have uh the entire context right defined. So it's just a matter of confirming or denying if there is an execution path that we transfer the ownership. That's one and then we inspect each one of those. That's it. Uh sorry can we go back to the previous I'm excited to see because I'm angry but uh yeah so that that's pretty much it. Yeah so

that's the plan. I'm working on this currently and let's hope we can use it to reduce the false positives because now the method is complaining about is triggering alerts for uh a lot of stuff that are where the ownership would be transferred. Uh and this is the only method that I was able to uh propose so far. If we go to the next slide, um this is the architecture from a high level perspective. Very simple as I mentioned. One, uh instrumenting the code, uh hooking the free call to the freed object, uh scanning the stacks and then rescanning uh again uh confirming that this is a stable dangling pointer um and then unwinding the stack just

like resolving the function name and so on. Uh if you go to the next slide, this is where we're going to start having a little bit of fun and you need to be careful. So I can I can control this, you know. Uh so the first demo exactly. Okay. So I have a lot of scripts. Some of them uh some of those I'm using them to um No, we can stop the video actually. I'm going to just do a quick introduction. I'm so sorry. I don't know. Yeah, technology can get so hard sometime. Okay, so I I built a very ugly gooey software. I didn't even change the name of the main window, but because there were a lot of scripts,

some of them I I use it for stack and windings, some to search for the symbols, uh to do the scans to confirm the existence of the point and so on. So I said, okay, let's reassemble all the functionality in a very ugly software and eyes on the price. This is the this is the free, right? Um the first demo is for uh a code that I wrote right like test basically. So of course it does work. Uh but when we try on Chromium there will be a lot of false positives. Uh I'm not sure maybe some true positives. That's why we need to be careful. I'm going to maybe stop the uh debugging when we do live demos later if

we have time. But uh we can play the video. Yeah. Oops. So basically I just have a simple program. Uh I'm going to provide the name of the function that I want to uh monitor. The program will just print the P and it would wait. It will not trigger the free uh just for uh demo purposes. That's it. Here I'm looking for the symbol that I want to uh monitor. It's the free that it's loaded inside the binary. There are a lot. I'm going to provide it there. and then just press start again. We're gonna try to hook the free, grab the address, scan the stacks, identify the pointers, unwind the stack, and then discover the functions that own

those pointers and uh and report the uh use after. Okay, it does take time trying to hook. So that's the program to the right and this is the detection logic here. Okay. Yeah. A lot of useful stuff. By the way, I'm doing stack estimation. Yeah. So I'm not going to unwind the stack like forever. I have maximum depth like going to go back uh 100 frame for example and that's it. Uh sorry not sure. Did you saw the adopt the red when it says Okay, perfect. Um, >> I mean they've seen it, right? You've seen >> Yeah, that one. Okay, so here it says, "Hey, stable use after free." Perfect. Um, so free is freeing this address,

right? We found two stack pointers pointing to the free address, right? Dangling pointers. Those are the two pointers. And then my stuck and winding program which is little bit weak I'll be honest in some cases it cannot resolve the name of the disallocator color for some reason it's a Freda limitation I'm using Freda for instrumentation by the way so I'm saying argument of the disallocator color or local variable of the main right but again this is the maximum that I was able to do uh with the the second winder there are there are public second winders that can do better by the way But since I'm using Freda, Freda by default as far as I know

doesn't have a stack uh an order that would give you uh more information about uh which function uh is uh holding those variables. Okay. So to summarize, dangling pointers successfully detected uh stack and winding work a little bit work fine. Uh and then we are able to identify the owning uh logics the logics are the function that owns the the pointers basically uh and yeah that's yeah that's pretty much it for this one and uh I did the test for several use case for dangly pointers 15 use 11 sorry here but those are the basic ones like error path free there are some of the callbacks container misuse general uh global pointer cleanup so several use cases and it does work

perfectly for dangling pointer detection Uh I'm extremely satisfied with the u stack scanning uh part of it. Uh and then if you go to the next slide. Yeah. Now uh advanced use cases. So we took this concept and we said why not doing more stuff like for example uh adding the ability to analyze several symbols at the same time right? So I added the functionality here. If we play the video. Uh, so as you can see, this is the agrioi interface. Oh, here here I'm doing test on chromium by the way. We can stop. So I added a feature here that will list all the process chromium um processes. You can see the GPU, the

network. It's going to make things faster for me because the main target is chromium. Uh, this is where the money is, right? My father is reading. So, so I mean there is even a button to start chromium. No, no, it's very useful by the way. It will start it load the symbols and uh with send box disabled because you cannot instrument uh send boxed processes by the way. That's one of the drawbacks. Yeah, I mean it's not a big deal to be honest. And I can add other flags if needed. Uh but uh what you will see here is an example on how monitor or how can I add lot of symbols at the same

time. Uh so yeah we can play the video. All right. So here I'm gonna select the networking uh process in Chromium. It's running in the background if you see it. And then I'm going to provide um this is where I'm looking for the symbol. So it's a regular expression to find all the free symbols basically. Uh

It's going to take a while. Okay. So, here we are seeing like tens of freeze, right? A lot of free symbols in Chromium. I selected one randomly for the demo. This is SN1 and I can just add this symbol and I can keep adding a lot of symbols. So, if you want to study a lot of symbols at the same time, it's also possible and it's going to do the same logic. uh and sorry it's going to trigger lot lot of windows there because it's going to try to instrument all the subprocess in chromium at the same time and monitor all those symbols so to summarize uh no that's another demo okay but to summarize you can study a lot of symbols

at the same time but if we can do better why not if we can instrument all the symbols the 40 I mean 46,000 is what I was able to to get to get using the free keyword, but I'm sure there are at least 100,000 symbol in Chromium codebase that will result in freeing objects. So, if we can do this and monitor all of them, why not and detect all use after free at once and solve the problem once for all. So, that's what I did. Uh I started like extracting the 46,000 simple uh right it was not a good idea, but anyway. And uh this is not the entire list but just to do some tests. Uh and if we play the

video actually um work in progress. Okay. So oh sorry uh if we can pause here I use AI added models because okay so we have 46 symbols right they would trigger the free behavior but you you still need to trigger those symbols in your test right you need to trigger the free behavior right. So what I did I used edms to generate HTML and CSS and where to make sure that I can trigger the free automatically in all my tests. So this is the idea and that's why you see OpenAI at the end of this script name. But uh yeah so the script going to take all the symbols one by one instrument all chromium processes

and do the same logic and try to detect user basically. Um yeah here we are hooking the symbol in all the sub processes and as you can see uh there is a HTML file generated for this one. Um it did work great for some of the symbols. Sometimes the HTML code does not trigger the free behavior in some cases and I agree maybe there is an improvement there and maybe we can use anger uh maybe uh but uh yeah we will see but that was the idea uh work in progress. I got a lot of interesting use cases. I put some screenshots here and again I need to be careful because we don't know whether it's a true positive

or a false positive and I didn't have the time to triage it but we have a database also to log all the information like hey what is the symbol what is the process name where we analyze the symbol uh and where is the code that we use to trigger the free right uh yeah so I'm calling them quests because for each symbol I have an entire quest I need to trigger the free and scan the stacks But anyway, so work in progress. I have a lot of information to triage and maybe some CVES to report. Let's hope so. Or yeah, that's that's pretty much it for this one. Yeah.

Yeah. That's one of the example that I mean I have a lot. We are speaking about hundreds of but that's one example. Remove child node does make sense. I mean it will trigger like the free behavior basically right uh I'm hiding the name of the functions that it's holding you never know I don't want to go to jail especially now but uh yeah we need to triage all of those alerts I think after improving the concept we'll get less false positives more true positives and it does worth it to spend some time triaging those but now I don't know I mean I spent weeks trying to triage some of those I reported one by the way

>> and it was a true positive but it was reported on the same week actually I was going to include screenshots of the discussion with the coming back team but uh it was the same week like okay I didn't tell my father this but anyway so if we if we go to the next slide yeah so this is the summary okay I think we are doing good all the time so um yeah to summarize the key contributions and forward strategy news new use after feed detection method I think It's scientifically does make more sense than just fuzzing and using asan to uh print useful information. Uh we are outperforming fuzzing and asan under specific conditions when the logic

on the pointer at the moment when the free was called is the one that will trigger the use behavior. Uh yeah uh high accuracy in detecting dangly pointers. uh we demonstrated scalability when you saw like we did the test on like thousands of symbols. Um we leveraged AI to trigger the uh free behavior and we are currently studying improve improvements with anger uh to cover other user after free use cases. But those are the major key contributions and the forward strategy I would say and with that I think we are good with the presentation. Yeah. Thank you.

Any questions? Oh, yeah. Exactly. So, the plan exact. No, that's a good point. Uh, and my bad I didn't cover this. So, the plan is uh yes, I'm going to outsource the code. I need to work a little bit on the design. It's a very ugly uh quick interface to be honest. Any designers here can help. But other than that, yes, uh it's going to be open sourced. I would say to be honest we can open source it maybe before the improvements uh just to get more uh help in terms of improving the false positive and and false negative rate. Uh but yeah it's going to be uh open source. Yeah, maybe after I report some TVs and get

some money from my father. But yeah, of course.

>> Uh in your experience, how much does sandbox uh factor in preventing uh even if you find a valid >> uh for use for use after free I I'll be honest. I mean in the presentation we didn't cover a lot of exploitation techniques but for me I mean if you go through the backtracker uh and you see like some some of those are being reported for sandbox processes so I would say so in order to prove something is uh an assumption is wrong because the assumption here is does sandbox prevent this right in order to prevent the assumption is wrong we just give one counter example which is hey there are few user reported for sandbox processes

right so I don't think it's useful today scientifically speaking right Maybe it's trying to add a few use cases, but uh yeah, >> if if you found a user for free in a sandbox process, >> you're going to get more money. Let's see. >> No, seriously. I mean, yeah, you will see even in the title in sandbox or discussion maybe >> unsandboxed is more valuable. >> Yeah, of course. Yeah. Yeah. Any other questions? Yeah. Is this portable to other native compiled languages or is this very exclusive to just C++ programs? >> Uh okay. So that's a good point. So uh this is a I would say language independent approach. Um however there is a good point to mention

here. Um it's about the need for the debugging symbols. I didn't cover this in the presentation. You don't really need debugging symbols for the program that you are analyzing with the exception of one debugging symbol which is exactly which is for the free that you are yeah so in other words imagine you have a small program you wrote with like C C++ the debugging symbols for your program are not needed but your program would be loading DLS that contain the definition of free and those debugging symbols are needed uh but uh it's it's language independent Yeah. Any other questions? >> Sure. Anger team, >> why did you need to write your own unwinder? What's wrong with you?

>> Yeah. Okay. >> If they're in the room, they're going to be very hurt. >> Yeah. So, that's why I like working with them. I mean, they are very knowledgeable. But here's here's what I at least what I learned. I like I watched presentations about persons wrote their own and so on. I'm I'm using freedom, right? So basically what I'm doing is I'm taking the program and I'm injecting JavaScript. I'm not sure how I can call lib and winder in the JavaScript that I injected in code, but if I can do I I think it's going to do much better than what I did. Of course. Yeah. Okay, good. Thank you.