Strange Calc
I got this new calculator app from my friend! But it’s really weird, for some reason it needs admin permissions to run??
Taking a look at file calc.exe
, we can see calc.exe: PE32 executable (GUI) Intel 80386, for MS Windows, UPX compressed
which means it’s a Windows executable and also packed with UPX.
We can unpack it with UPX by running upx -d calc.exe
. Once unpacked, I decided to analyze the strings using flare-floss to see if there’s any encoded or dynamically generated strings.
\t<assemblyIdentity
\t type="win32"
\t processorArchitecture="*"
\t version="3.0.0.0"
\t name="AutoIt3"
The string AutoIt3
is a dead giveaway that this is an AutoIt script compiled into an executable. We can decompile it using AutoIT Extractor and get the source code.
We can see an interesting string $a
that is encoded and decoded using the x
function. The decoded string is then written to a file r(4) & r(2) & r(3) & r(1) & ".jse"
and executed using MSScriptControl.ScriptControl
. We can base64 decode the string and then convert from Microsoft Script encoding to get the plaintext code.
Lastly, I converted the Javascript code to Python and ran it to get the flag.
And we get the flag!
Base-p-
That looks like a weird encoding, I wonder what it’s based on.
楈繳籁萰杁癣怯蘲詶歴蝕絪敪ꕘ橃鹲𠁢腂𔕃饋𓁯𒁊鹓湵蝱硦楬驪腉繓鵃舱𒅡繃絎罅陰罌繖𔕱蝔浃虄眵虂𒄰𓉋詘襰ꅥ破ꌴ顂𔑫硳蕈訶𒀹饡鵄腦蔷樸𠁺襐浸椱欱蹌ꍣ鱙癅腏葧𔕇鱋鱸𓁮聊聍ꄸꈴ陉𔕁框ꅔ𔕩𔕃驂虪祑𓅁聨朸聣摸眲葮𖠳鵺穭𒁭豍摮饱恕𓉮詔葉鰸葭楷洳面𔕃𔑒踳𔐸杅𐙥湳橹驳陪楴氹橬𓄱蝔晏稸ꄸ防癓ꉁ𖡩鵱聲ꍆ稸鬶魚𓉯艭𔕬輷茳筋𔑭湰𓄲怸艈恧襺陷项譶ꍑ衮汮蹆杗筌蹙怰晘缸睰脹蹃鹬ꕓ脶湏赑魶繡罢𒉁荶腳ꌳ蕔𔐶橊欹𖥇繋赡𐙂饎罒鵡𒉮腙ꍮ楑恤魌虢昹𒅶效楙衎𔕙ꉨ𓈸𔑭樯筶筚絮𓁗浈豱ꉕ魔魧蕕聘筣鹖樫ꍖ汸湖萰腪轪𓉱艱絍笹艨魚詇腁𒁮陴顮虂癁
Looking at the characters, it resembles base65536 encoding. I used an online base65536 decoder to decode the string. This reveals a base64 encoded string:
H4sIAG0OA2cA/+2QvUt6URjHj0XmC5ribzBLCwKdorJoSiu9qRfCl4jeILSICh1MapCINHEJpaLJVIqwTRC8DQ5BBQ0pKtXUpTej4C4lBckvsCHP6U9oadDhfL7P85zzPTx81416LYclYgEAOLgOGwKgxgnrJKMK8j4kIaAwF3TjiwCwBejQQDAshK82cKx/2BnO3xzhmEmoMWn/qdU+ntTUIO8gmOw438bbCwRv3Y8vE2ens9y5sejat497l51sTRO18E8j2aSAAkixqhrKFl8E6fZfotmMlw7Z3NKFmvp92s8+HMg+zTwaycvVQlnSn7FYW2LFYY0+X18JpB9LCYliSm6LO9QXvfaIbJAqvNsL3lTP6vJ596GyKIaXBnNdRJahnqYLnlQ4d+LfbQ91vpH0Y4NSYwhk8tmv/5vFZFnHWrH8qWUkTfgfUPXKcFVi+5Vlx7V90OjLjZqtqMMH9FhMZfGUALnotancBQAA
Popping it into handy CyberChef and using magic reveals it’s a gzip compressed file. By base64 decoding and decompressing the file, we get a PNG. Using an online color picker like here, we can get the hex value of each palette color and convert it to ASCII to get the flag.
Mimi
Uh oh! Mimi forgot her password for her Windows laptop! Luckily, she dumped one of the crucial processes running on her computer (don’t ask me why, okay)… can you help her recover her password? NOTE: This file on its own is not malware per say, but it is likely to raise antivirus alerts. Would recommend examining this inside of a virtual environment. NOTE: Archive password is mimi
First, let’s unzip the archive using 7z x mimi.zip
and take a look at the file using file mimi
:
mimi: Mini DuMP crash report, 18 streams, Tue Sep 10 02:33:22 2024, 0x461826 type
Based on the challenge prompt, we assume this is a memory dump of LSASS. Volatility does not support MiniDump files, but Mimikatz does ;). I spent a decent amount of time trying to get Mimikatz running on my Desktop (thanks Defender…) but kept running into errors. After some searching, I learned of pypykatz which is a pure Python implementation of Mimikatz.
python3 -m pip install pypykatz --break-system-packages
pypykatz lsa minidump ~/Downloads/mimi
Scrolling up to the very top we see a LogonSession for the user mimi
:
== LogonSession ==
authentication_id 709786 (ad49a)
session_id 1
username mimi
domainname windows11
logon_server WINDOWS11
logon_time 2024-09-10T02:32:50.802254+00:00
sid S-1-5-21-940291183-874774319-2012240919-1002
luid 709786
== MSV ==
Username: mimi
Domain: windows11
LM: NA
NT: 5e088b316cc30d7b2d0158cb4bd9497c
SHA1: c1bd67cf651fdbcf27fd155f488721f52fff64fa
DPAPI: c1bd67cf651fdbcf27fd155f488721f52fff64fa
== WDIGEST [ad49a]==
username mimi
domainname windows11
password flag{7a565a86761a2b89524bf7bb0d19bcea}
password (hex)66006c00610067007b00370061003500360035006100380036003700360031006100320062003800390035003200340062006600370062006200300064003100390062006300650061007d0000000000
== Kerberos ==
Username: mimi
Domain: windows11
== WDIGEST [ad49a]==
username mimi
domainname windows11
password flag{7a565a86761a2b89524bf7bb0d19bcea}
password (hex)66006c00610067007b00370061003500360035006100380036003700360031006100320062003800390035003200340062006600370062006200300064003100390062006300650061007d0000000000
== DPAPI [ad49a]==
luid 709786
key_guid 0432784d-4b00-4b75-83af-2cdcc9aabb23
masterkey a862ddb9e230fd284a02322c308ee1acd85a76b672c733cdbe6492462c5ded9709d319da4c9ec96e1f4cc52650ee0122be61938eef489182fb01bf313b1a56ab
sha1_masterkey bb1bff78b80d6d4aeb9d78502bb32d77715ccc00
And we see the flag in the WDIGEST section!
System Code
Follow the white rabbit. NOTE: Bruteforce is permitted for this challenge instance if you feel it is necessary.
rant: this was such a bad challenge.
We are given a website that prompts you for an input.
The first thing that stood out was the Credit
button which links to the repository the website is based off of.
The challenge author gave a lot of hints regarding recon and enumeration, so my first though was feroxbuster
, but there wasn’t any files or directories found using common.txt
, directory-list-2.3.*
, etc. So, I then focused on the GitHub repo. For example, README.md
exists, but does it exist on the webserver (assuming they just did a git clone
). Trying http://challenge.ctf.games:32436/README.md we see it exists! So, let’s compare all the GitHub files to get a list of all the different files to further hone in on.
Running this, we get
File matrix/glyph order.txt is the same
File matrix/LICENSE is the same
File matrix/prettier_command.txt is the same
File matrix/screenshot.png is the same
File matrix/README.md is the same
File matrix/webgpu_notes.txt is the same
File matrix/js/colorToRGB.js is the same
File matrix/js/config.js is different
File matrix/js/main.js is the same
File matrix/js/camera.js is the same
File matrix/js/webgpu/mirrorPass.js is the same
File matrix/js/webgpu/endPass.js is the same
File matrix/js/webgpu/stripePass.js is the same
File matrix/js/webgpu/main.js is the same
File matrix/js/webgpu/rainPass.js is the same
File matrix/js/webgpu/palettePass.js is the same
File matrix/js/webgpu/utils.js is the same
File matrix/js/webgpu/bloomPass.js is the same
File matrix/js/webgpu/imagePass.js is the same
File matrix/js/regl/quiltPass.js is the same
File matrix/js/regl/mirrorPass.js is the same
File matrix/js/regl/stripePass.js is the same
File matrix/js/regl/main.js is the same
File matrix/js/regl/rainPass.js is the same
File matrix/js/regl/palettePass.js is the same
File matrix/js/regl/utils.js is the same
File matrix/js/regl/lkgHelper.js is the same
File matrix/js/regl/bloomPass.js is the same
File matrix/js/regl/imagePass.js is the same
File matrix/svg sources/texture_simplified.svg is the same
File matrix/svg sources/coptic_texture_simplified.svg is the same
File matrix/svg sources/gothic_texture_simplified.svg is the same
File matrix/svg sources/huberfish_a.svg is the same
File matrix/svg sources/huberfish_d.svg is the same
File matrix/shaders/glsl/quiltPass.frag.glsl is the same
File matrix/shaders/glsl/rainPass.intro.frag.glsl is the same
File matrix/shaders/glsl/stripePass.frag.glsl is the same
File matrix/shaders/glsl/bloomPass.combine.frag.glsl is the same
File matrix/shaders/glsl/palettePass.frag.glsl is the same
File matrix/shaders/glsl/rainPass.frag.glsl is the same
File matrix/shaders/glsl/rainPass.effect.frag.glsl is the same
File matrix/shaders/glsl/bloomPass.highPass.frag.glsl is the same
File matrix/shaders/glsl/bloomPass.blur.frag.glsl is the same
File matrix/shaders/glsl/rainPass.raindrop.frag.glsl is the same
File matrix/shaders/glsl/rainPass.symbol.frag.glsl is the same
File matrix/shaders/glsl/rainPass.vert.glsl is the same
File matrix/shaders/glsl/imagePass.frag.glsl is the same
File matrix/shaders/glsl/mirrorPass.frag.glsl is the same
File matrix/shaders/wgsl/imagePass.wgsl is the same
File matrix/shaders/wgsl/stripePass.wgsl is the same
File matrix/shaders/wgsl/endPass.wgsl is the same
File matrix/shaders/wgsl/palettePass.wgsl is the same
File matrix/shaders/wgsl/bloomBlur.wgsl is the same
File matrix/shaders/wgsl/bloomCombine.wgsl is the same
File matrix/shaders/wgsl/rainPass.wgsl is the same
File matrix/shaders/wgsl/mirrorPass.wgsl is the same
File matrix/lib/regl.js is the same
File matrix/lib/holoplaycore.module.js is the same
File matrix/lib/regl.min.js is the same
File matrix/lib/gpu-buffer.js is the same
File matrix/lib/gl-matrix.js is the same
File matrix/assets/megacity_msdf.png is the same
File matrix/assets/msdf_command.txt is the same
File matrix/assets/pixel_grid.png is the same
File matrix/assets/gtarg_tenretniolleh_msdf.png is the same
File matrix/assets/metal.png is the same
File matrix/assets/gothic_msdf.png is the same
File matrix/assets/gtarg_alientext_msdf.png is the same
File matrix/assets/matrixcode_msdf.png is the same
File matrix/assets/resurrections_glint_msdf.png is the same
File matrix/assets/huberfish_a_msdf.png is the same
File matrix/assets/neomatrixology_msdf.png is the same
File matrix/assets/Matrix-Code.ttf is the same
File matrix/assets/huberfish_d_msdf.png is the same
File matrix/assets/mesh.png is the same
File matrix/assets/resurrections_msdf.png is the same
File matrix/assets/Matrix-Resurrected.ttf is the same
File matrix/assets/sand.png is the same
File matrix/assets/coptic_msdf.png is the same
File matrix/playdate/.gitignore is the same
File matrix/playdate/INSTRUCTIONS.md is the same
File matrix/playdate/matrix_lua/Source/main.lua is the same
File matrix/playdate/matrix_lua/Source/pdxinfo is the same
File matrix/playdate/matrix_lua/Source/images/matrix-glyphs.png is the same
File matrix/playdate/matrix_lua/Source/images/fade-gradient.png is the same
File matrix/playdate/matrix_c/CMakeLists.txt is the same
File matrix/playdate/matrix_c/main.c is the same
File matrix/playdate/matrix_c/Source/pdxinfo is the same
File matrix/playdate/matrix_c/Source/images/matrix-glyphs.png is the same
File matrix/playdate/matrix_c/Source/images/fade-gradient.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/88.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/77.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/63.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/62.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/76.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/89.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/60.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/74.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/48.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/animation.txt is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/49.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/75.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/61.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/59.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/65.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/71.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/70.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/64.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/58.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/8.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/72.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/66.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/67.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/73.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/9.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/14.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/28.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/29.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/15.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/17.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/16.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/12.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/13.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/39.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/11.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/10.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/38.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/35.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/21.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/20.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/34.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/22.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/36.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/37.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/23.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/27.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/33.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/32.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/26.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/18.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/30.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/24.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/25.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/31.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/19.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/95.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/81.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/4.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/56.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/42.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/43.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/5.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/57.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/80.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/94.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/82.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/41.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/55.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/7.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/69.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/68.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/54.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/6.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/40.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/83.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/87.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/93.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/78.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/44.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/2.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/50.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/3.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/51.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/45.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/79.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/92.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/86.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/90.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/84.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/53.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/1.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/47.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/46.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/52.png is the same
File matrix/playdate/matrix_c/Source/images/launcher/card-highlighted/85.png is the same
There is only one different file, js/config.js
. This is where I got stuck for a while, trying to compare the webserver’s config.js to the GitHub default config.js. One though was the color palette— maybe the hsl()
colors if converted to HEX would be an ASCII string? But, that didn’t really get me anywhere.
My next thought was just bruteforcing strings (since the challenge permits it), so started trying characters, quotes, etc from The Matrix
and Alice in Wonderland
but no dice there either.
I went back to analyzing the config.js
since it was my only lead and noticed a configuration property called backupGlyphsTwr
which had zero references in the GitHub.
It wasn’t until I took a break and got home I realized Twr
was THE WHITE RABBIT!!
So, I generated permutations of abcdef to try as inputs.
And the permutation bfdaec
gives us the flag!
MOVEable
Ever wanted to move your files? You know, like with a fancy web based GUI instead of just FTP or something? Well now you can, with our super secure app, MOVEable! Escalate your privileges and find the flag.
We’re provided with a simple Flask application, with just one component: app.py
. Based on the name, MOVEable
and because this is HuntressCTF (which means John Hammond is involved) I figured this is a reference to MOVEit
because of the name and the fact John Hammond helped research MOVEit to uncover the attack chain. For those unfamiliar, the MOVEit vulnerability allowed unauthenticated RCE via SQLi and deserialization.
The first thing I looked at was the login functionality:
Immediately, two things stood out:
- The SQL query is crafted via injecting variables aka no parameterization
- We use
executescript
instead ofexecute
which means we can run other queries besides theSELECT
statement
However, there is also a DBClean function, which (in theory) sanitizes input from SQL injection. It strips
, '
, and "
and replaces \
with '
’.
So we’ll probably have to bypass this filter to get SQL injection to login as a user. Let’s keep on looking through the code, the next piece the download functionality:
This is a GET request which takes a filename
and sessionid
parameter and will retrieve a file via unpickling. Remember that MOVEit
exploited deserialization and here we are… using pickle
:
“Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream (from a binary file or bytes-like object) is converted back into an object hierarchy. (https://docs.python.org/3/library/pickle.html)
So, now we have an attack chain planned out.
- SQL injection to get a valid user session ID
- Download
flag.txt
using the provided session ID
Which seems easy, but in reality, it isn’t. If we look at the init_db
function:
It poses problems with our plan. The first being that there are no users and the second being the flag.txt
is not really a flag. So, we need to adjust our attack chain:
- SQL injection to INSERT a user into the
users
table - SQL injection to INSERT a session into the
activesession
table - SQL injection to INSERT a malicious pickle into the
files
table - Then call the
/download/<file>/<session>
to get our pickle to execute!
With a gameplan in mind, let’s attack it. I first started by creating the inverse of DBClean, so I could create normal SQL queries without needing to constantly consider filter bypasses.
This replaces '
with \
(which DBClean will then turn back into a '
), spaces into /**/
which SQLite will parse as whitespace, and "
with \"
.
Next, we generate our queries. For example, inserting a malicious user. And just a reminder, we’re able to call multiple queries, ie: SELECT ...; INSERT
because the Flask app uses .executescript()
. If it uses .execute()
, this specific attack chain would have been mitigated.
We do the same thing for session:
And then we generate our malicious pickle:
We now have three SQL queries which will insert a user, session, and file. All we need to do now is /download/<filename>/<session>
and when pickle.loads()
is called, our pickle will get unpickled and turned into a Python object, causing subprocess
to run our reverse shell! Putting it all together into a solve.py
:
Palimpsest
Our IT department was setting up a new workstation and started encountering some strange errors while installing software. The technician noticed a strange scheduled task and luckily backed it up and grabbed some log files before wiping the machine! Can you figure out what’s going on?
We’re provided four files:
Application.evtx
Security.evtx
System.evtx
Updater Service.xml
Based on the challenge prompt, the first thing to investigate is the scheduled service. Doing cat Updater\ Service.xml
there’s one section that really stands out:
It grabs TXT
records for the domain 5aa456e4dbed10b.pyrchdata.com, decodes from base64, and executes it as a PowerShell command. So, let’s query the TXT record.
Then, we can decode from base64:
We have some slightly obfuscated PowerShell. It’s pretty apparent what it’s doing, based on the neW-oBJECT Io.ComPreSsION.dEflATeStReAm([sySTem.IO.mEMORYsTREAM][sYstEM.cOnveRT]::FROmBAsE64string
. Luckily, I have a handy Python script called deflate.py that allows me to deflate PowerShell memorystreams without using PowerShell. Updating the base64 string in the script and running the script:
Another layer of obfuscation. This time we have an array of numbers. At the very end, we also see a -BxOR'ox5D'
statement, so looks like it’s iterating through each element of the array and XORing with 0x5d. We can reverse this with a simple Python script as well 😄
This is the last layer! It’s more heavily obfuscated than the others, but it’s still pretty trivial.
- Create an array of numbers 40000-65000
- Open file
%AppData%/flag.mp4
- Call
Get-EventLog
onApplication
logs- Filter by
Source
=mslnstaller
- Filter by
InstanceId
in range of 40000-65000
- Filter by
- Sort based on
Index
- Write the
Data
toflag.mp4
- Close the handle on
%AppData%/flag.mp4
You can easily reverse this if you’re on Windows by using PowerShell, which is what my team did initially:
Or, if you’re working on a non-Windows OS, you can utilize things like Python evtx
library or chainsaw
. I opted for the latter: first converting the Application.evtx
into JSON:
Then, I created a Python script to replicate the filtering logic of the PowerShell script:
Running this script will iterate through the events and if it’s a valid event (source and EventID match), it will place the binary data in the chunk based on RecordID. Then, we just clear unused chunks and write the file to flag.mp4
!
GoCrackMe3
I didn’t keep good documentation of this one. It was more trial and error until something worked. Despite not being a good writeup, I’m including it because there were only ~100 solves after 20 days. It was basically a lot of patching. For example, 0x004f7a76 JZ
to JNZ
would give the ‘Access still denied’ message. Then at 4f7fcd
you could patch to get ‘Actually, I don’t feel like printing the flag…’
I kept repeating the patching of the logic (basically just invert everything) and changing some of the JMP
branches, and eventually you can get to 004f81a4
which generates chunks of the flag in memory. By default, it only does 3 chunks: 221fccaa8
, flag{32b2
, 42024a30b
and you need to patch the for loop to get the last chunk: edda76fdc2
.
I cheesed this pretty hard since it was out of order, but I just generated all permutations and tried each one.
flag{221fccaa832b242024a30bedda76fdc2}
flag{221fccaa832b2edda76fdc242024a30b}
flag{221fccaa842024a30b32b2edda76fdc2}
flag{221fccaa842024a30bedda76fdc232b2}
flag{221fccaa8edda76fdc232b242024a30b}
flag{221fccaa8edda76fdc242024a30b32b2}
flag{32b2221fccaa842024a30bedda76fdc2}
flag{32b2221fccaa8edda76fdc242024a30b}
flag{32b242024a30b221fccaa8edda76fdc2}
flag{32b242024a30bedda76fdc2221fccaa8}
flag{32b2edda76fdc2221fccaa842024a30b}
flag{32b2edda76fdc242024a30b221fccaa8}
flag{42024a30b221fccaa832b2edda76fdc2}
flag{42024a30b221fccaa8edda76fdc232b2}
flag{42024a30b32b2221fccaa8edda76fdc2}
flag{42024a30b32b2edda76fdc2221fccaa8}
flag{42024a30bedda76fdc2221fccaa832b2}
flag{42024a30bedda76fdc232b2221fccaa8}
flag{edda76fdc2221fccaa832b242024a30b}
flag{edda76fdc2221fccaa842024a30b32b2}
flag{edda76fdc232b2221fccaa842024a30b}
flag{edda76fdc232b242024a30b221fccaa8}
flag{edda76fdc242024a30b221fccaa832b2}
flag{edda76fdc242024a30b32b2221fccaa8}
I got the correct flag on my third attempt. Also, using https://github.com/getCUJO/ThreatIntel for Ghidra helps with the process a lot. You can also use this PR by https://github.com/monoidic which adds golang 1.20 support.