某app zzReqSign 算法还原分析过程


前言

工欲善其事必先利其器 准备工具

  1. Fiddler 或任意一款抓包工具
  2. 真机或者模拟器
  3. VSCode
  4. Frida
  5. Jadx\Jeb\GDA 任选一款
  6. IDA

一、抓包确定目标

分析加密第一步 先抓包确定参数 所以老规矩 打开FD先抓包
在这里插入图片描述其中 zzReqSign 便是我们需要还原的算法 我们查课发现没有加固 直接丢进jadx进行反编译

二、反编译定位加密位置

在这里插入图片描述
通过jadx反编译后搜索初步定位到这里 发现是个native 方法 那么加密在so层 上面 System.loadLibrary(“signLib”); 就是加载so的指令 其中 signLib就是so名字

三、反编译定位加密位置

解压apk 去lib目录寻找是否有这个文件
在这里插入图片描述
发现确实有这个so 拖入IDA 导出函数 搜索 getSign

定位如下位置:
在这里插入图片描述
代码如下:

int __fastcall Java_com_zhuanzhuan_sign_SignUtil_getSign(JNIEnv_ *a1, int a2, int a3, int a4)
{
  const char *app_sign_sha1; // r0
  struct _jobject *v9; // r8
  signed int v10; // r5
  int DevID; // r0
  struct _jobject *v12; // r8
  int v13; // r9
  jbyte *v14; // r6
  jsize v15; // r10
  _BYTE *v16; // r8
  signed int i; // r11
  jbyte v18; // r4
  int v19; // r1
  JNIEnv_ *v20; // r4
  int v21; // r9
  int MD5; // r10
  int v24; // [sp+8h] [bp-30h]
  struct _jobject *v25; // [sp+Ch] [bp-2Ch]
  struct _jobject *v26; // [sp+10h] [bp-28h]
  JNIEnv_ *v27; // [sp+14h] [bp-24h]
  jbyte *v28; // [sp+18h] [bp-20h]

  if ( !a3 )
    return 0;
  app_sign_sha1 = get_app_sign_sha1(a1, a4);
  if ( !app_sign_sha1 )
    return 0;
  if ( strcmp(app_sign_sha1, app_sing_str) )
    return 0;
  v9 = toBytes(a1, a3);
  v10 = a1->functions->GetArrayLength(a1, v9);
  v28 = a1->functions->GetByteArrayElements(a1, v9, 0);
  DevID = getDevID(a1, a2);
  if ( !DevID )
    return 0;
  v26 = v9;
  v24 = DevID;
  v12 = toBytes(a1, DevID);
  v13 = 0;
  v14 = a1->functions->GetByteArrayElements(a1, v12, 0);
  v27 = a1;
  v25 = v12;
  v15 = a1->functions->GetArrayLength(a1, v12);
  v16 = malloc(v10);
  for ( i = 0; i < v10; ++i )
  {
    v18 = v28[v13 % v10];
    v19 = (v13 + 1) % v15;
    v13 += 2;
    v16[i] = v14[v19] ^ v18;
  }
  v20 = v27;
  v21 = v27->functions->NewByteArray(&v27->functions, v10 + 9);
  (v20->functions->SetByteArrayRegion)(v20, v21, 0, v10, v16, a3);
  v20->functions->SetByteArrayRegion(&v20->functions, v21, v10, 9, "smiletozz");
  MD5 = getMD5(v27, v21);
  v20->functions->DeleteLocalRef(&v20->functions, v21);
  free(v16);
  v20->functions->DeleteLocalRef(&v20->functions, v24);
  v20->functions->ReleaseByteArrayElements(&v20->functions, v25, v14, 0);
  v20->functions->ReleaseByteArrayElements(&v20->functions, v26, v28, 0);
  v20->functions->DeleteLocalRef(&v20->functions, v25);
  v20->functions->DeleteLocalRef(&v20->functions, v26);
  return MD5;

这段函数最终返回了MD5 MD5是由 MD5 = getMD5(v27, v21);而来的 我们姑且认为他是一个md5算法 点进去看看

在这里插入图片描述
代码如下:

int __fastcall getDigestedBytes(_JNIEnv *a1, int a2)
{
  struct _jobject *v4; // r6
  jmethodID v5; // r5
  jstring v6; // r0
  _jobject *v7; // r9
  _jmethodID *v8; // r0
  int v9; // r8

  v4 = a1->functions->FindClass(a1, "java/security/MessageDigest");
  v5 = a1->functions->GetStaticMethodID(a1, v4, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
  v6 = a1->functions->NewStringUTF(a1, "MD5");
  v7 = _JNIEnv::CallStaticObjectMethod(a1, v4, v5, v6);
  v8 = a1->functions->GetMethodID(a1, v4, "digest", "([B)[B");
  v9 = _JNIEnv::CallObjectMethod(a1, v7, v8, a2);
  a1->functions->DeleteLocalRef(a1, v4);
  a1->functions->DeleteLocalRef(a1, v7);
  return v9;

在这里插入图片描述 插播一条广子 yzm平台 有需要的朋友们可以看看
点我直达
新用户注册加群即送10000点余额

四、frida hook验证

这段就比较简单了 反射java调用md5算法 到这里好像已经分析完毕 貌似就是个md5算法而已 是不是这样呢?我们试验一下

rida hook java层 getSign方法
代码如下:

let SignUtil = Java.use("com.zhuanzhuan.sign.SignUtil");
SignUtil["getSign"].overload('java.lang.String', 'android.content.Context').implementation = function (str, context) {
    console.log(`SignUtil.getSign is called: str=${str}, context=${context}`);
    let result = this["getSign"](str, context);
    console.log(`SignUtil.getSign result=${result}`);
    return result;
};

抓包结果为:zzReqSign: 47383db507e87badc5bc9ce348a6193e
我们去hook结果搜索
在这里插入图片描述
下面为结果 上面是明文 我们md5一下

在这里插入图片描述

五、进一步分析so

发现结果并不对 那么肯定是在md5之前还有其他操作 我们返回so继续分析

在这里插入图片描述
我们看到有个getDevID 方法

getDevID 代码如下:

int __fastcall getDevID(int a1, int a2)
{
  int v4; // r2

  v4 = (*(*a1 + 452))(a1, a2, "getDeviceId", "()Ljava/lang/String;");
  return j__JNIEnv::CallStaticObjectMethod(a1, a2, v4);
}

也是反射的java 这里对应的好像就是java 层

在这里插入图片描述
我们hook一下此方法 拿到值

let SignUtil = Java.use("com.zhuanzhuan.sign.SignUtil");
SignUtil["getDeviceId"].implementation = function () {
    console.log(`SignUtil.getDeviceId is called`);
    let result = this["getDeviceId"]();
    console.log(`SignUtil.getDeviceId result=${result}`);
    return result;
};

在这里插入图片描述
值=SignUtil.getDeviceId result=BE304BAE68E9C99571DEE26718102680

在这里插入图片描述

六、算法还原

这个md5加密前经过了一段简单处理 代码就不放出来了 有兴趣的自己去研究研究 很简单
在这里插入图片描述


结束语

  1. 云在青天水在瓶
  2. 你以前的选择成为了现在的你,无法改变,而你现在的选择将造就未来的你。

------------------------------------------------END--------------------------------------------

  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值