吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 5238|回复: 58
上一主题 下一主题
收起左侧

[Android 原创] 【详细分析】新版笔趣阁签名校验分析

  [复制链接]
跳转到指定楼层
楼主
lianquke 发表于 2022-5-28 19:32 回帖奖励
  • 【零】起因

不少人都搞过笔趣阁app,之前的版本(2021年以来)都是一层腾讯御安全,常规脱修后pmshook(mt去签普通版)即可过掉签名验证。
不过新版本(2022年5月),增强了签名校验,使得普通版不再有效。

一天,某耗发了个新版本让我试试。于是,就有了以下的分析。







  • 【一】所用工具
  • mt管理器
  • 任意崩溃日志记录器
  • IDA Pro
  • Android studio
  • 笔趣阁新版本


  • 【二】初探
壳常规脱修。签名,运行。
闪退,看崩溃日志。


日志如下:

[Asm] 纯文本查看 复制代码
    FATAL EXCEPTION: main
    Process: com.biquge.ebook.app, PID: 3741
    java.lang.NoSuchMethodError: no non-static method "Lcom/jni/crypt/project/CryptDesManager;.<init>(Ljava/lang/String;)V"
            at com.jni.crypt.project.CryptDesManager.cVerify(Native Method)
            at com.jni.crypt.project.CryptDesManager.init(CryptDesManager.java:1)
            at com.biquge.ebook.app.app.AppContext.onCreate(AppContext.java:5)
            at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1193)
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
            at android.app.ActivityThread.access$1500(ActivityThread.java:257)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1982)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:236)
            at android.app.ActivityThread.main(ActivityThread.java:8056)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)



看样子是说,com.jni.crypt.project.CryptDesManager.cVerify里调用了一个不存在的非静态方法Lcom/jni/crypt/project/CryptDesManager;.<init>(Ljava/lang/String;)V
该方法在libCryptDesManager.so中

打开IDA,看看这个so。

输出表里的四个Java_xxx并没有CryptDesManager.cVerify方法。
说明该方法为动态注册(我不确定,请大佬纠正)。

代开string窗口


一眼看到了好几个老朋友。

getApplicationInfo
getPackageInfo
signatures
这都是调用的安卓API获取的安装包信息,包括签名。





众所周知,signatures获取的签名,是能被pms过掉的。但是为何依旧闪退?
so里的代码没有混淆,十分清晰。

我们不得不怀疑,Java层有其他校验。


  • 【三】Java层定位

此时,安装包已用pms(mt去签普通版)处理过。
这里用的是mt自带的日志注入功能。

如图


我选择了全局注入,打印string类型的返回值

安装,授予存储权限,运行,看日志。

在发生闪退的前几行,获取了apk安装路径?

我们有充分的理由怀疑这里是校验apk是否未修改。

合理推测:
  • so层signatures校验
  • Java层安装包校验


后续验证,此推测正确。


进入获取apk路径的代码看一看。


进入a方法

smali指令不够清晰,转Java看看


看到这里就明白了,通过applicationinfo的sourceDir获取apk路径。

  • 【4】解决方案
  • 各大过签工具,不用多强,支持Java重定向即可;
  • pms(mt)过so层校验,书写一点代码,实现局部重定向;
  • 获取apk后如何校验?能不能改一些东西,伪装原包?
  • 将libCryptDesManager.so中的有效代码还原成Java,校验代码删除。还原后libCryptDesManager.so就可以删了;
  • 爆破改so,过掉so层,Java层同2或3。


  • 【5】示例
以上五种方法我全试了,都能搞定。最难的是方法4,还原Java代码,不再演示,各位可以自己尝试。

我演示一下方法2和方法3

方法2:
首先,mt过签普通版。
接着,在获取apk路径的地方,换成原包路径。
我选择的是将原包放到lib/arm64-v8a目录下,重命名为libshell.so,然后,将路径指向此文件即可。

