1. 事情起因
闲的
2. 使用jadx反编译apk文件(无壳)进行静态分析
2.1 搜索guid参数 定位代码位置 (选择第三个)
public static String a() {
StringBuffer stringBuffer = new StringBuffer();
ExtraInfo b = b();
stringBuffer.append("?userid=" + b.userid);
stringBuffer.append("&adimei=" + Utils.b());
stringBuffer.append("&adoaid=" + Utils.o());
stringBuffer.append("&adandroidid=" + Utils.k());
stringBuffer.append("&deviceid=" + Utils.j());
stringBuffer.append("&platform=android");
stringBuffer.append("&network=" + b.network);
stringBuffer.append("&version=" + b.version);
stringBuffer.append("&rand=" + b.rand);
stringBuffer.append("&netspeed=1024");
stringBuffer.append("&time=" + b.time);
stringBuffer.append("&channel=" + AppEnvLite.k());
stringBuffer.append("&dui=" + Utils.j());
stringBuffer.append("&imei=" + Utils.b());
stringBuffer.append("&guid=" + Security.init(AppEnvLite.d(), b, AppEnvLite.c));
try {
stringBuffer.append("&device=" + URLEncoder.encode(Build.DEVICE, "utf-8"));
stringBuffer.append("&devicebrand=" + URLEncoder.encode(Build.BRAND, "utf-8"));
stringBuffer.append("&devicemanufacturer=" + URLEncoder.encode(Build.MANUFACTURER, "utf-8"));
stringBuffer.append("&model=" + URLEncoder.encode(DeviceUtils.b, "utf-8"));
stringBuffer.append("&androidversion=" + URLEncoder.encode(Build.VERSION.RELEASE, "utf-8"));
stringBuffer.append("&androidversioncode=" + URLEncoder.encode(Integer.valueOf(Build.VERSION.SDK_INT).toString(), "utf-8"));
} catch (Throwable unused) {
}
try {
stringBuffer.append("&smid=" + ShumeiUtilsLite.a());
stringBuffer.append("&sm_deviceid=" + ShumeiUtilsLite.a());
} catch (Throwable unused2) {
}
try {
boolean c = EmulatorCheck.a().c();
stringBuffer.append("&isEmulator=" + c);
} catch (Exception unused3) {
}
return stringBuffer.toString();
}
stringBuffer.append("&guid=" + Security.init(AppEnvLite.m35467d(), b, AppEnvLite.f56796c));
2.2 先看看他传参具体是什么
1. AppEnvLite.m35467d() 是一个 Context 类型的对象
public static Context m35467d() {
return f56806m;
}
2. b 是由 m32322b 函数返回的一个自定义数据类型
ExtraInfo b = m32322b();
// m32322b 函数
public static ExtraInfo m32322b() {
long currentTimeMillis = System.currentTimeMillis() / 1000;
double random = Math.random();
String aQ = UserUtilsLite.m28409aQ();
if (aQ == null || aQ.length() < 2) {
aQ = YoukeHelper.m27267a();
}
ExtraInfo extraInfo = new ExtraInfo();
extraInfo.userid = aQ.trim();
extraInfo.deviceId = C4681Utils.m27396j();
extraInfo.network = m32309h(AppEnvLite.m35467d());
extraInfo.version = AppEnvLite.m35462i();
extraInfo.rand = String.valueOf(random);
extraInfo.time = String.valueOf(currentTimeMillis);
return extraInfo;
}
// ExtraInfo 数据类型
public class ExtraInfo {
public String deviceId;
public String network;
public String rand;
public String time;
public String userid;
public String version;
}
3. AppEnvLite.f56796c 是一个固定值
public static String f56796c = "3fwwdqy5jkozihv2naqebb0adsw7wsaq";
2.3 分析 Security.init 函数
进入 Security 类可以看到 他是进行了一个so库的调用 我们把他的 so 库文件拿出来
package com.huajiao.utils;
import android.content.Context;
/* loaded from: classes2.dex */
public class Security {
public static native String convertKey(String str);
public static native String decode(String str, String str2);
public static native String init(Context context, ExtraInfo extraInfo, String str);
static {
System.loadLibrary("hjsecurity");
}
}
2. ida静态分析
ida -> Exports -> 找到 Java_com_huajiao_utils_Security_init 函数 -> 进入
进去以后 按F5
生成 伪C代码 Ctrl+F9
加载JIN文件 并处理一下函数类型
int __fastcall Java_com_huajiao_utils_Security_init(_JNIEnv *env, jclass context, jclass extraInfo, jstring str)
{
jclass v6; // r8
const struct JNINativeInterface *functions; // r0
int v8; // r0
int v9; // r5
int v10; // r1
int v11; // r11
int v12; // r10
int v13; // r9
void *v14; // r5
int v15; // r2
int v16; // r8
int v17; // r0
signed int v18; // r1
char *v19; // r3
signed int v20; // r5
int v21; // r0
int v22; // r3
int v23; // r4
int v24; // r9
int v25; // r8
int v26; // r5
size_t v28; // [sp+0h] [bp-C0h] BYREF
int v29; // [sp+4h] [bp-BCh]
char *v30; // [sp+8h] [bp-B8h]
size_t *v31; // [sp+Ch] [bp-B4h]
void *v32; // [sp+10h] [bp-B0h]
int v33; // [sp+14h] [bp-ACh]
_JNIEnv *v34; // [sp+18h] [bp-A8h]
char v35[16]; // [sp+1Ch] [bp-A4h] BYREF
int v36[14]; // [sp+2Ch] [bp-94h]
jstring v37; // [sp+64h] [bp-5Ch]
void *v38; // [sp+68h] [bp-58h]
jstring v39; // [sp+6Ch] [bp-54h]
jstring v40; // [sp+70h] [bp-50h]
void *v41; // [sp+74h] [bp-4Ch]
jstring v42; // [sp+78h] [bp-48h]
jstring v43; // [sp+7Ch] [bp-44h]
void *v44; // [sp+80h] [bp-40h]
jstring v45; // [sp+84h] [bp-3Ch]
void *v46; // [sp+88h] [bp-38h]
jstring v47; // [sp+8Ch] [bp-34h]
void *v48; // [sp+90h] [bp-30h]
jstring v49; // [sp+94h] [bp-2Ch]
void *v50; // [sp+98h] [bp-28h]
v32 = &_stack_chk_guard;
v6 = env->functions->GetObjectClass(env, str);
v37 = env->functions->NewStringUTF(env, "deviceid=");
v38 = (void *)infoFiled(env, str, v6, "deviceId");
v36[0] = env->functions->GetStringLength((JNIEnv *)env, v37);
v36[1] = env->functions->GetStringLength((JNIEnv *)env, v38);
v39 = env->functions->NewStringUTF(env, "netspeed=1024");
v36[2] = env->functions->GetStringLength((JNIEnv *)env, v39);
v40 = env->functions->NewStringUTF(env, "network=");
v41 = (void *)infoFiled(env, str, v6, "network");
v36[3] = env->functions->GetStringLength((JNIEnv *)env, v40);
v36[4] = env->functions->GetStringLength((JNIEnv *)env, v41);
v42 = env->functions->NewStringUTF(env, "platform=android");
v36[5] = env->functions->GetStringLength((JNIEnv *)env, v42);
v43 = env->functions->NewStringUTF(env, "rand=");
v44 = (void *)infoFiled(env, str, v6, "rand");
v36[6] = env->functions->GetStringLength((JNIEnv *)env, v43);
v36[7] = env->functions->GetStringLength((JNIEnv *)env, v44);
v45 = env->functions->NewStringUTF(env, "time=");
v46 = (void *)infoFiled(env, str, v6, "time");
v36[8] = env->functions->GetStringLength((JNIEnv *)env, v45);
v36[9] = env->functions->GetStringLength((JNIEnv *)env, v46);
v47 = env->functions->NewStringUTF(env, "userid=");
v48 = (void *)infoFiled(env, str, v6, "userid");
v36[10] = env->functions->GetStringLength((JNIEnv *)env, v47);
v36[11] = env->functions->GetStringLength((JNIEnv *)env, v48);
v49 = env->functions->NewStringUTF(env, "version=");
v50 = (void *)infoFiled(env, str, v6, "version");
v36[12] = env->functions->GetStringLength((JNIEnv *)env, v49);
functions = env->functions;
v34 = env;
v36[13] = functions->GetStringLength(&env->functions, v50);
v8 = 0;
v9 = 0;
while ( v8 != 14 )
{
v10 = v36[v8++];
v9 += v10;
}
v30 = aEac63e66d8c4a6;
v28 = strlen(aEac63e66d8c4a6);
v29 = v28 + v9;
v31 = &v28;
v33 = (int)&v28 - ((v28 + v9 + 8) & 0xFFFFFFF8);
v11 = 0;
v12 = 0;
while ( v11 != 14 )
{
v13 = 0;
v14 = *(&v37 + v11);
v15 = (int)v34->functions->GetStringUTFChars(&v34->functions, v14, 0);
v16 = v36[v11];
v17 = v33 + v12;
while ( v13 < v16 )
{
*(_BYTE *)(v17 + v13) = *(_BYTE *)(v15 + v13);
++v13;
}
v34->functions->ReleaseStringUTFChars(&v34->functions, v14, (const char *)v15);
v12 += v16;
++v11;
}
v18 = 0;
v19 = v30;
v20 = v28;
v21 = v33 + v12;
while ( v18 < v20 )
{
*(_BYTE *)(v21 + v18) = v19[v18];
++v18;
}
v22 = v33;
v23 = (int)v34;
*(_BYTE *)(v33 + v29) = 0;
v24 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v23 + 668))(v23, v22);
v25 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v23 + 656))(v23, v24);
v26 = (*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)v23 + 676))(v23, v24, 0);
j_MD5(v26, v25, v35);
(*(void (__fastcall **)(int, int, int))(*(_DWORD *)v23 + 680))(v23, v24, v26);
return j_byteArrayToHex(v23, v35, 16);
}
v6 = env->functions->GetObjectClass(env, str); // 获取一个java类型
v37 = env->functions->NewStringUTF(env, "deviceid="); // cstring-> jstring
v38 = (void *)infoFiled(env, str, v6, "deviceId"); // 取java类的 某一参数值
v36[0] = env->functions->GetStringLength((JNIEnv *)env, v37); // 取jstring 的长度
因为C我也不是不会 但是能看懂几个函数就行 到时候使用 frida hook 我们看到 最后是 使用 J_md5 进行加密的
j_MD5(v26, v25, v35);
套娃????
// attributes: thunk
int __fastcall j_MD5(int a1, int a2, int a3)
{
return MD5(a1, a2, a3);
}
最后函数 是MD5 我们就Hook 这个函数 写代码
void *__fastcall MD5(int a1, int a2, void *a3)
{
void *v5; // r4
_BYTE v7[92]; // [sp+0h] [bp-78h] BYREF
v5 = &unk_A03C;
if ( a3 )
v5 = a3;
if ( !j_MD5_Init(v7) )
return 0;
j_MD5_Update(v7, a1, a2);
j_MD5_Final(v5, v7);
j_OPENSSL_cleanse((int)v7, 0x5Cu);
return v5;
}
3. frida hook
let SoName = "libhjsecurity.so";
function HookSoMd5() {
let FuncAddr_MD5 = Module.findExportByName(SoName, "MD5")
if (FuncAddr_MD5 != null) {
console.log("Hook MD5函数 地址:" + FuncAddr_MD5)
Interceptor.attach(FuncAddr_MD5, {
onEnter: function (args) {
console.log("[MD5] arge :", args[0].readCString())
},
onLeave: function (retval) {
console.log("[MD5] retval:", hexdump(retval))
}
})
}
}
function main() {
HookSoMd5()
}
setImmediate(main)
注意:在Hook之前请先点击一下登录
frida -U -F -l .\Hook.js
[Mi MIX 2S::花吱 ]-> [MD5] arge : deviceid=c90d4cae48099b77fa3995042a961d6fnetspeed=1024network=wifiplatform=androidrand=0.8669308120110475time=1658394061userid=900270713970272598version=1.11.19.69eac63e66d8c4a6f0303f00bc76d0217c
[MD5] retval: 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
ff84867c ba cd 8f 98 3a 91 ed ff bf b2 1e 12 52 b8 fa 90 ....:.......R...
ff84868c 09 00 00 00 20 00 00 00 0d 00 00 00 08 00 00 00 .... ...........
ff84869c 04 00 00 00 10 00 00 00 05 00 00 00 12 00 00 00 ................
ff8486ac 05 00 00 00 0a 00 00 00 07 00 00 00 12 00 00 00 ................
ff8486bc 08 00 00 00 0a 00 00 00 81 00 00 00 91 00 00 00 ................
ff8486cc a1 00 00 00 b5 00 00 00 c1 00 00 00 d1 00 00 00 ................
ff8486dc e9 00 00 00 f1 00 00 00 01 01 00 00 11 01 00 00 ................
ff8486ec 29 01 00 00 35 01 00 00 41 01 00 00 55 01 00 00 )...5...A...U...
ff8486fc f0 5d 7e 5c f0 5d 7e 5c 00 00 00 00 10 2a 80 ea .]~\.]~\.....*..
ff84870c 98 03 87 13 70 10 87 13 3e 49 61 15 50 f9 0b 70 ....p...>Ia.P..p
ff84871c 60 00 87 13 20 bc 0e 70 d3 6d 9e c5 48 87 84 ff `... ..p.m..H...
ff84872c 20 bc 0e 70 24 91 b6 df d4 93 84 ff 04 00 00 00 ..p$...........
ff84873c 20 a1 65 15 80 b1 58 15 98 03 87 13 f0 b7 5b 15 .e...X.......[.
ff84874c 07 00 00 00 06 00 00 00 00 00 40 3f 00 00 00 00 ..........@?....
ff84875c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
ff84876c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
这一段就是 guid 生成的源文本了
直接md5加密 就好了 (注意替换需要的内容) 后面 eac63e66d8c4a6f0303f00bc76d0217c
是固定的