android-加壳加固
Posted 蝶泳奈何桥.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android-加壳加固相关的知识,希望对你有一定的参考价值。
title: android-加壳加固
categories: Android
tags: [android, 加壳, 加固, 混淆]
date: 2022-06-20 18:00:23
comments: false
mathjax: true
toc: true
android-加壳
前篇
- Android之Apk加壳 - https://blog.csdn.net/LVXIANGAN/article/details/84956476
- Android动态加载Dex机制解析 - https://blog.csdn.net/wy353208214/article/details/50859422
- Apk加固原理学习与复现 (好文) - https://www.anquanke.com/post/id/247644
- android黑科技系列——Apk的加固(加壳)原理解析和实现 (好文) - https://www.cnblogs.com/chenxd/p/7820087.html
- Android最初的加固 (好文) - https://www.jianshu.com/p/8e578dc2c5db
- Android开发学习之路-加固实践 (好文, 貌似来源于上一个连接) - https://blog.csdn.net/eastmoon502136/article/details/103703950
- demo - https://github.com/eastmoon1117/StudyTestCase/tree/master/DexPack/ShellApk
- https://github.com/longtaoge/AndroidShell
- 浅谈 Android Dex 文件 - https://www.infoq.cn/article/u5ld584clblpyln8extu
- Android dex,odex,oat,vdex,art文件结构
- 分享一个自己做的函数抽取壳 - https://bbs.pediy.com/thread-271139.htm
- https://github.com/luoyesiqiu/dpt-shell
- 通过内存加载DEX文件技术,完成一键DEX加固脚本 - https://github.com/yongyecc/dexshellerInMemory
- 用AppComponentFactory实现变种爱加密壳保护的策略分析 - https://bbs.pediy.com/thread-268008-1.htm
- dpt-shell抽取壳项目源码及其逆向分析 - http://tttang.com/archive/1728/
- Android APP漏洞之战(11)——整体加壳原理和脱壳技巧详解 - https://bbs.pediy.com/thread-273293.htm#msg_header_h2_1
- Android App加固原理与技术历程 - https://juejin.cn/post/6844904176070164488
- APP加固种类甄别与侦查 (好文) - https://zhuanlan.zhihu.com/p/509957240
- Android垃圾代码生成插件 - https://github.com/qq549631030/AndroidJunkCode
as 原生混淆 Proguard 没啥卵用
- 几种Android混淆和逆向工具介绍 - https://blog.51cto.com/u_15060511/4080326
Proguard的混淆方法就是对其中的类名和方法名去除其对应的意思,因为,逆向工作者可以根据类名和方法名猜出函数的意思,可以大大降低逆向难度,但是Proguard并没有对指令进行改变,所以使用Proguard进行混淆的强度比较低。
整体流程
- Android最初的加固 - https://www.jianshu.com/p/8e578dc2c5db
ClassLoader
- ClassLoader理解及使用 - https://juejin.cn/post/6844903998013571086
so 文件查看符号表
-
查看命令
$ nm -D libx8a3pjbix.so
-
只显示 T (方法), 加个 awk
$ nm -D libx8a3pjbix.so | awk 'if($2=="T")print $3'
踩坑
java 壳 套 kotlin 源 闪退
报错找不到资源 id: java.lang.RuntimeException: Unable to start activity ComponentInfocom.jared.testshell/com.jared.apktest.MainActivity: android.content.res.Resources$NotFoundException: Drawable com.jared.apktest:dimen/abc_text_size_display_4_material with resource ID #0x7f050040
- 原因未明, 但是 kotlin/java 壳 套 java 源 就没问题, kotlin 壳 套 kotlin 源 也没问题
so 库开发
- AS的JNI和NDK开发—入门篇 - https://juejin.cn/post/6844903873866366984
so 库里脱壳
- [原创]入门级加固–3种加固方式学习记录 - https://bbs.pediy.com/thread-255220.htm
- Android APK 加固技术探究(二) - 如何解密 dex 文件 - https://juejin.cn/post/6985040096042942495/
ida 分析 so
- IDA静态分析so文件 - https://zhuanlan.zhihu.com/p/358218034
hook
- Hook 插件化框架 ( 使用 Hook 方式替换插件 Activity 的 mResources 成员变量 ) - https://blog.51cto.com/u_14202100/5080958
- Android 换肤那些事儿, Resource包装流 ?AssetManager替换流 - https://juejin.cn/post/6844903902060478477
- 【Android 插件化】Hook 插件化框架 ( 使用 Hook 方式替换插件 Activity 的 mResources 成员变量 ) - https://blog.csdn.net/shulianghan/article/details/119619952
- https://github.com/han1202012/Plugin_Hook
插件化
- 浅谈Android插件化 - https://juejin.cn/post/6973888932572315678
- Android插件化主流框架和实现原理 - https://blog.csdn.net/chuhe1989/article/details/104622513
- 常见android插件框架对比 - https://www.jianshu.com/p/a73b4b0288ea
- Android 插件化之ClassLoader加载Dex文件 - https://github.com/13767004362/HookDemo
- 【Android插件化】启动没有在Manifest中注册的Activity (好文) - https://blog.csdn.net/u013293125/article/details/105407056
- https://github.com/ydslib/PluginTest01
插件框架对比
- 滴滴的 VirtualAPK (4 年期开始就貌似不维护了) - https://github.com/didi/VirtualAPK
- 360 的 RePlugin - https://github.com/Qihoo360/RePlugin
- https://github.com/Qihoo360/RePlugin/wiki/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B
源码记录
- Activity启动流程源码分析 - https://hitendev.github.io/2018/03/29/Activity%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/
混淆
- 6个常用Java 源代码 保护工具(混淆、加密、底层) - https://www.cnblogs.com/mq0036/p/14922232.html
- 细数常用的5款Java代码混淆器! - https://zhuanlan.zhihu.com/p/105409587
- Allatori 混淆可以加密字符串 - https://blog.csdn.net/Viviha/article/details/104801930
实测加固流程
-
直接把 apk 当成 zip 解压到一个 目录 a 中
-
让后对 dex, so 加固处理
-
然后把 目录 a 用 zip 压缩为 apk 文件
压缩过程中, resources.arsc 文件不能压缩, 要以文档形式存储
ZIP_STORED
, 不然会出现这个错误 [安装到 安卓 11+ (API 级别 30) 机子未 4 字节对齐 或者 resources.arsc 被压缩了](#安装到 安卓 11+ (API 级别 30) 机子未 4 字节对齐 或者 resources.arsc 被压缩了) -
对压缩好的 apk 进行 4 字节对齐
$ zipalign.exe -p -f -v 4 I:/unalign.apk I:/align.apk
-
对 4 字节对齐好的 apk, 用 apksigner (不是 jarsigner) 进行签名.
$ java -jar apksigner.jar sign -verbose --v1-signing-enabled false --v2-signing-enabled true --ks "E:/test_jks.jks" --ks-key-alias test_alias --ks-pass pass:test_pass --key-pass pass:test_pass --out I:/signed.apk --in I:/align.apk
踩坑
apktool 编译 apk 时报 values-v31 错误
报错: res\\values-v31\\colors.xml:3: error: Error: Resource is not public.
这个错误时 sdk 使用了 31+ 造成的, apktool 还不支持 31+,
-
解决办法是把 sdk 设置为 30
compileSdkVersion 30 buildToolsVersion "30.0.2" defaultConfig minSdkVersion 19 targetSdkVersion 30
apktool 编译 apk 时引用库 sdk 超过 30
报错
Execution failed for task ':app_shell:checkDebugAarMetadata'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
> The minCompileSdk (31) specified in a
dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
is greater than this module's compileSdkVersion (android-30).
Dependency: androidx.appcompat:appcompat:1.4.1.
AAR metadata file: C:\\Users\\wilker\\.gradle\\caches\\transforms-3\\34a5f42d2f1863af6e2f0b71a2ab8437\\transformed\\appcompat-1.4.1\\META-INF\\com\\android\\build\\gradle\\aar-metadata.properties.
壳 apk 里引用库 androidx.appcompat:appcompat:1.4.1
是使用 sdk 31 编译的
- 解决办法是引用不超过 sdk 30 编译的库
implementation 'androidx.appcompat:appcompat:1.3.1'
apktool 编译 apk 时报错 requestLegacyExternalStorage
报错: AndroidManifest.xml:42: error: No resource identifier found for attribute 'requestLegacyExternalStorage' in package 'android'
- 解决办法: 移除掉 ‘requestLegacyExternalStorage’ 配置 即可
壳运行时 启动 activity 失败
报错
Process: com.rmgrummy.pro, PID: 15023
java.lang.RuntimeException: Unable to instantiate activity ComponentInfocom.rmgrummy.pro/com.yang.androidaar.ReferrerActivity: java.lang.ClassNotFoundException: Didn't find class "com.yang.androidaar.ReferrerActivity" on path: DexPathList[[zip file "/data/user/0/com.rmgrummy.pro/app_payload_odex/payload.apk"],nativeLibraryDirectories=[/data/user/0/com.rmgrummy.pro/app_payload_lib, /system/lib, /vendor/lib]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2570)
因为在 源 apk 中配置了启动项为 com.yang.androidaar.ReferrerActivity
, 而壳中有没有去 loadClass
- 解决办法有两种
- 启动时在 壳 代码里去 load 配置在 壳 apk 中 AndroidManifest.xml 里配置的启动 activity
- 修改 壳 apk 中 AndroidManifest.xml 里配置的启动 activity 为 壳 代码 load 的 activity
脱壳后运行 源 apk 时不支持 kotlin 反射
报错: kotlin.jvm.KotlinReflectionNotSupportedError: Kotlin reflection implementation is not found at runtime. Make sure you have kotlin-reflect.jar in the classpath
报错 java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter cookieJar
可能是 源 apk 里引用的 第三方 sdk 里面有使用 kotlin 编译的库, 所以报了这个错误
-
解决办法: 在 壳 工程里引用一下 kotlin 的反射库:
implementation "org.jetbrains.kotlin:kotlin-reflect:1.4.32"
参考: https://stackoverflow.com/questions/36440295/kotlin-jvm-kotlinreflectionnotsupportederror-kotlin-reflection-implementation-i
脱壳后运行 源 apk 时找不到对应 cpu 的 so 库
报 Android 错找不到对应 cpu so 的弹窗提示
虽然脱壳后有对应的 so 库在指定 cpu 目录, 但是报错
-
解决办法: 在 壳 工程里创建 对应 cpu 的目录, 并且创建一个空 libXXX.so 库即可 (暂时不清楚为啥), 如
lib\\armeabi-v7a\\libBugly.so
或lib\\arm64-v8a\\libBugly.so
!!!PS: 如果同时创建两个 cpu 目录
lib\\armeabi-v7a\\libBugly.so
或lib\\arm64-v8a\\libBugly.so
, 也会弹窗报错, 只能创建对应 cpu 的 so 文件如果是上架 google, 则可以创建两个, 因为谷歌会根据 cpu 分发不同的 so 的 apk 给用户安装.
脱壳后运行 源 apk 时找不到对应 cpu 的 dex
报错
java.lang.IncompatibleClassChangeError: Structural change of androidx.fragment.app.Fragment is hazardous (/data/user/0/com.rmgrummy.pro/app_payload_odex/payload.dex at compile time, /data/app/com.rmgrummy.pro-1/oat/x86/base.odex at runtime): Virtual method count off: 179 vs 184
Landroidx/fragment/app/Fragment; (Compile time):
Static fields:
在调用显示界面的代码时报了这个错误, 是因为 源 apk 打包时没有打运行机子 cpu 的 so
- 解决办法: 打 源 apk 时打包运行机子的 so 库即可
安装到 安卓 11+ (API 级别 30) 机子未 4 字节对齐 或者 resources.arsc 被压缩了
报错: adb: failed to install xxx.apk: Failure [-124: Failed parse during installPackageLI: Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary]
-
这里有有可能有两个问题
-
resources.arsc 被压缩了
-
解决办法: 在压缩 apk 目录文件时, 对 resources.arsc 特别处理, 不进行压缩
默认 zip 压缩类型是
ziplib.ZIP_DEFLATED
, 需要针对这个文件设置为ziplib.ZIP_STORED
, Python 参考代码# 压缩 srcDir 目录为 dstFile def zipDir(srcDir: str, dstFile: str, mode: int = ziplib.ZIP_DEFLATED, isIncludeParent: bool = True): with ziplib.ZipFile(dstFile, 'w', mode) as zip: pDir = isIncludeParent and os.path.dirname(srcDir) or srcDir for root, dirs, files in os.walk(srcDir): for file in files: absDir = os.path.join(root, file) relativeDir = absDir.replace(pDir, "") if "resources.arsc" in relativeDir: # 特殊处理这个文件 zip.write(absDir, relativeDir, ziplib.ZIP_STORED) else: zip.write(absDir, relativeDir)
-
参考: NEPTUNE ANDROID11 RESOURCES.ARSC不支持压缩问题解决 - https://www.freesion.com/article/75641402392/
-
-
apk 包未 4 字节对齐
- 签名前, 4 字节对齐一下, 然后再签名
$ zipalign -p -f -v 4 in_unalign.apk out_align.apk
参考: Android之通过 apksigner 对 apk 进行 手动签名 - https://blog.csdn.net/q610098308/article/details/105138228
-
安装到 安卓 11+ 机子报错至少要 scheme v2
报错: ERROR: Target SDK version 32 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme
-
解决办法: 使用
apksigner.jar
去签名, 不要用jarsigner.jar
$ java -jar apksigner.jar sign -verbose --v1-signing-enabled false --v2-signing-enabled true --ks [证书文件.jks] --ks-key-alias [证书别名] --ks-pass pass:[证书密码] --key-pass pass:[别名密码] --out [out_sign.apk] --in [in_unsign.apk]
解压 native 库失败
报错: INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2
-
解决办法: 打开AndroidManifest.xml 在 application 节点添加:
android:extractNativeLibs="true"
参考: https://blog.csdn.net/kidults/article/details/106570878
以上是关于android-加壳加固的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向脱壳解决方案 ( DEX 整体加壳 | 函数抽取加壳 | VMP 加壳 | Dex2C 加壳 | Android 应用加固防护级别 )
Android 逆向加壳技术简介 ( 动态加载 | 第一代加壳技术 - DEX 整体加固 | 第二代加壳技术 - 函数抽取 | 第三代加壳技术 - VMP / Dex2C | 动态库加壳技术 )