The Problem: firmware.ins (See README for instructions on extracting the image.)

The Clue: Who knew embedded web servers ran PHP natively? And it's easy to read! Or is it?!

Warning: This challenge’s flag reqiures the player to generate the flag by taking an MD5 hash of a defined PHP function named mb_version.

Summary

When I submitted the correct flag, I became the 9th person to solve this challenge (with a total of 12 solves at the end of the event). And that seemed rather surprising to me after knowing how straight forward the challenge is. I am not sure if players were generally uninterested in the challenge or if the barrier to entry seemed high. Despite unintentionally spoiling this challenge for myself, I thought it was very fun.

From the clue we know we are looking for a PHP file. Easy! They are in the www directory on the extracted file system. The only problem is all of the PHP files are encrypted, so their contents are unreadable. This part had me stumped. Honestly, if I didn’t spoil the challenge for myself while trying to do some research; I probably wouldn’t have solved it. Simply put, a web server uses the PHP binary to parse and execute PHP code. This means that in order to serve these encrypted PHP files, the PHP binary needs to know how to decrypt them. To determine what this process entails, open the PHP binary (from the firmware, not your local environment!) in ghidra.

Ghidra identifies and analyzes the binary we provide it. When ghidra has completed its analysis, pop open the detected functions and you will see a strange function named screw_aes. Now, this seems like a good place to start. AES is a well-known encryption spec. Examining ghidra’s decompiler output it doesn’t seem like there is anything going on here. Let’s check the references to this function. We can see that a password is passed as an argument to the screw_aes function. Winner, winner, chicken dinner! We can use this password to decrypt all of the PHP files.

Once all of the files have been decrypted we can rely on grep to help us find mb_version. Finally, after locating the code block, we can send it through the MD5 hashing function to generate the flag.

Steps to Solve

  1. Download firmware archive.
  2. Extract filesystem from image using binwalk.
  3. Open, analyze, and reverse-engineer PHP binary with ghidra.
  4. Using the password recovered in the previous step, we can generate an AES key: 3834326434326239383837366635383166306466626566623063643262356333
  5. Use key with OpenSSL to decrypt PHP files.
  6. Locate mb_version function in decrypted files.
  7. Generate flag data: cat usr/www/3.0/config/version.php.dec.php | tail -n 13 | head -n 12 | md5sum
  8. Format flag data: flag{2b1f15fa0db8460d17d573ee7d491271}