俗里俗气 发表于 2021-10-20 19:03

某社区登录协议分析

1.首先对该APP抓包 获取请求字段:params =Jv4t3j/jzbV2ISssFo/Kvqtk6FCp271qkQSZEMXbAS0EThLEPpptyEwcl4wtj0QpnN5LWOtEeLaFofhV9xs0S0Rfdl4kOQX0vsEKJg==

2.根据观察不难看出此为base64编码,是否为变种未知,字段为 params

3.对App进行反编译,定位 “params" 位置 共有两处,并且观察方法名,确定为该位置

​https://img-blog.csdnimg.cn/57d8025948694d08b9abf02f83b024e1.png?data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==​​

4.我们通过Frida Hook该方法参数,获取传参值,代码如下

"""
jscode =
Java.perform(function () {
    var Utils = Java.use("com.asdfg2.daili.Common.HttpUtils");
    Utils.post.implementation = function (a,map,c,d)
      send(a);
      
       var keyset = map.keySet();
      var it = keyset.iterator();
      while(it.hasNext()){
            var keystr = it.next().toString();
            var valuestr = map.get(keystr).toString();
            send(keystr+" " +valuestr);
      }
   
      send("-----------");
    }
});
"""
Map 参数如下: password 9d12c191dd8169de8515e174184f74bf mobile 15842731659

5. password 在传参前就已经加密,但是经验证为MD5加密,跟进 XXTEA.encryptToBase64String方法,str2参数:encryptKey = "weichats"

str1参数:{"password":"9d12c191dd8169de8515e174184f74bf","mobile":"15842731659"}

final String string = MyApplication.getPreferences().getString("access_token", "");
      final String json = (map == null || map.size() == 0) ? null : new Gson().toJson(map);
      if (!TextUtils.isEmpty(json)) {
            json = XXTEA.encryptToBase64String(json, BuildConfig.encryptKey);
      }
6. Hook参数返回值可以发现,该参数返回值为Post的请求体

public static final String encryptToBase64String(String str, String str2) {
      byte[] encrypt = encrypt(str, str2);
      if (encrypt == null) {
            return null;
      }
      return Base64.encode(encrypt);
    }

6. encrypt 是通过 encrypt方法返回,类型为byte[]

public static final byte[] encrypt(String str, String str2) {
      try {
            return encrypt(str.getBytes("UTF-8"), str2.getBytes("UTF-8"));
      } catch (UnsupportedEncodingException unused) {
            return null;
      }
    }
7. 该返回调用其重载方法代码如下

public static final byte[] encrypt(byte[] bArr, byte[] bArr2) {
      if (bArr.length == 0) {
            return bArr;
      }
      return toByteArray(encrypt(toIntArray(bArr, true), toIntArray(fixKey(bArr2), false)), false);
    }

8.在重载方法encrptt中返回值参数调用 toIntArray方法,fixKey方法,toByteArray,encrypt方法 代码如下

private static int[] encrypt(int[] iArr, int[] iArr2) {
      int length = iArr.length - 1;
      if (length < 1) {
            return iArr;
      }
      int i = (52 / (length + 1)) + 6;
      int i2 = iArr;
      int i3 = 0;
      while (true) {
            int i4 = i - 1;
            if (i <= 0) {
                return iArr;
            }
            int i5 = DELTA + i3;
            int i6 = (i5 >>> 2) & 3;
            int i7 = i2;
            int i8 = 0;
            while (i8 < length) {
                int i9 = i8 + 1;
                i7 = iArr + MX(i5, iArr, i7, i8, i6, iArr2);
                iArr = i7;
                i8 = i9;
            }
            i2 = iArr + MX(i5, iArr, i7, i8, i6, iArr2);
            iArr = i2;
            i3 = i5;
            i = i4;
      }
    }

private static byte[] toByteArray(int[] iArr, boolean z) {
      int i;
      int length = iArr.length << 2;
      if (z) {
            i = iArr;
            int i2 = length - 4;
            if (i < i2 - 3 || i > i2) {
                return null;
            }
      } else {
            i = length;
      }
      byte[] bArr = new byte;
      for (int i3 = 0; i3 < i; i3++) {
            bArr = (byte) (iArr >>> ((i3 & 3) << 3));
      }
      return bArr;
    }
}


