# 币安加持币圈热门APP(Wild Cash) 算法解密

By [dream](https://paragraph.com/@lovefy) · 2022-11-25

---

昨天一个名为Wild Cash的App火遍全网，每个群都在讨论它，币安加持，零撸赚钱，光这些就足够吸引眼球啦,用Fiddler 抓包发现是https协议的，但是经过了加密，好在APK没有加密，让我们来试试能不能找出算法

![可以看到，发包和收包都是加密过的](https://storage.googleapis.com/papyrus_images/0753b1ffe2702e288b8ebe371b45c4aeefc3ba3596eea76093e53de545f01b02.png)

可以看到，发包和收包都是加密过的

用jadx解码然后搜索关键字定位到加密算法的地方，可以发现用的是aes算法

    package com.bo.hooked.common.d.d;
    
    import androidx.exifinterface.media.ExifInterface;
    import java.util.ArrayList;
    import java.util.List;
    import javax.crypto.Cipher;
    import javax.crypto.spec.GCMParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.android.codec.binary.Base64;
    import org.apache.commons.android.codec.language.Soundex;
    
    public class b {
        private static final String a = a(a());
        private static final String b = new String(new char[]{'A', 'E', 'S'});
    
        public static String a(String str, String str2, byte[] bArr) throws Exception {
            byte[] a = a(str);
            Cipher instance = Cipher.getInstance(a);
            instance.init(2, new SecretKeySpec(str2.getBytes(), b), new GCMParameterSpec(128, bArr));
            return new String(instance.doFinal(a));
        }
    
        private static String a(List<String> list) {
            StringBuffer stringBuffer = new StringBuffer();
            for (String append : list) {
                stringBuffer.append(append);
            }
            return stringBuffer.toString().replace(new String(new char[]{Soundex.SILENT_MARKER}), "");
        }
    
        private static String a(byte[] bArr) {
            return Base64.encodeBase64String(bArr);
        }
    
        private static List<String> a() {
            ArrayList arrayList = new ArrayList();
            arrayList.add(ExifInterface.GPS_MEASUREMENT_IN_PROGRESS);
            arrayList.add(new String(new char[]{'E', 'S', '/'}));
            arrayList.add("-G");
            arrayList.add("-C-M/");
            arrayList.add(new String(new char[]{'N', 'o', 'p', 'a', Soundex.SILENT_MARKER, 'd', 'd'}));
            arrayList.add("in-g");
            return arrayList;
        }
    
        private static byte[] a(String str) {
            return Base64.decodeBase64(str);
        }
    
        public static String b(String str, String str2, byte[] bArr) throws Exception {
            byte[] bytes = str.getBytes();
            Cipher instance = Cipher.getInstance(a);
            instance.init(1, new SecretKeySpec(str2.getBytes(), b), new GCMParameterSpec(128, bArr));
            return a(instance.doFinal(bytes));
        }
    }
    

经过frida hook 和调试，发现用的是AES/GCM/Nopadding，加密和解密用的KEY一致，但是vi有区别，两者区别在于发包时以时间戳为基础生成一个vi,而返回数据解包时用的vi是固定的

![加密算法](https://storage.googleapis.com/papyrus_images/629636ffd91693ecf33e720e9561fb1355e064cb1a3e2ee7fc712afa7fbf9e53.png)

加密算法

![固定KEY值](https://storage.googleapis.com/papyrus_images/fb8f0bc74901ae84bfb47638d2e2518263a381b60afabbc3e7b778b3cee79c68.png)

固定KEY值

用frida注入代码做了测试，能成功加密解密：

    function RequestBodyEncrypt(currentTimeMillis,data)  {
        var b = Java.use("com.bo.hooked.common.d.d.b")
        var a = Java.use("com.bo.hooked.common.d.g.a")
        var GCMParameterSpec = Java.use("javax.crypto.spec.GCMParameterSpec")
        //var currentTimeMillis = 1669299738910
        var key = a.h()
        var vi = a.a(currentTimeMillis)
        return b.b(data, key, vi)
    }
    
    function RequestBodyDecrypt(currentTimeMillis,data)  {
        var b = Java.use("com.bo.hooked.common.d.d.b")
        var a = Java.use("com.bo.hooked.common.d.g.a")
        var GCMParameterSpec = Java.use("javax.crypto.spec.GCMParameterSpec")
        //var currentTimeMillis = 1669299738910
        var key = a.h()
        var vi = a.a(currentTimeMillis)
        return b.a(data, key, vi)
    }
    
    
    function ResponseBodDecrypt(data)  {
        var b = Java.use("com.bo.hooked.common.d.d.b")
        var a = Java.use("com.bo.hooked.common.d.g.a")
        var GCMParameterSpec = Java.use("javax.crypto.spec.GCMParameterSpec")
        var key = a.h()
        var vi = a.d()
        return b.a(data, key, vi)
    }
    
    function encodeBase64String(data) {
        return Java.use("com.bo.hooked.common.d.d.b").a(data)
    }
    
    ResponseBodDecrypt("h60M054rQgQtxxVjZXwJDDMHFftNihcRgL9EBM0drMqjK2VAdqmhAvZTpIojbqIImLQQ9ac0R0xNUhVd7Y4pHNnV/qK9fkKCCKJ/KhZHgqOyHkY=")
    RequestBodyDecrypt(1669299738910,"XXoGEyU6pa+fo28P2YN5ySJ+Ad9vKi73kuropUlvVsvcNNiNwrLBAA/qhjT6")
    RequestBodyEncrypt(1669299738910,"{\"status\":\"0\",\"tapCount\":\"1\"}")
    

![成功解码](https://storage.googleapis.com/papyrus_images/7ca3aa190080569818a5bfc70f5ea0e7fd51a3cc4cca000c12a8cffc053c2121.png)

成功解码

---

*Originally published on [dream](https://paragraph.com/@lovefy/app-wild-cash)*
