P.Y.G-亮亮 发表于 2022-7-24 11:52

某吱 app 逆向


可以说是用了技巧吧 静态分析也是可以分析出来的

## 1.        事情起因

### ``闲的``

## 2.        使用jadx反编译apk文件(无壳)进行静态分析

###                         2.1        搜索guid参数 定位代码位置 (选择第三个)

```java
    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();
    }

```

```Java
stringBuffer.append("&guid=" + Security.init(AppEnvLite.m35467d(), b, AppEnvLite.f56796c));
```

###                         2.2        先看看他传参具体是什么

#### 1. ``AppEnvLite.m35467d() 是一个 Context 类型的对象``

```java
    public static Context m35467d() {
      return f56806m;
    }
```

#### 2. ``b 是由m32322b 函数返回的一个自定义数据类型``

```java
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 是一个固定值``

```java
public static String f56796c = "3fwwdqy5jkozihv2naqebb0adsw7wsaq";
```

###                         2.3 分析 Security.init 函数

#### ``进入 Security 类可以看到 他是进行了一个so库的调用 我们把他的 so 库文件拿出来``

```java
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文件并处理一下函数类型

```c
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; // BYREF
int v29; //
char *v30; //
size_t *v31; //
void *v32; //
int v33; //
_JNIEnv *v34; //
char v35; // BYREF
int v36; //
jstring v37; //
void *v38; //
jstring v39; //
jstring v40; //
void *v41; //
jstring v42; //
jstring v43; //
void *v44; //
jstring v45; //
void *v46; //
jstring v47; //
void *v48; //
jstring v49; //
void *v50; //

v32 = &_stack_chk_guard;
v6 = env->functions->GetObjectClass(env, str);
v37 = env->functions->NewStringUTF(env, "deviceid=");
v38 = (void *)infoFiled(env, str, v6, "deviceId");
v36 = env->functions->GetStringLength((JNIEnv *)env, v37);
v36 = env->functions->GetStringLength((JNIEnv *)env, v38);
v39 = env->functions->NewStringUTF(env, "netspeed=1024");
v36 = env->functions->GetStringLength((JNIEnv *)env, v39);
v40 = env->functions->NewStringUTF(env, "network=");
v41 = (void *)infoFiled(env, str, v6, "network");
v36 = env->functions->GetStringLength((JNIEnv *)env, v40);
v36 = env->functions->GetStringLength((JNIEnv *)env, v41);
v42 = env->functions->NewStringUTF(env, "platform=android");
v36 = env->functions->GetStringLength((JNIEnv *)env, v42);
v43 = env->functions->NewStringUTF(env, "rand=");
v44 = (void *)infoFiled(env, str, v6, "rand");
v36 = env->functions->GetStringLength((JNIEnv *)env, v43);
v36 = env->functions->GetStringLength((JNIEnv *)env, v44);
v45 = env->functions->NewStringUTF(env, "time=");
v46 = (void *)infoFiled(env, str, v6, "time");
v36 = env->functions->GetStringLength((JNIEnv *)env, v45);
v36 = env->functions->GetStringLength((JNIEnv *)env, v46);
v47 = env->functions->NewStringUTF(env, "userid=");
v48 = (void *)infoFiled(env, str, v6, "userid");
v36 = env->functions->GetStringLength((JNIEnv *)env, v47);
v36 = env->functions->GetStringLength((JNIEnv *)env, v48);
v49 = env->functions->NewStringUTF(env, "version=");
v50 = (void *)infoFiled(env, str, v6, "version");
v36 = env->functions->GetStringLength((JNIEnv *)env, v49);
functions = env->functions;
v34 = env;
v36 = functions->GetStringLength(&env->functions, v50);
v8 = 0;
v9 = 0;
while ( v8 != 14 )
{
    v10 = v36;
    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;
    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;
}
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 = env->functions->GetStringLength((JNIEnv *)env, v37);// 取jstring 的长度




#### 因为C我也不是不会 但是能看懂几个函数就行到时候使用 fridahook我们看到 最后是 使用 J_md5 进行加密的

```c
j_MD5(v26, v25, v35);
```

#### 套娃????

```c
// attributes: thunk
int __fastcall j_MD5(int a1, int a2, int a3)
{
return MD5(a1, a2, a3);
}
```

#### 最后函数 是MD5   我们就Hook 这个函数   写代码

```c
void *__fastcall MD5(int a1, int a2, void *a3)
{
void *v5; // r4
_BYTE v7; // 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



```js
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(" arge :", args.readCString())
            },
            onLeave: function (retval) {
                console.log(" retval:", hexdump(retval))
            }
      })
    }
}
function main() {
    HookSoMd5()
}
setImmediate(main)
```

#### 注意:在Hook之前请先点击一下登录

```shell
frida -U -F -l .\Hook.js

-> arge : deviceid=c90d4cae48099b77fa3995042a961d6fnetspeed=1024network=wifiplatform=androidrand=0.8669308120110475time=1658394061userid=900270713970272598version=1.11.19.69eac63e66d8c4a6f0303f00bc76d0217c
retval:            0123456789ABCDEF0123456789ABCDEF
ff84867cba cd 8f 98 3a 91 ed ff bf b2 1e 12 52 b8 fa 90....:.......R...
ff84868c09 00 00 00 20 00 00 00 0d 00 00 00 08 00 00 00.... ...........
ff84869c04 00 00 00 10 00 00 00 05 00 00 00 12 00 00 00................
ff8486ac05 00 00 00 0a 00 00 00 07 00 00 00 12 00 00 00................
ff8486bc08 00 00 00 0a 00 00 00 81 00 00 00 91 00 00 00................
ff8486cca1 00 00 00 b5 00 00 00 c1 00 00 00 d1 00 00 00................
ff8486dce9 00 00 00 f1 00 00 00 01 01 00 00 11 01 00 00................
ff8486ec29 01 00 00 35 01 00 00 41 01 00 00 55 01 00 00)...5...A...U...
ff8486fcf0 5d 7e 5c f0 5d 7e 5c 00 00 00 00 10 2a 80 ea.]~\.]~\.....*..
ff84870c98 03 87 13 70 10 87 13 3e 49 61 15 50 f9 0b 70....p...>Ia.P..p
ff84871c60 00 87 13 20 bc 0e 70 d3 6d 9e c5 48 87 84 ff`... ..p.m..H...
ff84872c20 bc 0e 70 24 91 b6 df d4 93 84 ff 04 00 00 00   ..p$...........
ff84873c20 a1 65 15 80 b1 58 15 98 03 87 13 f0 b7 5b 15   .e...X.......[.
ff84874c07 00 00 00 06 00 00 00 00 00 40 3f 00 00 00 00..........@?....
ff84875c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
ff84876c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00................
```

#### ``deviceid=c90d4cae48099b77fa3995042a961d6fnetspeed=1024network=wifiplatform=androidrand=0.8669308120110475time=1658394061userid=900270713970272598version=1.11.19.69eac63e66d8c4a6f0303f00bc76d0217c``

#### 这一段就是 guid 生成的源文本了

#### 直接md5加密 就好了 (注意替换需要的内容) 后面 ``eac63e66d8c4a6f0303f00bc76d0217c`` 是固定的

李佑辰 发表于 2022-7-24 14:47

看起来不错的样子!

Maogoyi 发表于 2022-7-24 15:35

支持...........................................支持

mahengyuan 发表于 2022-7-24 15:37

原来如此优秀啊哈哈

han1058349250 发表于 2022-7-24 15:53

看看大佬们的思路

w547890 发表于 2022-7-24 16:38

看看大佬们的思路

yeduwuren 发表于 2022-7-24 16:40

万分葱白,可惜不懂,我要好好学习天天向上

魔神哥哥bivi 发表于 2022-7-24 16:54

看起来很好啊~感谢分享:loveliness:

v12608 发表于 2022-7-24 16:55

看起来不错

pfy 发表于 2022-7-24 17:40

如果是套壳的怎么破?
页: [1] 2 3 4 5 6 7 8
查看完整版本: 某吱 app 逆向