近期在开发一款软件时,遇上了加密、解密数据方面的一些技术问题无法攻克,于是抱着试试看的态度使用 jadx-gui
工具进行反编译一下。哎,居然还成功了,更骚的是,这一款App没有对应用进行混淆、加密、加固,没多久我就研究明白了他们的应用是如何解决我所遇到的问题,升职加薪又离我更近一步了🤭
但是呢,为了防止我所编写的软件遇上像我这样的老六,特地写一篇文章来告诉大家如何能成为我这样的老六,以及如何加强App的软件防护等级。
目录
- 反编译
- jadx-gui
- 预防反编译
- 代码混淆
- 应用加固
- 其它
- SDK 加固 & 插件加固
- 加密重要数据
- 使用C/C++代码
- 防止调试
反编译
可以用于反编译 App 的工具有很多,敲命令行实现反编译的已经成为过去式了,这里分享一个有 GUI ,同时也是博主目前在使用的反编译工具:jadx
jadx-gui
jadx-gui
是用于从Android Dex
和Apk
文件生成 Java 源代码的命令行和 GUI 工具。
我们可以借助该工具,实现反编译 App。
这里我使用 StepDemo 作为演示的项目,下载 jadx
安装到电脑上,使用 jadx
打开一个 .app
或 .apk
文件 ,就可以得到如图的 app 信息。
使用 Android Studio 查看项目的源代码是这样:
将 StempDemo
打包成一个 .apk
或者 .aab
,使用 jadx
打开后自动反编译的代码:
咋样?你学会了没?
预防反编译
哈!反编译很简单吧!
上面讲了如何反编译他人的 app ,接下来就讲解,如何预防你们的 app 被某个老六给反编译抄走辛辛苦苦写的代码😊
代码混淆
代码混淆可以说是应用安全中最基础的知识了,但同时也是坑最多的方式之一。
关于代码混淆可参考往期文章 👉【Android】App攻防之代码混淆
打开 app 项目的 build.gradle.kts
文件,启用 isMinifyEnabled
即可开启混淆。
android {
buildTypes {
// 应用处于release模式时
release {
isMinifyEnabled = true // 开启混淆
isShrinkResources = true // 开启资源压缩
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
// 设置定义混淆规则的文件
"proguard-rules.pro"
)
}
// 应用处于debug模式时
debug {
isMinifyEnabled = true // 开启混淆
isShrinkResources = true // 开启资源压缩
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
// 设置定义混淆规则的文件
"proguard-rules.pro"
)
}
}
}
打包完成,我们再来反编译一下。通过以下反编译前、后对比,就可以看出,右边的代码相对于左边的代码变得更加复杂了,同时,开启混淆的 apk 文件比未开启混淆的 apk 占用空间更小。
小结
1.代码混淆只是增加了代码复杂度,对于有耐心的人来说,破解你的代码只是时间问题。
2.代码混淆若混淆规则编写不正确,会出现各种离谱的问题,且难以追踪问题产生原因。
3.代码混淆只是混淆了代码,并没有对 app 的资源文件进行加密,使得资源文件容易被他人窃取。
应用加固
应用加固的方式有很多,比如说 360 加固助手、百度应用加固、网易易盾等,360 加固助手每个月都是有免费加固次数使用,本文使用的是 360 加固助手。
点击下载 360 加固助手
使用 360 加固助手加固后的 app 再使用 jadx
打开,app 的源码、资源等信息已经提取不到了。
其它
SDK 加固 & 插件加固
SDK 加固、插件加固没有免费实现的方式,目前 360 加固助手、百度应用加固、网易易盾等,都需要花钱开通 VIP 才能使用该功能。
加密重要数据
对于一些重要的数据,如:API密钥,可以使用加密算法进行加密,然后在运行时进行解密。
使用C/C++代码
将一些关键的算法或者逻辑使用 C/C++ 实现,并通过 JNI 调用。因为 C/C++ 代码编译后为机器码,相比 Java 代码更难以反编译。
防止调试
当应用完成开发准备上线时,可以添加部分代码防止应用被调试。如下:
- 在
AndroidManifest.xml
文件中,添加android:debuggable="false"
以阻止用户调试。
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:debuggable="false">
...
</application>
- 在代码中添加判断是否处于
Debug
模式,若处于Debug
模式,则退出应用程序。
if (android.os.Debug.isDebuggerConnected()) {
// 当前处于调试模式,可以执行相应的操作,例如退出应用
android.os.Process.killProcess(android.os.Process.myPid());
}