Operation Orchid picoCTF 2022 Solution

Published: July 20, 2023

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.

bash
gunzip disk.flag.img.gz
bash
mmls disk.flag.img
bash
fls -r -o <OFFSET> disk.flag.img | grep -E 'flag|ash_history'
bash
icat -o <OFFSET> disk.flag.img <ASH_HISTORY_INODE>
bash
icat -o <OFFSET> disk.flag.img <FLAG_ENC_INODE> > flag.txt.enc
bash
openssl aes256 -d -in flag.txt.enc -out flag.txt
bash
cat flag.txt

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1
    Find files and inspect .ash_history
    Observation
    I noticed the challenge description mentioned that the flag was encrypted using OpenSSL with a password, and the disk image contained a .ash_history file, which suggested that the user who ran the encrypt command left the exact command (including the plaintext password) recorded in shell history.
    Use fls -r to find the .ash_history inode, then icat to 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.img directly to search for the password or flag.

    strings on a raw disk image produces megabytes of noise from filesystem metadata, deleted file fragments, and inode tables. The ash_history content is present but buried and fragmented across sectors, so grepping for 'openssl' in the strings output will almost certainly miss it. Using fls to locate the inode and icat to extract the exact file bytes is the reliable approach.

    Tried: Using fls without the -o offset flag, targeting the raw image directly.

    The disk image contains a partition table, not a bare filesystem, so fls without an offset sees an unrecognized structure and exits with an error. Running mmls disk.flag.img first reveals the correct sector offset for the Linux partition, which must be passed as -o <offset> to fls and icat for them to interpret the ext filesystem correctly.

    Learn more

    Bash history (~/.bash_history) records every command typed in a terminal 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 via ps aux), and potentially shell log files. The safer approach is to use -pass file:keyfile or let OpenSSL prompt interactively, which keeps the password out of both history and process listings.

    In real forensics, bash history often reveals attacker tooling, downloaded scripts, data exfiltration commands, and privilege escalation attempts. Attackers sometimes try to clear history with history -c or by setting HISTSIZE=0, but the on-disk .bash_history file may still contain entries if the session wasn't terminated cleanly.

  2. Step 2
    Decrypt the file
    Observation
    I noticed the .ash_history contained the exact openssl aes256 encrypt command with the password in plaintext, which meant inverting that command with the -d flag and the same password was sufficient to recover the original 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 -d flag and running openssl aes256 -in flag.txt.enc -out flag.txt with the recovered password.

    Without -d, OpenSSL defaults to encryption mode and re-encrypts the already-encrypted file, producing a doubly-encrypted blob instead of plaintext. The command exits with code 0 and produces output, so there is no obvious error - the output just contains ciphertext instead of the flag. Adding -d switches OpenSSL to decryption mode.

    Tried: Using a different OpenSSL cipher subcommand such as openssl enc -aes-256-cbc instead of openssl aes256.

    The exact cipher subcommand matters because it determines key derivation parameters and CBC settings. If the .ash_history shows openssl aes256 -k password, using openssl enc -aes-256-cbc with different flags (like -pbkdf2 or -iter) will derive a different key from the same password and produce a decryption failure or garbled output. Always mirror the exact command from the history file.

    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 aes256 subcommand uses AES in CBC mode by default with a password-based key derivation function (EVP_BytesToKey) and a random salt (when -salt is specified). The salt is prepended to the ciphertext so that decryption can derive the same key. The -d flag switches from encryption to decryption mode.

    The irony of naming a password unbreakablepassword1234567 while storing it in bash 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 bash 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.

Key takeaway

Shell history files like .bash_history and .ash_history are persistent forensic artifacts that record every interactive command, including sensitive arguments passed on the command line. Passing secrets as command-line flags exposes them to the process list, shell logs, and history files simultaneously. In real-world incident response, history files are among the first artifacts examined because they reveal attacker tooling, lateral movement, and data exfiltration commands in chronological order.

Related reading

Want more picoCTF 2022 writeups?

Useful tools for Forensics

What to try next