Page cover image

IrisCTF 2025

by TFS

Challenge Category

Cryptography

KittyCrypt - Emoji Mapping

Solution
  • File 1: main.go (provided code for encoding).

  • File 2: example_input.txt: Contains You fools! You will never get my catnip!!!!!!!.

  • File 3: example_output.txt: Contains encoded emojis for the input.

  • File 4: flag_output.txt: Contains encoded emojis for the flag.

Tools/Methods Used

  • Python Scripting: Script crafted to reverse the encoding process.

  • Emoji Mapping: Recreated mapping between emojis and hexadecimal characters.

  • Key Deduction: Extracted transformation keys by comparing input and output.

Goals

  1. Reverse the encoding process from main.go.

  2. Deduce the keys used for encoding.

  3. Decode the flag from the flag_output.txt file.

Solution

Encoding Overview

  1. Input Transformation: Each character is transformed using random keys (char + key).

  2. Hex Conversion: Transformed characters are converted to hexadecimal.

  3. Emoji Mapping: Hexadecimal values are mapped to emojis based on a predefined CharSet.

Decoding Process

  1. Reverse emoji mapping to hexadecimal using a custom function.

  2. Convert the hexadecimal string to the intermediate transformed text.

  3. Deduce the keys by comparing the transformed text with example_input.txt.

  4. Reverse the key transformation to recover the original flag text.

Python Script

import json
from collections import defaultdict

# Define CharSet mapping for decoding
CharSet = {
    "🐱": "0", "🐈": "1", "😸": "2", "😹": "3",
    "😺": "4", "😻": "5", "😼": "6", "😽": "7",
    "😾": "8", "😿": "9", "🙀": "A", "🐱‍👤": "B",
    "🐱‍🏍": "C", "🐱‍💻": "D", "🐱‍👓": "E", "🐱‍🚀": "F"
}

# Reverse CharSet for decoding emojis back to hex
# Reverse CharSet for decoding emojis back to hex
def reverse_charset(emojis):
    result = ""
    buffer = ""
    max_emoji_length = max(len(k) for k in CharSet)  # Determine longest emoji
    i = 0

    while i < len(emojis):
        buffer = ""
        # Try to match from current position with longest possible emoji
        for j in range(max_emoji_length, 0, -1):
            if i + j <= len(emojis):
                buffer = emojis[i:i + j]
                if buffer in CharSet:
                    result += CharSet[buffer]
                    i += j - 1  # Move index forward by matched length
                    break
        else:
            raise ValueError(f"Unrecognized emoji sequence: {buffer}")
        i += 1  # Move to next character after match
    return result


def debug_emojis(emojis):
    print("Debugging Emojis:")
    for idx, char in enumerate(emojis):
        print(f"Index {idx}: {char} (Code: {ord(char)})")



# Deduce keys from example input and output
def deduce_keys(example_input, example_output):
    # Decode emojis to hex and then to the intermediate text
    hex_decoded = reverse_charset(example_output)
    intermediate_text = bytes.fromhex(hex_decoded).decode()

    # Calculate keys
    keys = [ord(intermediate_text[i]) - ord(example_input[i]) for i in range(len(example_input))]
    return keys

# Decode flag output
def decode_flag(flag_output, keys):
    # Decode emojis to hex and then to the intermediate text
    hex_decoded = reverse_charset(flag_output)
    intermediate_text = bytes.fromhex(hex_decoded).decode()

    # Reconstruct original text by reversing the key transformation
    original_text = "".join(chr(ord(intermediate_text[i]) - keys[i]) for i in range(len(intermediate_text)))
    return original_text

# Load input and outputs
with open("example_input.txt", "r", encoding="utf-8") as f:
    example_input = f.read().strip()

with open("example_output.txt", "r", encoding="utf-8") as f:
    example_output = f.read().strip()

with open("flag_output.txt", "r", encoding="utf-8") as f:
    flag_output = f.read().strip()


