Skip to content

Latest commit

 

History

History
86 lines (59 loc) · 5.36 KB

binary-exploitation-methodology.md

File metadata and controls

86 lines (59 loc) · 5.36 KB
description cover coverY
10/02/2023
0

📖 Binary Exploitation Methodology

Binex Methodology 101

Know Your Target

  1. Identify your target.
  2. Identify it's attack surface and gain a better understanding of what the best course of action is.
  3. What memory protections are in play?
  4. Is the binary x86 or x64?
  5. Do you have source code?
  6. "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.
  7. Ask yourself what is it's purpose? Can we send the program data?

Identifying Crucial Information for Exploitation

  1. file <binary> -- What is the architecture? Stripped or not stripped? Dynamically or statically linked?
  2. checksec <binary> -- RELRO? NX? Canaries? PIE?
  3. strace ./binary -- What syscalls are being made?
  4. ltrace ./binary -- What external functions are we seeing from dynamic linking (as long as we're dynamically linked)?

Static Analysis (Reversing)

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!!!

Dynamic Analysis (Debugging)

Load the program in your debugger of choice, I prefer pwndbg.

  1. List out functions: info functions
  2. View disassembly of lucrative functions and take note of their EBP/RBP address: disass foo or disass main
  3. Break at certain points in the program or break at a certain address: b main or b *0xf7da2150
  4. Run the program: r or run with arguments (sometimes needed) r <arg_here>
  5. Step through current instruction: si
  6. Jump to next instruction: n
  7. Print out your stack, ask yourself if you see anything important (e.g. AAAA's or 0x41414141): x/60wx $rip or x/60wx $eip or x/60wx $ebp or x/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.
  8. Does the program take input? Can we overwrite data?
  9. Identify the buffer or argument that we can overflow and it's size -- say the buffer size if 128 for this example.
  10. Generate a cyclic pattern: cyclic 200
  11. Copy/paste the cyclic pattern and send it to the input of our program
  12. At what point does it overwrite the EBP or RBP? Grab that string.
  13. Find the offset to EBP or RBP: cyclic -l <string_here>
  14. It is at this point where we can verify the information we found above in our static analysis!
  15. 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.

Questions to ask Yourself

  1. How does the target binary consume data? gets(), scanf(), etc.
  2. Where does the data go in memory? Statically on the stack or dynamically on the heap with malloc() for example?
  3. How much data do we need to get to the return address? How far is the buffer from the return address?
  4. 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)?