各位老铁,早上好!今天咱们来聊聊安卓混合应用(Hybrid App)里那些“裸奔”的 JavaScript 代码,看看怎么用 Jadx 和 Apktool 把它们揪出来,让它们无处遁形。
引子:Hybrid App 的爱恨情仇
Hybrid App,顾名思义,就是“混血”App。它既有 Native App 的一些优点,比如可以访问设备硬件,又有 Web App 的跨平台能力。简单来说,就是用 WebView 控件加载 HTML、CSS 和 JavaScript 代码。
这种架构的优点很多,比如开发效率高、维护成本低、跨平台能力强。但是,它也有一个致命的缺点:JavaScript 代码容易被提取出来,存在一定的安全风险。
想象一下,如果你的 Hybrid App 里有一些核心的业务逻辑,比如支付算法、数据加密算法等,都被人轻轻松松地提取出来了,那岂不是要凉凉?
所以,保护 Hybrid App 里的 JavaScript 代码,是一个非常重要的课题。但是,在保护之前,我们首先得知道怎么把它提取出来,才能更好地进行防御。
第一部分:Apktool 的庖丁解牛
Apktool 是一个反编译 Android APK 文件的神器。它可以把 APK 文件解压成易于阅读的 smali 代码和资源文件。
1. Apktool 的安装与使用
首先,你需要下载 Apktool。官方网站是:https://ibotpeaches.github.io/Apktool/
下载完成后,按照官方文档进行安装。安装完成后,就可以使用 Apktool 来解压 APK 文件了。
apktool d your_app.apk
这条命令会将 your_app.apk
解压到一个名为 your_app
的文件夹里。
2. 寻找 JavaScript 的蛛丝马迹
解压完成后,我们需要在解压后的文件夹里寻找 JavaScript 代码的蛛丝马迹。
通常情况下,Hybrid App 的 JavaScript 代码会放在 assets
文件夹或者 www
文件夹里。
所以,我们可以先看看这两个文件夹里有没有 .js
文件或者 .html
文件。
ls your_app/assets
ls your_app/www
如果找到了 .js
文件或者 .html
文件,就可以用文本编辑器打开它们,看看里面有没有 JavaScript 代码。
3. WebView 的身影
除了直接放在 assets
或者 www
文件夹里,JavaScript 代码也可能通过 WebView 加载。
这时候,我们需要查看 AndroidManifest.xml
文件,找到使用了 WebView 的 Activity。
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
找到 Activity 之后,我们需要查看 Activity 的 Java 代码,看看它是怎么加载 WebView 的。
通常情况下,Activity 的 Java 代码会放在 smali
文件夹里。
找到 Activity 的 smali 代码后,我们可以搜索 loadUrl
方法,看看它是怎么加载 JavaScript 代码的。
例如:
.line 25
iget-object v0, p0, Lcom/example/myapp/MainActivity;->webView:Landroid/webkit/WebView;
const-string v1, "file:///android_asset/www/index.html"
invoke-virtual {v0, v1}, Landroid/webkit/WebView;->loadUrl(Ljava/lang/String;)V
这段 smali 代码表示,MainActivity
中的 WebView 加载了 file:///android_asset/www/index.html
这个 URL。
通过这种方式,我们可以找到 WebView 加载的 JavaScript 代码。
第二部分:Jadx 的代码解剖
Jadx 是一个反编译 Android APK 文件的 Java 代码的反编译器。它可以将 APK 文件中的 DEX 文件反编译成 Java 代码。
1. Jadx 的安装与使用
首先,你需要下载 Jadx。官方网站是:https://github.com/skylot/jadx
下载完成后,按照官方文档进行安装。安装完成后,就可以使用 Jadx 来反编译 APK 文件了。
jadx your_app.apk
这条命令会将 your_app.apk
反编译成 Java 代码,并打开一个图形界面。
2. 寻找 JavaScript 的身影
在 Jadx 的图形界面里,我们可以像浏览 Java 代码一样,浏览 APK 文件中的 Java 代码。
我们需要找到使用了 WebView 的 Activity,然后查看 Activity 的 Java 代码,看看它是怎么加载 JavaScript 代码的。
例如:
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/www/index.html");
}
}
这段 Java 代码表示,MainActivity
中的 WebView 加载了 file:///android_asset/www/index.html
这个 URL。
通过这种方式,我们可以找到 WebView 加载的 JavaScript 代码。
3. Java 调用 JavaScript
除了 WebView 加载 JavaScript 代码,Java 代码也可以直接调用 JavaScript 代码。
例如:
webView.evaluateJavascript("javascript:callFromJava('Hello from Java!')", null);
这段 Java 代码表示,Java 代码调用了 JavaScript 代码中的 callFromJava
方法,并传递了一个字符串参数 Hello from Java!
。
我们需要搜索 evaluateJavascript
方法,看看 Java 代码是怎么调用 JavaScript 代码的。
第三部分:实战演练
接下来,我们用一个简单的 Hybrid App 来演示一下如何提取 JavaScript 代码。
1. 创建一个简单的 Hybrid App
首先,我们创建一个简单的 Hybrid App。这个 App 只有一个 Activity,Activity 里有一个 WebView,WebView 加载一个 HTML 文件。
activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<WebView
android:id="@+id/webView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
:
package com.example.myapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/www/index.html");
}
}
index.html
:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>Hello from HTML!</h1>
<script>
function callFromJava(message) {
alert(message);
}
</script>
</body>
</html>
将 index.html
文件放在 assets/www
目录下。
2. 使用 Apktool 解压 APK 文件
将 App 打包成 APK 文件后,使用 Apktool 解压 APK 文件。
apktool d app-debug.apk
3. 找到 JavaScript 代码
解压完成后,在 app-debug/assets/www
目录下可以找到 index.html
文件。打开 index.html
文件,就可以看到 JavaScript 代码了。
4. 使用 Jadx 反编译 APK 文件
使用 Jadx 反编译 APK 文件。
jadx app-debug.apk
5. 找到 Java 代码
反编译完成后,在 Jadx 的图形界面里,可以找到 MainActivity.java
文件。打开 MainActivity.java
文件,就可以看到 Java 代码了。
6. 总结
通过 Apktool 和 Jadx,我们可以轻松地提取 Hybrid App 里的 JavaScript 代码。
第四部分:JavaScript 代码保护策略
既然我们已经知道怎么提取 JavaScript 代码了,那么接下来就需要考虑如何保护 JavaScript 代码,防止被轻易提取。
以下是一些常用的 JavaScript 代码保护策略:
策略 | 优点 | 缺点 |
---|---|---|
代码混淆 | 增加代码阅读难度,使攻击者难以理解代码逻辑 | 只能增加破解难度,不能完全防止破解 |
代码压缩 | 减小代码体积,加快加载速度 | 降低代码可读性,但对于专业的攻击者来说,作用有限 |
代码加密 | 对代码进行加密,只有运行时才能解密 | 增加了运行时的开销,可能影响性能 |
代码完整性校验 | 校验代码是否被篡改,如果被篡改则停止运行 | 需要额外的校验机制,增加了复杂度 |
WebView 安全设置 | 禁用 WebView 的一些不安全特性,比如文件访问、JavaScript 接口等 | 可能会影响 App 的功能 |
Native 代码封装核心逻辑 | 将核心逻辑放在 Native 代码里,增加破解难度 | 增加了开发和维护成本 |
动态加载 | 将部分 JavaScript 代码放在服务器上,运行时动态加载,增加攻击者获取完整代码的难度 | 需要网络连接,增加了复杂度和潜在的风险 |
1. 代码混淆
代码混淆是一种常用的 JavaScript 代码保护策略。它可以将代码中的变量名、函数名等替换成无意义的字符串,增加代码阅读难度。
常用的 JavaScript 代码混淆工具有:
- UglifyJS
- JavaScript Obfuscator
- Closure Compiler
2. 代码压缩
代码压缩可以减小代码体积,加快加载速度。同时,它也可以降低代码可读性,增加破解难度。
常用的 JavaScript 代码压缩工具有:
- UglifyJS
- YUI Compressor
- Google Closure Compiler
3. 代码加密
代码加密是一种更强的 JavaScript 代码保护策略。它可以将代码进行加密,只有运行时才能解密。
常用的 JavaScript 代码加密工具有:
- JScrambler
- DexGuard (Android 平台)
4. 代码完整性校验
代码完整性校验可以校验代码是否被篡改,如果被篡改则停止运行。
可以使用 MD5、SHA 等算法对代码进行校验。
5. WebView 安全设置
禁用 WebView 的一些不安全特性,比如文件访问、JavaScript 接口等。
6. Native 代码封装核心逻辑
将核心逻辑放在 Native 代码里,增加破解难度。
7. 动态加载
将部分 JavaScript 代码放在服务器上,运行时动态加载,增加攻击者获取完整代码的难度。
总结:攻防永无止境
今天我们学习了如何使用 Apktool 和 Jadx 提取 Hybrid App 里的 JavaScript 代码,以及一些常用的 JavaScript 代码保护策略。
需要注意的是,攻防永无止境。任何一种保护策略都不能完全防止破解。我们需要不断学习新的攻击技术和防御技术,才能更好地保护我们的 App。
希望今天的分享对大家有所帮助!下次再见!