Welcome All!

I am very pleased you have taken the time to come and visit!

The plan for this blog is to provide the decoding outcome of both mobile and computer applications, with the hope that it may be helpful to someone else along the way!

These applications will either be from case work, not supported by forensic applications at the time, or applications that have peeked my interest.

I had intended to have more dog related puns… unfortunately i have run out for now. I know, i didn’t think it was paw-sible either.

Decrypting the ‘AVG’ Photo Vault

Screenshot of AVG Menu

I have been holding onto this post for a while now, one of the first applications I attempted to decrypt which took a very long time. ‘AVG AntiVirus – Mobile Security & Privacy’ is as the name suggests an antivirus solution, the Android equivalent of its well known computer counterpart. The mobile application contains additional features such as the ability to restrict access to applications and more relevant to this post, the ability to place ‘private photos in a password-protected Vault to prevent snooping’. ‘Photo Vault’ has been implemented in AVG on Android for a number of years.

‘Photo Vault’ requires the user to login to a Google Account to gain access to this feature. Once this has been completed they are free to use the vault, however, if they are using the free version they will be limited to 10 files that can be encrypted.

If the device supports it the user will be able to set their fingerprint to unlock the vault. After initial setup a user can change the unlock type to a pattern instead of a PIN, but there is no way to disable the original PIN. This becomes important when looking at how the application handles encryption / decryption.

Changing from PIN to Pattern

Examination into the application identified the following key locations:

Media Files
Key Artefact Locations

The PIN / Pattern

PinSettingsImpl.xml‘ is stored under ‘/data/data/com.antivirus/shared_prefs‘ and contains entries for both the PIN and pattern set by the user:

‘PinSettingsImpl.xml’ Screenshot

Light work can be made of both entries. ‘encrypted_pin‘ is the user created PIN code stored as a SHA1 hash value. In order to identify the number the hash value relates to one can apply some ‘Google-Fu‘ and search for the value online:

Google Result for ‘7110eda4d09e062aa5e4a390b0a572ac0d2c0220’

A PIN code has been identified in the first search result and in this case corresponds to the correct PIN code ‘1234’. ‘encrypted_pattern‘ is also a SHA1 hash value and corresponds to the numbers selected while creating the pattern lock. Patterns for Android devices and their applications are generally interpreted as a keypad system starting at 00 running through to 08, from left to right. As an example, the above ‘encrypted_pattern‘ corresponds to ‘0>3>6>7>8’, the pattern could be interpreted as starting at ‘1’, but the way in which it is programmed means in the background it starts at ‘0’.

Pattern Example Layout

Rather than taking the values directly from the grid and hashing them, they are first taken from hex and then run through the hashing algorithm. If this were a password rather than a PIN or pattern lock there could be a huge number of potential combinations, taking into account variable lengths, characters; uppercase, lowercase, special characters, language etc. Dealing with a PIN or pattern is more simple, there will be a finite number of combinations which means that rainbow tables can be created as a lookup for the values or they can be more easily bruteforced. This is all in respect to SHA1 hash values, not talking about more complex algorithms that are designed as cryptographic functions which put mechanisms in place to slow the attempts of bruteforcing.

Although there are many programs out there that already have the rainbow tables incorporated or have the ability to bruteforce these values, the code for identifying the PIN in python has been included below to give a better understanding of how it could work:

import sys
from hashlib import sha1

## Take the PIN hash as the first argument
AVGPIN = sys.argv[1]

## For each passcode it will need to run the hash function and compare the hashed result to the hash from the file 
## If it is wrong it will keep trying until it gets to '9999'

for i in range(0,10000):
    currentPIN = ('{0:04}'.format(i)).encode('utf-8')
    ## Section of code to try the hash process and assign PasscodFound if correct
    ## Compare the current PIN SHA1 and the provided AVG PIN
    if sha1(currentPIN).hexdigest() == AVGPIN:
        print(f'FOUND PIN:\t\t\t\t\t****{currentPIN.decode("utf-8")}****')
        pinFound = True
    ## If the PIN is not found then exit
    if not pinFound:
        print('****PIN not found, program will exit***')

The above code is written for python 3 and takes one argument, the PIN hash. Realistically the above code would not be the quickest way of identifying the PIN as there is no optimisation and because of the finite number of PINs available a rainbow table would be quicker but the code works as a free solution that can be applied to other applications as well; providing that they are being created in the same way. Note: the code is limited to 4 digit codes, as in the AVG application.

Media Files & Decryption

Encrypted Data Structure

Media files are stored within subfolders of ‘/sdcard/Vault’. All of these folders contain files of interest, however, they are all encrypted. For each encrypted media file there is a corresponding ‘.thumbnail‘ and ‘.mid_picture‘. ‘.thumbnail‘, as the name suggests is a thumbnail representation of the image and ‘.mid_picture‘ an even smaller version.

Files are linked together by their filenames, corresponding to the time the file was encrypted as a Unix timestamp. The files are differentiated by file location only, thumbnails residing in the ‘.thumbnail‘ directory etc. In addition to the encrypted media files there is the ‘.metadata_store‘ folder, containing another encrypted file. When this file is decrypted it reveals the details of all files encrypted using the application including details such as original file name and size:

Decrypted Data from ‘.metadata_store’ File

Each encrypted media file has a standard header, in which the IV and the size of the encrypted data can be obtained:

File Header Example

Encrypted media files start with the IV length, followed by the IV itself, the length of the encrypted data represented as a 4 byte value and finally the encrypted data equalling that length. In the example above the values are:

IV Length0x10 = 16 bytes
Encrypted Data Length0x00033D40 = 212288 bytes
Encrypted Data212288 of encrypted data
File Header Details

In some previous applications the IV and Key have been the same across all files. In this application the IV is randomly generated at the time of encryption and stored in the encrypted file as seen above. The key however is generated in a very specific, programmatic way.

The Key

Encryption within the application is part of the reason it took so long for me to complete it. During analysis I identified the type of encryption as AES_CBC and could identify the key and IV required to perform the decryption. Tracing back the origins of the IV has been demonstrated above but the Key was more difficult. As a result of the analysis it was determined that several steps are required to get the right encryption / decryption key. The explanation may seem long winded but it does all work out in the end, it will be broken down into sections and then summarised at the end.

The first part requires several inputs, some eagle eyed readers may have seen references to it when the encrypted files were covered. It’s technically the second part of the process but it is best covered here. The file containing some of the required values is stored within the ‘.key_store‘ folder, in this example named ‘AVG-Encrypted-1645550081160‘. It is essentially a key file and can be interpreted as the following:

LengthThe length of data in the file. 0x50 = 80
Global IVFirst IV stored in file, 16 bytes (variable)
First Encrypted Value32 byte encrypted value (variable)
Second Encrypted Value32 byte encrypted value (variable)
Key Values Explained

Now these values have been identified, lets have a look at the first stage of the key generation process, the PBKDF2 key derivation function. In order to generate / derive a PBKDF2 key several elements are required; saltpassworditerationskey length and hash mode. Similarly to the ‘Secret Calculator Photo Vault’ application, some of the values are hard coded in the application and are as follows:

Key Length32 Bit
Hash ModeSHA1
Hard Coded PBKDF2 Values

The salt for the key generation is the ‘Global IV‘ identified above. The password is slightly more tricky.

Stage one of getting the password is taking the users PIN and running it through the SHA1 hash algorithm. This provides the same value as identified as the ‘encrypted_pin‘.

Next, the SHA1 hash is run through the SHA256 hash algorithm, in this case resulting in the value ‘a0626c0a5edb4b637d7e25d2290792a0a3094da0b5d4413641a130bbcf46ef85‘. So, take the PIN and run through SHA1, the result is then run through SHA256.

That is how the Java code reads and the value generated by carrying out this process did not work in producing the correct key. It was at this point that things got a bit more difficult. During the dynamic code analysis I could see references to the password value and it seemed to resemble the SHA256 as above but it wasn’t 100% the same. After some research around the anomaly it was identified that something in the code was likely causing the issue. Below is the input parameters for the PBKDF2 key derivation from the application code:

Code Snippet Breakdown

A very specific anomaly occurs within Java on Android when using the ‘toCharArray’ function. Several articles on the internet outline this issue and in short it is to do with unpresentable data during the conversation of certain bytes. During the conversion those values that it cannot represent are replaced with the string ‘efbfbd’. This concept becomes important when looking to generate the correct password to use for the PBKDF2 key derivation. Rather than using the SHA256 value that would normally be generated the ‘toCharArray’ function alters the ‘password‘ input significantly. The example value above changes to the below value:


The anomaly, in this case, results in a significantly longer value, which is not always the case. In order to deal with this anomaly a custom Android application was created, replicating the code from the application in order to generate a list of all possible PIN numbers. However, unlike the python code provided earlier, the application was written to reproduce the ‘toCharArray’ variation of the ‘password‘ creating a rainbow table to be used for the key derivation function. Note: the custom code has not been included in this case as the results will be provided instead.

Now the correct string has been generated it provides the last piece for the PBKDF2 derivation producing the value required for the next stage. In this example it produces: ‘d025fb14e02802e9c98fe0dfed87b546‘. PBKDF2 derivation can be accomplished using CyberChef:

To summarise the process so far the diagram below attempts to provide a collation of the steps:

Key Derivation Function Diagram 1

Unfortunately the process doesn’t stop there as the new value is used as part of the next cryptographic function. During the analysis it was determined that in order to obtain the key a further decryption process was required, this was in the form of AES_CBC. Seen in previous posts, in order to facilitate AES_CBC encryption / decryption there are two values required; the Key and the IV. The IV in this case is the ‘Global IV‘ as detailed above and the Key is the newly generated value from the PBKDF2 key derivation.

The final stage to obtain the correct encryption key requires the decryption of the last two values from the ‘.key_store‘ file, named in this post as ‘First Encrypted Value‘ and ‘Second Encrypted Value‘ (note: these are not the names referenced in the applications code).

Code Snippet for Key Decryption

In Java there are two methods generally used for encryption, ‘doFinal’ and ‘update’. ‘doFinal’ is used for the data in its entirety whereas ‘update’ can be used for blocks of data, for example taking larger pieces and feeding them through in chunks. The code snippet above from the application demonstrates that the values are being used with the ‘update’ method. Meaning it is dealing with the values separately, the reason why will be demonstrated below.

Using Python it is possible to accomplish the task and generate the correct key. Below is a snippet of code which will take the contents of the ‘.key_store‘ file, starting at the ‘Global IV‘, and replicate the steps from the application in order to decrypt the values individually in a way similar to ‘update‘:

### Import required modules
from Crypto.Cipher import AES
from base64 import b64encode
from hashlib import sha256

### Static values
pbkdf2Key = "d025fb14e02802e9c98fe0dfed87b546"
fullFile = "A0 E9 D9 52 6A 6B 8A 4D 7D F3 1E A5 E8 5E DE 05 36 B7 DB FB 6F 3E 4A 06 A9 20 B7 80 DD A2 19 E8 4A DC 18 E5 FC 0D 3E 60 5F 4B F6 9B 2E D0 16 60 23 0D 33 B0 C8 FF A3 65 D3 B7 C2 1E A5 62 66 1A 31 31 F5 70 8A 6D 2C BD 1C D9 61 78 B5 0C 4E BC"

### Create new instance of AES Cipher
cipher = AES.new(bytes.fromhex(pbkdf2Key), AES.MODE_CBC, (bytes.fromhex(fullFile)[:16])[:AES.block_size]) 

### data = bytes 16:48 (as per java code)
data = bytes.fromhex(fullFile)[16:48]

### data1 = bytes 48 to end of file as per java code
data1 = bytes.fromhex(fullFile)[48:]

### Decrypt 'first encrypted value'
decrypted = cipher.decrypt(data)

### Print decrypted value
print(f'First Encrypted Value\t{decrypted.hex()}')

### Decrypt 'second encrypted value'
decrypted1 = cipher.decrypt(data1)

### New instance of sha256 hash
hashStr = sha256()

### Run the decrypted data through sha256 hash

### Print decrypted value
print(f'Second Encrypted Value\t{decrypted1.hex()}')

### Print the hash value as hex 
print(f'Calculated Hash\t\t{hashStr.hexdigest()}')

The splitting of the values serves a specific purpose and goes to answer; How does the application know whether the decryption key generated is correct? This is accomplished by carrying out another function on-top of the decryption and comparing the values. The application takes the result of the first ‘update‘ function and compares this value to the SHA256 of the second ‘update‘ function. If the decrypted ‘First Encrypted Value‘ and the SHA256 of the decrypted ‘Second Encrypted Value‘ match then the supplied password is correct.

Key Verification Flow

Using the values from this example and those cited within the python code above, three values are printed. The first is the decryption of the ‘First Encrypted Value‘ and the second value, ‘279657…‘ is the ‘Master Encryption Key‘, generated after the ‘Second Encrypted Value‘ value has been decrypted. The third is the SHA256 of the ‘Master Encryption Key‘ for comparison to the first value:

Python Output

Being overzealous in trying to make sure its understood, the below diagram shows the whole process hopefully aiding in making sense of the above:

Master Encryption Key Diagram

No access to ‘/data/data/’

Realistically the encryption in this application has been designed so that in order to decrypt the data the PIN needs to be known. Whether that is by getting the hash value from the preferences file or by knowing the PIN, either way this would be required to generate the overarching ‘Master Encryption Key‘. Strictly speaking we have used the preferences file in order to bruteforce the passcode, and could have just used the SHA1 hash directly from the file. But what happens when there is no access to ‘/data/data’, such is the case when the type of extraction is restricted in a way which does not result in the acquisition of the application data? We would still have the encrypted files from the SD card / emulated SD card but we wouldn’t be able to validate the users PIN code using the preferences file.

However, it is possible to brute force and identify the correct PIN code and in turn identify the correct decryption key required. This can be achieve in two ways, the first is using the file from within the ‘.metadata_store‘ folder and the second is by utilising the same function that the application uses to determine if the ‘Master Encryption Key‘ is correct.