# Deduce keys and decode the flag
keys = deduce_keys(example_input, example_output)
flag = decode_flag(flag_output, keys)

print("Decoded Flag:", flag)

Execution Steps

  1. Place all provided files in the script directory.

  2. Run the script:

    python decodekitty.py
  3. Output will display the decoded flag.

Final Answer

irisctf{s0m371m3s_bY735_4r3n7_wh47_y0u_3xp3c7}

Summary

The encoding process was reversed by deducing transformation keys from example input-output pairs and reconstructing the original text. This allowed successful decoding of the flag.

Remarks/Tags/Lessons Learned

  • Key Deduction: Known input-output pairs simplify reverse engineering.

  • Dynamic Mappings: Handling custom mappings like emojis requires attention to detail.

  • Tags: ctf, emoji encoding, reverse engineering, golang, python.


Forensics

deldeldel - USB PCAP Analysis from Keyboard Device

Solution
  • File: klogger.pcapng (USB capture with over 9000 rows).

Tools/Methods Used

  • Wireshark/TShark: To analyze USB protocol data in the .pcapng file.

  • Usb_Keyboard_Parser.py: A Python script from 5h4rrk's repository to parse USB keyboard HID data.

Goals

  1. Identify the type of USB data in the .pcapng file.

  2. Decode the HID data captured in the USB packets.

  3. Extract the hidden flag from the keystrokes.

Solution

Thought Process

  1. Observing the file name (klogger.pcapng) and the USB protocol in the capture hints at a USB keyboard data challenge.

  2. USB keyboards communicate keystrokes via HID (Human Interface Device) data in USB packets.

  3. Decoding the keystrokes will reveal the typed text, potentially containing the flag.

