# Bearcat CTF 2025

Hey, fellow hackers! 🏴‍☠️&#x20;

Today, I’m dropping a writeup for the Bearcat CTF 2025 challenges!️. I teamed up with my squad, *P4rad0x.* Let’s jump straight into the action! 🚀

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FmgMiDr8axuNfHZQf2IYn%2Fbearcatctf%20team.jpg?alt=media&#x26;token=ce004a24-5e58-4f91-b6a2-9630ee05d6b6" alt=""><figcaption><p>P4rad0x Team</p></figcaption></figure>

## Web

### Global Redirect - 100

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FrXQmFJJVACLbiy8XE2Pe%2Fglobal-redirect.jpg?alt=media&#x26;token=825b71b8-ddcc-40f5-9cee-cecf4003b8cd" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

At first glance, it looks like a **boring** old login page to me. But, there’s always something more beneath the surface. Let’s break it down!

The challenge presents us with a simple login page asking for a username and password. My first instinct? I decided to peek at the **page source**&#x20;

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FvT32r7lLlZCLH1YfM7dl%2Fglobal-redirect_exp.jpeg?alt=media&#x26;token=f198a9ed-4188-4cb2-96db-fe5ca52a726a" alt=""><figcaption><p>View Page Source</p></figcaption></figure>

and found something *very* interesting—**a JavaScript script handling authentication!**

```javascript
<script>
  function loginAuthenticate(){
    var password = document.getElementById("password");
    var hash = sjcl.hash.sha256.hash(password);
    var hexRepresentation = sjcl.codec.hex.fromBits(hash);
    if (hexRepresentation == "2a70282a868c0ca9e6fe5bb5cf2ac2ea6b523062102bada26fb87091d511e3f1"){
      alert("welcome Home Admin");
      window.location = "./0078f62f00305b73de6ccace8f9fc1f68a8f1dcec865d33fcacbaf255ddefaa7";
    }else{
      alert("Incorrect Password. Please Try Again");
    }
    alert(hash);

  }
</script>
```

Now, what’s happening here?

1. The script takes the password entered by the user.
2. It **hashes** the password using **SHA-256**.
3. It compares the hashed value with a **hardcoded** hash.
4. If it matches, it redirects the user to a new page.

**Key takeaway:** The password isn't checked on the server

The script reveals the secret **redirect location**:

```
http://chal.bearcatctf.io:39724/0078f62f00305b73de6ccace8f9fc1f68a8f1dcec865d33fcacbaf255ddefaa7
```

Visit the URL, the admin page was wide open, and sitting right there was our **flag**:

**BCCTF{T1ck3t\_t0\_0wn3rsh1p!}**

## Reversing

### Say Cheese - 150

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2Fz19NvNr718azQ4KtlLue%2Fsay_cheese.jpg?alt=media&#x26;token=07ea9333-a81b-4859-aff7-4417bd717bef" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

In this challenge, A **Python script**, it is a simple flag checking program.&#x20;

In that the **ciphertext, key and the encoder function** is given, Let’s break it down step by step!

{% code overflow="wrap" %}

```python
import base64

def encoder(input_str, key):
    encoded_chars = []
    for i in range(len(input_str)):
        key_c = key[i % len(key)]
        encoded_c = chr((ord(input_str[i]) + ord(key_c)) % 256)
        encoded_chars.append(encoded_c)
    encoded_str = ''.join(encoded_chars)
    return base64.b64encode(encoded_str.encode()).decode()

def main():
    print("""         _--"-.
      .-"      "-.
     |""--..      '-.
     |      ""--..   '-.
     |.-. .-".    ""--..".
     |'./  -_'  .-.      |
     |      .-. '.-'   .-'
     '--..  '.'    .-  -.
          ""--..   '_'   :
                ""--..   |
                      ""-' """)
    ciphertext = "wpbCi8KIwpfCh8OPwph5wqnCosK6woTCqcKnwq13wrfCh8KzwqnCpMKKccOJwrh8wqTCl3LDgcKHw4U="
    key = "THECAT"
    inp = input("Enter your cat: ")
    encoded_flag = encoder(inp, key)
    if ciphertext == encoded_flag:
        print("YAY you found the cat!")
    else:
        print("Not so easy cheesy huh?")

if __name__ == "__main__":
    main()
```

