The Old Way To Decrypt The Malicious Code of CamScanner


On August 27, 2019, Kaspersky published an article about an Android application called CamScanner. They detected that this very popular app, more than 100 million downloads, contained a malicious dropper component: An advertising dropper in Google Play

I am often curious about the technical details in order to know the latest techniques used by bad actors. So I decided to give it a look. In their article, Kaspersky gave the list of IOCs. I downloaded c69a2d2b0bf67265590c9be65cd4286b on Koodous

According to the article:

When the app is run, dropper decrypts and executes the malicious code contained in the file in the app resources.

fs0c131y@Elliots-MacBook-Pro:~/CamScanner$ apktool --no-src d 7aed7771b15d795bcd5ee119885613a3d5124f46d72c501fce3429f6c3c78ba4 -o apktool.out  
fs0c131y@Elliots-MacBook-Pro:~/CamScanner$ find apktool.out -name  
fs0c131y@Elliots-MacBook-Pro:~CamScanner$ file apktool.out/assets/  
apktool.out/assets/ data
fs0c131y@Elliots-MacBook-Pro:~/CamScanner$ binwalk apktool.out/assets/

Thanks to Apktool we managed to obtain the file called As expected, due to the encryption, this file is not a zip file for the moment. We need to understand how CamScanner decrypt it.

So I opened Jeb and search “mutter” in the bytecode and as said in the article, the decryption is done in a class called Duration. Now we have 2 choices:

  • We can use Frida in order to intercept the output of the “decrypt method” at the runtime. The only constraint is that we need to be here at the correct moment.
  • We can decrypt the zip file outside of the app context by using a good old Java class.

Let’s look at the 2nd option. I created a new folder, moved the in it and created a new file called


In this I created a main function and copy paste the code of the decryption code from CamScanner.

import android.content.Context;  
import android.os.Process;  
import java.util.ArrayList;

If I check the imports, I see 2 Android specific imports. In order to compile our Java class we need to get rid of these two imports.


These 2 imports are used to get the zip file from the assets and give a specific name to the decrypted file.


Simplification done, easy right?

I also remove the unused methods and add generic try catch everywhere and we have our final decryptor.

import java.util.ArrayList;``public class Duration {``    public static void main(String[] args) {  
        fireman("", "ugi");  
    }``    private static void climate(InputStream arg15, OutputStream arg16, int arg17) {  
        try {  
            byte[] v1 = new byte[4];  
            int v1_1 = arg17 ^ ((v1[0] & 0xFF) << 24) + ((v1[1] & 0xFF) << 16) + ((v1[2] & 0xFF) << 8) + ((v1[3] & 0xFF) << 0);  
   byte[( ^ v1_1) & 0xFF]);  
            ArrayList v3 = new ArrayList();  
            int v4;  
            for(v4 = 0; v4 < 0x100; ++v4) {  
            }``            int[] v4_1 = new int[0x100];  
            long v7 = (long)v1_1;  
            int v6;  
            for(v6 = 0; v6 < v4_1.length; ++v6) {  
                v7 = (long)(((int)((v7 * 0x3EAABF9EL + 0xACL & 0xFFFFFFFFL) >>> 16)));  
                v4_1[((Integer)v3.remove(((int)(Math.abs(v7) % (((long)v3.size())))))).intValue()] = v6;  
            }``            byte[] v3_1 = new byte[0x400];  
            while(true) {  
                int v5 =;  
                if(v5 <= 0) {  
                }``                int v6_1;  
                for(v6_1 = 0; v6_1 < v5; ++v6_1) {  
                    v3_1[v6_1] = (byte)v4_1[(v3_1[v6_1] ^ v1_1) & 0xFF];  
                }``                arg16.write(v3_1, 0, v5);  
        } catch (Exception e) {  
    }``    public static File fireman(String arg5, String arg6) {  
        try {  
            File v4 = new File("~/CamScanner/");  
            InputStream v0 = new FileInputStream(v4);  
            File v4_1 = new File("~/CamScanner/", "");  
            FileOutputStream v5_1 = new FileOutputStream(v4_1);  
            int v6 = arg6.hashCode() > 0 ? arg6.hashCode() : -arg6.hashCode();  
            Duration.climate(v0, v5_1, v6 % 0x100);  
            return v4_1;  
        } catch (Exception e) {  
        }``        return null;  

We are ready to compile it and decrypt our zip file.

fs0c131y@Elliots-MacBook-Pro:~/CamScanner/decryptor$ javac  
Note: uses unchecked or unsafe operations.  
Note: Recompile with -Xlint:unchecked for details.``fs0c131y@Elliots-MacBook-Pro:~/CamScanner/decryptor$ java Duration``fs0c131y@Elliots-MacBook-Pro:~/CamScanner/decryptor$ file Zip archive data, at least v2.0 to extract``fs0c131y@Elliots-MacBook-Pro:~/CamScanner/decryptor$ unzip decrypted  
  inflating: classes.dex

And voila! We decrypted and have a new DEX file to analyse.

I wanted to share this story for one reason: don’t get lost with all the fancy tools available on the Internet, sometimes a gold old Java class is enough to do what you want to do.