In the previous demo, we extracted different segments of the firmware image.
Of most interest was the Squashfs filesystem,
which is a read‑only compressed Linux file system.
We very quickly identified a file containing usernames and password hashes,
one of which we were able to crack with John the Ripper.
We also identified an XML file called default_config.
Configuration files can be treasure troves of information about a system,
so in this demo,
we'll use reverse engineering techniques to find the key to unlock this file.
Dropping into the etc folder of the squashfs filesystem,
we see a number of files that we could explore,
including what appears to be a binary file relating
to the MT7628 system on chip, one to look at later perhaps.
However, the default_config file holds most interest for us in this demo.
Inspecting the contents of this file, we see that it's encrypted.
Let's start our reverse engineering journey by trying to understand
what programs within the OS called default_config.xml.
For this,
we can use grep and specify the r option to search
recursively through the file system,
the n option to print the line number with the output,
and the w option for exact matches to the pattern
which we specify with a ‑e option.
We want to start searching from the root of the file system,
so we specify double dots in quotes to move to a
level above the current etc folder.
And very quickly,
we see that the only reference to the default_config.xml file is
in a shared object file in the library folder.
As we only got one return, it turns out that we didn't need the n and w options.
However,
it's good practice to use them as it will help to narrow down
your search in more complex firmware images.
If this file calls an encrypted file,
it's reasonable to assume that it needs to decrypt it.
So how does it do it?
Let's use ghidra to start reverse engineering the libcmm shared object file.
We begin by creating a new project and calling it TL‑WR841N.
We then drag the libcmm shared object file into the Project pane.
The file is automatically detected to be compiled
for a 32‑bit MIIPs architecture.
Ghidra then does its thing and carries out
preliminary analysis and imports the file.
Clicking on the dragon's head,
we launch the code browser and confirm that we want to analyze the file,
except in the default options.
Ghidra can look pretty intimidating when you first get started,
but be patient with it and explore its functionality, it's incredibly powerful.
It's outside the scope of this course to get into Ghidra in any depth,
but I'll provide some useful resources at the end.
Let's start by searching for strings that match default_config.xml.
The search can take a little while to complete as there is a lot to go through.
However, eventually, we start to get some results through,
and finally, we see a total of four references pointing to two locations.
The dm_loadCfg function looks like a good place to start so let's follow
that up by clicking on the first entry in the table.
Scrolling through the dm_loadCfg function,
we come to a function called dm_decrypt.
We don't have enough information at this stage to follow
through all of the variable references,
but let's take a punt and follow this function call by
clicking on the dm_decrypt function.
At the beginning of the dm_decrypt function,
8 bytes of data are copied from memory to a variable called auStack40.
Dm_decrypt then calls a function which is a wrapper for des encryption
functions from within the libc util shared object file.
The call to this function takes five parameters.
Parameters 1 to 4 are accounted for by the call to dm_decrypt,
but the final 1 is the auStack40 variable.
This has all the hallmarks of being a decryption key,
an 8‑byte data value copied from memory and called
into a function for des decryption.
Clicking on the reference to the suspected decryption key in the Decompile
listing pane takes us to the data value in the Listing pane,
and here we can see 8 bytes of data and hexadecimal
that might be our decryption key.
Let's give it a try.
Back at the Linux command line, we call openssl,
the general purpose crypto and secure communications toolkit.
We specify enc ‑d for decrypt mode and des as the encryption algorithm.
We then use ‑K to specify the key copying in the
hex key we identified in Ghidra.
We then used ‑in to identify the file to be decrypted and ‑out to
specify the name we want to give to the decrypted file.
We get a bad decrypt error message,
but let's ignore it like we've done with all the other error messages so far.
The decrypted file has been created so let's inspect it and see what we have.
And there we go,
a fully decrypted configuration file full of lots of
useful and sensitive information.
For example, here we see a pin for a voice mail service,
and here we see it,
an enabled by default user account for a storage service with
default Username admin and default Password of admin.
There is more to be found, so keep looking.