rednaga / APKiD

Android Application Identifier for Packers, Protectors, Obfuscators and Oddities - PEiD for Android
Other
2.07k stars 296 forks source link

[DETECTION] Vasco OneSpan Protector #201

Open enovella opened 4 years ago

enovella commented 4 years ago

Provide the file

Source: https://www.onespan.com/about/news/united-bulgarian-bank-selects-onespan-help-fight-social-engineering-and-mobile-malware Sample: https://www.apkmonk.com/download-app/bg.ubb.mobile/5_bg.ubb.mobile_2019-11-04.apk/

Describe the detection issue Protector https://www.onespan.com/blog/trust-through-mobile-app-shielding-and-hardening

APKiD current results...

>  apkid ~/Downloads/bg.ubb.mobile_2019-11-04.apk 
[+] APKiD 2.1.0 :: from RedNaga :: rednaga.io
[*] /home/edu/Downloads/bg.ubb.mobile_2019-11-04.apk!classes.dex
 |-> anti_vm : Build.FINGERPRINT check, Build.HARDWARE check, Build.MANUFACTURER check, Build.TAGS check, possible VM check
 |-> compiler : r8
[*] /home/edu/Downloads/bg.ubb.mobile_2019-11-04.apk!classes2.dex
 |-> anti_debug : Debug.isDebuggerConnected() check
 |-> anti_vm : Build.FINGERPRINT check, Build.MANUFACTURER check, Build.MODEL check, Build.PRODUCT check, Build.TAGS check, device ID check, possible Build.SERIAL check, subscriber ID check
 |-> compiler : r8 without marker (suspicious)

Additional context OneSpan may use Promon underneath in some versions

package com.vasco.digipass.sdk.utils.devicebinding.obfuscated;

import android.content.Context;
import android.content.SharedPreferences;
import com.vasco.digipass.sdk.utils.devicebinding.DeviceBindingSDKException;
import com.vasco.digipass.sdk.utils.utilities.UtilitiesSDK;
import com.vasco.digipass.sdk.utils.utilities.UtilitiesSDKCryptoResponse;

class a {
    private final String a;
    private final Context b;
    private final byte[] c;

    a(Context arg2, String arg3) {
        this.c = new byte[]{-22, 109, -105, 38, 74, 0xD1, 0x8C, 28, -104, 110, 0x4F, 11, -75, -83, 88, 14};
        this.b = arg2;
        this.a = arg3;
    }

    private void a(String arg6, String arg7) {
        try {
            SharedPreferences v0 = this.b.getSharedPreferences("OneSpan_DeviceBinding", 0);
            if(arg7 != null) {
                if(v0.getString(arg6, null) != null) {
                    return;
                }

                UtilitiesSDKCryptoResponse v7 = UtilitiesSDK.encrypt(3, 4, this.c(this.a), this.c, arg7.getBytes());
                if(v7.getReturnCode() == 0) {
                    v0.edit().putString(arg6, UtilitiesSDK.bytesToHexa(v7.getOutputData())).apply();
                    return;
                }

                throw new DeviceBindingSDKException(v7.getReturnCode());
            }
        }
        catch(Exception v6) {
            throw new DeviceBindingSDKException(-4408, v6);
        }
    }

    String a() {
        return this.b("Jj61U8yBQiwrifsukk9qgw");
    }

    void a(String arg2) {
        this.a("Jj61U8yBQiwrifsukk9qgw", arg2);
    }

    private String b(String arg5) {
        try {
            String v5_1 = this.b.getSharedPreferences("OneSpan_DeviceBinding", 0).getString(arg5, null);
            if(v5_1 == null) {
                return null;
            }

            UtilitiesSDKCryptoResponse v5_2 = UtilitiesSDK.decrypt(3, 4, this.c(this.a), this.c, UtilitiesSDK.hexaToBytes(v5_1));
            if(v5_2.getReturnCode() == 0) {
                return new String(v5_2.getOutputData());
            }

            throw new DeviceBindingSDKException(v5_2.getReturnCode());
        }
        catch(Exception v5) {
            throw new DeviceBindingSDKException(-4407, v5);
        }
    }

    private byte[] c(String arg5) {
        if(arg5 == null) {
            arg5 = "";
        }

        UtilitiesSDKCryptoResponse v5 = UtilitiesSDK.deriveKey(3, arg5.getBytes(), this.c, 1000, 0x20);
        if(v5.getReturnCode() == 0) {
            return v5.getOutputData();
        }

        throw new DeviceBindingSDKException(v5.getReturnCode());
    }
}
enovella commented 4 years ago

