# 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} ---