how2pwn?
At some point, everyone has their own method as to how to approach a CTF pwn challenge. However, when you're starting out, it is perfectly normal to find yourself totally lost when faced with a program and unsure as to where to begin looking or what to do.
A Textbook Approach to Pwn
If you already have some experience in doing Pwn challenges and are fairly confident in it, feel free to move ahead and skip this section!
If you are totally new and need a guideline on how you can best approach a challenge, this is for you. We will explore a 5 step process on how we can approach and attempt to solve a pwn challenge.
- Running and Fuzzing the Program
- Analyzing the Source Code
- Understanding the Exploit
- Writing the Exploit
- Debug your Exploit
Let's see what each of these steps entails.
1. Running and Fuzzing the Program
Fuzzing is when we provide invalid, malformed, or unexpected inputs into a system to reveal software defects and vulnerabilities. (i.e. large strings, negative integers etc.)
In short, we try to input as much nonsense as we can to break a program!
Running the program is extremely important as it helps us gain a very quick understanding of the program functionalities.
Fuzzing the program helps us to potentially find bugs in a program quickly. If we are able to crash the program, it might imply that there is a vulnerability that we can exploit!
2. Analyze the Source Code
Running the program only shows us what the program wants us to see, but we are blind to other things that the program may be doing under the hood.
We will have to analyze the code of the program to gain a better understanding of how the program works. This is known as static analysis.
-
If the program crashed in step 1, this is where you triage and find out what bug is present in the program.
-
The idea of source code analysis is to have a brief understanding on what each function does in general.
When we try to look for vulnerabilities in a source code, one tip is to look out for inputs that a program takes in. Are these inputs vulnerable? This could be our entrypoint to triggering a bug!
If the source code is not provided to us, we will have to go one step further to use a tool such as IDA/Ghidra to reverse engineer the program. Find out more here
3. Understand the Exploit
If you have reached this stage, it means that you have already found a vulnerability from the previous 2 stages.
Ask yourself some questions:
-
What kind of vulnerability is it?
-
What does this vulnerability allow us to do?
-
What is our end goal and what do we want to accomplish?
Start planning how you can make use of the vulnerability to accomplish your objective.
4. Writing the Exploit
We typically write our exploits using the pwntools
python library.
pwntools
is a python library that is used to easily interact with executables/remote services and also comes with many convenient functionalities specific to pwning.
You can find a pwntools guide here, but ultimately, you will only become familiar with it through practice.
5. Debugging the Exploit
Most of the time, even if we have planned out and written our exploit, it is not going to work out of the box.
A huge part about writing exploits is also the ability to debug it. Attach your debugger to your pwntools script with gdb.attach(p)
.
Using the debugger, why did the program crash? What instruction did it crash on?
What are you expecting to see in your debugger? (i.e. if doing ROP, you expect to see your ROP chain at the ret
instruction on the top of the stack)
Does your exploit work as intended? Why not and how can we fix it?
Conclusion
Definitely, if you are a pro and have your own workflow, then you don't have to strictly follow this. This is merely a recommendation for beginners who are totally lost.
Most of the guides in this chapter will follow the structure covered above.