{% endcode %}

In this Python script, it does the following:

1. **Takes user input** (a string).
2. **Encodes** it using a function called `encoder()`.
3. **Compares** the encoded result to a hardcoded `ciphertext`.
4. If they match, it prints **"YAY you found the cat!"**, otherwise, it denies us.

Here’s the important part—the **encoder function**:

```python
def encoder(input_str, key):
    encoded_chars = []
    for i in range(len(input_str)):
        key_c = key[i % len(key)]
        encoded_c = chr((ord(input_str[i]) + ord(key_c)) % 256)
        encoded_chars.append(encoded_c)
    encoded_str = ''.join(encoded_chars)
    return base64.b64encode(encoded_str.encode()).decode()
```

It’s basically **modifying each character** of the input based on the key **"THECAT"**, then encoding it in **base64**.

Since I don’t know the **original input** that produced the given **ciphertext**, I need to **reverse** the encoding process.

Looking at the logic:

* Each character in the input string is **shifted** using `(ord(input[i]) + ord(key[i % len(key)])) % 256`.
* To undo it, we just **reverse the shift**:

{% code overflow="wrap" %}

```python
import base64

def decoder(ct, key):
    d_b64 = base64.b64decode(ct).decode()
    d_chars = []
    # print(len(d_b64))
    for i in range(len(d_b64)):
        key_c = key[i % len(key)]
        d_c = chr((ord(d_b64[i]) - ord(key_c)) % 256)
        d_chars.append(d_c)
    return ''.join(d_chars)

ciphertext = "wpbCi8KIwpfCh8OPwph5wqnCosK6woTCqcKnwq13wrfCh8KzwqnCpMKKccOJwrh8wqTCl3LDgcKHw4U="
key = "THECAT"

flag = decoder(ciphertext, key)
print("FLAG:", flag)
```

{% endcode %}

**BCCTF{D1d\_y0U\_h4v3\_a\_G0ud4\_T1m3}**

### Easy - 300

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2F0Mlc2UKQaChAwdy4OJkW%2Feasy_encrypt.jpg?alt=media&#x26;token=7f1efe50-28a0-43b8-9529-1883e52ebfc0" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

In this challenge, I am going to do a simple reverse engineering.

I am given an **ELF executable file**. This file prompts for user input and checks if it matches a hidden flag.

To peek inside, I uploaded the binary into **Ghidra**—a powerful tool for reverse engineering. I navigated to the **main function**, and guess what❓&#x20;

There were a bunch of interesting lines dealing with variables and a mysterious XOR function!

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FmLik6FRLCRTEE9TOFDAz%2Feasy%20ghidra.png?alt=media&#x26;token=57d1cbfe-c472-41ab-807c-63ac84c36d65" alt=""><figcaption><p>Main Function</p></figcaption></figure>

**XOR** is a common trick used to encrypt and decrypt data. The program had a set of encrypted values, and it used a key to **XOR** them back into the original flag.

Here's how it worked:

* The program stored some values in variables.
* These values were passed into the **XOR** function along with a **key** (0x37333331).
* The function returned the decrypted result, which was then compared with user input.

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FBUUnhmKSI8tT9neD2aYC%2Feasy_ghidra3.jpeg?alt=media&#x26;token=b0cd0eb2-4c49-472d-939f-2e86850eec88" alt=""><figcaption><p>Xor Function</p></figcaption></figure>

I found these values in the program:

```c
local_168 = 0x7f04487763707073
local_160 = 0x435d4005406c0405
local_158 = 0x734107796803406e
local_150 = 0x4c
```

Using Python’s `struct` module, I wrote a simple script to change the format to little endian.

{% code overflow="wrap" %}

