QNAP firmware extractor module - from 0 to full firmware analysis

Posted on Feb 8, 2022

On one of our last penetration tests we had a QNAP device in front of us. While we started investigating the device via the network, we also wanted to use our firmware scanner EMBA for the automated firmware analysis tasks. The firmware was available from the QNAP download site and starting EMBA with the default profile looks like a quick win. After a while we realised that EMBA was running into the deep-extraction mode and finally failed extracting the needed firmware. The initial check on a not extracted firmware is typically the entropy value:

QNAP_entropy_binwalk

An entropy value of straight 1 typically means the firmware is compressed or encrypted. After some digging and research we identified that the firmware update files from the download site are somehow encrypted. Additionally, Binwalk was able to give another hint on it:

QNAP_decrypt_binwalk

This was good. The bad was, that Binwalk was not able to extract the firmware. This means we had to start with some recon work. We found the interesting project qnap-utils which should be able to decrypt QNAP firmware images. In issue 1 also the source code of a working version of the needed PC1 tool was linked. After compiling it on a current Kali Linux machine we were able to extract a tgz archive from the update image.

QNAP_decrypt

We wrote a quick EMBA module for the decryption and everything should be good to go. We designed it in a way to identify the QNAP encrypted firmware via Binwalk. With the -y parameter Binwalk supports checking only specific signatures. In our case we run Binwalk with the “qnap encrypted” signature in the P02 module for the identification:

binwalk -y “qnap encrypted” “$CHECK_FILE”

If the output of this command includes “QNAP encrypted firmware footer , model” then the QNAP decryption module is used. The compiled PC1 binary which is needed for the decryption process is placed in the ./external folder. On a user installation this is done by the EMBA installer and so the module just needs to execute this binary with the correct set of parameters.

After updating everything we were ready for the first run. The firmware got decrypted and during the deep-extraction a lot of filesystem areas where extracted. As EMBA is doing a lot of tests on a firmware this scan took quite a while. After finishing the testing process EMBA has identified around 50 software components with version details and a lot of other interesting stuff like the used binary protections and weak binary functions.

QNAP_binary_functions

During our investigation of the results, we realized that most of these results were based on our static analysis module - s09. This also means that the very powerful version detection via dynamic analysis was mostly failing. With this in mind our investigation on how to improve the testing results started. First issue we identified during checking the project qnap-utils was that the extracted filesystem we generated with our deep-extraction mode was there but it was very messy. This was not a problem for all the static analysis mechanisms, but for dynamic analysis with qemu a non clean filesystem was a blocker (at this time). To get a better filesystem we analyzed the code from the extract_qnap_fw.sh script and ported it into the QNAP decryption module as additional extractor for QNAP firmware. As the original code was a bash script it was quite easy to port it to EMBA and do some cleanup to make it shellcheck compatible.

Another issue we identified was the problem that the emulator was not able to recover needed stuff from the extracted data. We will take a deeper look at this in a following blog post. After all these modifications EMBA was finally able to identify 94 software components with version details:

QNAP_software_components