From CTFs to Real-Exploitation (Part 3)
This is Part three of our series on going from the basics of exploit development to real-world targets. Its my take that once you have the foundations of exploit dev, you need to pair that with a good, intuitive understanding of vulnerabilities. That understanding then gets applied here in bettering your exploit development. We covered getting started with vulnerability research to improve your exploit development in Part 2
There is an accompanying YouTube discussion where we talk about all the following points and have more of a back-and-forth discussion.
As with the others, this is an opinionated take, and there is no one “right” way to go about it. Ultimately, you need to follow your own motivations because that is the biggest difficult I see facing people.
The Bad News
There is a well-trodden path for the basics of exploit development. Everyone seems to have their own vanilla buffer overflow tutorial, the path up to ROP is pretty well-defined. After that the path poorly defined, part of that is because there is an agreement and understanding of what the foundational concepts are. Once you have that foundation though you can go off into many areas.
There is no one path forward, instead, it’s dictated by your targets. When you run into a vulnerability that say corrupts heap meta-data then you start digging into heap allocator vulnerabilities, when you run into some new mitigation you research it. Especially on modern hardened systems, exploits become more target specific it’s not just an infoleak + control flow hijack and ROP, but chaining smaller primitives together in creative ways to get there now. You have to learn how to learn and power through the frustration of not knowing.
The Good News
The good news though is that once you have those foundations, all of exploit development really is approachable to you. You can totally do this. In my opinion, it is about getting the right type of practice now, and target specific knowledge. The hard part is getting your head around the generalized exploitation concepts.
Once you get the basic primitives you might gain, its a bit like Lego, you’re putting the pieces together to build your exploit. It takes creativity to determine how to build what you need from what you have, and how to work with the existing structure. Once you understand the basic pieces, you can gain experience through practice to develop an intuitive understanding through exploration. That exploration is important, as with the purpose of vulnerability research, the idea is still about having an intuitive understanding of vulnerabilities. From that you can begin reasoning about exploitation and putting the pieces together.
Missing Skill - Developing Strategies
We could call out other skills that CTFs and toy binaries don’t really teach, and there definitely are other skills that are important. The ability to discover and create your own exploit strategies though is the most crucial skill to develop.
Once upon a time the advice was to find other exploits and reimplement them. That was solid advice when the goal there was to understand ROP, or using an info-leak to deal with ASLR. These sorts of high-level, generic techniques could be learned through the copying process as they can be widely applied. More recent exploits tend to be more complex, things like data-only attacks or chaining weaker primitives into something more reminiscent of older exploits. These require a much better understanding of your target to recognize places you can gain new primitives from, and understand the data that exists and reason about how it can be useful for exploitation.
I’d argue that while reimplementing old exploits is a good practice, there are some steps you can take to develop the creativity you need as well.
Choosing a Target
As mentioned at the start, your target will dictate the knowledge you need to pick up. So let’s talk about choosing your first targets.
Interest. Just like vulnerability research, choose something that you’re motivated to learn about. You’re going to be deep-diving into this software, make it something you’re actually interested in. Again, Do what excites you.
Open Source. Again, just like vulnerability research, focus on one skill at a time. Learn to find primitives and gadgets in source code, reverse engineering just becomes an addition step being added to the process and hurts learning the skill.
History of Public Research. Unlike vulnerability research this time as you’re getting started you’ll want to choose something that has some public research. Your first few times trying to work out your own strategies you’re going to be glad to build off the shoulders of previous work and gain inspiration from them.
Procrastination Project. Sometimes it helps to switch to something else and have your mind work on something else for a time. I tend to call this my procrastination project, it’s the project I work on when I want to procrastinate working on the project I’m supposed to work on. It gives you something else to think about when you’re stuck, and exposure to other paradigms that you might not see if you focus on a single target. Exposure to new ideas is definitely a plus.
Three Strategies for Practice Developing Strategies
While we present these options in a sort of linear way, don’t treat it as a ladder that you grow from one to the next. There is a progression but recognize the unique skills each focuses on. If you notice that you’re lacking in one area, practice that skill.
Follow a Write-up, then add your own twist
In this section I am hand-waving the actual practice of finding new strategies and talking about higher-level how to practice it. I will get into more specific after this section.
Especially at the start, just find a somewhat recent writeup of a vulnerability, make sure its something that isn’t too direct in terms of exploitation, and reimplement it directly. As a first step, this is just really to prove to yourself that you can understand and approach modern exploits. By looking at existing exploits you’re also going to get exposed to some of the already known tactics. You’ll often find that even with highly complicated exploits containing multiple layers of primitives, they converge upon certain common targets and tactics. You’ll of course get to learning to find them on your own too, but having some inspiration to draw from helps.
Once you’ve followed the write-up, you’re going to want to practice applying your own creativity. Add your own twist to these exploits. Hopefully, you chose something with at least a couple stages. Change a gadget out and come up with your own replacement. There are a lot of ways to do this, and you shouldn’t always target replacing the same part of an exploit.
If you’ve got an info-leak, try leaking something else, try coercing the heap/stack into leaking something else, or reading another segment of memory. Then build an exploit off something else that you can leak.
If its a write-primitive, find a new write-target.
UAF, find a new object for the reuser, or maybe a new after-free path.
Add a self-imposed restriction, deal with a mitigation even if its not implemented
Require stability or portability
The intent here is to get practice exploring software to spot new gadgets and primitives you can chain with the vulnerability. Finding these alternatives is the same skill as trying to find it in the first place, but by working with a writeup you already know about what will definitely work so you don’t need to worry about some of that yet. This will be insanely frustrating when you don’t see any alternatives but fight through it. Frustration is part of this work; embrace it.
Write-up as a Hint Sheet
Find a write-up but use it only to understand the crash and vulnerability. For the exploitation, use it only if you need to, and only to get yourself unstuck.
This is to give you some practice figuring out how to first abuse a vulnerability for your first primitive and gadgets without being biased by knowing how it was done before. You should also keep going onto the first chain, but if you find yourself getting stuck early, just going and trying to implement a first gadget or so can be a useful way to practice.
Starting with a CVE or Crash Report
This is going to tie in a bit with your vulnerability research skills and triaging vulnerabilities. Start off with just a crash, or a CVE with enough information for you to reproduce the crash. You don’t want the root cause of the vulnerability spoiled for yourself though. There are two purposes here, one is to try and find new primitives to be gained from a single crash, sometimes there isn’t one, that’s for you to practice figuring out. The other part of this is just triaging, which is more of a vulnerability research skill but figure out if the crash is exploitable or worth investing the time into trying to exploit.
What’s interesting here is to track your own predictions, at first it might feel like a shot in the dark but with some experience over time you’ll notice that you have an intuition about the exploitability of something. No way to get there without just doing it though. So track your prediction and track your correctness. Pay attention to whether or not someone else produced an exploit for it once you’ve declared something non-exploitable. If someone does, go back and figure out what you missed. I think seeing what you missed is one of the most useful tricks to furthering your own ability honestly but it’s not something you can really count on.
Developing Exploit Strategies and Techniques
I’ve talked plenty about how to practice doing this but how do you actually do it.
Time spent in reconnaissance is seldom wasted
I used this quote during the vulnerability research post also, but taking the time early on to explore and just play with the application pays off in end. The better your understanding of the entire system and ability to reason about it, the better prepared you’ll be to spot potential gadgets.
That is what you’re really doing here: spotting gadgets. You have a vulnerability that grants you a vulnerability-specific primitive. Something like you can overflow into adjacent memory with controlled data, you can read OOB at an aligned address, or decrement arbitrary memory, whatever. Now you draw on your understanding of the system architecture to determine where using that primitive to corrupt, disclose or otherwise do something useful which is your gadget.
Without taking the time to understand the system, you are blind when doing that.
I find it useful to write things out, actually I’m a white-boarder I draw and graph everything out and visualize it on a whiteboard next to my desk. Do what works for you.
Write out exactly what you have, especially when you have multiple primitives.
Write out potential gadgets you’ve seen but don’t have a primitive for
Write out what you want
Connect the dots, brainstorm ways to get from what you have to what you want. Toss in the absurd and crazy ideas get it all out.
Eliminate the impossible. After the ideas have been written, start eliminating them with concrete reasoning. It’s important to note why because your assumptions might be wrong and you’ll want to return to them once you’ve gained a gadget.
Be Creative and Answer your own Questions
This is probably my most important tip and the one that leads to the most exploration and intuitive understanding. While learning (its less practical to do this if you’re working under time constraints such as on a job) if you ever think to yourself “What if I...” or “Could I...” or something like that and you do not know the answer.
Drop everything and find out.
These are the rabbit holes you want to go down, because if you have the question once you’ll probably have it again. Take the time and just answer it. Going down these rabbit holes really adds up to a wealth of knowledge over time if you do it consistently. The more you do it, the more questions you’ll be able to answer too.
Take breaks liberally
I know “Try Harder” is a common phrase in this industry, but I prefer “Be Lazy.” Take your breaks, take care of yourself. I’ve found time and time again that coming back to a problem after a break I’m much more productive than if I suffer through it. I’m not sure if there is a psychological reason for it, but it feels to me like I just put a task in the background but my brain keeps working on it. I’ve learned to just take breaks and do something non-exploit related. Watch a movie/YouTube, read, take a walk whatever, just get your mind off it and come back when you’re less frustrated and more relaxed/refreshed.
It’s also important not to get burned out. Grinding away too much at a problem without taking breaks to the point of boredom can ultimately lead to less productivity in the long run. Again, this ties back with motivation, don’t let a problem drain the motivation out of you.
Take Inspiration From the Work of Others
So, in combination with the practice ideas above, you don’t want to spoil yourself but you can gain inspiration from exploits on other systems. While I don’t do any browser exploitation, I’ve drawn many ideas from browser exploits. If you’re stuck, just go read some writeups on random platforms you never know where you’ll get inspiration from.
Related to this, there is benefit to the struggle also, deriving concepts on your own will bring about a much deeper understanding. You shouldn’t always jump right to hunting for inspiration and the solutions of others every time you struggle. It is going to be your call on how much frustration you can take, but it is important to do both, getting exposure to the work of others, and figuring things out yourself.
Pay Attention To What Is Going On
This aligns with getting inspiration from the work of others, but read writeups, pay attention to what’s going on at conferences (hacker cons and academic). This is a bit of self-promotion but we do a weekly podcast (September through May) covering the latest vulnerabilities, exploits, research and whatever we find interesting. Working on that podcast over the last couple years has exposed me to a lot of new ideas, and my hope is to share that with the listeners. Of course there are other sources of information. As part of preparing the podcast, I follow a lot of feeds and I’ve aggregated some of the best into a single feed: 0dayfans.com there is a feeds.txt containing a list of specific blogs to check out.
As always, if you disagree, or have questions, we love the discussion. Join us on discord.
And as a parting thought if you’ve gotten this far, this is a a frustrating field, you need to learn to embrace your frustration accordingly. It gets easier, but it’s rarely easy. Those easy moments come from a lot of frustrating moments. Enjoy it.