```python
import struct

local_168 = 0x7f04487763707073
local_160 = 0x435d4005406c0405
local_158 = 0x734107796803406e

def to_little_endian(value):
    return struct.pack("<Q", value)

hexa = to_little_endian(local_168).hex() + to_little_endian(local_160).hex() + to_little_endian(local_158).hex() + '4c'

print(f"In little-endian: {hexa}")
```

{% endcode %}

This gave me the properly formatted encrypted flag. Using CyberChef’s **XOR operation** with the key 1337, I decrypted the hidden message.

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FwbMicTRA7j97rha06N5M%2Feasy_flag.png?alt=media&#x26;token=b0b8fb62-da77-4cd9-9fac-7cadecedaf08" alt=""><figcaption><p>CyberChef</p></figcaption></figure>

**BCCTF{7H47\_w4snt\_s0\_H4rD}**

## Miscellaneous

### What you see - 200

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FgSur4xXwelXMGh3fey7k%2Fwhatyousee.jpg?alt=media&#x26;token=c9e49f0a-fd1c-42b2-b631-c5dc35bfef45" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

The challenge, **"What You See"**, gave me just a simple image file.

First things first, I ran the usual checks:

🛠 **`exiftool`** – Nothing suspicious in the metadata.\
🛠 **`file` command** – Just a regular JPG file.

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash"><strong> r1pp3r 🔱 god2eye ~/Documents/CTF/bearcatctf25 
</strong>  λ file CtfProblem.jpg 
CtfProblem.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 1080x1080, components 3
 r1pp3r 🔱 god2eye ~/Documents/CTF/bearcatctf25 
  λ exiftool CtfProblem.jpg 
ExifTool Version Number         : 12.76
File Name                       : CtfProblem.jpg
Directory                       : .
File Size                       : 261 kB
File Modification Date/Time     : 2025:02:02 01:20:13+05:30
File Access Date/Time           : 2025:02:03 14:12:20+05:30
File Inode Change Date/Time     : 2025:02:02 02:03:53+05:30
File Permissions                : -rw-r--r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : None
X Resolution                    : 1
Y Resolution                    : 1
Image Width                     : 1080
Image Height                    : 1080
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:4:4 (1 1)
Image Size                      : 1080x1080
Megapixels                      : 1.2
</code></pre>

Hmm… no easy giveaways. Time to **dig deeper**!

Since the challenge hints were **"Inspect, Extract, Reveal"**, I tried 🛠 **StegSolve**, a tool that used to analyze images in different planes by taking off bits of the image.

After sometime, Setting it to **"Red Plane 6"**, I saw a **hidden message in the image**:

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2Fj6Mx6tXaj8j7S4dt002f%2Fwhatyousee_pass.png?alt=media&#x26;token=deec9970-12dd-4055-be21-325e1732d3ec" alt=""><figcaption><p>StegSolve</p></figcaption></figure>

`📝'the password is "ctf"'`

Now, we had a **password**—but for what? 🤔

Knowing the file might contain **embedded data**, I turned to 🛠 **StegHide**, a steganography program which hides bits of a data file in some of the least significant bits of another file in such a way that the existence of the data file is not visible and cannot be proven.

<pre><code><strong> r1pp3r 🔱 god2eye ~/Documents/CTF/bearcatctf25 
</strong>  λ steghide extract -sf CtfProblem.jpg 
Enter passphrase: 
wrote extracted data to "secret-text".
</code></pre>

It asked for a password. **I entered "ctf"**, and **a hidden file popped out!** 🎉

Inside the file **"secret-text"**, there it was—the **flag**! 🏁

**BCCTF{w34k\_s4uc3\_4\_u}**

## Cyptography

### Seeing Triple - 400

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FONN7y00Eb1lbRd2IO24u%2Fseeingtriple.jpg?alt=media&#x26;token=907e875e-9be7-4367-a7ec-ad4a5d390129" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

This one had me **seeing triple**—literally! The challenge, **"Seeing Triple"**, dropped a text file on us that looked like a **wall of 3’s**.

