Logo Havoc Hacking Articles

K17 CTF Writeup

⚡ Hack the Logic ⚡

Sep 21, 2025 - 5 minute read
feature image CTF Challenges

Sanity Checker

Make sure you read the rules carefully before starting! We spent a lot of time writing them...

Visit https://ctf.secso.cc/rules:

Rules🚩

   No flag sharing or helping other teams in any unfair way. This will result in immediate disqualification from the event.
   No attacking the infrastructure in any way. This includes brute-forcing flags or challenges. For example, please do not use scanning tools such as DirBuster or SQLmap.
   The scope of what you're allowed to attack are all the domains that match *.k17.kctf.cloud and *.k17.secso.cc.
   No "flag hoarding" or dumping flags at last minute, submit the work when you solve it.
  Choose the correct team division as per the prizes page.
   All flags have the regex /^K17{.*}$/, unless otherwise specified. For example, the sanity check flag is K17{we_hop3_y0u_h@ve_Fun}.
   Do NOT post fake flags.
  Any decisions made by K17 CTF organisers is final.
  Important: HAVE FUN!!!

Flag: K17{we_hop3_y0u_h@ve_Fun}.

that was fun though!!!!

Next one

Discord chall.

Discord There are hidden 0x9e and 0x9f characters in the following message:

Hey, sorry about the delay but it looks we reached the global IP quota limit 💀

if you see a challenge is down, move onto a different challenge or try solving it locally. once again, really sorry everybody
<9e><9f><9e><9e><9f><9e><9f><9f><9e><9e><9f><9f><9e><9e><9e><9f><9e><9e><9f><9f><9e><9f><9f><9f><9e><9f><9f><9f><9f><9e><9f><9f><9e><9f><9f><9f><9e><9f><9f><9f><9e><9f><9f><9e><9e><9f><9e><9f><9e><9f><9e><9e><9f><9f><9e><9e><9e><9f><9f><9e><9e><9e><9f><9f><9e><9e><9f><9f><9e><9e><9e><9e><9e><9f><9f><9e><9f><9f><9e><9f><9e><9e><9f><9f><9e><9e><9f><9f><9e><9f><9e><9f><9f><9f><9f><9f><9e><9f><9f><9f><9e><9f><9e><9e><9e><9e><9f><9f><9e><9e><9e><9e><9e><9f><9e><9f><9f><9f><9f><9f><9e><9f><9f><9e><9f><9e><9f><9f><9e><9e><9f><9f><9e><9e><9e><9f><9e><9e><9f><9f><9e><9f><9f><9f><9e><9f><9e><9f><9f><9f><9f><9f><9e><9f><9e><9e><9e><9e><9f><9f><9e><9e><9f><9f><9e><9f><9f><9f><9e><9f><9e><9e><9e><9f><9f><9e><9e><9e><9f><9e><9e><9e><9e><9f><9e><9e><9f><9e><9e><9e><9e><9f><9e><9e><9f><9e><9e><9e><9e><9f><9e><9f><9f><9f><9f><9f><9e><9f>
cameron

Decode by mapping 0x9e to bit 0, 0x9f to bit 1:

text = open("discord.txt", "r").read()

data = []

for ch in text:
    if ord(ch) == 0x9e:
        data.append(0)
    elif ord(ch) == 0x9f:
        data.append(1)

# https://stackoverflow.com/questions/20541023/in-python-how-to-convert-array-of-bits-to-array-of-bytes
data = bytes(
    [sum([byte[b] << (7 - b) for b in range(0, 8)]) for byte in zip(*(iter(data),) * 8)]
)

print(data)

Flag:

K17{weLc0m3_t0_k17_C7F!!!}.

Next one

Radioactive

radioactive This is the picture we are given. There is a NSA Site Number: 21540061 sign. Search for it on https://www.rfnsa.com.au/, we got https://www.rfnsa.com.au/2154006/detail.

Gilbert Road
(East of Field 1 Fred Caterson Reserve),
CASTLE HILL NSW 2154

flag: K17{-33.717,150.987}

The next

Smoothie

smoothie

From the comment:

$ exiftool chall.png
Comment                         : Q3JlYXRlZCB3aXRoIEdJTVA=
$ echo "Q3JlYXRlZCB3aXRoIEdJTVA=" | base64 -d
Created with GIMP

We know that it is created with GIMP. After trying the effects in GIMP, we find the correct one and reverse the effect:

  1. Open the image in GIMP.

  2. Go to Filters > Blur > Pixelize.

  3. Set the Block Width and Block Height to 10.

  4. Click OK to apply the effect.

    or as we know this is a swirling effect so we can reverse it by applying the same effect again.easy to reverse the swirl effect by applying the same effect again.

The flag is : K17{tw1st_0f_f4t3}

The next one

El_camel

elcamle in this challenge we need to exploit a vulnerability in the ElGamal encryption scheme.this here my dear friend deepseek came in hand i asked for the script and there it was ,modified a little bit then boom!!!!

