3、静态分析入门:APK解包、反编译工具(jadx、apktool)、AndroidManifest.xml分析。

好,咱们进入正题。静态分析,说白了就是不动手跑代码,直接看源码和配置文件来找漏洞。我刚开始做安全那会儿,觉得动态调试才酷,后来发现——静态分析才是基本功,而且效率极高。你想想看,一个APK扔进来,几分钟就能摸清它的“底裤”颜色,多痛快。

3.1 为什么要做静态分析?

静态分析的目的很简单:在不执行代码的情况下,发现应用的安全缺陷。它就像医生看X光片,不用开刀就能知道骨头有没有裂。

我个人习惯,拿到一个APK后,先做三件事:

  • 解包:把APK当成一个压缩包,拆开看看里面有什么文件。
  • 反编译:把DEX字节码转成可读的Java代码或Smali代码。
  • 分析清单:重点看AndroidManifest.xml,这里藏着大量信息。

这三步走完,这个应用的基本面就清楚了。我在项目中遇到过好几次,光靠分析Manifest文件就发现了组件暴露、权限滥用等问题,根本不需要跑代码。

核心观点:静态分析是安全测试的起点,也是性价比最高的环节。别跳过。

3.2 APK解包:拆开看看里面有什么

APK其实就是一个ZIP压缩包,改个后缀名就能解压。但专业的做法是用工具。

3.2.1 手动解包(了解原理)

你可以直接把APK后缀改成.zip,然后用解压软件打开。里面大概有这些东西:

  • classes.dex:核心代码,Dalvik字节码。
  • AndroidManifest.xml:应用配置文件,二进制格式。
  • resources.arsc:编译后的资源文件。
  • lib/:原生库(.so文件)。
  • META-INF/:签名信息。

嗯,这里要注意:直接解压出来的AndroidManifest.xml是二进制格式,人眼是看不懂的。所以我们需要专业的解包工具。

3.2.2 使用apktool解包(推荐)

apktool 是我最常用的工具之一。它能把APK解包成可读的Smali代码和资源文件,还能把二进制Manifest转成文本格式。

基本用法:

# 解包
apktool d target.apk -o output_dir

# 回编(重新打包)
apktool b output_dir -o new.apk

解包后,你会得到一个文件夹,里面包含:

  • smali/:反编译后的Smali代码。
  • AndroidManifest.xml:已经转成可读的XML格式。
  • res/:资源文件。
  • original/:原始文件备份。
小技巧:apktool解包时默认会保留签名信息。如果你想修改代码后重新打包,记得用 -r 参数跳过资源反编译,或者用 --no-res 加快速度。

3.3 反编译工具:jadx vs apktool

解包只是第一步,真正的重头戏是反编译——把字节码还原成Java代码。这里有两个主流工具:jadxapktool。它们各有千秋,我一般搭配使用。

工具 输出格式 优点 缺点
jadx Java源码(.java) 可读性高,接近原始代码;支持GUI和命令行 对混淆代码还原度一般;大项目可能卡顿
apktool Smali汇编(.smali) 还原度高,支持修改后回编;适合做二次开发 Smali代码可读性差,需要学习成本

3.3.1 jadx:快速看源码

jadx 是我个人最推荐的反编译工具。它能把DEX文件直接转成可读的Java代码,而且支持GUI界面,点一点就能看。

命令行用法:

# 直接反编译APK
jadx target.apk -d output_dir

# 只反编译classes.dex
jadx classes.dex -d output_dir

# 带GUI启动
jadx-gui target.apk

我在项目中遇到过很多次,用jadx打开APK后,直接搜索关键词(比如“password”、“secret”、“key”)就能找到硬编码的敏感信息。有一次,我甚至在一个金融类应用里找到了数据库明文密码……嗯,那场面,挺尴尬的。

注意:jadx反编译的代码是“近似”的,不是100%还原。遇到混淆严重的代码,它可能会生成一些奇怪的变量名(比如 a.a.b())。这时候就需要结合Smali代码来看了。

