Description
Flag.txt was encrypted into flag.txt.enc using OpenSSL AES256. Use Sleuth Kit to browse the disk image, find the encrypted file and .ash_history, then decrypt the file using the password from .ash_history.
Decompress the disk image: gunzip disk.flag.img.gz.
Use mmls disk.flag.img to find the main partition offset, then fls -r -o <offset> to list files.
Find flag.txt.enc and the .ash_history file using fls, extract both with icat.
Read .ash_history to recover the AES decrypt command, then run it.
gunzip disk.flag.img.gzmmls disk.flag.imgfls -r -o <OFFSET> disk.flag.img | grep -E 'flag|ash_history'icat -o <OFFSET> disk.flag.img <ASH_HISTORY_INODE>icat -o <OFFSET> disk.flag.img <FLAG_ENC_INODE> > flag.txt.encopenssl aes256 -d -in flag.txt.enc -out flag.txtcat flag.txtSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Find files and inspect .ash_history
ObservationThe description says the flag was encrypted with OpenSSL and a password, and the image carries a .ash_history file. Whoever ran that encrypt command left it in shell history, password and all.Usefls -rto find the .ash_history inode, thenicatto extract it. The history shows exactly how flag.txt was encrypted, including the password. That is all you need to undo the process.What didn't work first
Tried: Running
strings disk.flag.imgdirectly to search for the password or flag.strings on a raw disk image returns megabytes of noise from filesystem metadata, deleted fragments, and inode tables. The history content is in there, buried and fragmented across sectors, so grepping for openssl in that output will very likely miss it. Locate the inode with fls and extract the exact bytes with icat.
Tried: Using
flswithout the-ooffset flag, targeting the raw image directly.The image holds a partition table rather than a bare filesystem, so fls with no offset meets an unrecognized structure and exits. Run mmls first for the Linux partition's sector offset, then pass it to both fls and icat so they read the ext filesystem correctly.
Learn more
Shell history (here
~/.ash_history, since the image runs Alpine's ash shell rather than bash) records every command typed in an interactive session and persists across reboots. It is one of the first places a forensic investigator examines when analyzing a disk image, because it shows exactly what commands a user ran - including commands with sensitive arguments like passwords, API keys, and file paths.The critical mistake here is passing the password directly on the command line with
-k password. This exposes the password in at least three places: the shell history file, the process list (readable by other users while the command is running viaps aux), and potentially shell log files. The safer approach is to use-pass file:keyfileor let OpenSSL prompt interactively, which keeps the password out of both history and process listings.In real forensics, shell history often reveals attacker tooling, downloaded scripts, data exfiltration commands, and privilege escalation attempts. Attackers sometimes try to clear history with
history -cor by settingHISTSIZE=0, but the on-disk history file may still contain entries if the session wasn't terminated cleanly.Step 2Decrypt the file
ObservationThe history holds the exact openssl aes256 encrypt command with its password in plaintext. Invert it with -d and the same password to recover flag.txt.Run the inverse openssl command (-d) on flag.txt.enc to produce flag.txt and read the picoCTF flag.What didn't work first
Tried: Omitting the
-dflag and runningopenssl aes256 -in flag.txt.enc -out flag.txtwith the recovered password.Without -d, OpenSSL defaults to encrypting and re-encrypts the already-encrypted file into a doubly-encrypted blob. It exits cleanly and produces output, so nothing looks wrong; the output is just more ciphertext. -d switches it to decryption.
Tried: Using a different OpenSSL cipher subcommand such as
openssl enc -aes-256-cbcinstead ofopenssl aes256.The exact cipher subcommand matters, because it fixes the key derivation parameters and the CBC settings. Swap the recorded command for a differently-flagged one, adding -pbkdf2 or -iter, and the same password derives a different key, giving a decryption failure or garbled output. Mirror the command from the history file exactly.
Learn more
AES-256 (Advanced Encryption Standard with a 256-bit key) is the current gold standard for symmetric encryption. It is used by governments, militaries, and commercial software worldwide. Unlike DES or 3DES, AES has no practical known attacks against the algorithm itself when used correctly - the weakness demonstrated here is entirely in key management, not the cipher.
OpenSSL's
aes256subcommand uses AES in CBC mode by default with a password-based key derivation function (EVP_BytesToKey) and a random salt (when-saltis specified). The salt is prepended to the ciphertext so that decryption can derive the same key. The-dflag switches from encryption to decryption mode.The irony of naming a password
unbreakablepassword1234567while storing it in shell history illustrates the real-world principle that the strength of encryption is only as good as the security of the key. AES-256 is mathematically unbreakable with a good key, but a key stored in plaintext in a recoverable file provides no protection at all.
Interactive tools
- Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
- File Magic IdentifierIdentify file types from magic numbers. Paste hex bytes or drop a file to detect PNG, JPEG, ZIP, PDF, ELF, PCAP, SQLite, and dozens of other formats.
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
Flag
Reveal flag
picoCTF{h4un71ng_p457_1d02...}
Sister challenge to Operation Oni - same disk-image methodology, different artifact. Oni rewards you with an SSH key; here the shell history hands you the password to a locally encrypted file. Verify the encrypted blob actually decrypts (the openssl `-d` exit code is 0) before assuming you've grabbed the right file from the image.