Insomni’Hack write-up : “The Secr3tMgr Lock” challenge

Olivier Chatail Writeups

The following write-up details a solution to one of the Insomni’Hack Capture The Flag challenge.

Insomni’Hack is a Swiss security conference in Geneva which hosts an on-site CTF competition. https://insomnihack.ch/

The 2017 edition of the competition took place in March from Friday the 24th 6pm to Saturday the 25th 3am, 4 members of Devoteam were among the competitors.

The contest featured several types of challenges, from traditional web/exploit/forensics to game hacking.

The Secr3tMgr Lock challenge

The challenge, categorized as Forensics, is about finding a user’s unlocking secret from a (seemingly) RAM dump.

We know that the flag/secret follows the pattern INS{xxxxx}.

The solution

First we download the challenge archive and unzip it.

Three files are provided : a binary, a System.map and a module.dwarf.

We suppose the binary is a RAM image, we will then use the Volatility tool and create an Android profile to parse accurately the image. System.map (kernel symbol table) and module.dwarf  are necessary to build up the profile, they describe the binary internals for volatility.

We then retrieve latest volatility source and include our new profile.

 

We verify that it has been included properly and understood by the tool.

 

Things can get started !

Among the basic information listing we retrieve the file system using linux_recover_filesystem Volatility plugin to look for password/pin related files :

  • /data/system/gesture.key : contains an unsalted hash of the unlock pattern
  • /data/system/password.key : contains salted hashes of the unlock password
  • /data/system/device_policies.xml : contains various information on the unlock password
  • /data/data/com.android.providers.settings/databases/settings.db : SQLite database containing a key identifying the salt used for generating the password’s hashes

 

Let’s take a look at the retrieved files.

gesture.key : contains the hash da39a3ee5e6b4b0d3255bfef95601890afd80709, which is the unsalted hash for an empty string… Wrong way.

password.key : contains a very long string, seems to be the concatenation of two hashes.

After researches this string is the concatenation of the SHA1 salted hash (first 40 bytes) and MD5 salted hash (last 32 bytes).

device_policies.xml : contains a detailed description of the password, it seems that the password is 10 characters long, contains 2 special chars, 7 letters (5 uppercase, 2 lowercase) and 1 digit.

settings.db: do not contain the key lockscreen.password_salt.

 

We have so far almost everything we need :

Salted hashes, password description, algorithm used.

The salt is missing, in order to see if it has been migrated under another database (different OS version, Cyanogen…) we go for a blind search in the other settings databases.

We quickly got it, the salt seems to be stored here in /data/system/locksettings.db.

The salt is stored here as an int64, we need its hexadecimal value because it is used as such to calculate the hash.

Now that we have all required elements in hand, a precise bruteforce can be started using John the Ripper. For processing speed, the MD5 hash will be the target of our bruteforce.

Since the hash is a salted MD5 we have to use the advanced JTR dynamic options, they describe different way of calculating (un)salted hashes.

In our case, we learned from our researches that the hash is calculating as follows :

MD5(password+salt)

According to the documentation, we then need to describe the input as dynamic_1 for JTR.

The input file looks like the following :

In order to use effectively JTR features and the information from device_policies.xml, the expected format is described to JTR using the mask feature.

And we get the flag in less than a minute !

Thanks to all people involved in Insomni’Hack organization and promotion.

Olivier CHATAIL