Free Ski
Difficulty:
Shown in Report
Go to the retro store and help Goose Olivia ski down the mountain and collect all five treasure chests to reveal the hidden flag in this classic SkiFree-inspired challenge.
Objective Image
Back
Challenge

HONK! Well hello there in the Dosis Neighborhood. Funny thing - I used to just wander the Geese Islands going BONK all day with no thoughts at all. Then suddenly I started thinking… and talking!
But listen - if Frosty turns this place into a permanent winter, geese can’t migrate. Being stuck forever? Not natural, even for a newly-thinking goose.
This little game here looks simple… maybe too simple. Winning it fairly might be close to impossible
My advice?* If you ain’t cheatin’, you ain’t tryin’*.
Now go show that mountain who’s boss!

Solution

First, we'll get the program and the Python script to extract the contents of a PyInstaller generated executable file:

wget https://www.holidayhackchallenge.com/2025/assets/FreeSki.exe
wget https://raw.githubusercontent.com/extremecoders-re/pyinstxtractor/refs/heads/master/pyinstxtractor.py

python3  pyinstxtractor.py FreeSki.exe
[+] Processing FreeSki.exe
...
[+] Possible entry point: FreeSki.pyc

To decompile, I use a new decompiler that is still in beta: PyLingual.
Installation and use are very simple:

git clone https://github.com/syssec-utd/pylingual
cd pylingual
python -m venv venv
. ./venv/bin/activate
pip install poetry>=2.0

poetry install
pyproject.toml changed significantly since poetry.lock was last generated. Run `poetry lock` to fix the lock file.
poetry lock
poetry install
(venv) C:\Temp\FreeSki.exe_extracted>pylingual FreeSki.pyc
...
[23:44:54] INFO     Loading FreeSki.pyc...                                                             decompiler.py:444
[23:44:55] INFO     Detected version as 3.13                                                           decompiler.py:452
           INFO     Loading models for 3.13...   
...
[23:51:09] INFO     Decompilation complete                                                             decompiler.py:479
           INFO     79.31% code object success rate                                                    decompiler.py:480
           INFO     Result saved to decompiled_FreeSki.py    

Here is the result of the decompilation: decompiled_FreeSki.py

This time, we'll let AI help us and explain the program:

Analyze the following python game:

<code pasted>

It’s a deterministic Pygame ski game that hides a flag in encoded_flag per mountain. The treasures you collect don’t contain the flag; their positions are used as a seed to XOR-decode that encoded_flag. The decompiler mangled a few functions, but the crypto is clear and easy to reproduce offline.
...
If you want, I can write a clean standalone Python script that reconstructs Mountains, computes treasure_list for each one, and prints all their flags without touching Pygame at all.

Of course, we accept this help and get an auxiliary tool generated: freeski_flag_extract.py

python freeski_flag_extract.py
Mountain: Mount Snow
  Treasures (elev, horiz_mod):
    elevation=2966, horiz_mod=113
    elevation=2420, horiz_mod=85
    elevation=1718, horiz_mod=188
    elevation=1094, horiz_mod=142
    elevation=466, horiz_mod=85
  Flag: frosty_yet_predictably_random