Skip to main content0xAdham

Command Palette

Search for a command to run...

BYUCTF: Incontinent

Written by
Avatar of 0xAdham
0xAdham
Published on
--
BYUCTF: Incontinent

Platform: BYUCTF Challenge: Incontinent Category: Pwn Difficulty: Easy

Flag

byuctf{incontinent_is_one_of_my_favorite_words_lol}

Target

<remote-host>:1366. Local incontinent_dist prints a placeholder; real flag is in the same stack slot on the remote.

  • ELF 64-bit, non-PIE (EXEC), NX on, dynamically linked, not stripped.
  • Prompt: "I've got the flag securely locked up, anything you want to say to it?" Hint: "make it a little more leaky" + the name Incontinent → an info leak.

Recon

main builds a local string on the stack (movabs immediates) at [rbp-0x70]:

"the real flag will be here on remote. If you can see this, try what you just did on the remote server"

Then:

rodata confirms the format strings: "You said: ", "%s", "\nHave a nice day".

The bug: not format string, missing NUL

The printf uses a fixed "%s" with input as the argument, so format specifiers in the input are not interpreted. The classic format-string bug doesn't apply. The real flaw: read never null-terminates, and printf("%s", input) walks memory until it hits a \0.

Stack layout (rbp-relative):

Send exactly 32 non-NUL bytes: read fills [rbp-0x90, rbp-0x70) with no terminator, so %s prints my 32 bytes and continues straight into flag_buf, dumping the flag until its own NUL.

  • Too few bytes → an uninitialized NUL in the gap stops printf early (short input leaks nothing).
  • Too many (>32, up to 50) → starts overwriting the flag's first bytes.
  • 32 bridges the gap exactly. No newline (it's read, not fgets).

Solution

Local test leaks the placeholder; remote leaks:

Takeaways

  • read(fd, buf, n) does not null-terminate, so any later %s/strlen/strcpy on that buffer over-reads into adjacent memory. Pad to the exact distance of the secret to bridge the gap deterministically.
  • "format string" instinct can be a bait: check whether user input is the format (printf(buf)) or just an argument (printf("%s", buf)). Here it was the latter, and the bug was termination, not specifiers.
  • Compute the leak distance straight from the frame: input @ rbp-0x90, flag @ rbp-0x70 → 32 bytes.
  • The name is the spec: incontinent = can't hold it in = it leaks.

0xAdham

Edit on GitHub
Last updated: --