description | cover | coverY |
---|---|---|
10/02/2023 |
0 |
- Identify your target.
- Identify it's attack surface and gain a better understanding of what the best course of action is.
- What memory protections are in play?
- Is the binary x86 or x64?
- Do you have source code?
- "Play" with the program, what is it's purpose? -- This will help us contextualize the purpose of the program and for us to be able to understand it's logic. Make sure you're in a safe environment (e.g.) a VM that's not "NAT'd" to your host's connection if you are not sure about the binary's origin.
- Ask yourself what is it's purpose? Can we send the program data?
file <binary>
-- What is the architecture? Stripped or not stripped? Dynamically or statically linked?checksec <binary>
-- RELRO? NX? Canaries? PIE?strace ./binary
-- What syscalls are being made?ltrace ./binary
-- What external functions are we seeing from dynamic linking (as long as we're dynamically linked)?
What can we see when we throw our binary in Ghidra or IDA?
NOTE:
If our binary is stripped, it will be stripped of all debugging symbols and we will need to find the entry point of our program and start from there and find main()
.
If our binary is not stripped, we will be able to immediately identify main() as well as other functions. At this point, it is important to identify lucrative functions needed for our exploitation process.
Start off by using context gained from our steps above in an attempt to further contextualize the binary's purpose and begin renaming variables, functions, and making data type conversions to make understanding the program easier on your eyes.
Leave comments on where you believe there may or may not be a vulnerability.
Can we see canaries in our program in the Assembly or decompilation (pseudocode)?
Take note at which function will give us our offset to EBP
or RBP
as this will aid in our padding for our exploit:
So, what can we gain from this?
We see that 0x4c
is the hex value of our EBP.
Let's convert that to decimal:
We get 76, how crazy is that??
We can further verify this with Dynamic Analysis and using a cyclic pattern to see where we begin to overwrite!!!
Load the program in your debugger of choice, I prefer pwndbg
.
- List out functions:
info functions
- View disassembly of lucrative functions and take note of their
EBP
/RBP
address:disass foo
ordisass main
- Break at certain points in the program or break at a certain address:
b main
orb *0xf7da2150
- Run the program:
r
or run with arguments (sometimes needed)r <arg_here>
- Step through current instruction:
si
- Jump to next instruction:
n
- Print out your stack, ask yourself if you see anything important (e.g. AAAA's or 0x41414141):
x/60wx $rip
orx/60wx $eip
orx/60wx $ebp
orx/60wx $esp
-- this will print out 60 words in hex from the instruction pointer, base pointer, or stack pointer. Just keep track of which architecture your binary is so it might be$ebp
or$rbp
, for example. - Does the program take input? Can we overwrite data?
- Identify the buffer or argument that we can overflow and it's size -- say the buffer size if 128 for this example.
- Generate a cyclic pattern:
cyclic 200
- Copy/paste the cyclic pattern and send it to the input of our program
- At what point does it overwrite the
EBP
orRBP
? Grab that string. - Find the offset to EBP or RBP:
cyclic -l <string_here>
- It is at this point where we can verify the information we found above in our static analysis!
- We can then use this information to begin building out our padding for our payload to deliver an exploit to the program and help us meet our goal.
- How does the target binary consume data?
gets()
,scanf()
, etc. - Where does the data go in memory? Statically on the stack or dynamically on the heap with
malloc()
for example? - How much data do we need to get to the return address? How far is the buffer from the return address?
- Where do we need to divert execution to? To a function such as
hackme()
? A reverse shell at the start of our buffer (if the NX-bit is not set and we have an executable stack)?