---
# System prepended metadata

title: BearcatCTF 2025

---

# Write Up BearcatCTF 2025
![android-chrome-512x512](https://hackmd.io/_uploads/H1itoLhu1e.png)

---
## web
### 1. global-redirect
![image](https://hackmd.io/_uploads/H1HhsL2_ke.png)
Truy cập trang:  
![image](https://hackmd.io/_uploads/SkjTs83O1g.png)
Đọc src:  
![image](https://hackmd.io/_uploads/r1rJ3LhOJx.png)
Thêm endpoint:  
> http://chal.bearcatctf.io:39724/0078f62f00305b73de6ccace8f9fc1f68a8f1dcec865d33fcacbaf255ddefaa7

![image](https://hackmd.io/_uploads/ByOz2Lh_yx.png)

> Flag: BCCTF{T1ck3t_t0_0wn3rsh1p!}

---
## rev
### 1. Say Cheese
![image](https://hackmd.io/_uploads/SkfOhI3dkl.png)
Đề cho:  
```py=
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()

```

Script solve:  

```py=
import base64

def decoder(encoded_str, key):
    decoded_str = base64.b64decode(encoded_str).decode()
    decoded_chars = []
    key_len = len(key)
    
    for i in range(len(decoded_str)):
        key_c = key[i % key_len]
        decoded_c = chr((ord(decoded_str[i]) - ord(key_c)) % 256)
        decoded_chars.append(decoded_c)
    
    return ''.join(decoded_chars)

def main():
    ciphertext = "wpbCi8KIwpfCh8OPwph5wqnCosK6woTCqcKnwq13wrfCh8KzwqnCpMKKccOJwrh8wqTCl3LDgcKHw4U="
    key = "THECAT"
    
    decoded_flag = decoder(ciphertext, key)
    print("Decoded flag:", decoded_flag)

if __name__ == "__main__":
    main()
```
> Flag: BCCTF{D1d_y0U_h4v3_a_G0ud4_T1m3}

---
## osint
### 1. Been Touring the Arctic
![image](https://hackmd.io/_uploads/Bkjka8h_Jx.png)
Bài cho file `.kml`, bỏ vào GG earth, có được hình tượng con bearcat, tra 1 hồi là có:  
> Flag: BCCTF{Arctictis_binturong}

---
### 2. Building Breakers
![image](https://hackmd.io/_uploads/BkOEpL2_ye.png)
Bài cho ảnh:  
![building](https://hackmd.io/_uploads/SJ9BpL3_yl.png)
Dùng lens có ngay:  
Swiss National Museum (Schweizerisches Landesmuseum) ở Zurich, Thụy Sĩ.  
> Flag: BCCTF{Swiss_National_Museum}

---
## Misc
### 1. What you see
![image](https://hackmd.io/_uploads/BkGiTI2uke.png)
Bài cho 1 ảnh, dùng aperi có được pass:  
![image](https://hackmd.io/_uploads/SyKkCLn_yg.png)
Dùng pass `ctf`, có được:  
![image](https://hackmd.io/_uploads/HyGfAI3_1x.png)
> Flag: BCCTF{w34k_s4uc3_4_u}

---
### 2. Ohio Against The World
![image](https://hackmd.io/_uploads/SyF5TeAO1g.png)
Tools stego gif:
> https://github.com/dtmsecurity/gift

```bash=
python3 gift-cli.py --source TheEarth.gif recover TheTruth.txt

strings TheTruth.txt | grep bcc
bcctf{sWaG_L!k3_0h1O}Vj
```
> Flag: bcctf{sWaG_L!k3_0h1O}

---
## crypto
### 1. Seeing Triple
![image](https://hackmd.io/_uploads/rkHB0U3Oye.png)
Dùng cyberchef là ra:  
![image](https://hackmd.io/_uploads/S1Vu0I3d1g.png)
> Flag: BCCTF{Its_Jus#_H3x}

---
### 2. sqRSA
![image](https://hackmd.io/_uploads/r1g3cCLnOkl.png)
Bài cho:  
```py=
from Crypto.Util.number import getPrime, bytes_to_long
from Crypto.Util.Padding import pad

with open('flag.txt','rb') as fil:
    FLAG = fil.read()

e = 2
p = getPrime(512)
q = getPrime(512)
n = p*q

print(f'{e = }')
print(f'{p = }')
print(f'{q = }')
print(f'{n = }')

m = bytes_to_long(pad(FLAG,100))
c = pow(m, e, n)

print(f'{c = }')

phi = (p-1)*(q-1)
d = pow(e,-1,phi) # It always errors here?!!?!

print(f'{phi = }')
print(f'{d = }')

pt = pow(c,d,n)
assert pt == m
```
```bash=
e = 2
p = 8946541176074654913817717054410771331419218032593785296134838490312525894218240553305396599307555077734655624876704161811830296918000348456470769765921767
q = 8932929811422923151480388874853984777290071075825590049173830382535883452482114410463430296988680318519251836647527145507992221700683938654669731212502879
n = 79918824380879984230214478212107859789970760434299554608805294793725784734356035450441094355662829397276452220713697299759466084320223642049726452788651518853937184518959195516619507938497758925978032369947277889352888108330331269331130005097469138112607532759174992940835608455793923500626923539208576267193
c = 17349894155329354363328734000800652637346887108866919240446747423455120556394923514564284438906649577094462846372316919957176356395706169922421515974398971844608693078173465906525109301576180786133798467234128571459625488335621909834995712400917418963473920470534646258784866422718709370743346105151573384808
Traceback (most recent call last):
  File "sqRSA.py", line 23, in <module>
    d = pow(e,-1,phi) # It always errors here?!!?!
ValueError: base is not invertible for the given modulus
```

Script solve:  
```py=
from Crypto.Util.number import long_to_bytes
from Crypto.Util.Padding import unpad

# Given values from the challenge
e = 2
p = 8946541176074654913817717054410771331419218032593785296134838490312525894218240553305396599307555077734655624876704161811830296918000348456470769765921767
q = 8932929811422923151480388874853984777290071075825590049173830382535883452482114410463430296988680318519251836647527145507992221700683938654669731212502879
n = 79918824380879984230214478212107859789970760434299554608805294793725784734356035450441094355662829397276452220713697299759466084320223642049726452788651518853937184518959195516619507938497758925978032369947277889352888108330331269331130005097469138112607532759174992940835608455793923500626923539208576267193
c = 17349894155329354363328734000800652637346887108866919240446747423455120556394923514564284438906649577094462846372316919957176356395706169922421515974398971844608693078173465906525109301576180786133798467234128571459625488335621909834995712400917418963473920470534646258784866422718709370743346105151573384808

# Since e = 2, we can try taking the square root modulo n
def sqrt_mod_n(c, p, q, n):
    # Find sqrt mod p
    mp = pow(c, (p + 1) // 4, p) if p % 4 == 3 else None
    # Find sqrt mod q
    mq = pow(c, (q + 1) // 4, q) if q % 4 == 3 else None
    
    if mp is None or mq is None:
        raise ValueError("p or q is not congruent to 3 mod 4")
    
    # Use Chinese Remainder Theorem to combine
    coef1 = pow(q, -1, p) * q
    coef2 = pow(p, -1, q) * p
    
    # Calculate all possible roots
    r1 = (mp * coef1 + mq * coef2) % n
    r2 = (mp * coef1 - mq * coef2) % n
    r3 = n - r1
    r4 = n - r2
    
    return [r1, r2, r3, r4]

try:
    # Get all possible square roots
    possible_messages = sqrt_mod_n(c, p, q, n)
    
    # Try each possible message
    for m in possible_messages:
        try:
            # Convert to bytes and try to unpad
            potential_flag = unpad(long_to_bytes(m), 100)
            # If it successfully unpads and looks like a flag, print it
            if b'flag' in potential_flag.lower() or b'{' in potential_flag:
                print(f"Found flag: {potential_flag.decode()}")
        except Exception as e:
            continue

except Exception as e:
    print(f"Error: {e}")
```
> Flag: BCCTF{Don7_b3_4_squArE_ac6c54f792c90a69b8}

---
## forensics
### 1. Lost City
![image](https://hackmd.io/_uploads/rJQVzDhO1x.png)

Mở file `.pcap`, follow tcp stream là thấy được 1 ảnh jpg, lưu về có flag:  
![image](https://hackmd.io/_uploads/Hy3oheAdye.png)

![image](https://hackmd.io/_uploads/HyykTeCOkx.png)
> Flag: bcctf{fTp5_n0T_so_53cReT}

---

### 2. Around the World
![image](https://hackmd.io/_uploads/SyX8MD3uJg.png)
Bài cho file ảnh nhưng thực ra là file gif, thay header là xong:  
![image](https://hackmd.io/_uploads/BJK4pgA_1e.png)
> Flag: bcctf{C1F_M4g1c_Rev34l}

---