Steps Taken

  1. Analyzed the PCAP File:

    • Opened klogger.pcapng in Wireshark.

    • Observed URB_INTERRUPT packets, which typically contain HID data for USB keyboards.

  2. Used Usb_Keyboard_Parser.py:

    • Downloaded the script from 5h4rrk/CTF-Usb_Keyboard_Parser.

    • This script decodes USB HID data into readable keystrokes using predefined mappings of USB HID codes to characters.

  3. Executed the Parser:

    python Usb_Keyboard_Parser.py klogger.pcapng

    Output:

    [-] Found Modifier in 310 packets [-]
    
    [+] Using filter "usb.capdata" Retrieved HID Data is :
    
    Hheey   AAalicce! Ii  tthink  Ii''m  ssupppooseed  too  giivee yoou   tiss fllaag:
    
    iriisctfF{[tthis_akeyloggeer_iisS_too_hard_to_use}

Understanding the Output

  • The parser successfully decoded the USB HID data.

  • Some keystrokes appeared doubled due to repeat packets (Hheey, AAalicce, etc.), but the text was clear enough to identify the flag.

Final Answer

irisctf{this_keylogger_is_too_hard_to_use}

Summary

The challenge involved analyzing USB keyboard data captured in a .pcapng file. Using the Usb_Keyboard_Parser.py script, the HID data was decoded into readable keystrokes, revealing the flag.

Remarks/Tags/Lessons Learned

  • USB HID Data: USB keyboards send data as HID packets, which can be parsed to reconstruct keystrokes.

  • Wireshark/TShark Integration: Tools like Wireshark and TShark are invaluable for analyzing USB traffic.

  • Scripting Tools: Custom parsers like Usb_Keyboard_Parser.py simplify the process of decoding complex USB captures.

  • Tags: usb, keylogger, HID, ctf, packet analysis, python.


Tracerm 1 - Large Logs Pattern Analysis

Solution
  • File: logs.json (500,000 rows of network logs).

Tools/Methods Used

  • Python Scripting: To analyze and filter network activity.

  • Pattern Matching: Regular expressions to identify suspicious domains and user activities.

  • Command-Line Utilities: strings and grep for targeted searches in large datasets.

Goals

  1. Identify any suspicious or illegitimate network activity.

  2. Trace the activity back to the responsible user.

  3. Extract the username for the flag.

Solution

Thought Process

  1. The description mentions illegal activity on the network, so the task likely involves finding suspicious domains or unauthorized access.

  2. Since the file is a JSON log with 500,000 rows, using scripts and targeted searches would be the most efficient approach.

  3. The flag format irisctf{username} suggests we need to identify the user associated with the illegitimate activity.

Steps Taken

  1. Initial Analysis with Python:

    • Analyzed the logs to extract all domains accessed, excluding internal company domains (*.insurance.corp).

    • Wrote the following Python script:

      import collections
      import re
      
      def analyze_logs(file_path):
          domains = collections.Counter()
      
          with open(file_path, 'r') as f:
              for line in f:
                  # Extract Domains
                  domain_match = re.search(r'\b([a-zA-Z0-9.-]+\.[a-zA-Z]{2,6})\b', line)
                  if domain_match:
                      domain = domain_match.group(1)
                      # Exclude domains ending with 'insurance.corp'
                      if not domain.endswith('insurance.corp'):
                          domains[domain] += 1
      
          print("\nLeast 10 Domains (Excluding 'insurance.corp'):")
          for domain, count in domains.most_common()[-10:]:
              print(f"{domain}: {count}")
      
      # Example Usage
      log_file = 'logs.json'  # Replace with your actual log file
      analyze_logs(log_file)
    • Output:

      Least 10 Domains (Excluding 'insurance.corp'):
      g.co: 12
      deloitte.com: 12
      justgiving.com: 12
      slate.com: 8
      as.com: 8
      breachforums.st: 4
      bmj.com: 4
      welt.de: 4
      copious-amounts-of-illicit-substances-marketplace.com: 2
      smith-wesson.com: 2
  2. Identified Suspicious Domain:

    • The domain breachforums.st stood out as potentially illegal.

    • Used strings and grep to locate all log entries related to this domain:

      strings logs.json | grep breach
    • Output:

      {"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 06:33:36.80", "data": {"timestamp": "2024-12-04 06:33:36.803488", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.33.18.209", "src_port": 52836, "dest_ip": "10.33.0.2", "dest_port": 53, "transaction_id": 50295, "queries": [{"type": "A", "class": "IN", "name": "breachforums.st"}]}}
      {"host": "primary", "source": "stream:dns", "sourcetype": "stream:dns", "_time": "2024-12-04 06:33:37.18", "data": {"timestamp": "2024-12-04 06:33:37.175597", "protocol_stack": "ip:udp:dns", "transport": "udp", "src_ip": "10.33.0.2", "src_port": 53, "dest_ip": "10.33.18.209", "dest_port": 52836, "transaction_id": 50295, "answers": [{"type": "A", "class": "IN", "name": "breachforums.st", "addr": "185.129.102.136"}]}}
    • Source IP associated with the queries: 10.33.18.209.

  3. Traced IP to a User:

    • Searched for logs containing the IP 10.33.18.209 and uid (user identifier):

      strings logs.json | grep 10.33.18.209 | grep uid
    • Output:

      {"host": "primary", "source": "udp:514", "sourcetype": "syslog", "_time": "2024-12-04 04:58:36.95", "data": {"_raw": "2024-12-04 04:58:35.622504||https://sso.evil-insurance.corp/idp/profile/SAML2/Redirect/SSO|/idp/profile/SAML2/Redirect/SSO|5b52053ac1ab1f4935a3d7d6c6aa4ff0|authn/MFA|10.33.18.209|Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3 Edge/16.16299|https://sso.evil-insurance.corp/ns/profiles/saml2/sso/browser|llloyd||uid|service.evil-insurance.corp|https://sso.evil-insurance.corp/idp/sso|url:oasis:names:tc:SAML:2.0:protocol|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect|urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST|kzYQV+Jk2w3KkwmRjR+HK4QWVQ3qzLPLgA5klV2b8bQT+NLYLeqCZw5xUGKbx1U1158jlnUYRrILtVTtMkMdbA==|urn:oasis:names:tc:SAML:2.0:nameid-format:transient|_60b0fd4b0ed5bba3474faeb85b3944e|2024-12-04 04:58:35.622504|_c4b56d58-625b-49aa-b859-4a2068422979||||urn:oasis:names:tc:SAML:2.0:status:Success|||false|false|true"}}
    • Username associated with the IP: llloyd.

Final Answer

irisctf{llloyd}

Summary

By analyzing the logs, we identified breachforums.st as a suspicious domain and traced the activity to IP 10.33.18.209. Further searches revealed that the user responsible was llloyd, allowing us to complete the challenge.

Remarks/Tags/Lessons Learned

  • Log Analysis: Large datasets can be navigated efficiently using tools like Python and grep.

  • Suspicious Patterns: Focusing on anomalies (e.g., suspicious domains) helps narrow down the search.

  • Attribution: Tracing activity to users or devices is critical in forensic investigations.

  • Tags: log analysis, forensics, ctf, json, python scripting.


OSINT

Checking Out of Winter -

Solution


Sleuths and Sweets -

Solution


Not Eelaborate -

Solution


Late Night Bite -

Solution


fuel deal -

Solution


Radio Frequency

dotdotdot - Audio Signal (.iq) Analysis with Morse Code

Solution
  • File: dotdotdot.iq

Tools/Methods Used

  • Inspectrum: A tool for analyzing IQ (in-phase and quadrature) files. (Inspectrum)

  • Morse Code Decoding: Manual transcription and decoding of visible Morse code.

Goals

  1. Open the .iq file and analyze its contents.

  2. Identify any patterns or messages within the file.

  3. Decode the extracted Morse code to obtain the flag.

Solution

Thought Process

  1. .iq files are commonly associated with signals that can be analyzed visually for patterns using tools like Inspectrum.

  2. The description implies Morse code is embedded within the file, which needs to be extracted and decoded.

Steps Taken

  1. Opened the File in Inspectrum:

    • Loaded dotdotdot.iq into Inspectrum.

    • Initially, no visible patterns were found.

  2. Adjusted Power Levels:

    • Adjusted the power max and power min settings in Inspectrum.

    • This revealed a clear line of Morse code in the spectrogram.'

  3. Manually Transcribed Morse Code:

    • Carefully transcribed the Morse code line from the spectrogram.

    • Resulting Morse code:

      .. .-. .. ... -.-. - ..-. -. ----- .---- ... ...--
      --. ----- -
      -. ----- - .... .---- -. --.
      ----- -.
      -- -.-- -- ----- .-. ... .
  4. Decoded Morse Code:

    • Translated the Morse code manually using a Morse code chart:

      • Morse Code:

        .. .-. .. ... -.-. - ..-. -. ----- .---- ... ...--
        --. ----- -
        -. ----- - .... .---- -. --.
        ----- -.
        -- -.-- -- ----- .-. ... .
      • Plaintext:

        IRISCTFN01S3
        G0T
        N0TH1NG
        0N
        MYM0RSE
  5. Constructed the Flag:

    • Combined the plaintext lines to form the flag.

    • Final Flag: irisctf{n01s3_g0t_n0th1ng_0n_my_m0rse}

Final Answer

irisctf{n01s3_g0t_n0th1ng_0n_my_m0rse}

Summary

By analyzing the .iq file in Inspectrum, adjusting the power levels, and manually transcribing and decoding the visible Morse code, the challenge was successfully solved, and the flag was retrieved.

Remarks/Tags/Lessons Learned

  • Signal Visualization: Tools like Inspectrum are essential for analyzing IQ files and identifying hidden patterns.

  • Morse Code Decoding: Manually decoding Morse can be tedious but effective when automated solutions are unavailable.

  • Tags: iq files, morse code, ctf, signal analysis, manual decoding.


Last updated