APK anti-analysis
Contents
APK anti-analysis methods used
1. Wrong ZIP header data values
2. Wrong values in the manifest structure
2.1. Magic value
2.2. Array of strings’ offsets
2.3. Style pool
3. Long filenames
Signature recommendations
APK anti-analysis methods used
Techniques in this group abuse the values in specific structures, which are crucial for APK analysis. These evasions are actually possible because of the differences in how the Android launcher treats them and how the analysis tools approach the same data. While the main responsibility of the launcher is to execute an application and perform only basic sanity checks, analysis tools strive to provide as much information as possible about an APK. If some logic discrepancies are encountered during the process of analysis, the tool fails, thus showing the presence of an anti-analysis trick.
1. Wrong ZIP header data values
The clue about something strange inside the APK archive (which should be a usual ZIP archive) is seen in the message shown by JEB Pro:
APK is usually not split into multi-disk archives, so this information has to be checked inside - by analyzing the ZIP header data. The necessary entry is the central directory file header. The end of this record EOCD contains information about disk count at offsets 4 and 6. We will also pay attention to the offsets 10 and 12, as explained below.
EOCD fields
Offset | Bytes | Description |
---|---|---|
0 | 4 | End of central directory signature = 0x06054b50 |
4 | 2 | Number of this disk (or 0xffff for ZIP64) |
6 | 2 | Disk where central directory starts (or 0xffff for ZIP64) |
8 | 2 | Number of central directory records on this disk (or 0xffff for ZIP64) |
10 | 2 | Total number of central directory records (or 0xffff for ZIP64) |
12 | 4 | Size of central directory (bytes) (or 0xffffffff for ZIP64) |
16 | 4 | Offset of start of central directory, relative to start of archive (or 0xffffffff for ZIP64) |
20 | 2 | Comment length (n) |
22 | n | Comment |
EOCD marks the end of ZIP so the required byte sequence can be found at the end of the file:
The processed struct, along with fixes (explained below), looks like this:
Based on the very large values in the disk number fields, it is clear that the malware developers edited these fields and entries. If to compare this APK with any other legitimate APKs, it will be seen that in these APKs, values elDiskNumber and elStartDiskNumber are equal to 0. And in the current case the disk numbers should be set to 0 as well.
Also, the values elEntriesInDirectory and elDirectorySize are the same in legitimate APKs as opposed to the target one. As elEntriesInDirectory has ushort type (2 bytes long), its maximum value is 65536 – and can’t be equal to 139122 which is set in elDirectorySize. It means that the value of elDirectorySize must be equal to the value of elEntriesInDirectory, not vice versa, i.e., we set the value of elDirectorySize to 1075. This number corresponds to the files inside the APK, i.e. ZIP archive, but we could not know about it before the fix was done indeed.
2. Wrong values in the manifest structure
2.1. Magic value
The AndroidManifest file must start with specific magic numbers (0x00080003 or 0x00080001) as expected by APKTool:
However, upon closer examination of this apktool issue, it appears that the only correct value in AndroidManifest header is 0x00080003, which is equal to the constant name CHUNK_AXML_FILE in the apktool source code, not CHUNK_AXML_FILE_BROKEN which stands for 0x00080001.
And the analyzed file starts with 0x00080000. By changing it to the correct value, this issue becomes mitigated.
2.2. Array of strings' offsets
Another trick to fool analysis tools lies in the incorrent offset in the array of string offsets:
To analyze what causes this exception, we first make a breakdown of AndroidManifest structure:
By checking the offset shown in the exception, we understand that the issue is in the scStringOffsets array field, in its last element (0x24 + 0x160 = 0x184 – the exact offset shown in the exception). When examining this array closely, we see that the offset of the last string is pointing out of the file.
The string “theme” is wrongly interpreted as an offset value in the last element of the array, number 87. This means that the value of the scStringCount should be less by 1, i.e., set to 86. Now there are 87 elements in the array, all of 4 bytes, multiplication of 87*4 is equal to 348, which is 0x15C in hex. As scStringOffsets fields starts at 0x24, now it ends at 0x24+0x15C, which is equal to 0x180 – exactly what is expected in the analysis tool.
2.3. Style pool
In this trick, the value of the scStylePoolOffset field points out from the actual AndroidManifest file. Based on the scStyleCount field (equal to 0), it is a logical assumption that the file shouldn’t contain “styles”, and the value of this field should be 0 as well.
3. Long filenames
This technique is related to the files inside the APK. Developers added a large number of files inside nested directories to the asset folder. As a result, the length of the file name and path is over 300 characters.
These files break the logic of tools that cannot remap file locations and may fail during APK decompilation – like apktool. After analyzing the API calls from bytecode, we can see that there are no actual references to these files. It means that such files can be manually removed from the APK as they are not required anymore.
Signature recommendations
No signature recommendations are provided for this evasion group, as the techniques are speaking for themselves. If analysis tools fail to process a sample with some errors shown, it’s likely a sign of a used anti-analysis trick.