起因是 MikuFans 某个活动进行了版本升级,之前的不能用了,抓包分析后发现有个 task_sign 需要逆向 app ,所以有了这篇文章
静态分析(Static Analysis)是指在不运行代码的情况下,采用词法分析、语法分析等各种技术手段对程序文件进行扫描并生成程序的反汇编/反编译代码,然后阅读反汇编/反编译代码来掌握程序功能的一种技术。
静态分析是最简单的了,适合我们这种萌新。
本次分析的目标是 MikuFans,由于他没有加壳,适合没有经验的萌新(比如我)直接上手。
反编译代码使用 jadx 工具,jadx 官方下载地址:https://github.com/skylot/jadx/releases
寻找关键代码
直接搜索关键词 task_sign 试试,得到如下三条结果
三条结果都是类似的,只有三条可以一一点击查看,我这里看着第三条有个 activity(活动),所以先选择了他。
发现 task_sign 是名为 completeTask 方法的形參之一,简单观察发现,就在上面几行就有这个方法的调用。
可以看到 completeTask 是在 OGVActivityApiService.b.a 中调用的。
我们尝试搜索一下这个调用的代码,搜索 OGVActivityApiService.b.a 或者 OGVActivityApiService。注意忽略大小写,指不定调用时就变小写开头了(当然也不一定),学过面向对象的语言基本都知道吧。
确实搜索到了 b.a 的调用,而且参数个数和我们想要的是一致的。点进去看看
。
似乎已经接近答案了。
分析代码
這是方法調用的實參列表
OGVActivityApiService.b.a(r5, r6, r7, r8, r9, r10, r11, r12, r13)
這是調用的方法的形參列表
OGVActivityApiService.b.a(OGVActivityApiService oGVActivityApiService, String str, String str2, String str3, String str4, String str5, Continuation continuation, int i2, Object obj)
這是 completeTask 方法的形參列表
completeTask(@nullable @Query("position") String str, @Nullable @Query("task_id") String str2, @Nullable @Query("token") String str3, @Nullable @Query("timestamp") String str4, @Nullable @Query("task_sign") String str5, @NotNull Continuation continuation);
completeTask 的实参列表就省略,虽然他有一堆的类似于 i & 1 != ? null : str 的三目运算,但是怎么想都知道只有返回 str 才能得到结果啊
我們將上面几個列表相應的位置一一對應,得到以下關係
r5 oGVActivityApiService
r6 str position
r7 str2 task_id
r8 str3 token
r9 str4 timestamp
r10 str5 task_sign
r11 continuation
r12 i2
r13 obj
可以看出,r10 為 task_sign,這是本次逆向的目標,r8 為 token,這是已知的,r9 為 timestamp 這個也是已知的。
分析簡化得到以下僞代碼
r10 = md5(r14.$timestamp + '這是固定值,我這裏不放出來了' + r8).toString('hex');
由 java.lang.String r9 = r14.$timestamp 可知,第一処的 r6 實際上就是請求中的 timestamp,為已知。
第二処的 r6 是固定值,為已知。
第三處的 r8 為 token,為未知。
所以僞代碼應該是這樣的:
task_sign = md5(timestamp + '這是固定值,我這裏不放出來了' + token).toString(
'hex'
);
最终结果
最後轉化爲實際 Node.js 代碼
import crypto from 'crypto';
const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');
const sign = (timestamp, token) =>
md5(timestamp + '這是固定值,我這裏不放出來了' + token);
或者 python 寫法
import hashlib
def sign(timestamp, token):
return hashlib.md5((timestamp + '這是固定值,我這裏不放出來了' + token).encode('utf-8')).hexdigest()