别被外壳骗了,那只是柔软的伪装 - 某小说App Token算法分析

一、目标

今天的目标是这个 token 参数的算法,这个样本比较适合初学者,难度1星。

二、步骤

脱壳

先把apk拉进jadx

很明显不对劲,这种只有2-3个类的,就是加壳之后的明显特征,至于加了什么壳, qihoo 已经很明白告诉我们了,就是数字壳。

之前的教程我们介绍过 FRIDA-DEXDump脱壳或者刷个脱壳rom, 当然最方便的还是找个脱壳云服务。(私信给我,我把云服务的地址发你)

字符串查找

这种 com.bytexxx / com.baidx / com.ss 之类的看上去就很妖艳的都是大厂的sdk,都是来迷惑你的道心的。

只有像这种带着app包名中类似单词的才是你的小清新。

token长得很想base64,所以我们点 com.novel.basic.token.Base64 进去看看,看上去是一个自己实现的base64类。

没看出有啥特别的,先不管,我们从左边展开类名,看看 com.novel.basic.token 包下面还有哪些类?

神奇的是,我们没有找到 com.novel.basic.token 包,也许是dump的时候丢了。更神奇的是,我们找到了一个 com.novel.basic.token.xz 包,里面有个看上去浓眉大眼的 TokenUtil类

java 复制代码
public class TokenUtil {
    ...

public static String g(Map<String, String> map) {
        ArrayList<String> arrayList = new ArrayList(map.keySet());
        Collections.sort(arrayList);
        StringBuffer stringBuffer = new StringBuffer();
        for (String str : arrayList) {
            String str2 = map.get(str);
            stringBuffer.append("&");
            stringBuffer.append(str + "=" + str2);
        }
        return stringBuffer.toString().substring(1, stringBuffer.length());
    }

    public static String h(String str, String str2) {
        String str3;
        try {
            str3 = e(f(str, str2) + "_" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
            str3 = "";
        }
        return d(str3);
    }

    public static void i(String[] strArr) throws Exception {
        HashMap hashMap = new HashMap();
        hashMap.put(PackageDocumentBase.OPFTags.packageTag, "com.mianfeinovel");
        hashMap.put("os", "android");
        hashMap.put("v", "1.0.1");
        hashMap.put("channel", "blf1298_12243_001");
        hashMap.put("udid", "aaaaaaaaaaaa");
        String g = g(hashMap);
        System.out.println("/v1/recommend/female?" + g + "&token=" + h("/v1/recommend/female", g));
    }

...
}

从 i 函数上分析, token的运算很有可能是 h函数干的, 那就啥也不说了,hook先

Hook验证

java 复制代码
function main() {   
    Java.perform(function () {
        var threadef = Java.use('java.lang.Thread');
        var threadinstance = threadef.$new();

        let TokenUtil = Java.use("com.novel.basic.token.xz.TokenUtil");
        TokenUtil["h"].implementation = function (str, str2) {
            console.log(`TokenUtil.h is called: str=${str}, str2=${str2}`);
            let result = this["h"](str, str2);
            console.log(`TokenUtil.h result=${result}`);
            return result;
        };
	
    });	
}

setTimeout(main, 5000);
// setImmediate(main);

由于是加壳应用,所以需要延迟个几秒再去hook对应的函数,给壳一点加载的时间。

跑一下,运气不错,就是我们要的结果

bash 复制代码
[M2010J19SC::cn.ttkmfxs.novel ]-> TokenUtil.h is called: str=/v1/ipcn, str2=channel=zxf2019_19206_001&ip=&os=Android&package=cn.ttkmfxs.novel&udid=01bb90d6de80f3cb01bb90d6de80f3cb&v=3.3.24.R
TokenUtil.h result=B993s65X5IwPTsXrgV%2F2rNvCYKcIjT4lyXrthojQ0LY%3D

三、总结

这个样本的算法比较清晰,可以直接扣出java代码,或者让ai转成其他的语言。

很多加壳应用最大的难点就是壳,敲开壳之后就是一马平川了。

做逆向运气很重要,真的。

坚硬只是表现

相关推荐
方白羽7 小时前
Android Gradle 缓存与文件目录深度解析
android·gradle·android studio
曲幽10 小时前
Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招!
android·termux·nohup·services·wake-lock
plainGeekDev11 小时前
单例模式 → object 声明
android·java·kotlin
程序员陆业聪11 小时前
读者点单·03|Compose 与传统 View 混用的 12 个真实坑
android
程序员陆业聪12 小时前
读者点单·02|Android 启动优化实战:Trace 抓取→Application 编排→冷启动全流程拆解
android
Coffeeee12 小时前
帮你快速理解AI Agent之我想招个Android实习生
android·人工智能·agent
恋猫de小郭13 小时前
苹果 AirPods 协议,Android 也可以使用完整版 AirPods 能力
android·前端·flutter
黄林晴13 小时前
告别无效重建:Gradle 9.6.0 解决 CI 构建缓存失效痛点告别无效重建:Gradle 9.6.0 解决 CI 建筑缓存失效痛点
android·gradle
张风捷特烈14 小时前
Flutter 类库大揭秘#01 | path_provider架构与设计
android·flutter
_阿南_1 天前
Android文件读写和分享总结
android