如有内容存在侵权或不当之处,请联系我,我将第一时间删除或修正。环境及版本:

image-20250912174533239.png (44.95 KB, 下载次数: 2)
下载附件
2025-9-14 16:59 上传
通过观察,logininfo被加密了分析Java层:将apk放到桌面,打开jadk,把apk拖进去,搜索"logininfo"

image-20250912192155751.png (64.07 KB, 下载次数: 2)
下载附件
2025-9-14 17:02 上传
只有这一个,点进去观察能看到doEncrypt传入了 jSONObject.toString() + com.wuba.loginsdk.network.l.a.a()是账号密码组成的json格式的数据转成字符串和另外一个字符串拼接而成.跟进a方法继续分析public static java.lang.String a() {
java.lang.String r2;
android.net.NetworkInfo r2;
//省略不是那么重要的代码
java.lang.String r3 = !android.text.TextUtils.isEmpty(com.wuba.loginsdk.internal.l.a.H().L()) ? com.wuba.loginsdk.internal.l.a.H().L() : "";
if (!com.wuba.loginsdk.b.b.v(com.wuba.loginsdk.b.d.L)) {
r3 = "";
}
java.lang.String r1 = com.wuba.loginsdk.network.l.a.c.replace("%nettype", r2).replace("%deviceid", com.wuba.loginsdk.data.b.K()).replace("%thirdinfo", com.wuba.loginsdk.thirdapi.ThirdUtils.generateInjectThirdInfo()).replace("%preMobileMaskMd5", android.text.TextUtils.isEmpty(r3) ? "" : com.wuba.loginsdk.utils.DeviceUtils.encryptionMD5(r3.getBytes())).replace("%preMobileMaskFormat", com.wuba.loginsdk.utils.o.e(r3)).replace("currentTimeMillis", java.lang.String.valueOf(java.lang.System.currentTimeMillis())).replace("randomUUID", com.wuba.loginsdk.utils.DeviceUtils.getRandomUUID());
com.wuba.loginsdk.log.LOGGER.d("NetWorkFactory", r1);
return r1;
}
​这里能看到返回的r1是由com.wuba.loginsdk.network.l.a.c这个字符串通过replace方法处理过后得到,定位com.wuba.loginsdk.network.l.a.c的位置

image.png (75.07 KB, 下载次数: 1)
下载附件
2025-9-14 17:13 上传
继续跟进b方法public static String b(Context context) throws Throwable {
String imei = DeviceUtils.getImei(context);
String model = DeviceUtils.getModel();
String osVersion = DeviceUtils.getOsVersion();
String model2 = DeviceUtils.getModel();
String deivceLanguage = DeviceUtils.getDeivceLanguage();
String deviceCountry = DeviceUtils.getDeviceCountry();
String brand = DeviceUtils.getBrand();
String displayHxW = DeviceUtils.getDisplayHxW(context);
String applicationName = DeviceUtils.getApplicationName(context);
String versionName = DeviceUtils.getVersionName(context);
String timeZone = DeviceUtils.getTimeZone();
String simOperatorType = DeviceUtils.getSimOperatorType(context);
String cPUSerial = DeviceUtils.getCPUSerial();
String deviceMemory = DeviceUtils.getDeviceMemory(context);
String androidID = DeviceUtils.getAndroidID(context);
String applicationId = DeviceUtils.getApplicationId(context);
String wifiSSID = DeviceUtils.getWifiSSID(context);
String wifiIPAddress = DeviceUtils.getWifiIPAddress(context);
String emulatorMsg = DeviceUtils.getEmulatorMsg(context);
boolean zIsDeviceRoot = DeviceUtils.isDeviceRoot();
int i = !TextUtils.isEmpty(emulatorMsg) ? 1 : 0;
StringBuilder sb = new StringBuilder();
sb.append("\u0001");
sb.append(imei);
sb.append(f34988b);
sb.append("android");
sb.append(f34988b);
sb.append(model);
sb.append(f34988b);
sb.append(osVersion);
sb.append(f34988b);
sb.append("%nettype");
sb.append(f34988b);
sb.append(model2);
sb.append(f34988b);
sb.append(deivceLanguage);
sb.append(f34988b);
sb.append(deviceCountry);
sb.append(f34988b);
sb.append(brand);
sb.append(f34988b);
sb.append(displayHxW);
sb.append(f34988b);
sb.append(applicationName);
sb.append(f34988b);
sb.append(versionName);
sb.append(f34988b);
sb.append(timeZone);
sb.append(f34988b);
sb.append(simOperatorType);
sb.append(f34988b);
sb.append("");
sb.append(f34988b);
sb.append(cPUSerial);
sb.append(f34988b);
sb.append(deviceMemory);
sb.append(f34988b);
sb.append(f34988b);
sb.append(f34988b);
sb.append(wifiSSID);
sb.append(f34988b);
sb.append(wifiIPAddress);
sb.append(f34988b);
sb.append("");
sb.append(f34988b);
sb.append("");
sb.append(f34988b);
sb.append(zIsDeviceRoot ? 1 : 0);
sb.append(f34988b);
sb.append("%deviceid");
sb.append(f34988b);
sb.append(i);
sb.append(f34988b);
sb.append(emulatorMsg);
sb.append(f34988b);
sb.append("%thirdinfo");
sb.append(f34988b);
sb.append(androidID);
sb.append(f34988b);
sb.append(applicationId);
sb.append(f34988b);
sb.append("%preMobileMaskMd5");
sb.append(f34988b);
sb.append("%preMobileMaskFormat");
sb.append(f34988b);
sb.append("currentTimeMillis");
sb.append(f34988b);
sb.append("randomUUID");
LOGGER.d("NetWorkFactory", sb.toString());
return sb.toString();
}这个方法就是把一系列系统参数拼接到一起,f34988b是#需要注意的一点是这个字符串最前面有一个控制字符\u0001(我最开始没看这个方法,直接hook的doEncrypt拿的明文,这个控制字符看不到,hook这hook那,搞了好久才发现),返回doEncrpt继续分析