private static int[] toIntArray(byte[] bArr, boolean z) {
      int[] iArr;
      int length = (bArr.length & 3) == 0 ? bArr.length >>> 2 : (bArr.length >>> 2) + 1;
      if (z) {
            iArr = new int[(length + 1)];
            iArr = bArr.length;
      } else {
            iArr = new int;
      }
      int length2 = bArr.length;
      for (int i = 0; i < length2; i++) {
            int i2 = i >>> 2;
            iArr = iArr | ((bArr & UByte.MAX_VALUE) << ((i & 3) << 3));
      }
      return iArr;
    }

private static byte[] fixKey(byte[] bArr) {
      if (bArr.length == 16) {
            return bArr;
      }
      byte[] bArr2 = new byte;
      if (bArr.length < 16) {
            System.arraycopy(bArr, 0, bArr2, 0, bArr.length);
      } else {
            System.arraycopy(bArr, 0, bArr2, 0, 16);
      }
      return bArr2;
    }




9.字段   UByte.MAX_VALUE= -1    DELTA = -1640531527

private static int MX(int i, int i2, int i3, int i4, int i5, int[] iArr) {
      return ((i ^ i2) + (iArr[(i4 & 3) ^ i5] ^ i3)) ^ (((i3 >>> 5) ^ (i2 << 2)) + ((i2 >>> 3) ^ (i3 << 4)));
    }
10.至此encrypt(str, str2) 返回的数组算法跟进完毕,代码内容均为基础算法

11. 最后调用 Base64.encode(encrypt)很显然这是Base64的编码,我们可以利用Java自带的Base64包,替换为Base64.getEncoder().encodeToString(encrypt)

12.在Java层分析完毕,开始模拟进行Post提交。

import requests
proxies = {

    'http': 'http://127.0.0.1:8899', 'https': 'http://127.0.0.1:8899'
}

loginl = {
      "User-Agent": "okhttp-okgo/jeasonlzy",
      "accessToken":"",
      "Content-Type": "application/x-www-form-urlencoded",
      "Host": "ios.bz-cf.com",
      "Connection": "Keep-Alive"
         }

fdata ={
      "params" : 'Jv4t3j/jzbV2ISssFo/Kvqtk6FCp271qkQSZEMXbAS0EThLEPpptyEwcl4wtj0QpnN5LWOtEeLaFofhV9xs0S0Rfdl4kOQX0vsEKJg==',

    }
print(fdata)

r = requests.post("http://ios.bz-cf.com/index/user/login", data=fdata, headers=loginl, verify=False,proxies=proxies)
print(r.text)
​https://img-blog.csdnimg.cn/8360a440e62347a7bff6e6b5a0e53aad.png?data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==​​data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
13.提交后返回正常,该App并未将关键算法放于so层,导致轻易暴漏。由于没有使用ida,不涉及汇编调试,大家可以轻松解决。

涛之雨 发表于 2021-10-21 10:13

推荐使用md(MarkDown)书写,会更易于阅读和排版
此外建议使用代码块包裹代码部分,
另有图片加载异常,请直接上传图片到吾爱然后作为附件插入,
csdn的图片容易盗链。

wantwill 发表于 2021-10-21 16:54

谢谢分享!

amscracker 发表于 2021-10-21 17:09

CSDN的资源要不到两天就会被防盗链

俗里俗气 发表于 2021-10-21 21:59

amscracker 发表于 2021-10-21 17:09
CSDN的资源要不到两天就会被防盗链

csdn就是我写的 图片懒的截图了哈哈

cjc3528 发表于 2021-10-22 12:22

这个教程内容真不错,不过我水平不够,不是很懂,还需要继续学习,谢谢分享了

zhangsf123 发表于 2021-10-28 00:27

其实,很多代码或者app都没深入考虑加密。找到源码后,直接就破解掉了。

EricLee66 发表于 2021-11-2 20:55

感谢楼主的教程,很实用。最近也在学习安卓逆向相关内容,一起进步

7026ziw 发表于 2021-11-2 22:32

懂了漂亮,感谢

wantwill 发表于 2021-11-9 15:48

学习了 学习了 感谢分享
页: [1]
查看完整版本: 某社区登录协议分析