Android逆向实战:Native层分析实战

今天我们来分析一个核心算法在 Native 层的 APP。

APP8

APP8 地址:https://app8.scrape.center/

APP8 说明:

核心加密算法在 Native 层实现,适合做so模拟调用或者逆向分析。

既然核心算法在 Native,那 Java 层就简单看看,重点看 Native 的代码。

image-20250216154839200image-20250216154854048

image-20250216154903029

代码还是老样子,找到请求数据的代码,发现这次是新增了一个叫 NativeUtils 的类,里面加载了一个叫 native 的 so 文件,函数签名是一个叫 encrypt 的函数,参数有两个,一个字符串,一个整型。

Native 层分析

现在 Java 层看完了,打开 ida 直接分析 so 文件。

image-20250216155128770

打开 so 文件后,一眼望去,左侧的函数列表几乎没有混淆,所有的函数一目了然,如果所有的 APP 都是这样的就好了哈哈。

既然没什么混淆,还要确定一件事情,so 导出的 encrypt 函数是动态注册的还是静态注册的,如何确定呢?直接在左侧的函数列表中搜索 Java 开头的函数,如果可以搜索到想要的函数,这个函数就是静态注册的,如果搜索不到,那么这个函数就是动态注册的。

image-20250216165522365

搜索一下 Java,发现可以搜索到一个函数,正好就是刚才的 encrypt 函数,静态注册的函数函数名都是有规律的,Java_com_goldze_mvvmhabit_utils_NativeUtils_encrypt,函数名是 Java + 包名 + 类名 + 方法名,使用下划线拼接成一个字符串。这个函数名正好符合要求,双击一下跳过去看看具体的实现。

image-20250216165821575

按 Tab 键或者 F5 键,可以将当前的汇编代码转成伪 C 代码,方便查看具体的逻辑。函数总共四个参数,其中前两个是 JNI 环境指针和未使用的 jclass 参数(静态方法),后面两个参数是实际 Java 代码中传入的参数,一个字符串和一个整型。

image-20250216172302162

查看伪 C 代码,一点混淆都没有,了解 C++ 的小伙伴应该能看懂,具体的流程我已经使用注释都标识出来了。加密流程和之前基本上一致,不过这里多了一个硬编码的盐值,别忘了在实际编写代码的时候加上。

大概的加密流程就是准备几个字符串,push 到 C++ 的一个容器类中,容器类可以理解为 JavaArrayList<String> ,然后计算 sha1 值,重新 push 到了另一个容器类,push 时间戳,转成 base64,完事。

将其转成 Python 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import base64
import hashlib
import time

import requests

page = 1
limit = 10


def encrypt(off):
t = str(int(time.time()))
l = ['/api/movie','9fdLnciVh4FxQbri',str(off), t]
sha1 = hashlib.sha1(','.join(l).encode()).hexdigest()
return base64.b64encode(','.join([sha1, t]).encode()).decode()


url = 'https://app8.scrape.center/api/movie'

for a in range(10):
data = {
'offset': (page - 1) * limit,
'limit': limit,
'token': encrypt((page - 1) * limit)
}
print(data)
r = requests.get(url, params=data).json()
print(r)
page += 1
time.sleep(1)

image-20250216174108874

复用了部分之前的代码,改改添加两个参数就可以成功的抓到数据了。

最终代码见:https://github.com/libra146/learnscrapy/tree/main/Android/APP8

总结

APP8 的 so 几乎没有混淆,逆向的难度不高,适合练手用。正常来说在其他商业 APP 中不大可能见到这样的 APP 哈哈,so 中混淆函数名+动态注册是最基本的,再加点反调试,多搞几个 so,可能搞了半天连加密算法在哪个 so 都不知道。不过话说回来,学习还是要循序渐进,一步一步从简单的开始,逐渐过渡到有难度的 APP。

本文章首发于个人博客 LLLibra146’s blog

本文作者:LLLibra146

更多文章请关注公众号 (LLLibra146):LLLibra146

版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!

本文链接
https://blog.d77.xyz/archives/56c1c763.html