image-20250912192256258.png (68.32 KB, 下载次数: 2)
下载附件
2025-9-14 17:00 上传
很清楚地看到了doEncrypt方法内部逻辑,把明文转成byte数组传入native方法encrypt

image.png (61.08 KB, 下载次数: 2)
下载附件
2025-9-14 17:14 上传
分析so层:解压apk,拿到lib\armeabi-v7a\下面的libcom_wuba_uc_rsa.so,打开ida分析是个动态注册的,直接进入Jni_Onload

image.png (110.05 KB, 下载次数: 2)
下载附件
2025-9-14 17:15 上传
点击off_C004( JNINativeMethod 数组的地址)

image-20250912193226748.png (75.49 KB, 下载次数: 2)
下载附件
2025-9-14 17:05 上传
一眼就看到了加密方法,继续跟进

image.png (167.66 KB, 下载次数: 2)
下载附件
2025-9-14 17:16 上传
进入j_encrypt_defaultint __fastcall encrypt_default(int byte_len, int byte, int out)
{
int result; // r0
int v6; // r0
_BYTE *v7; // r4
int v8; // r8
int i; // r6
int v10; // r0
int v11; // [sp+Ch] [bp-434h]
_DWORD v13[3]; // [sp+14h] [bp-42Ch] BYREF
_BYTE v14[128]; // [sp+20h] [bp-420h] BYREF
_BYTE v15[128]; // [sp+A0h] [bp-3A0h] BYREF
_BYTE v16[768]; // [sp+120h] [bp-320h] BYREF
​
result = -1;
if ( byte_len 0 )
++v6;
v16[128 * v6] = 1;
v11 = v6 = byte_len )
{
j_base64_encode_uc(v16, v11 | 1, out); //base64
return 0;
}
v10 = i Vp$qT#T=phf MA
image-20250914105830574.png (105.36 KB, 下载次数: 1)
下载附件
2025-9-14 17:06 上传
填充

image-20250914110416648.png (56.6 KB, 下载次数: 2)
下载附件
2025-9-14 17:07 上传
用时间戳当作随机数种子,生成随机数填充回到rc4,先看看rc4加密逻辑

image-20250914162440083.png (16.96 KB, 下载次数: 1)
下载附件
2025-9-14 17:08 上传

image-20250914162633164.png (42.92 KB, 下载次数: 1)
下载附件
2025-9-14 17:09 上传
通过j_ch_init初始化,返回一个128长度的数组,再传入j_ch_crypt进行一些列运算,得到真正的S盒,然后进行运算拿到结果,再进行rc4加密(非标准rc4,标准的S盒长度是256)

image-20250914164434306.png (107.26 KB, 下载次数: 2)
下载附件
2025-9-14 17:09 上传
sq是hook j_ch_init的Onleave的第一个参数

image-20250914164349136.png (147.57 KB, 下载次数: 1)
下载附件
2025-9-14 17:16 上传
代码是ai写的,自己简单改改就好了,就不贴代码了新手小白第一次尝试,难免有疏漏或不足,欢迎各位批评指正。总结加密流程: 分块加密,每一块最长117,这一块先rsa再rc4,再把每一块加密结果拼接在一起,再在字节数组最后面拼接上0x01,再进行base64加密(+替换成-,/替换成_.=替换成B)