The ‘.metadata_store‘ folder contains an encrypted file which when decrypted contains the following:

Decrypted Data from ‘.metadata_store’ File

The very first part of the decrypted data, ‘{“version’, is consistent in every install I have seen and the file is always present within the encrypted files. In order to identify the correct PIN / encryption key, carry out the process as detailed above for each possible passcode and attempt to decrypt that file. If the first part of the decrypted data is ‘{“version’, then the PIN / ‘Master Encryption Key‘ is correct and the media files can be decrypted. If ‘{“version’ is not at the start of the decrypted data then it needs to try the next PIN and so on.

Another option is to use the same process that the application uses. Similar to the above approach, each variant of PIN would need to go through the process of PBKDF2 derivation to generate the derived key. However, instead of using this to decrypt the file and checking for ‘{“version’, the derived key would be used to decrypt the ‘First Encrypted Value‘ and ‘Second Encrypted Value‘. The comparison of the SHA256 hash of the generated key to the decrypted ‘First Encrypted Value‘ would take place. If these match then the PIN and key are correct.

The code to carry out that process is longer than the theory but the process provides an examiner the chance to decrypt and view the files even if the files are rouge on an SD Card or the extraction type has not retrieved the relevant ‘/data/data’ folder. Lets not forget that not all applications can be reverse engineered or there simply isn’t the time to do it in all cases, however, if we can identify the PIN code for this application it may be the same for another one on the same handset.


The process used to generate the key in this case is very long on paper but programmatically can be achieved fairly easily with the exception of the abnormality seen in the Java ‘toCharArray’ function. This has been circumvented by generating all possible occurrences by replicating the original application code in a small Android app, which hopefully saves other people from needing to do the same.

It is possible to both identify the users PIN and pattern lock for the application if there is access to ‘/data/data/’. Furthermore it is possible to identify the users PIN in cases where access to ‘/data/data/’ is not possible by leveraging a bruteforce attack on known data or by using the same validation method implemented by the application.

Although snippets of code have been included for the purposes of explaining some concepts, a full script has been created and made available on my GitHub. The script is designed to take the relevant ‘/data/data/’ folder and derive the users PIN / pattern and decrypt any encrypted data provided. The script also has the function if provided with encrypted data only to bruteforce and identify the PIN, decrypting the data at the same time. During the post there is mention of the mobile application used to generate the rainbow table of values required for the PBKDF2 key derivation, the code for the mobile application is not included however the file containing the results is available on the GitHub page.

As always, any feedback, queries or questions are always welcome on here or on Twitter @4n6chewtoy.


Decrypting ‘LOCKED Secret Calculator Vault’

This weeks post was prompted from a live case and actually didn’t take too long to work through because of how remarkably similar the application is to a previous post: ‘Decrypting the ‘Calculator’ App(s)‘. Which means it will follow very closely whilst highlighting the slight differences between them.

‘LOCKED Secret Calculator Vault’ mimics the functionality of a calculator whilst hiding a vault behind a user created PIN / pattern lock. The files are encrypted using “proven military-grade AES encryption which is used by governments & banks worldwide. Hide photo, Lock photos and videos, then put them into your private Calculator vault. Now they are in the safest place in the world! Nobody can reach them except you.” This application also has the ability to store encrypted notes as well as a built in browser.

Examination into the application identified the following key locations:

Media Files
Key Artefact Locations

The Lock

Although the default lock type is PIN it can also be protected with a pattern lock. Within the ‘/data/data/com.lkd.calculator/shared_prefs’ folder is the preferences file, ‘share_locked_vault.xml‘. This file contains a number of encrypted values:

The above screenshot shows the encrypted PIN and pattern, highlighted in red. In all likelihood the ‘share_locked_vault.xml‘ file will only show the encrypted PIN denoted by the tag ’57DFEA9AEC99CD87013E3862B9DE5B7D’. The less common encounter is the other highlighted value which is the encrypted pattern.

The PIN is entered by typing the PIN into the calculator and pressing equals. In order to enter a pattern, the user holds the 3 dots in the top right corner which opens up a user input screen for the pattern:

Lock Code Entry and Access

Media Files

Similarly to the other calculator application, media files are stored separately, split into subfolders based on file types. A separate encrypted database file is stored in its own folder. The media files in this location are encrypted, with some caveats.

Recursive View of ‘.locked_vault’

Something I noticed when encrypting the files during the tests was the option to encrypt the files as ‘Full’ or ‘Light’. Files encrypted using ‘Full’ were fully encrypted and are prepended with the letter ‘h’. If the ‘Light’ option is selected the file is created and prepended with the letter ‘e’. Both then use the same UUID naming convention. The biggest difference between the two is that the file doesn’t get encrypted if the ‘Light’ option is selected, it simply loses its file extension and gets a name change.

Decryption – Pattern / PIN

All cryptographic functions that occur in the application use the same hard coded encryption key: Rny48Ni8aPjYCnUI. This key is converted to hex before use. The encryption mode used is AES_CBC which typically takes 2 arguments; the key and the IV. In this application the key and IV are the same value: Rny48Ni8aPjYCnUI.

Any data within the ‘share_locked_vault.xml‘ file, including the user created PIN and pattern, can be decrypted in this way using this value and algorithm. The following screenshot of CyberChef shows the process of decrypting the PIN lock:

CyberChef Decrypting PIN

The pattern lock can be decrypted in the same way. One thing to note is how the decrypted numbers correlate to the users pattern lock. In the example below decrypting the pattern results in the string ‘03678‘.

CyberChef Decrypting Pattern

This style of mapping is similar to some of the other Android applications and the pattern can be determined using the grid below, which shows this pattern relates to a ‘L’ shape:

Pattern Screen Layout

Decryption – Media Files

In a very similar way, media files can be decrypted using the hardcoded Key and IV:

CyberChef Decrypting Media Files

Decryption – Database Files

The database file, ‘locked_vault.db‘, is also encrypted using the same value. However, rather than converting the value to hex it can be used directly as the passphrase to decrypt it.

Using ‘DB Browser (SQLCipher)’ the database can be imported and decrypted:

DB Browser (SQLCipher) Database Decryption

It is important to make sure that within the encryption settings the SQLCipher is set to 3, otherwise it will not work.

The database file holds information pertaining to the encrypted files and status before encryption. It is also the location for browser artefacts and ‘notes’ if the user has chosen to use this feature:

Decrypted Notes from Database


This application shares the majority of the cryptographic features as the previous post: ‘Decrypting the ‘Calculator’ App(s)‘. The main differences relate to the naming and location of files but the method by which they are encrypted / decrypted, AES_CBC and the hard coded Key Rny48Ni8aPjYCnUI, remain the same.

A script was created for the previous post and has now been edited and uploaded to cover this application. The script does not handle the decryption of the database as it is easily handled in ‘DB Browser (SQLCipher)’. The script can be found on GitHub here.

I would always encourage feedback so if you found this helpful etc then hit me up in the comments on here or my twitter @4n6chewtoy.

Decrypting ‘Secret Calculator Photo Vault’

Snippet of Application from Android Play Store

Calculator applications that store more than you think on the face value are becoming more common. Recently I assisted with a request to decrypt data stored in one such application. Luckily, the investigator already had the PIN to the application and could manually view the files. Manual examination is always the bare minimum aim with this type of application but given the opportunity we want the files decrypted so we can better interact with the them and potentially gain more information.

Secret Calculator Photo Vault: Hide Keep Safe Lock’ uses ‘Military Grade Encryption AES-256 bit‘ to keep files safe within the application. The developers also make the following statement: ‘Secret Calculator’s architecture was developed with the help of data security consultants experts to make sure that nobody, including our team, will be able to access your private photo locker without knowing your pass phrase, even if your device is stolen!‘. To a point this is correct, but it will be demonstrated later in the post how access to the encrypted files can be granted.

Examination into the application identified the following key locations:

Media Files
Table of Key Artefact Locations

Normally having the PIN identified first makes sense but in this case showing the process used to encrypt / decrypt the media files is better suited before hand.

Media Files

Interestingly in this case the media files are stored under subfolders of the application files, rather than on the emulated SD card, so acquiring the data may not be as straight forward.

Tree View of Encrypted Files Directory

Media files are encrypted and stored within subfolders respective to their contents ‘pics’ and ‘vids’. ‘vid_thumbnails’ exists storing one file per video in the main ‘vids’ folder. Files are stored with randomly assigned GUIDs with appropriate extensions.

The media files are encrypted using a method seen in a previous post, Decrypting ‘Apps Lock & File Encryption — GOLD version’, Facebook Conceal API. As a reminder, the Facebook Conceal API is designed for ‘Efficient storage encryption for Android’ and utilises AES_GCM encryption under the hood.

Facebook Conceal provides documentation around the structure of the encrypted files. The IV can be a variable length depending on how the developer implements it.

The below illustration shows the structure of the encrypted file header.

Encrypted File Header
File StartAlways 0x01
Key Type0x01 (128bit) 0x02 (256bit)
IV24 bits long
Encrypted DataLength Varies
Key Features of Encrypted File

Files encrypted in this application are done so using a 256 bit key with a 24 bit IV.

The encrypted data continues to the end of the file up to the last 32 bits which is the GCM Authentication Tag (Auth Tag). The Auth Tag is used to verify the encrypted / decrypted data. It isn’t required for the purposes of decrypting the data but can be used to verify the integrity.

Encrypted File Footer

Decrypting the Media Files

There are 2 key parts to the encryption / decryption process and the first part is linked to the PIN set for the application. All required details for both parts are stored in the file ‘AppPreferences.xml’ found within the ‘shared_prefs’ folder.

AppPreferences.xml Preview

Initially a PBKDF2 key is generated. In order to generate a PBKDF2 key several elements are required; salt, password, iterations, key length and hash mode.

Some of the values are hard coded in this application and are as follows:

Key Length64 bit
Hash ModeSHA256

As for the remaining values, the salt and the password. The salt is identified within the ‘AppPreferences.xml’ as the tag ‘pbkdf2_salt‘. This value decoded from Base64 and represented as hex provides the salt required to generate the PBKDF2 Key. The password, in this case a PIN, is not saved on the device (which I will cover later) so it deals with it on the fly. In the case of my tests it was 1234 which I could use with the details above to generate my PBKDF2 key. Easily accomplished with CyberChef:

CyberChef Generating PBKDF2 Key Generation

To make it a bit easier to keep track of, I will call this the Primary Key. The resultant Primary Key is used later in the process.

The next value requiring attention is the ‘symmetric_encrypted_files_encryption_key‘, which is encrypted using the Facebook Conceal API, in other words AES_GCM. The value first needs to be decoded from Base64 and then converted to hex revealing the structure:

Encrypted String

As with the encrypted media files the encrypted key starts with the standard 0x01 indicator followed by the key length indicator, again 256 bit. Next is the IV then followed by the encrypted data, when decrypted produces a 64 bit key. The remainder of the data is the Auth Tag but isn’t strictly a requirement as the data can be decrypted without it. Using the Primary Key and the IV identified within the symmetric key it is possible to decrypt the encrypted data above, producing the Master Key. In this example the data would be as follows:

Encrypted Data
Master Key
Data from Symmetric Key Decryption

Decrypting using AES_GCM does not always work in tools such as CyberChef which is why I haven’t included its use. The next stage would be to decrypt the media files as the master key, required to decrypt them, is now known.


The process above requires the users PIN to be known as the PIN is used to create the primary key, without that there is no way to decrypt the symmetric key. My issue was understanding how the application was verifying the user PIN and what I didn’t realise was that it only checks at the end of the decryption process. This is done using the value ‘hashed_files_encryption_key‘ from the same AppPreferences.xml file.

Once the user enters any passcode into the application, the PBKDF2 key is generated and regardless of whether it is correct or not, it is used to decrypt the symmetric key, the result being the master key. However, it is not guaranteed to be correct. Upon completing those cryptographic functions the generated master key is taken from hex and run through the SHA256 hashing algorithm. The result is then compared to the Base64 decoded value stored as ‘hashed_files_encryption_key‘. If it matches the user got the right PIN, if it doesn’t nothing will happen and no decryption of media will take place, with access to the application not granted. The diagram below should make this more clear:

Key Generation and Decryption Diagram

Encrypting the data in this way means that the correct PIN needs to be known in order to decrypt data. If the PIN was not known it would need to be brute forced, taking each possible PIN and running it through the above process in order to make the comparison.


A very interesting scenario where the PIN was already known removing the requirement to understand how the PIN verification function worked. However, to make it more practical for any future involvement with the application it was necessary to do so. Without the PIN, decryption of the files is not possible meaning the PIN needs to be provided or brute forced.

Facebook Conceal API made another appearance, along with a first time appearance of PBKDF2 Key generation. Coupled together made for a more difficult time understanding the inner workings.

I have created a script which just needs adjusting to properly implement the bruteforce function before it is made available. I have also now created a GitHub which can be found here. There is currently only the original script made for dealing with MEO file encryption: https://theincidentalchewtoy.wordpress.com/2021/11/09/meo-file-encryption-software/.

I would always encourage feedback so if you found this helpful etc then hit me up in the comments on here or my twitter @4n6chewtoy.

Decrypting ‘WeVault’

New year new post! Wishing everyone a happy new year!

This weeks post deserves a shout out to a couple of “unbelievably talented forensic investigators” (self described). Michael Tussaud and Corey Sugden.

A great collaboration that made this post possible.

Easing into the year with another encrypted media application on Android.

“WeVault is a photo vault to lock your private photos and videos, with password, pattern or fingerprint lock. If you want to keep some pictures and videos safe, WeVault will be a trustable tool.” WeVault allows a user to change the application icon in order to disguise it.

Security is of a top priority, “Everything in WeVault is AES-256 encrypted. Military grade encryption keeps you safe.”

Key artefacts for this application are found in the following locations:

Media Files
Key Artefact Locations

The Lock

Key credentials are stored within the preferences file:


The values for ‘pattern_lock_pwd’ and ‘user_email’ are encrypted values stored as Base64, decrypted they are as their name suggests the user email and pattern lock used on the device.

Decryption of these values will be covered below, as they are both intrinsically linked.

User Email

Analysis determined that the ‘user_email’ entry is encrypted with both a hardcoded Key and IV, using AES_CBC encryption.

Hard coded Key and IV values

When the values above are taken from hex to their ascii representation, the plaintext values used for the encryption are:

Decoded Key and IV

Using the Key and IV the encrypted ‘user_email’ can be decrypted. In this example, the encrypted ”user_email’ value when converted from base64 is ‘95503d475e02fab9175bc44bcdaacdbcdbc1d8a09db0289ef646e8ed86630529’.

CyberChef can be used to decrypt this value with the provided Key and IV:

CyberChef Decryption ‘user_email’

Generally speaking from experience, decrypting the users email from within this application would not have a large impact on an investigation as the likelihood is that the email address is present elsewhere in the extraction. However, in this application being able to decrypt the exact user email used to setup the account is key in being able to decrypt the media files.

The Main Encryption Key

The main encryption key used to encrypt / decrypt the pattern lock and media files is generated on the fly and isn’t written out to a file. It is possible to trace the function that creates the value and replicate it outside of the application.

The function takes the email, in this case theincidentalchewtoy@gmail.com and interlaces the letters ‘qmor‘ after each letter in the email which gives:


This value is not the encryption key. To get the encryption key the resultant value needs to be run through the SHA256 hashing algorithm:


To aid anyone that needs to generate their own keys, the below script will carry out the email manipulation and output the required key:

import hashlib
email = 'theincidentalchewtoy@gmail.com'
interlace = 'qmor'
newstring = ''
i = 0
for letter in email:
    newstring = newstring + letter
        newstring = newstring + interlace[i]
        i = 0
        newstring = newstring + interlace[i]
    i +=1

All that’s required is to change the ’email’ string in the code. This code does not decrypt the encrypted email address as this can be easily achieved using CyberChef (https://tinyurl.com/2p9hksa6), just paste your Base64 value into the input field.

In order to decrypt the pattern lock, the newly created Key and the standard IV from before are used. First, decode and convert the ‘pattern_lock_pwd’ , in this example the value to decrypt is: de8849cd40a67f05e936fa3f814352af6e4b7815aa3d9387576a5c1e11c0ff01. Again using CyberChef, the encrypted value can be decrypted:

Decrypting the Pattern Lock

The resultant value, ‘yMCyShXci7/UEUJ5c1dGlSMEWPA=’, needs to be converted from Base64 to hex which provides the SHA1 hash value of the pattern, ‘c8c0b24a15dc8bbfd411427973574695230458f0’. This hash value is one seen before (in previous posts) and corresponds to an ‘L’ shape. Many tools are able to look this value up in rainbow tables to identify the corresponding pattern.

Media Files

Media files are stored within a series of subfolders under ‘/sdcard/.QMVault’. Each media file that is encrypted is named as a Unix timestamp and has a separate corresponding metadata file.

The meta data file, stored under ‘/sdcard/.QMVault/medias/meta’, is identifiable by the file extension ‘m’. These are encrypted using the email based Key seen above and the same IV used throughout. It is stored as Base64 which needs converting first but the decryption results show it stores information about the original image file including MD5 hash and original storage location:

Decrypted Metadata File

Encrypted image files are named the same as their counterpart meta data files with the exception that they have no file extension and are stored within the root of the ‘medias’ folder. Each encrypted media file starts with a variable length header, and contains information similar to the metadata file but is stored unencrypted.

This file, as with its corresponding meta data file, shows the MD5 hash value being the same. The encrypted file starts immediately after the closing curly brackets and continues to the end of the file.

Of interest is the presence of the email address associated with the encrypted file, which is now known to be integral to the encryption / decryption of the files. This means even with the absence of the preferences file with the encrypted user email it is still possible to decrypt the media files. In cases where an encrypted file is found orphaned by the application, the above script can be used to generate the key required for decryption.


As it has been demonstrated, it is possible to decrypt the pattern lock and user email from the preferences file. The importance of being able to identify an applications lock is going to be dependant on the investigation but at the very least gives the ability of carrying out a manual examination of the application. It is always worth noting that although it has been possible to decrypt the pattern lock for this application, it may not be possible to do so for another application on the device and people being creatures of habit may give access to the application with the same pattern lock.

The script within the post can be used to generate the required decryption key from the preferences file OR from the encrypted media files themselves. The script I have made can be used in either case.

Next week I WILL be creating a GitHub to make the scripts available and will encourage anyone that finds the blog or the scripts useful to let me know.

Decrypting ‘Apps Lock & File Encryption — GOLD version’

Giving a big shout out to Michael Tussaud for this weeks post. A great collaboration with a fur-end made this possible.

Keeping with the theme of encrypted files and Android applications this week.
‘Apps Lock & File Encryption — GOLD version’ is a secure application which allows users to protect their ‘data with file encryption and decryption.

Key artefacts for this application are found in the following locations:

Media Files
Pattern Lock
Table of Key Locations

The Lock

The pattern lock is located within the ‘applocker.db’ database file which is stored unencrypted:

Pattern Stored in Database File

An interesting storage mechanism for the pattern lock which I had never seen stored in such a way.

Breaking down the format of the pattern shows that instead of the pattern lock being represented as 0-9 or 1-9, it is represented as a grid / coordinate system. Each pair of numbers represents a square reading across the grid and then down.

Media Files

Media files are stored encrypted within subfolders of the SD Card.

When a user encrypts a file 2 files are created, the main file and a preview file. The preview file is what the user sees when they open the application, essentially a thumbnail of the main image.

File names are stored as Unix Millisecond timestamps, the time and date the files were encrypted.

While examining the code, it was initially difficult to ascertain the type of encryption that was being used. No direct calls to AES or other types of encryption could be identified, but in each case the structure of the files appeared consistent. Research identified that the encryption in use was the Facebook Conceal API. The Facebook Conceal API designed for ‘Efficient storage encryption for Android’.

In the background Facebook Conceal implements AES_GCM which is why it was not immediately obvious which type of encryption was in use.

Facebook Conceal provides documentation around the structure of the encrypted files. The IV can be a variable length depending on how the developer implements it.

The below illustration shows the structure of the encrypted file header.

File StartAlways 0x01
Key Type0x01 (128bit) 0x02 (256bit)
IV24 bits long
Encrypted DataLength Varies

In this case, a 256 bit key is being used with a 24 bit IV.

The encrypted data continues to the end of the file up to the last 32 bits which is the GCM Authentication Tag (Auth Tag). The Auth Tag is used to verify the encrypted / decrypted data. It isn’t required for the purposes of decrypting the data but can be used to verify the integrity.

Encrypted File Footer

The Key

The encryption key is stored in a file within the ‘shared_prefs’ folder. Each key is randomly generated when the application is first used to encrypt a file. Keys are stored as a Base64 value in the ‘shared_prefs’ file.

Decoding the value from Base64 and converting it to hex provides a 256bit encryption key. Using this key and the IV embedded within each file enables the decryption of the data.


Providing that access to the /data/data/ folder can be obtained, it is possible to decrypt the encrypted media files. As the PIN is not used as part of the encryption process there is no requirement to identify it, however, for the purposes of manual verification this is stored as part of the coordinate system which can be interpreted without the need to perform any decryption.

I have put together a script that will go through and decrypt the files from the SD Card and output the decrypted contents. As the Auth Tag is not a requirement for the decryption the script does not utilise it.

If this has been any use then please let me know!

Decrypting the ‘Calculator’ App(s)

This week I have been looking at another Android application designed to keep files secure. ‘Calculator – hide photos’ has many features, including a vault ‘…Through the AES encryption algorithm, encrypt the content that you do not want to share with others, and the file format, size without any restrictions, but also support taking pictures and recording videos.’

One of many applications which presents itself as a functioning calculator but can hide a wealth of data in the background.

‘One of many initially’ referenced the fact that these types of applications are not that uncommon, however, the developers of this application base all of their applications on ‘Sgallery’ (https://play.google.com/store/apps/details?id=com.hld.anzenbokusu&hl=en&gl=US). This means that this post initially covering 1 application is applicable to 4 of their applications:

(This post is based on version 10.0.2 but I have also tested it on the most up-to-date version 10.1.1)

All data throughout this post was written based on test data from the application with the package name ‘com.hld.anzenbokusufake’. However, it can be applied to all 4 applications.

Initial Calculator Screen
Hidden Pattern Screen

Examination into the application identified the following key locations:

Media Files

The Pattern Lock

Within the ‘/data/data/com.hld.anzenbokusufake/shared_prefs’ folder is the preferences file, ‘share_privacy_safe.xml‘. This file contains a number of encrypted values:

Although it’s not obvious, the above screenshot shows the encrypted pattern lock along with the encrypted tag.

Media Files

Media files are stored separately, split into subfolders based on file types. A separate encrypted database file is stored in its own folder. During testing I didn’t see the ‘account’ folder populated. The media files in this location are also encrypted.


When presented with a locked application my first port of call is always to try and get manual access. That way if the application is protecting files using encryption that I can’t work out or replicate in my own code, I can get the application to do the heavy lifting for me and show me the decrypted data. In the case of this app, the pattern and the files can both be covered at once.

Within the applications code there is reference to a hard coded value, along with 2 other functions which appear to be concatenated into one string:

Although it may be difficult to see, the above code boils down to being:

‘Rny4 + ? + ?’ .

After some more digging I found that the code always generates the same value, Rny48Ni8aPjYCnUI.

During further examination it was determined that all cryptographic functions, including the encryption of the pattern lock and media files, use this value as part of an AES_CBC algorithm.

The Pattern Lock – Decrypted

CyberChef Decrypting Pattern Lock

Using CyberChef is a nice way to test this out and see it in action. If we take the value, Rny48Ni8aPjYCnUI, and convert it to its hexadecimal equivalent we are left with the key required to decrypt the pattern. If we take a look at the decrypted value and convert it from hex, we are left with a string of ‘03678‘. As with some of the other Android applications we can determine that this maps out to the android pattern layout which makes our pattern an ‘L’ shape:

Pattern Screen Layout

Media Files – Decryption

As it has been mentioned, the media files are also encrypted with the value ‘Rny48Ni8aPjYCnUI‘. Interestingly, rather than having a blank IV or one that changes with each file, as is common with AES_CBC, it simply uses the same value as the encryption key.

CyberChef Decrypting Media File

Each file can be decrypted in this way. There is no correlation between the pattern and the encryption key. Regardless of the pattern lock the Key and IV are the same in each instance of the application.

The Database – Decryption

The database file, ‘privacy_safe.db‘, is also encrypted using the same value. However, rather than converting the value to hex it can be used directly as the passphrase to decrypt it.

Using ‘DB Browser (SQLCipher)’ the database can be imported and decrypted:

DB Browser (SQLCipher) Database Decryption

It is important to make sure that within the encryption settings the SQLCipher is set to 3, otherwise it will not work.

Some Additional Information

Just in case it comes in handy.

It’s possible to change the default pattern to a PIN lock instead. Luckily, its also encrypted with the same key:

Encrypted PIN

Taking this value it simply decrypts directly to the PIN code, without the need for any further interpretation:

PIN Decrypted in CyberChef

During the process of setting up the application the user is prompted to setup a recovery answer in case they forget their password (not that it would really be an issue). This is stored in the same preferences file as the encrypted pattern and PIN lock details. This is also encrypted with the same key.

Within the preferences file the recovery question is denoted by the value ‘A4CDA7B11C92D7943C99DFE00A362E1503D904E2932364D4D66F22966789A926‘. When decrypted it shows the tag as ‘security_question’.

Recovery Question Decryption


To summarise, the value Rny48Ni8aPjYCnUI or its hexadecimal equivalent 526e7934384e693861506a59436e5549 is used to encrypt / decrypt the pattern / PIN and any media files encrypted using the application.

This mechanism is the same for the other applications shown at the start of the post made by the same developers.

I have made a script which can decrypt the media files and the pattern lock in a streamlined process. I will more than likely be making a github page so I will make it available on there! If you would like it in the meantime then let me know!

Also, please let me know if you have found this helpful, it would be nice to know its not fur nothing.

Xiaomi AppLock – So What?

Welcome back!

This weeks post is less about seeding test data or breaking down an application at a code level and more about working with data at hand.

I was lucky enough to have a Xiaomi POCO X3 Pro (M2102J20SG) slide across my desk. I was given the required PIN code to get access to the device so I didn’t have to spend any time getting initial access to the device.

Luckily, with this PIN code I was able to carry out full filesystem extraction. A full filesystem being the most comprehensive extraction for this device. With many labs implementing Standard Operating Procedures (SOPs) and in all honesty this should be a part of any examination regardless, I set out to carry out my manual examination.

Unfortunately, although I was provided with the PIN to gain access to the device, I was met with a secondary lock. It wasn’t as obvious as it probably sounds. I had my extraction and as I was going through the manual examination, I couldn’t find some of my applications, so I started to do some research.

The Lock

I will briefly cover off the process of setting it up, but for a full breakdown take a look at this link: https://c.mi.com/thread-1807300-1-0.html.

How to hide and unhide Apps icon in POCO Launcher
How to hide and unhide Apps icon in POCO Launcher

This function is built into the POCO X3 Pro and allows for the hiding of applications from the main users area, which are then accessible by swiping up twice. It can also be accessed through the ellipsis in the top right hand corner of the applications screen. Once setup the user can choose the type of lock to be used. Although this is built in to the POCO the POCO Launcher 2.0- Customize, Fresh & Clean, or ‘launcher’ can also be downloaded and installed onto other Android devices from the Play Store. Which sits under the package: com.mi.android.globallauncher.

The Data

The main artefacts for the application reside within the following location:


Using data in this location it is possible to identify the details required to gain access to the hidden applications.

The preference file, ‘…/shared_prefs/com.mi.android.globallauncher_preferences.xml‘ contains an entry for the ‘…apps_lock_password’:

<string name=”hide_apps_lock_password”>7bccfde7714a1ebadf06c5f4cea752c1</string>

Due to the length of the string I took a guess that it would be an MD5 hash value. From what I have seen, when an MD5 hash value is used to implement ‘secure’ aspects, the background protections of the value are non existent.

As if by magic, using hashcat I was able to bruteforce the value. The hash in this case is generated as a result of a pattern lock. There is a finite number of points it can contain but also, there is a minimum amount that the pattern lock can be. Which means, the execution of the following command against a hashcat instance should provide the plaintext pattern lock:

hashcat64.exe -m 0 -a 3 7bccfde7714a1ebadf06c5f4cea752c1 -i –increment-min=2 –increment-max=8

This will go from 00 through to 99999999. Although slightly overkill as it will be trying combinations that are not possible, because its MD5 it won’t take long to run through.

Not to go back on my earlier post about the pattern lock mechanism and how it works (generally) however, in this case the layout of the pattern sequence runs from 1-9, rather than 0-8. Which means, the above hash value would map out as 1 > 2 > 3 > 6.


Although this isn’t the most secure of applications and didn’t take long to work through, there are a few points to take away. In an era where encryption is easy to implement and easy to make our jobs more difficult, if we can gain access to applications that are less secure, it may lead to gaining access to those application that are more secure. If the initial lock screen on the device was a pattern and I wasn’t provided it, but I had access to some aspects of a filesystem, I may be able to use that data to get full access to the device.

Some applications are so hard to decode that manual examinations are quicker and sometimes even more fruitful. Without gaining access to applications in this way, data (evidence) may not be identified.

At the end of the day, chainmail armour is only as strong as its weakest link.

No additional code ‘bits’ are required for this process, but if you have any suggestions or comments, just let me know.

DoMobile AppLock

This is going to turn into a two fur one post…

Once again, this was prompted by an active case. Come to think of it, I’m not sure what the requirement was at the time, it may have been to get manual access to the application (in the first instance) and quickly escalated. I was faced with a pattern locked application, and although it was suspected that I had all of the data, it was not possible to manually access the application.

Note: All the data in this post is generated test data 🙂

The App

AppLock from DoMobile (https://play.google.com/store/apps/details?id=com.domobile.applockwatcher&hl=en_GB&gl=US) is available for Android devices and has an absolute plethora of functions. It can hide itself, it can passcode lock applications, it has a browser, but most importantly it has a Vault. Vault simply allows a user to “hide pictures and videos” with a great tag line of No pin, no way”, which admittedly I didn’t see until writing this which did make me chuckle.

Running the application allowed me to see what the options were when setting it up initially and at what points it would prompt for a code.

Initial App Setup
Empty Vault Example

Initial setup prompts for the creation of a pattern lock and access to the Vault requires no additional authentication past the main screen. Suggesting that the initial pattern authentication is used throughout the application. It is possible to change from a pattern to a password within the application settings.

The Data – A First Look

First things first, lets have a look at where the data is being stored. No surprises, /data/data/com.domobile.applock contains our application data. The Google Play Store ID should coincide with the folder name, however this version, 2.9.6, is a slightly older version and as such is not stored under com.domobile.applockwatcher.

In my initial examinations, I’m shamelessly looking for an easy win. A file that shows the pattern lock in pain text, something to give me access right off the bat. The following file made me think I had found it:


This XML file has a fair amount of data, for the most part it relates to artefacts that probably aren’t that interesting, apart from this one:

<string name=”image_lock_pattern”>5iD8nqU1t66HeyKz31Dr0vDKmAYOD5xolVCmc6RKHJE=</string>

Excellent, I’ve got the pattern…well, I have a version of the pattern. It looks like a familiar format, most likely Base64. Still an easy win, decode it with a handy swift-army-knife CyberChef and there’s our pattern…:

CyberChef Base64 Decode

Okay. I know what the pattern is and that does not look right. My easy win just got a bit more complicated.

Code Analysis

Now that things have ramped up a bit, I’m moving onto analysing the code. Again, in this post I don’t go into great detail about the process of my dynamic and static code analysis, purely because the post would end up being 1024 times longer. So, think of this of more of a summary of the key findings.

We know decoding the above value as Base64 didn’t really help, but if we start looking at manipulating that value further (using CyberChef) and turn that data into its hexadecimal representation we get the following value:


This is an interesting length, 32 bytes long, seems to be a very specific length. Could be…a hash value of some kind, could be a key…

At this point I fell HARD down a rabbit hole trying to work out how this value is used to determine the pattern lock.

During the dynamic code analysis I kept seeing calls to another value in the ‘com.domobile.applock_preferences.xml‘ file:

<string name=”pk_applock_uuid”>1145f0545b244b65adb2bc9aa9aedac4</string>

At the same time I saw references to the following file:


Examining this file I find yet ANOTHER Base64 encoded value.

Contents of File 5fc841468e5294c9ef23bec5d3520c73

How do both of these have anything to do with…anything? This is where I find that taking the UUID, ‘1145f0545b244b65adb2bc9aa9aedac4’, and running it through as an MD5 hash provides ‘5fc841468e5294c9ef23bec5d3520c73’. The application looks into the preferences file and identifies the UUID, it runs it through the MD5 hash algorithm in order to identify the file name it requires. We can now disregard the UUID value from the preferences file itself as it appears its used to track the file rather than the value being part of further functions.

But what about the value inside the file?


Looking through the code and tracking functions through dynamic analysis, I keep seeing references to ‘AES’ and references to the hashing algorithm ‘SHA-256’. I go on another deep dive, this time for those cryptographic entries and I find this:

Code Snippet

Once I find this, I go to town. From this point on, I am able to work backwards, identifying the use of the values I have found above. And, at the same time, I am able to work out how the pattern is stored, start to finish. So, here it goes…

There are two main cryptographic functions that take place. The key file discovered before (the blob of Base64) plays a BIG part in how it all works. Two key pieces of information are required for this part to work.

The key file is created when the application is first setup, some sort of random generation to keep the application secure. The key file is random, what isn’t random is the hard coded data used to encrypt the contents…

Having looked at the code, I can see an IV and Key are used as part of an AES_CBC encryption function. Although the key file is random, the IV is hardcoded in the application file:

Hard coded IV

In order to get the IV into the correct format for the function, the application converts the value to hex. The Key is slightly more obfuscated, but boils down to being the result of the SHA-256 hash of the unsuspecting word…’domobile‘. So what ever happens, the initial Key and IV are always:

Default Key and IV

These values are used to decrypt the key file. A sneaky little SHA256 hash is run on the result, which provides a secondary key used as part of the next process. The below diagram aims to illustrate how these key findings work together.

If we use the values from the example above, the process and the result looks like this:

CyberChef Decrypting the Secondary Key

Examining the use of the secondary key by analysing the applications code, it was possible to determine that this key is used to encrypt / decrypt the pattern lock. It uses the same crypto function to do this, AES_CBC, and also uses the same IV as before, 32303131303731313230313730373131.

Taking the value from the preferences file, decoding it from Base64 and getting its hex representation as we did before, e620fc9ea535b7ae877b22b3df50ebd2f0ca98060e0f9c689550a673a44a1c91, we can now use the secondary key to decrypt it:

There is some manipulation required at the end, as the result of the decryption provides another Base64 encoded value. We are interested in this value in hex. Decoded gives us the decrypted value of the pattern, ‘c8c0b24a15dc8bbfd411427973574695230458f0‘.

The Pattern

Thankfully after that it’s a bit less intense.

Patterns for Android devices and their applications are generally interpreted as a keypad system starting at 00 running through to 08, from left to right.

All of the data in this post has related to a ‘L’ shape pattern. Which in real terms is ‘00,03,06,07,08’. To get the value we see above, the pattern is run through as a SHA1 hash.

We now have the decrypted pattern as a SHA1 hash value. There are many options for identifying the pattern from this hash. The easiest way is to use a rainbow table of all possible patterns, alongside the known patterns. There are plenty of scripts and tools available that can do this, so I won’t cover that specific process here.

The Password

Although in my case I only had a pattern lock, I thought it made sense to have a look to see if the same process was implemented when using a password.

Slightly misleading, the password option is actually a PIN. Nevertheless, I setup a new set of test data with the PIN ‘0000’. Running through the same process as before, I started by checking the test data, there were new values in the shared preferences file. These looked pretty interesting and give an indication of what to expect / what I thought to expect.

The two entries I was most excited about was the Salt and the password_length:

Password Salt from Shared Prefs
Password Length from Shared Prefs

I would be telling a lie if I said I wasn’t a bit excited about the mention of a salt. Awesome, there’s going to be some other implementation of encryption here, where could it be, what could it be?

After a very short time checking for changes in the other files relating to the application I moved back to my code analysis and a lot sooner than planned I realised that the complex implementation I was looking for…was much more simple than the pattern lock. Behold, the keys to the kingdom…

Code Snipper for Passcode

What I soon realised was that…in order to protect the passcode, the application prepends the word ‘domobile‘ with the pin. In my case it makes it ‘0000domobile‘. If you take the resultant value and run it through as an MD5 hash you are provided with the same value as the ‘Salt‘ found in the preferences file.

MD5 Hash using CyberChef

Not as complicated as I had expected.

The Files

In a very abrupt and anticlimactic end to the post, we move to the files. A lot of time went into gaining access to the application to view it manually, when alas, the data is stored unencrypted on the SD card or emulated SD Card.

Deep within the application files is the database actively tracking all the movement of files from the main camera roll to the obscured location: ‘/data/data/com.domobile.applock/files/media/6c9d3f90697a41b‘.

As you can see, all files are moved within a series of subfolders within the following location:


The files are not encrypted in any way, at all. So why go through all the effort of getting the pattern or PIN code? Not every application is supported by forensic software, and not every examination can take ‘as long as it takes’ to gain access to that application. Getting access to codes or patterns help unlock other devices or other applications where access is is not possible. Not to mention, manual examination of an application goes a long way at court, ‘to see it how the user saw it’.

The End…

Not quite. All of the above was for the version required at the time, 2.9.6. I had a look and thought the version was quite old, I’ll take a quick look at the newest version and make sure nothings changed.

The version I then looked at was 3.5.7. Luckily the new version continued to use the same process for securing its pattern and passcode, score. At this point I assumed the media would be protected in the same way, with no real protection. I was saddened (actually rather happy to find) a different file structure and much more than that, encrypted files!

The two main locations we are looking at now is:


I took to looking at the files themselves. Rather a lot of mush (technical term). No intelligible data, until I scrolled to the bottom to find some JSON data identifying the original filename, date and the original MD5 hash. These appear to be replacing the entries in the database identified earlier.

Data in the Footer of the Encrypted File

There’s some great nuggets of information in here about the file, without having to decrypt anything.

Let’s see what can be done with these files. So far, most of the encryption algorithms have used hard coded or standard keys making the functions themselves insecure. Surely, for file based encryption there is going to be some nice variations to stop access to media, at the very least a new IV for each image?

No. It all boils down to some hardcoded values. Again. The Key and IV are the same for every single image that is now encrypted.

Standard IV and Key for Encrypting Files

The encryption method remains the same, AES_CBC, only this time using the key and IV above. The encrypted data for each file runs from the start of the file all the way through until the JSON data starts, any less and decryption will fail.

The End Result

In order to make the process smoother for anyone else that encounters the application (either versions), I have put together a script that decrypts the pattern for ingestion into other tools. I wanted to keep it lightweight and other tools will be able to deal with the hash in a matter of seconds, rather than generating the rainbow table or creating the values on the fly.

I have also made a script to handle the password / passcode section. This takes the preferences file and therefore knows the length of the passcode. A rainbow table approach is then used to match the value in the list. Given that the passcode can be between 1 and 16 numbers, the list is finite.

As for the encrypted files, I created another script that will programmatically go through and decrypt the files, producing their decrypted versions. At the same time, it will verify the MD5 hash against the decrypted file to ensure they are digitally the same. The additional information at the end of the files is also collated.

This post ended up wayyyy longer than I had originally expected, which is why the code and the specific steps for the analysis were not included. If either of these areas becomes something frequently requested I will begin to include them, although, it will definitely make the posts (even) longer.

If anyone has any questions or would like a copy of the script(s), please just let me know!

MEO – File Encryption Software

This is an application encountered on a live case. At the time, there were several containers that were protected with unknown passwords. A little like Schrodinger’s cat, an encrypted container of any size could hold the key item to crack the case or pictures of dogs in funny outfits…

A little background on MEO

MEO is provided by NCH Software as an “easy file encryption software for Mac or Windows that will encrypt or decrypt files of any type” and enables a user to encrypt files, folders or emails. It is extremely light weight and offers self-extracting containers.

MEO Encryption Interface

The software makes use of two different encryption algorithms, ‘blowfish’ and ‘DES’. In this case, all were encrypted using the blowfish algorithm (which means I never made it to looking at containers with ‘DES’.)

Once encrypted, the standard file extension for these types of containers is ‘.meo’.

The Structure

Some very simple examination of the hex of the files and a comparison between the evidential data and my own test data made it possible to identify the basic structure and key elements below:

MEO File Header Example
File Header‘ HCN 0.1’
Key Length‘20 00 00 00’ in little endian
Key32 bytes in length

The suggestion is the key length for blowfish encryption can be longer, however, throughout the testing and the case data it was only the 32 byte key length that was encountered.

The Key

Through a mix of static and dynamic code analysis it was possible to determine how the key is generated from the user provided password:

Key Workflow

The End Result

Specifically for the benefit of the many containers at hand, it made sense to develop a script which takes the ‘.meo’ file as an input, checks that it has the correct header (as per the above), pulls the key out and carries out the reverse of the above process to provide the user with the MD5 hash of the of the original users password.

Using hashcat it is then possible to bruteforce the password.

The script is in no way proprietary or sensitive, however, is available on request, rather than the code being posted directly here. If I receive feedback to the contrary then I will look to amend this post with a breakdown of the script. It’s the leashed I could do.

Create your website with WordPress.com
Get started