3.3.2 apktool + Smali:深入底层

当jadx搞不定的时候,就该apktool上场了。Smali代码虽然难读,但它是最接近原始字节码的表示形式。你想想看,混淆器再怎么混淆,Smali代码里的指令顺序和寄存器使用是骗不了人的。

举个例子,jadx反编译出来的代码可能是:

String str = "hello";
if (str.equals("world")) {
    // do something
}

但Smali代码里,你能看到具体的寄存器分配和指令:

const-string v0, "hello"
const-string v1, "world"
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v2
if-eqz v2, :cond_0

为什么要看Smali?因为有些恶意代码会通过动态加载、反射调用等方式隐藏行为,jadx可能直接跳过了,但Smali里能看得一清二楚。

3.4 AndroidManifest.xml分析:信息量巨大

AndroidManifest.xml 是应用的“身份证”。它声明了应用的所有组件、权限、硬件要求等。我每次拿到APK,第一件事就是打开这个文件,从头到尾扫一遍。

3.4.1 关键节点速查表

节点 作用 安全关注点
<uses-permission> 声明应用需要的权限 权限是否合理?有没有过度申请?
<application> 应用全局配置 android:debuggable="true"android:allowBackup="true"
<activity> 声明Activity组件 是否导出?有没有配置
<service> 声明Service组件 是否导出?有没有权限保护?
<receiver> 声明BroadcastReceiver 是否导出?接收的Action是否敏感?
<provider> 声明ContentProvider 是否导出?android:readPermissionandroid:writePermission是否设置?

3.4.2 常见安全风险点

我总结了几条“一眼就能看出问题”的检查项:

  • debuggable 为 true:应用可调试。这意味着攻击者可以附加调试器,窃取数据或修改逻辑。我曾经在某个银行App里发现这个标志没关,直接就能用adb调试……
  • allowBackup 为 true:允许备份。攻击者可以通过adb backup导出应用数据,包括SharedPreferences、数据库等。
  • 组件导出但未设置权限:比如一个Activity设置了 android:exported="true",但没有 android:permission 保护,那任何应用都可以启动它。
  • 滥用 android:protectionLevel:自定义权限如果设为 normaldangerous,其他应用可以轻易申请。
避坑指南:我曾经在分析一个社交应用时,发现它的ContentProvider导出了,但没有设置任何读写权限。结果我直接用adb命令查询,把整个用户数据库都拉下来了……嗯,从那以后,我每次看到 <provider> 都会多看一眼。

3.5 知识体系图:静态分析核心流程

下面这张图概括了静态分析的完整流程,从拿到APK到发现漏洞,每一步都离不开这些工具和技巧。

静态分析核心流程 APK文件 解包 (apktool) AndroidManifest.xml分析 反编译 (jadx / Smali) 发现安全漏洞 工具:apktool, jadx, jadx-gui, 文本编辑器

3.6 实战小贴士

最后,分享几个我自己的实战习惯:

  • 先看Manifest,再看代码:Manifest能告诉你这个应用有哪些组件、用了什么权限,心里有个谱。
  • 搜索敏感关键词:在jadx里直接搜 passwordsecretkeytokenapi_key,往往有惊喜。
  • 关注 WebView 相关代码:搜索 setJavaScriptEnabledaddJavascriptInterface,这些是WebView漏洞的高发区。
  • 别忽略 res/values/strings.xml:有些开发者会把API密钥、URL硬编码在字符串资源里。
我的习惯:我会把jadx反编译出来的代码导出成项目,然后用VS Code打开,配合全局搜索和正则表达式,效率比在GUI里点来点去高得多。

好了,静态分析入门就讲到这里。记住,工具只是手段,思路才是核心。你拿到一个APK,先想清楚“我要找什么”,然后再动手。下一节我们会深入动态分析,到时候再聊。


公众号:蓝海资料掘金营,微信deep3321