Some whiteboxing

package com.vasco.digipass.sdk.utils.utilities.wbc;

public class WbAesUtils {
    public static byte[][] init_array2(int arg0, int arg1) {
        return new byte[arg0][arg1];
    }

    public static byte[][][] init_array3(int arg0, int arg1, int arg2) {
        return new byte[arg0][arg1][arg2];
    }

    public static byte[][][][] init_array4(int arg0, int arg1, int arg2, int arg3) {
        return new byte[arg0][arg1][arg2][arg3];
    }

    public static byte[][][][][] init_array5(int arg0, int arg1, int arg2, int arg3, int arg4) {
        return new byte[arg0][arg1][arg2][arg3][arg4];
    }

    public static byte[][][][][][] init_array6(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
        return new byte[arg0][arg1][arg2][arg3][arg4][arg5];
    }

    public static byte[][] init_state() {
        return WbAesUtils.init_array2(4, 4);
    }

    public static byte[][][] init_strips128() {
        return WbAesUtils.init_array3(4, 4, 16);
    }

    public static byte[][][] init_strips32() {
        return WbAesUtils.init_array3(4, 4, 4);
    }

    public static byte[][][][] init_typeIA_input_sbox() {
        return WbAesUtils.init_array4(4, 4, 2, 16);
    }

    public static byte[][][][] init_typeIAs() {
        return WbAesUtils.init_array4(4, 4, 0x100, 16);
    }

    public static byte[][][][] init_typeIB_output_sbox_inv() {
        return WbAesUtils.init_array4(4, 4, 2, 16);
    }

    public static byte[][][][] init_typeIBs() {
        return WbAesUtils.init_array4(4, 4, 0x100, 16);
    }

    public static byte[][][][][] init_typeIIIs() {
        return WbAesUtils.init_array5(9, 4, 4, 0x100, 4);
    }

    public static byte[][][][][] init_typeIIs() {
        return WbAesUtils.init_array5(9, 4, 4, 0x100, 4);
    }

    public static byte[][][][][] init_typeIV_IAs() {
        return WbAesUtils.init_array5(4, 4, 15, 2, 0x80);
    }

    public static byte[][][][][] init_typeIV_IBs() {
        return WbAesUtils.init_array5(4, 4, 15, 2, 0x80);
    }

    public static byte[][][][][][] init_typeIV_IIIs() {
        return WbAesUtils.init_array6(9, 4, 4, 3, 2, 0x80);
    }

    public static byte[][][][][][] init_typeIV_IIs() {
        return WbAesUtils.init_array6(9, 4, 4, 3, 2, 0x80);
    }
}

Screenshot from 2020-01-04 03-09-00

enovella commented 4 years ago

Vasco OneSpan uses Promon, which also uses OLLVM:

[14:28 edu@xps ~] >  apkid Downloads/cf44e77e11cdcc7c3dc2a4112c369a2fac1637fa757b958302df4291f81aa1de.apk 
[+] APKiD 2.1.0 :: from RedNaga :: rednaga.io
[*] Downloads/cf44e77e11cdcc7c3dc2a4112c369a2fac1637fa757b958302df4291f81aa1de.apk!classes.dex
 |-> anti_vm : Build.MANUFACTURER check, possible Build.SERIAL check
 |-> compiler : dexlib 2.x
[*] Downloads/cf44e77e11cdcc7c3dc2a4112c369a2fac1637fa757b958302df4291f81aa1de.apk!lib/arm64-v8a/libejmfnmkjdmph.so
 |-> obfuscator : Obfuscator-LLVM version 3.5
[*] Downloads/cf44e77e11cdcc7c3dc2a4112c369a2fac1637fa757b958302df4291f81aa1de.apk!lib/x86/libejmfnmkjdmph.so
 |-> obfuscator : Obfuscator-LLVM version 3.5
[*] Downloads/cf44e77e11cdcc7c3dc2a4112c369a2fac1637fa757b958302df4291f81aa1de.apk!lib/armeabi-v7a/libejmfnmkjdmph.so
 |-> obfuscator : Obfuscator-LLVM version 3.5
ghost commented 4 years ago

Working on reversing this too :-) Sent a message your way.