Logo
A Northern Light in Cyber

How It Works

Challenges

Every challenge runs a bash script that is completely customizable by you. This means that anything that can be scripted can be a challenge. It is also in a sandbox which is stateless so when you refresh the page it all restarts. This allows you to even have a script that doesn't exactly work right which you can also test before your students have access.

Contests

The Contests themselves are super simple, they are the main hub that gives access to your flags. Contests are created with a title and a description of the contest itself. Below is their different states that you can change depending on if you want to allow your students access to the flags.

Active

  • Lets students access
  • Counts towards leaderboards and stats

Unactive

  • Does not let students access at all
  • Deactivating makes the contest disabled by default

Practice

  • Lets students access
  • Does not count towards leaderboards and stats

Disabled

  • Does not let students access at all
  • Great way to add flags without the students looking at them yet

Flags

Creating flags is the crutch of what you are able to do. Whether it be a complex challenge or a super simple one, we got you covered. Below is the properties every flag has:
  • Name
  • Description
  • Hints
  • Flag Placement
  • File System
  • Extra Configurations

Name, Description, Hints

These are the basics of every flag. You can have up to 3 hints per flag and they also don't hinder on the student if they are used or not. The name of the flag must be unique per contest. Meaning that you cannot have the same name for two different flags in the same contest.

File System and Extra Configurations

This is the heart of what makes our platform so flexible. The file system is just what it sounds like. Each flag has its own environment thus its own files and folders that you add to it. If you want a specific file in the environment for your students to use, you can simply just add it to the file tree.
The bash script is also what makes us unique. This is where the extra configurations comes into play. The script that runs to set up the environment is completely customizable to you. We do have some programs that are included in the base environment (g++ for example). If there are some you don't want added you can check it off the list and the commands for that program will be disabled. Any you do want added by default?

Testing

With any good software or anything that's created on the fly, you have to be able to test it. That's why we allow testing of flags right after creation to make sure what you wanted to create actually happened. Any errors that happen while running the bash script is right there inside the terminal you are testing on for easy debugging.

Placing the Flag

Flags can be placed using two distinct methods. Depending on how you want your students to find them. Either way you pick, the flag itself is in the format of NKCTF$:{ } Where inside the braces, is the hash itself which is unique to each student and challenge. This prevents reuse of flags and sharing.

File Based

Use Cases: file discovery, reverse engineering, permission based access

This is the easiest way to insert a flag. You provide the name of the file where you want the flag to go. Somewhere in the file, there must be the placeholder [FLAG] which we automatically replace once the challenge starts up. This method works with any file type (.txt, .py, .cpp, etc).

Environment Variable

Use Cases: hidden config, stealthy or logic based challenges, dynamic apps

The flag hash can also be placed as an environment variable within the environment itself. This way opens the door to more clever ways you can access the flag. You also have the ability to name the variable itself. To prevent bypassing the challenge itself, commands like printenv are disabled by default.

python

1import os
2flaghash = os.getenv("FLAG_HASH")
3print(flaghash)
You can even go a step further and use, for example, C++ along with the bash script to remove the source code thus the need to run the file instead of looking at the source code.

cpp

1#include <iostream>
2#include<cstdlib>
3using namespace std;
4
5int main() {
6	const char* var = getenv("FLAG_HASH");
7	cout << var << endl;
8}

bash

1#!/bin/bash
2g++ env.cpp -o env
3rm env.cpp

Want to Know More?

Whether you're an educator looking to build custom training scenarios, a CTF organizer looking for flexability, or just someone interested in how our platform works and want a peak - we would be more than happy to show you more. Feel free to reach out via our other page whether that be for a demo, questions, or anything else.
Get Started
© 2025 NorthernKyber. All rights reserved.