Team : `KCSC` # Lost Frequencies Given : ```111 0000 10 111 1000 00 10 01 010 1011 11 111 010 000 0``` I use dCode's Cipher Identifier to find the encryption type. ![image](https://hackmd.io/_uploads/S11Cz6Oqkx.png) Morse Decode : ![image](https://hackmd.io/_uploads/SJACz6O5yl.png) Flag : ```KashiCTF{OHNOBINARYMORSE}``` # Key Exchange Source : ``` from redacted import EllipticCurve, FLAG, EXIT from Crypto.Cipher import AES from Crypto.Util.Padding import pad import hashlib import random import json import os def encrypt_flag(shared_secret: int): sha1 = hashlib.sha1() sha1.update(str(shared_secret).encode("ascii")) key = sha1.digest()[:16] iv = os.urandom(16) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(FLAG, 16)) data = {} data["iv"] = iv.hex() data["ciphertext"] = ciphertext.hex() return json.dumps(data) #Curve Parameters (NIST P-384) p = 39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319 a = -3 b = 27580193559959705877849011840389048093056905856361568521428707301988689241309860865136260764883745107765439761230575 E = EllipticCurve(p,a,b) G = E.point(26247035095799689268623156744566981891852923491109213387815615900925518854738050089022388053975719786650872476732087,8325710961489029985546751289520108179287853048861315594709205902480503199884419224438643760392947333078086511627871) n_A = random.randint(2, p-1) P_A = n_A * G print(f"\nReceived from Weierstrass:") print(f" Here are the curve parameters (NIST P-384)") print(f" {p = }") print(f" {a = }") print(f" {b = }") print(f" And my Public Key: {P_A}") print(f"\nSend to Weierstrass:") P_B_x = int(input(" Public Key x-coord: ")) P_B_y = int(input(" Public Key y-coord: ")) try: P_B = E.point(P_B_x, P_B_y) except: EXIT() S = n_A * P_B print(f"\nReceived from Weierstrass:") print(f" Message: {encrypt_flag(S.x)}") ``` We didn't know the secret key and couldn't compute the discrete logarithm in NIST P-384, but we could choose a point to generate the key. So I choose `G` because I have `n_A * G` -> Get key -> Decrypt flag ![image](https://hackmd.io/_uploads/B1timaOcJg.png) ```python3= from Crypto.Cipher import AES from Crypto.Util.Padding import pad import hashlib import random import json import os def encrypt_flag(shared_secret,iv,ciphertext): sha1 = hashlib.sha1() sha1.update(str(shared_secret).encode("ascii")) key = sha1.digest()[:16] cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.decrypt(ciphertext) return ciphertext iv = bytes.fromhex("64bfec5a865fd6ceea42801aee359859") ciphertext = bytes.fromhex("364045520c5df308c0d6a07786b30fb8af5fb28107f9a71b6f8873fea1716a3994bee7502755ced9ddb5bd24636bbd25251e99c039c20f02f940fd19309d81d14c6172dcac987396cd33933e069051fb6af388194b2958e81581ddfd7b562889") shared = 25752146156231184352136833690884074974815288724508095765146482713286084034793899492822768810986485913758095295188712 print(encrypt_flag(shared,iv,ciphertext)) ``` Result : ``` b'NaeusGRX{L_r3H3Nv3h_kq_Sun1Vm_O3w_4fg_4lx_1_t0d_a4q_lk1s_X0hcc_Dd4J_wEBQCIuo}\n\nHint: DamnKeys\x03\x03\x03' ``` I think it's `Vigenere Cipher` and try decode : ![image](https://hackmd.io/_uploads/BJcvVTd9kx.png) Flag : ```KashiCTF{I_r3V3Al3d_my_Pub1Ic_K3y_4nd_4ll_1_g0t_w4s_th1s_L0usy_Fl4G_wSOGYKcl}``` # MMDLX - This challenge encoded (**base64**) the $\text{Flag}$ multiple times and did one **caesar encryption** the last result. - So, we need to brute force the $\text{key}$ for the caesar decryption, and use the `while` loop to decode the base64-encoded flag. - **Script**: ```python= from base64 import b64decode from string import * from tqdm import trange b64_data = open("MMDLX.txt", "r").read() upper_alphabet = ascii_uppercase lower_alphabet = ascii_lowercase def caesar_decrypt(ciphertext, key): plaintext = "" for i in ciphertext: if i.isalpha(): if i.isupper(): plaintext += upper_alphabet[(upper_alphabet.index(i) - key) % len(upper_alphabet)] else: plaintext += lower_alphabet[(lower_alphabet.index(i) - key) % len(lower_alphabet)] else: plaintext += i return plaintext for key in trange(0, 26): caesar_data = caesar_decrypt(b64_data, key) decoded_data = caesar_data try: while True: decoded_data = b64decode(decoded_data) if decoded_data == b"": # trường hợp mà nó tính base64 vô hạn lần break if b"KashiCTF{" in decoded_data: print(decoded_data) exit() except: continue ``` - Flag: **KashiCTF{w31rd_numb3r5_4nd_c1ph3r5}** # Random-Inator Source : ```python3= from redacted import PRNG, FLAG from Crypto.Cipher import AES from Crypto.Util.Padding import pad def encrypt(key, plaintext, iv): cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(plaintext, 16)) return iv+ciphertext # KashiCTF{ P = PRNG() KEY = P.getBytes(16) IV = P.getBytes(16) print(f"Doofenshmirtz Evil Incorporated!!!\n") print(f"All right, I don't like to repeat myself here but it just happens\nAnyhow, here's the encrypted message: {encrypt(KEY, FLAG, IV).hex()}\nOhh, How I love EVIL") while True: iv = P.getBytes(16) try: pt = input("\nPlaintext >> ") pt = bytes.fromhex(pt) except KeyboardInterrupt: break except: print("Invalid input") continue ct = encrypt(KEY, pt, iv) print(ct.hex()) ``` I don't know anything about the PRNG library, so what I can do is connect to the server and take a look. And I realized that the IV is repeated, and the key and IV are both generated by getBytes(16), so they share the same repetition. ![image](https://hackmd.io/_uploads/r1vNIT_q1x.png) We can see , in example `key=iv`. I didn't choose a different ciphertext because before it, there could be one or two other random values, so I was too lazy to find a new one. But before `9634..`, there was only `9634...` ![image](https://hackmd.io/_uploads/rJaivp_9ye.png) So i brute-force when `iv+ciphertext` start with `9634..` ![image](https://hackmd.io/_uploads/SJ8tO6u5Je.png) ```python3= from Crypto.Cipher import AES from Crypto.Util.Padding import pad def encrypt(key, plaintext, iv): cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.decrypt(plaintext) return iv+ciphertext # KashiCTF{ ct = bytes.fromhex("963483730151eb82840db14f17159c66ae57740f73423743302ecca63e5aee7b0d839df2585fb603e40526ac54099cf103529b23aac735a0c0e8e43a81cf113682e606f65bb42d1426cfebb94e8100818a77f0fa6c14e13476ec388aa8d3d0d0") iv = ct[:16] ciphertext = ct[16:] key = iv print(encrypt(key,ciphertext,iv)) ``` Flag : ```KashiCTF{Y0u_brOK3_mY_R4Nd0m_In4t0r_Curse_yOu_Perry_tH3_Pl4TYpus_n1iK9jh1}``` # Absolutely Encrypted Shenanigans Source : ```python3= from AES import encrypt, pad from redacted import secret, flag, EXIT import json import os plaintext = pad(flag, 16) for _ in range(10): iv = os.urandom(8)*2 key = os.urandom(16) try: ciphertext = encrypt(key, plaintext, mode="CBC", iv=iv) except: EXIT() print(json.dumps({ 'key': key.hex(), 'ciphertext': ciphertext.hex() })) inp = input("Enter iv: ") if (iv.hex() != inp): EXIT() print() plaintext = pad(secret, 16) iv = os.urandom(8)*2 key = os.urandom(16) try: ciphertext = encrypt(key, plaintext, mode="CBC", iv=iv) except: EXIT() print(json.dumps({ 'key': key.hex(), 'ciphertext': ciphertext.hex() })) def xor(b1, b2): if len(b1)!=len(b2): raise ValueError("Lengths of byte strings are not equal") return bytes([b1[i]^b2[i] for i in range(len(b1))]) def bytes2matrix(text): return [list(text[i:i+4]) for i in range(0, len(text), 4)] def matrix2bytes(matrix): s = b"" for l in matrix: s += bytes(l) return s def shift_rows(s): s[2][2], s[2][1], s[0][3], s[2][0], s[3][3], s[2][3], s[3][1], s[1][3], s[0][2], s[1][0], s[0][1], s[0][0], s[1][1], s[3][0], s[3][2], s[1][2] = s[2][2], s[3][3], s[0][0], s[1][1], s[2][1], s[1][2], s[3][0], s[2][3], s[0][3], s[0][2], s[3][2], s[0][1], s[3][1], s[1][0], s[2][0], s[1][3] return s xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1) def mix_single_column(a): t = a[0] ^ a[1] ^ a[2] ^ a[3] u = a[0] a[0] ^= t ^ xtime(a[0] ^ a[1]) a[1] ^= t ^ xtime(a[1] ^ a[2]) a[2] ^= t ^ xtime(a[2] ^ a[3]) a[3] ^= t ^ xtime(a[3] ^ u) return a def mix_columns(s): for i in range(4): s[i] = mix_single_column(s[i]) return s s_box = ( 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, ) def add_round_key(s, k): ns = [] for i in range(4): ns.append([]) for j in range(4): ns[i].append(s[i][j]^k[j][i]) return ns def sub_bytes(s, sbox=s_box): resmatrix = [] for i in range(4): resmatrix.append([]) for j in range(4): hexval=hex(s[i][j])[2:] if len(hexval)==1: a,b = 0,int(hexval,16) else: a,b = int(hexval[0],16), int(hexval[1],16) resmatrix[i].append(sbox[a*16+b]) return resmatrix N_ROUNDS = 10 def expand_key(master_key): r_con = ( 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, 0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39, ) key_columns = bytes2matrix(master_key) iteration_size = len(master_key) // 4 i = 1 while len(key_columns) < (N_ROUNDS + 1) * 4: word = list(key_columns[-1]) if len(key_columns) % iteration_size == 0: word.append(word.pop(0)) word = [s_box[b] for b in word] word[0] ^= r_con[i] i += 1 elif len(master_key) == 32 and len(key_columns) % iteration_size == 4: word = [s_box[b] for b in word] word = bytes(i^j for i, j in zip(word, key_columns[-iteration_size])) key_columns.append(word) return [key_columns[4*i : 4*(i+1)] for i in range(len(key_columns) // 4)] def encrypt_block(key, pt_block): round_keys = expand_key(key) state = bytes2matrix(pt_block) state = add_round_key(state, round_keys[0]) state = sub_bytes(state) state = shift_rows(state) for i in range(1,N_ROUNDS): state = mix_columns(state) state = add_round_key(state, round_keys[i]) state = sub_bytes(state) state = shift_rows(state) state = add_round_key(state, round_keys[N_ROUNDS]) ct_block = matrix2bytes(state) return ct_block def encrypt(key, plaintext, mode="ECB", iv=None): if len(plaintext)%16 != 0: raise ValueError("Invalid Plaintext") elif len(key)!=16: raise ValueError("Invalid Key") ciphertext = b"" if mode=="ECB": for i in range(0, len(plaintext), 16): ciphertext += encrypt_block(key, plaintext[i: i+16]) elif mode=="CBC": if (iv==None or len(iv)!=16): raise ValueError("Invalid IV") ciphertext += iv for i in range(0, len(plaintext), 16): ciphertext += encrypt_block(key, xor(ciphertext[i: i+16], plaintext[i: i+16])) return ciphertext[16:] def pad(text, blocksize): padding_len = blocksize - (len(text)%blocksize) padding = bytes([padding_len])*padding_len return text+padding ``` The important thing here is. ``` iv = os.urandom(8)*2``` ``` We have format flag is `KashiCTF` (8 characters) And we have key, and we can decrypt cipher in mode ECB and xor it with `KashiCTF` we can get iv. The different here is AES.py, we didnt have function `decrypt` , so i use chatgpt to make this. ```python3 def inv_shift_rows(s): s[2][2], s[3][3], s[0][0], s[1][1], s[2][1], s[1][2], s[3][0], s[2][3], s[0][3], s[0][2], s[3][2], s[0][1], s[3][1], s[1][0], s[2][0], s[1][3] = s[2][2], s[2][1], s[0][3], s[2][0], s[3][3], s[2][3], s[3][1], s[1][3], s[0][2], s[1][0], s[0][1], s[0][0], s[1][1], s[3][0], s[3][2], s[1][2] return s def inv_sub_bytes(s, sbox=s_box): inv_sbox = [sbox.index(x) for x in range(256)] return [[inv_sbox[b] for b in row] for row in s] def inv_mix_columns(s): for i in range(4): u = xtime(xtime(s[i][0] ^ s[i][2])) v = xtime(xtime(s[i][1] ^ s[i][3])) s[i][0] ^= u s[i][1] ^= v s[i][2] ^= u s[i][3] ^= v return mix_columns(s) # Using the original mix_columns again def decrypt_block(key, ct_block): round_keys = expand_key(key) state = bytes2matrix(ct_block) state = add_round_key(state, round_keys[N_ROUNDS]) for i in range(N_ROUNDS - 1, 0, -1): state = inv_shift_rows(state) state = inv_sub_bytes(state) state = add_round_key(state, round_keys[i]) state = inv_mix_columns(state) state = inv_shift_rows(state) state = inv_sub_bytes(state) state = add_round_key(state, round_keys[0]) return matrix2bytes(state) def decrypt(key, ciphertext, mode="ECB", iv=None): if len(ciphertext) % 16 != 0: raise ValueError("Invalid Ciphertext") elif len(key) != 16: raise ValueError("Invalid Key") plaintext = b"" if mode == "ECB": for i in range(0, len(ciphertext), 16): plaintext += decrypt_block(key, ciphertext[i: i+16]) elif mode == "CBC": if iv is None or len(iv) != 16: raise ValueError("Invalid IV") prev_ct_block = iv for i in range(0, len(ciphertext), 16): decrypted_block = decrypt_block(key, ciphertext[i: i+16]) plaintext += xor(prev_ct_block, decrypted_block) prev_ct_block = ciphertext[i: i+16] return plaintext def unpad(text): padding_len = text[-1] if text[-padding_len:] != bytes([padding_len]) * padding_len: raise ValueError("Invalid Padding") return text[:-padding_len] ``` Script : ``` from AES import * from pwn import * from ast import literal_eval io = remote("kashictf.iitbhucybersec.in", 51946) for i in range(10) : if i >=1 : print(io.recvline().decode()) datas = literal_eval(io.recvline().decode()) print(datas) key = bytes.fromhex(datas["key"]) ciphertext = bytes.fromhex(datas["ciphertext"] ) test = decrypt(key,ciphertext) iv = xor(test[:8] , b'KashiCTF') print(decrypt(key,ciphertext,"CBC", iv*2)) io.recvuntil(b"Enter iv:") io.sendline(str(iv.hex()).encode()*2) # print(decrypt(key,ciphertext,"CBC" , iv*2)) ciphertext = bytes.fromhex("67865f6cd1c006b2bfcbff3070b35a2baeb57be84376d9a5a84053ae03e1ef97f8bb2480fde468f39699ef496c72bbfdc8618166a1fe002aa5bca0b9aad52462") key =bytes.fromhex("3f916873df6a91297f50646442f2dc5a") test = decrypt(key,ciphertext) iv = xor(test[:8] , b'KashiCTF') print(decrypt(key,ciphertext,"CBC" , iv*2)) io.interactive() ``` Flag : ```KashiCTF{AES_Unbr34KAbl3_but_t0T4lly_br3Akable_mAyb3_AHEaoEeN}``` We can't use a library like pycryptodome to decrypt AES because some parts of it work differently, such as: ``` def shift_rows(s): s[2][2], s[2][1], s[0][3], s[2][0], s[3][3], s[2][3], s[3][1], s[1][3], s[0][2], s[1][0], s[0][1], s[0][0], s[1][1], s[3][0], s[3][2], s[1][2] = s[2][2], s[3][3], s[0][0], s[1][1], s[2][1], s[1][2], s[3][0], s[2][3], s[0][3], s[0][2], s[3][2], s[0][1], s[3][1], s[1][0], s[2][0], s[1][3] return s ``` The correct code from : https://github.com/boppreh/aes/blob/master/aes.py # Broken ? I think it should be in tag crypto ``` #!/usr/bin/env python3 import hashlib import socket import signal import sys HOST = "0.0.0.0" PORT = 1337 SECRET_KEY = b"REDACTED" def generate_hmac(message): return hashlib.sha1(SECRET_KEY + message.encode()).hexdigest() def signal_handler(sig, frame): print("\n[!] Server shutting down...") sys.exit(0) signal.signal(signal.SIGINT, signal_handler) def handle_client(client, addr): print(f"[*] Connection from {addr}") try: original_data = "count=10&lat=37.351&user_id=1&long=-119.827&file=random.txt" original_hmac = generate_hmac(original_data) client.sendall(f"Retrieve file using format: data|hmac\nExample: {original_data}|{original_hmac}\n".encode()) data = client.recv(1024) if not data: print(f"[-] Client {addr} disconnected.") return try: decoded_data = data.decode("utf-8").strip() except UnicodeDecodeError: decoded_data = data.decode("latin-1").strip() print(f"[*] Received Data: {decoded_data}") if "|" not in decoded_data: client.sendall(b"Invalid format. Use data|hmac\n") return user_data, received_hmac = decoded_data.rsplit("|", 1) user_data_bytes = bytes(user_data, "utf-8").decode("unicode_escape").encode("latin-1") h = hashlib.sha1() h.update(SECRET_KEY + user_data_bytes) computed_signature = h.hexdigest() print(f"[*] Computed Signature: {computed_signature} for body: {repr(user_data)}") print(f"[*] Received Signature: {received_hmac}") if computed_signature != received_hmac: client.sendall(b"Invalid HMAC. Try again.\n") else: try: params = dict(param.split("=") for param in user_data.split("&") if "=" in param) filename = params.get("file") if filename: with open(filename, "r") as f: content = f.read() client.sendall(f"File Contents:\n{content}\n".encode()) else: client.sendall(b"Invalid request format.\n") except FileNotFoundError: client.sendall(b"File not found.\n") except ConnectionResetError: print(f"[!] Client {addr} forcibly disconnected.") except Exception as e: print(f"[!] Error handling client {addr}: {e}") finally: client.close() print(f"[-] Closed connection with {addr}") def start_server(): print(f"[*] Listening on {HOST}:{PORT} ...") server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((HOST, PORT)) server.listen(5) while True: try: client, addr = server.accept() handle_client(client, addr) except KeyboardInterrupt: print("\n[!] Shutting down server...") server.close() sys.exit(0) if __name__ == "__main__": start_server() ``` This challenge is simply about a hash length extension attack. We just need to append `&flag.txt` to the plaintext and then compute the signature. The important part here is that we don’t know the length of the secret, but we can brute-force it (though it’s usually 16 or 32). https://github.com/thecrabsterchief/hash-length-extension Script ```python3= from pwn import * import HashTools from tqdm import trange for i in trange(64) : io = remote("kashictf.iitbhucybersec.in", 59457) io.recvuntil(b"Example: ") datas = io.recvline().decode()[:-1].split("|") original_data = datas[0].encode() sig = datas[1] append_data = b"&file=flag.txt" magic = HashTools.new("sha1") new_data, new_sig = magic.extension( secret_length=i, original_data=original_data, append_data=append_data, signature=sig ) # print(str(new_data)) send_data = str(new_data)[2:][:-1] + '|' + str(new_sig) user_data, received_hmac = send_data.rsplit("|", 1) try : user_data_bytes = bytes(user_data, "utf-8").decode("unicode_escape").encode("latin-1") io.sendline(send_data.encode()) print(io.recvall()) exit() except : pass io.close() ``` ![image](https://hackmd.io/_uploads/H1hfnp_91l.png) I think i didnt need bruteforce, just guess =)) Flag : ```KashiCTF{Close_Yet_Far_wUWyw7UEL}``` # Easy Jail ``` #!/usr/bin/env python3 print(" _ _ _ ") print(" | | | | | | ") print(" ___ __ _| | ___ _ _| | __ _| |_ ___ _ __ ") print(" / __/ _` | |/ __| | | | |/ _` | __/ _ \| '__|") print("| (_| (_| | | (__| |_| | | (_| | || (_) | | ") print(" \___\__,_|_|\___|\__,_|_|\__,_|\__\___/|_| ") def calc(op): try : res = eval(op) except : return print("Wrong operation") return print(f"{op} --> {res}") def main(): while True : inp = input(">> ") calc(inp) if __name__ == '__main__': main() ``` This challenge doesn’t have any blacklist, so we just need to import os, find the file `flag.txt path`, and read it. ![image](https://hackmd.io/_uploads/HkxnbaaO9kx.png) Flag : ```KashiCTF{3V4L_41NT_54F3_fD389n9T}``` # Easy Jail 2 ``` #!/usr/bin/env python3 print(" _ _ _ ") print(" | | | | | | ") print(" ___ __ _| | ___ _ _| | __ _| |_ ___ _ __ ") print(" / __/ _` | |/ __| | | | |/ _` | __/ _ \| '__|") print("| (_| (_| | | (__| |_| | | (_| | || (_) | | ") print(" \___\__,_|_|\___|\__,_|_|\__,_|\__\___/|_| ") BLACKLIST = ["open", "input", "eval", "exec", "import", "getattr", "sh", "builtins", "global"] def calc(op): try : res = eval(op) except : return print("Wrong operation") return print(f"{op} --> {res}") def main(): while True : inp = input(">> ") if any(bad in inp for bad in BLACKLIST) : print("Are you tying to hack me !!!!!") else : calc(inp) if __name__ == '__main__': main()#!/usr/bin/env python3 print(" _ _ _ ") print(" | | | | | | ") print(" ___ __ _| | ___ _ _| | __ _| |_ ___ _ __ ") print(" / __/ _` | |/ __| | | | |/ _` | __/ _ \| '__|") print("| (_| (_| | | (__| |_| | | (_| | || (_) | | ") print(" \___\__,_|_|\___|\__,_|_|\__,_|\__\___/|_| ") BLACKLIST = ["open", "input", "eval", "exec", "import", "getattr", "sh", "builtins", "global"] def calc(op): try : res = eval(op) except : return print("Wrong operation") return print(f"{op} --> {res}") def main(): while True : inp = input(">> ") if any(bad in inp for bad in BLACKLIST) : print("Are you tying to hack me !!!!!") else : calc(inp) if __name__ == '__main__': main() ``` Black list here is : `["open", "input", "eval", "exec", "import", "getattr", "sh", "builtins", "global"]` I read from https://jbnrz.com.cn/index.php/2024/08/15/pyjail/ , use `breakpoint` to bypass blacklist and do like `Easy Jail` ![image](https://hackmd.io/_uploads/HyOja6d51e.png) Flag : ```KashiCTF{C4N_S71LL_CL3AR_8L4CKL15T_mBLcLrsB}```