{% code overflow="wrap" %}

```
33333333333333343333333333333332333333333333333433333333333333333333333333333334333333333333333333333333333333353333333333333334333333333333333433333333333333363333333333333337333333363333333233333333333333343333333333333339333333333333333733333333333333343333333333333337333333333333333333333333333333353333333633333336333333333333333433333336333333313333333333333337333333333333333533333333333333373333333333333333333333333333333233333333333333333333333333333335333333363333333633333333333333343333333333333338333333333333333333333333333333333333333333333337333333333333333833333333333333373333333633333334
```

{% endcode %}

At first glance, the file was packed with **endless 3’s** and a few other numbers sprinkled in. The challenge name hinted at **threes everywhere**, so my first move was to **remove all the 3’s**.

❌ **Bad idea.** That left me with nothing useful.

Hmm… maybe the 3’s weren’t just noise? 🤔

Instead of removing **all** the 3’s, I looked for a **pattern**. Turns out, **"3333333"** (a long chain of 3’s) was acting as a separator!

By **removing those big clusters** before each different number, I was left with:

```
3432343334333534343637623439373437333566346137353733323335663438333337383764
```

This looked **a LOT like hex!**. I used the **xxd** command to convert back into **Ascii** and 🎉 **Boom! The flag!**

{% code overflow="wrap" %}

```bash
 r1pp3r 🔱 god2eye ~/Documents/CTF/bearcatctf25/crypto 
  λ echo -n 3432343334333534343637623439373437333566346137353733323335663438333337383764 | xxd -r -p | xxd -r -p
```

{% endcode %}

**BCCTF{Its\_Jus#\_H3x}**

## Osint

### Been touring the artic - 150

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2Fwbl3hlejqO7DYGAPhUWU%2Fbeen%20touring%20the%20artic.jpg?alt=media&#x26;token=ec5d75f9-03b6-4109-a541-733f71dd7aa8" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

Here I was given a **KML file**, which is a geographic data file used by applications like **Google Earth**. Naturally, my first step was to upload it into **Google Earth** and see where it led me.

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FTkqIDnWZaQ76pzNYXDfN%2Fcincinati%20bearcat.jpg?alt=media&#x26;token=b15c0cb5-5bd9-4d3a-89c9-994baf983491" alt=""><figcaption><p>Google Earth</p></figcaption></figure>

Once opened, the file pointed to a specific spot—**the University of Cincinnati**. But why? Looking closer,

The Title says "Cool Statue" makes me want to see the statue🧐, Then I saw a statue of a **Cincinnati Bearcat**, a well-known mascot of the university.

The flag was the **scientific name** of the animal. A quick search revealed that the **Cincinnati Bearcat** is actually an **Arctictis binturong**, commonly known as a **binturong** or “bearcat.”

**BCCTF{arctictis\_binturong}**

### Building Breakers - 200

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FRI6Os3KwbqljnBOIX0TI%2Fbuilding_breakers.jpg?alt=media&#x26;token=f445ebc2-36d1-421a-b04b-fe8d84f2abaf" alt=""><figcaption><p>Challenge Description</p></figcaption></figure>

This Challenge, I was given a **photo of a building**. ❌No coordinates—just an image. My job was to 🔎**identify** where this building was located.

<figure><img src="https://2619072038-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyCrT4YxGad5HFRKWhUG8%2Fuploads%2FFqys4DjpT51dwFLBNaFx%2Fbuilding.png?alt=media&#x26;token=3039203b-0589-4686-82f7-8efad6bbf1ba" alt=""><figcaption><p>building.png</p></figcaption></figure>

Now hunting for the landmark, Since I had no immediate clues, I used a combination of:

* **Google Reverse Image Search**
* **TinEye (another image search tool)**
* **Browsing famous buildings in Zürich**

After a long search, 🎉I finally found a match—it was the **Swiss National Museum** in Zürich, Switzerland!

**BCCTF{Swiss\_National\_Museum}**
