This is the data provided:
I suppose we'll be searching for something hidden. We're given a compressed file "invokeme.7z" (note the filename)... Inside, there is an image file (9.81 MB in size, pretty big).
I'm pretty confident at this point that this is a steganography challenge. The challenge description said that something was hidden for thousands of years, maybe it was referring to steganography's history.
The first recorded uses of steganography can be traced back to 440 BC
Lets solve this. We'll be using Linux this time.
Note: most of the tools we'll be using here don't come preinstalled on Ubuntu, so you'll have to manually install them. I wont go over that process here.
First thing, I want to make sure that this file is indeed a JPG or JPEG image (the file extension isn't always true, you know..). Lets use Linux's file command.
Confirmed! It's a JPEG file.
Here's our work plan:
- Inspect the image manually, maybe the flag is hidden somewhere, or a hint or so..
- Look up the Basic methods and tools used to hide data inside JPEG files
- Look up the Advanced methods and tools used to hide data inside JPEG files
- For each method/tool, check if any data was hidden inside our JPEG file using it
- Once we confirm the tool/method used, we'll extract the hidden data accordingly
1- Manual image inspection
The image is pretty big (5184x3456) and a has a lot of details, colors, lighting and stuff... So I couldnt make out anything useful from it.
2- Basic methods and tools used to hide data inside JPEG files
If you googled "steganography tools", you will stumble accross this wonderful collection of tools by Dominic Breuker.
The list of tools is pretty big, but we're currently interested only in the tools that support hiding data in JPEG files, so our list will be shorter.
Lets start first by the basic data-hiding methods (labeled "General screening tools" in the github page)
A. Check the EXIF-metadata of our JPEG file using exiftool
B. Check if other files are appended together... using binwalk
Nope.. just our innocent JPEG file
C. Checking for interesting strings.. I'll use the built-in strings command, and pipe its output to a grep command to give us the strings longer than 7 characters. And of course redirect that output to a text file.
Tried searching for "flag" or "fl4g" or "secret".... Nothing.
D. Use "foremost" to scan the headers and look for any weird data structures..
E. Checking for image corruption using "identify"..
Nope, looks fine.
That's it for the Basic tools. Lets dig deeper 💀
3- Advanced methods and tools used to hide data inside JPEG files
We'll continue on our wonderful Github list.
A. Using stegdetect. Maybe it will find something
B. Lets try stegoVeritas. It's a python script that manipuates the given image using various filters to make some colours or elements in the picture stick-out instead of blending in with the background.
We now have 38 files. Lets skim through them quickly..
Something caught my eye..
Yet the same spot doesnt look fishy at all in the original image
Or even in one of the red-filtered images.
Lets zoom in and see what's there
Sweet! Lets try this flag...
Note that it says: "l3757ryh4rd3r". That's "LetsTryHarder" in leetspeak.
What to do now?
Two possibilities.. Either this sentence we found is a part of a multi-step challenge. Or this is just a distraction to throw us off.
Anyways, we'll continue. Lets check the rest of the tools..
I tried it and got nothing
E. outguess from SSAK. It requires a password to decrypt the hidden data though, so I tried the word we found earlier "l3757ryh4rd3r". But this tool didn't work for some reason. Lets leave it for now.
F. steghide. It also requires a password to decrypt the data. Lets see...
Win!! and guess what? the extracted text file is called "reinvoke.txt"... Remember this challenge's zip-file name?
Lets grab the flag from our new text file.
Hmmm... That doesnt look like the flag to me. And it doesnt contain the word "flag" or "fl4g" or anything. This has got to be some sort of ciphertext.
After staring at this text for a couple of minutes, I noticed that some "words" are repetead.
Maybe a substitution cipher is used here.. Lets try all possibilities of Caesar cipher on this text.
I was stuck here for a few minutes, then I decided to google the words that were repeated a couple of times in this text. After a couple of searches, I stumbled upon a website that has similar text in its HTML:
<div class="encrypted-content" style="display:none"> kAm“%96 FD6D 7@C 5C@?6 E649?@=@8J 8C@H 52:=J[” 96 D2:5]k^Am </div>
Note that the "div" element's class is "encrypted-content". So this is some sort of encryption. Lets see how this website decrypts this...
A quick look on the website's JS files, I noticed a file called "decrypt.js"
Looks interesting, lets beautify it, and copy it to notepad++ and check it out with syntax highlighting.
It appears to be a Jquery file. But why was it named "decrypt.js"?
If we scroll to the end, we'll see a function called "unscramble". It appears to be modifying each character's unicode value.
Lets try it on our text, then study it later. Copy it over to the developer's console in the web browser.
Note that the ciphertext we want to decode contains line-breaks. so we have to remove those first because JS is picky about it.
I used a regex in notepad++ to search & replace.
No errors now, sweet!
Lets try our decryption function 🤞
Boom! that's our flag right there:
I'll also explain the decryption function briefly:
- Create an empty string to store our decryption results in. (Line 2729)
- Grab current character's unicode value using charCodeAt function, and store it in a local variable called nChar. (Line 2731)
- Make sure that nChar lies between 33 and 126 (ASCII printable values.. including symbols like @#$%, lowercase and uppercase English alphabets and English digits) . Otherwise, skip this character. (Line 2732)
- Add 14 to nChar ( nChar - 33 + 47)
- Do a modulo operation on the result with 94. (result % 94)
- Add 33 to the result.
- Then grab the letter represented by the result value using String.fromCharCode function.
- Add this letter to our output String created in step 1.