Java代码:
[Java] 纯文本查看 复制代码
public static String getApk(Context context) {
        StringBuilder stringBuilder = new StringBuilder();
        String lib = context.getApplicationInfo().nativeLibraryDir;
        String result = "/libshell.so";
        return stringBuilder.append(lib).append(result).toString();
    }




推荐用Java2smali插件

smali指令:
[Java] 纯文本查看 复制代码
.method public static getApk(Landroid/content/Context;)Ljava/lang/String;
    .registers 5
    .param p0, "context"    # Landroid/content/Context;

    .prologue
    .line 8
    new-instance v2, Ljava/lang/StringBuilder;

    invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V

    .line 9
    .local v2, "stringBuilder":Ljava/lang/StringBuilder;
    invoke-virtual {p0}, Landroid/content/Context;->getApplicationInfo()Landroid/content/pm/ApplicationInfo;

    move-result-object v3

    iget-object v0, v3, Landroid/content/pm/ApplicationInfo;->nativeLibraryDir:Ljava/lang/String;

    .line 10
    .local v0, "lib":Ljava/lang/String;
    const-string v1, "/libshell.so"

    .line 11
    .local v1, "result":Ljava/lang/String;
    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    invoke-virtual {v3, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v3

    return-object v3
.end method


将此方法替代原来的获取apk路径的代码即可。并且将“原包”重命名为libshell.so放进lib/arm64-v8a里

这就实现了手动局部重定向。
类:d.m.a.a.g
代码截图:





其实和Java原包重定向差不多了,那个只是反射弄了个总代。理。

方法3:

中间刷新了一次,数据都丢了,重写了一半。有点累了。
思路:查找 获取apk路径方法 的调用,看看获取后干了什么。



看到channel,结合以往经验,我们可以猜测是channel校验。
接着往下看,拿着两个参数(String和Map)去初始化了一个类对象作为返回值。

我们打印一下,这几个相关的类,看看参数值、返回值是什么。

这里我不再操作,用一个过签成功的包去打印。
总之,正确的应该是channel为“gw2022_5”,将channel对应的value赋值为“gw2022_5”即可。

类:d.m.a.a.c


类:d.b.a.a.k.a


提示一下方法4,可以用simplehook对那几个native函数的参数和返回值进行hook。
再结合ida分析,重写成java就容易一些了。


没有成品,思路更重要。

免费评分

参与人数 13威望 +2 吾爱币 +114 热心值 +13 收起 理由
kkpljat + 1 + 1 谢谢@Thanks!
gaosld + 1 + 1 热心回复!
xb521314 + 1 + 1 谢谢@Thanks!
victos + 1 + 1 谢谢@Thanks!
低调(d-iao) + 2 + 1 我很赞同!
dbgcode + 1 + 1 我很赞同!
小木剑 + 1 + 1 用心讨论,共获提升!
jackies + 1 + 1 用心讨论,共获提升!
dustlee + 1 + 1 谢谢@Thanks!
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
宾鹏博 + 1 + 1 谢谢@Thanks!
baiyunem + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
正己 + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
芽衣 发表于 2022-5-29 21:18
本帖最后由 芽衣 于 2022-5-29 21:22 编辑

我也去下了这个APP看了一下。
崩溃日志里面有onCreate的优先看onCreate,这APP止步于onCreate还是比较典型的防护设计。com.biquge.ebook.app.app.AppContext.onCreate(AppContext.java:5)他里面应该有什么调用,应该可以追到cVerify。



打开so以后这里是个布尔值,基本上就能知道做了什么导致com.jni.crypt.project.CryptDesManager.init异常,com.jni.crypt.project.CryptDesManager.init掉用cVerify了以后,肯定有什么判断导致代码出错,进而影响到onCreate。还原java没必要,因为他返回的就是个布尔值……

  v34 = (*env)->GetStaticMethodID(
          env,
          a2,
          "encodeContent",
          "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
  v35 = (*env)->CallStaticObjectMethod;
  v36 = (*env)->NewStringUTF(env, "OW84U8Eerdb99rtsTXWSILDO");
  v37 = (*env)->NewStringUTF(env, "SK8bncVu");
  v38 = v35(env, a2, v34, v50, v36, v37);
  v51 = (*env)->GetStringUTFChars(env, v38, 0);
  free(v30);
  v39 = (*env)->FindClass(env, "java/lang/String");
  v40 = (*env)->NewObjectArray(env, 65, v39, 0);
  v41 = 1;
  for ( i = 0; i != 65; ++i )
  {
    if ( v41 << 31 )
    {
      v43 = j_nativeTojstring(env, CHAR_KEYS[i]);
      (*env)->SetObjectArrayElement(env, v40, i, v43);
      v44 = (*env)->GetStringUTFChars(env, v43, 0);
      v45 = strcmp(v51, v44) == 0;
      v46 = v31;
      if ( v45 )
        v46 = 1;
    }



签名值正确值+OW84U8Eerdb99rtsTXWSILDO+SK8bncVu放入encodeContent进行处理,返回一个字符串。v45 = strcmp(v51, v44) == 0;是个字符串比较命令,返回的还是个布尔值……根据布尔值决定是否进行下一步的解码。如果直接返回布尔值不行就改so跳转。具体我没实操过,不过应该没什么难度。
 if ( v47 )
  {
    PY = "GM8LtuBQ";
    KEY = "rRDB457kgPxW1zMsVnscHDgG";
    DES_TYPE = "DESede";
    DES_MODE = "desede/CBC/PKCS5Padding";
    KEY_C = "OW84U8Eerdb99rtsTXWSILDO";
    PY_C = "SK8bncVu";
    DES_TYPE_C = "DESede";
    DES_MODE_C = "desede/CBC/PKCS5Padding";
  }
  else
  {
    DES_TYPE = &dword_3968;
    PY = &dword_396C;
    KEY = &off_3970;
    DES_MODE = &dword_3974;
    KEY_C = &off_3978;
    PY_C = &off_397C;
    DES_TYPE_C = &dword_3980;
    DES_MODE_C = &dword_3984;
    (*env)->ThrowNew(env, a2, "thrown from C code");
  }

沙发
正己 发表于 2022-5-29 12:30
本帖最后由 正己 于 2022-5-29 12:31 编辑

lianquke大佬带带!
3#
 楼主| lianquke 发表于 2022-5-29 12:34 |楼主
4#
宾鹏博 发表于 2022-5-29 17:03
谢谢楼主大佬分享
5#
32K 发表于 2022-5-29 17:36
笔趣阁么,我都用网页版的(滑稽)
头像被屏蔽
6#
hxs177466 发表于 2022-5-29 19:16
提示: 该帖被管理员或版主屏蔽
7#
 楼主| lianquke 发表于 2022-5-29 19:52 |楼主
32K 发表于 2022-5-29 17:36
笔趣阁么,我都用网页版的(滑稽)

鼎鼎大名了算是,网页版PC还好,移动端就不太友好了
8#
32K 发表于 2022-5-29 20:30
lianquke 发表于 2022-5-29 19:52
鼎鼎大名了算是,网页版PC还好,移动端就不太友好了

把网页PC版的地址存到手机里(咳咳)
9#
 楼主| lianquke 发表于 2022-5-29 20:43 |楼主
32K 发表于 2022-5-29 20:30
把网页PC版的地址存到手机里(咳咳)

我指的是屏幕比例什么的,dpi那些,手机上不适配
10#
32K 发表于 2022-5-29 20:52
lianquke 发表于 2022-5-29 20:43
我指的是屏幕比例什么的,dpi那些,手机上不适配

横屏、访问手机版
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2022-6-27 08:18

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表