The simplest way to exploit stack buffer overflow (i.e. when there is no mitigation like DEP, stack canary, or ASLR) is to overflow the buffer and overwrite the return address in the current stack frame.

The simplest way to exploit buffer overflow (when there is no stack protection) is to overflow the buffer and overwrite the return address in the current stack frame.

  • Figure out the address of the buffer by filling the input with something identifiable, like the pwntools cyclic pattern (which is a De Brujin sequence).
  • Figure out the value of EBP when buffer is being written to, since EBP points to the return address. Use a debugger for this, such as gdb (info registers) or Immunity Debugger (top-right panel).
  • Calculate the offset — the difference between the start of the buffer and where EBP points to. This is the length of the padding.
    • Attach debugger to process, or run the program using the debugger (normally you would want to set a breakpoint so that the program doesn’t exit)
    • Use cyclic(large_number) to overflow the buffer
    • The debugger should have the value of the RIP / EIP when the program crashed. Reverse the byte-order (if the architecture is little-endian) and feed the bytes into cyclic_find, i.e. cyclic_find(b'\x61\x61\x61\x61'). This will return the buffer index at which the desired return address should be injected. The number is also the length of the padding buffer.
  • Add the desired return address to the padding at the specified location. Remove the rest of the buffer if possible.
    • To specify an address, use pwntools’s p32 and p64. Each accepts the address as a number (e.g., 0x12345678). The returned value will be the correctly represented address for the endianness (set with context, little-endian by default).
    • Refer to the runtime’s calling convention for passing function arguments.
  • Feed the payload to the executable. When the vulnerable function returns, the processor will set the instruction pointer EIP to the overwritten return address.