from pwn import *

context(log_level="debug")


def receive_next_c(conn):
    while True:
        line = conn.recvline().decode().strip()
        if line.isdigit():
            return int(line)


def main():
    host = "challenge.secso.cc"  # Replace with actual host
    port = 7001  # Replace with actual port
    conn = remote(host, port)

    conn.recvuntil(b"special prize...\n")
    conn.recvline()
    p_line = conn.recvline().strip()
    q_line = conn.recvline().strip()
    p = int(p_line)
    q = int(q_line)

    conn.recvuntil(b"> ")
    conn.sendline(b"0")
    conn.recvuntil(b"> ")
    conn.sendline(b"1")

    c = receive_next_c(conn)

    for round in range(50):
        conn.recvuntil(b"(H or T)> ")
        A = pow(c, q, p)
        B = pow(c - 1, q, p)
        if A == 1:
            guess = "H"
        elif B == 1:
            guess = "T"
        else:
            guess = "H"
        conn.sendline(guess)

        if round < 49:
            c = receive_next_c(conn)
        else:
            conn.recvuntil(b"prize...\n")
            flag = conn.recvline().decode().strip()
            print(flag)

    conn.close()


if __name__ == "__main__":
    main()

solution

Flag: K17{el_gamal_th3_cam3l_h4s_s0me_nic3_squ4r3s}.

The next challenge is:

Pass_ me_the_salt

so lets begin…. This is the contents of the python script given chall.py

from hashlib import sha1
import os

logins = {}
salts = {}

def create_account(login, pwd):
    if login in logins.keys():
        return False
    
    salt = os.urandom(16)
    salted_pwd = salt + (pwd).encode()
    passw = sha1(salted_pwd).hexdigest()
    
    logins[login] = passw
    salts[login] = salt

    return True

def check_login(login, pwd):
    if login not in logins:
        return False

    salt = salts[login]
    salted_pwd = salt + bytes.fromhex(pwd)

    passw = sha1(salted_pwd).hexdigest()
    return passw == logins[login]

def change_password(login, new_pass):
    if login not in logins:
        return
    
    print(f"Current password: {logins[login]}")

    logins[login] = new_pass

if __name__ == "__main__":
    create_account("admin", "admin".encode().hex())

    while True:
        option = input("1. Create Account\n2. Login\n3. Change Password\n(1, 2, 3)> ")
        if option == "1":
            login = input("Login: ")
            pwd = input("Password: ")
            if create_account(login, pwd.encode().hex()):
                print("Account created!")
            else:
                print("Could not create account.")
        elif option == "2":
            login = input("Login: ")
            pwd = input("Password: ")

            if not check_login(login, pwd):
                print("Invalid login or password.")
                continue

            if login == "admin":
                if pwd != "admin".encode().hex():
                    print(f"Congratulations! Here is your flag: {os.getenv("FLAG")}")
                else:
                    print("Your flag is in another castle...")
            else:
                print(f"Login successful as {login}!")
        elif option == "3":
            login = input("Login: ")
            new_pass = input("New password: ")

            change_password(login, new_pass)
            print("Password changed!")
        else:
            print("Invalid option.")

so lets begin…. To solve this CTF challenge, the goal is to log in as the “admin” user with a password that is not the default hex-encoded “admin” (which is ‘61646d696e’) but still passes the authentication check. The vulnerability arises from a mismatch in how passwords are handled during account creation and login.

During account creation, the password is first hex-encoded and then encoded to bytes before being combined with the salt and hashed. For example, the admin account is created with the password “admin”, which becomes ‘61646d696e’ when hex-encoded. Then, in create_account, this hex string is encoded to bytes (b'61646d696e’) before hashing.

During login, the password input is expected to be a hex string, which is converted to bytes using bytes.fromhex(). To authenticate successfully, the bytes produced by bytes.fromhex(pwd) must match the bytes used during account creation. For the admin account, this means bytes.fromhex(pwd) must equal b'61646d696e’.

The hex representation of b'61646d696e’ is ‘36313634366436393665’. Therefore, by logging in with the password ‘36313634366436393665’, the authentication will succeed because it correctly reconstructs the bytes used during the hash computation. Additionally, since this password is not equal to ‘61646d696e’, the condition in the login check for admin will be satisfied, and the flag will be printed.

So lets go mr rodio!!!!!!!!

  1. Run the provided Python script.
  2. Select option “2” to login.
  3. Enter “admin” as the login.
  4. Enter “36313634366436393665” as the password.
  5. The flag will be displayed.
  6. Take a screenshot of the flag.

This approach exploits the password handling inconsistency to achieve successful authentication without needing to change the password or know the salt.

Flag: K17CTF{s4Lt_4nD_p3pper_is_ov3rr4t3d}.


Hope you enjoyed it :) Happy hacking :)