一、目标
今天的目标是这个 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转成其他的语言。
很多加壳应用最大的难点就是壳,敲开壳之后就是一马平川了。
做逆向运气很重要,真的。
坚硬只是表现