概述
(资料图片)
安卓 APK 中的混淆
混淆是软件开发中常用的技术,用于使代码更难理解、分析和逆向工程。它将代码转化为一种复杂而纷繁的形式,同时保留其功能。混淆的主要目标是阻碍对代码的未经授权访问,保护软件的知识产权或者隐藏软件的真实行为。
在 Android APK 中,常用多种混淆技术来保护代码,使其更难理解或逆向工程。其中一种技术是代码混淆,它将源代码转换为等效但更复杂的形式,使其难以解读和分析。另一种常用的技术是字符串加密,在这种技术中,敏感字符串(如 API 密钥或 URL)被加密,以防止轻易提取。此外,还采用控制流混淆来干扰代码的逻辑流程,使其难以跟踪程序的执行路径和理解其功能。
混淆对 Android 安全的影响
混淆技术的使用增加了安全研究分析的难度,并使一些基于签名的检测方法失效。字符串加密使得追踪关键信息变得具有挑战性。这些措施使得恶意软件更难以识别和追踪。
一种基于文本分类的软件包混淆检测方法
出于这些原因,我们的公司—— Liansecurity 开发了一款名为 "Incinerator" 的产品,旨在提供高效、准确和自动化的逆向工程服务。通过对恶意软件的广泛分析和先前混淆检测技术的研究,在我们的 Android APK 逆向工程产品 " 焚化炉 " 中实现了一种基于文本分类的混淆检测方法。根据我们的测试,我们的方法实现了 98% 的准确率,这超出了我们的期望。在接下来的章节中,我们将详细描述我们的方法。
背景
在检测 Android 应用程序中的混淆技术方面,最先进的系统是 "AndrODet"。在这项工作中,作者构建了一个混淆检测系统,针对每种混淆类型提取不同的特征,然后训练一个在线机器学习模型。下面列出了目标混淆类型和 AndrODet 实现后的测试结果:
标识符重命名:0.92
字符串加密:0.79
控制流混淆:0.67
AndrODet 在 Android 环境中的局限性
在 Android 的背景下,AndrODet 面临某些限制,影响其作为静态代码分析工具的准确性和有效性。主要集中在两个方面:
基于 APK 的计算和特征弱化
AndrODet 计算其度量指标是基于整个 APK,包括核心业务代码和关联的库文件。在 Android 生态系统中,依赖库可能会非常庞大,有时甚至比核心业务代码本身还要大。而且大多数情况下,依赖库并不需要进行混淆。当仅依靠整个 APK 进行计算时,这些大型未混淆的库的存在削弱了混淆部分的重要性,最终影响了 AndrODet 进行正确判断的准确性。
无法处理 Unicode 编码
AndrODet 计算距离的方法局限于 ASCII 编码。然而,使用 Unicode 编码进行混淆技术的使用越来越普遍。因此,AndrODet 无法处理和分析使用 Unicode 编码进行混淆的代码。这个限制阻碍了该工具在真实生产场景中准确检测和评估混淆代码的安全性和质量方面的能力。
AndrODet 的限制对其在真实生产场景中的准确性构成了挑战。了解这些限制及其对真实生产环境的影响对于寻求改进 Android 应用程序安全领域代码分析工具能力的研究人员和从业者至关重要。
我们的方法
我们的方法主要解决了代码混淆技术中最常见的标识符重命名的识别问题,这是恶意软件常用的混淆技术。我们的方法也可以扩展到字符串加密。在我们的研究中,我们观察到,当研究人员评估一个代码片段是否被混淆时,他们最初的判断依赖于类名、方法名和变量名的可理解性,以及可识别和常用的编码约定,即所谓的 " 编码英语 ",与类似 "a"、"Zb"、"c4"、"1li"、"0Oo" 等不容易理解的名称进行对比。最初,我们尝试了算法方法来解决这个问题,但测试结果不怎么理想。然而,我们突然想到,这实际上是一个经典的自然语言(NLP)分类问题。
凭借这一灵感,我们将混淆检测问题转化为文本分类问题,而深度神经网络处理文本分类,已经非常成熟。我们的测试结果也证明了这种转换非常成功。" 字符串加密 " 本质上也是一个文本分类问题,因此我们相信这种方法可以轻松扩展到字符串加密。
方法说明
第 1 步:反编译和 Smali 提取
第 1 步涉及反编译 AndroidAPK 和提取 Smali 代码。在我们的实现中,我们使用我们自己的反编译引擎 "Reactor"。其他开源工具,如 AndroGuard 或 Apktools 也可以。从每个类中,我们提取类名和类变量名,这些是下一步分析的输入。理论上可以提取更多特征,如函数参数名称和局部变量,但提取更多的特征对准确率没有太大的提升,因为前面的三个特征已经达到了很高的准确性。
第 2 步:创建训练集
创建两个不同的训练集。第 1 个训练集是混淆的类生成的数据,标记为 1。第 2 个训练集是未混淆的类生成的数据,标记为 0。
第 3 步:文本分类神经网络训练我们构建了一个文本分类神经网络。该神经网络使用步骤 1 中提取的特征和步骤 2 中的相应标签进行训练。通过利用深度学习网络模型进行训练。
该模型分成 3 层:嵌入层、LSTM 层和密集层。
1)嵌入层:嵌入层将输入整数序列转换为密集矢量表示。
2)LSTM 层:LSTM(长短期记忆)层是一种能够处理序列数据和捕获长期依赖关系的循环神经网络(RNN)。在该模型中,使用了具有 128 个单元的 LSTM 层。
3)Dense 层:Dense 层是一个全连接层,对 LSTM 层的输出进行线性变换并应用 sigmoid 激活函数。
第 4 步:训练
我们从 1000 个数据样本开始,发现结果已经非常不错。随着我们将样本量增加到 10000,准确率和验证准确率都变得非常令人满意。最终,我们的模型使用 100000 个数据样本进行了训练。我们试图进一步扩充数据集,但准确率和验证准确率没有提高。为了避免由单个 APK 生成的数据引起的偏差,我们从数据库中随机提取了几百个 APK 来生成我们的数据。从生成的数百万个数据样本中,我们随机选择了 100000 个进行训练。
训练结果如下:训练准确率:99.75%
验证准确率:98.50%
实验结果与分析
在实际应用中,为了确定一个 APK 是否被混淆,我们使用了一种方法,该方法涉及检查 APK 内的每个类是否进行混淆。通过将混淆类的数量除以类的总数,我们可以计算 APK 中混淆代码的比例。尽管在理论,针对每个类,判断可能出现假阳或者假阴,但是在判断一个 APK 是否存在现象时,很难出错,因为一个被混淆的 APK,需要确保它的大部分代码很难理解,这正是混淆的目的和最终呈现,大部分难以理解的类,是不能逃过模型的检测的。因此,我们的模型在确定 APK 中是否存在混淆时达到了接近 100% 的准确率。
第一轮训练后,我们从 Fdroid 和 Abuse 各获取了 1000 个 APK,进行验证测试。FDroid 代表良性 apk, abuse 代表恶意 apks,测试后,我们发现有较高概率出现假阳,一些非常短的内部类,例如 "Class: MainActivity ExternalSyntheticLambda15; Method:
下面是我们抽取随机的 100 个测试样本,因为我们的模型校验准确率是 98.5%,所以测试结果中,混淆覆盖率 1%,2% 这样的情况,应该判断为没有混淆。剩下结果中的 4% ( md5:8328cd96c931d06d25f67d42a50fd20d ) 这个是误报,分析原因是因为这个 apk 的类非常少,三条假阳数据导致了这个错误。其他的 5% ( 923df6854199e999fdd274729b28a1ad ) ,7% ( 71e293f29e636112e0a00ebac8cf3eb8 ) 都是真实存在的混淆。所以这个模型,判断混淆的准确率接近 100%,而且 APK 中存在非常少量的混淆也是可以检测出来。
我们的训练集中并没有出现 unicode 的混淆样本,但是在测试的时候,这种情况也会被识别为混淆,因为模型对非混淆的文本有非常好的识别,所以即便出现样本中没有出现的其他混淆情况,也可以识别。
APK | APK Md5 | Obfuscation Coverage |
et.nWifiManager.apk | 11c43f6d781457352e5e61e725998ea8 | 0% |
jackpal.androidterm.apk | 8bbc3d9173e6d6b19e561a8651e83731 | |
com.boombuler.widgets.contacts.apk | 8328cd96c931d06d25f67d42a50fd20d | 4% |
cz.jirkovsky.lukas.chmupocasi.apk | 86f763c8cf4530e1c46c75d26374855a | 99% |
com.example.poleidoscope.apk | 08cf9be157669f3e0f7dd88975fdc22c | 1% |
dufmvh.frdnoj.oggtsh.apk | cf2f9963933457dcdd1f28fec054cd07 | 56% |
ua.com.radiokot.lnaddr2invoice.apk | c1ade85027c6178e43daac2e957ba9b1 | 96% |
org.openbmap.unifiedNlp.apk | 79ce98b9d38490625ad15f5948afe32f | |
com.dekics.chat.message.apk | dc84f225fdb1c21071ee70d43af39224 | 50% |
org.getdisconnected.libreipsum.apk | a394d3131303bd24bdcddc7e0a507f0d | |
com.pnr.engproverbsandsayings.apk | 1d28e138a9ecf1c9b3240868879bbd54 | 10% |
org.ligi.blexplorer.apk | 49619da57858ffdd6bd55bb5b962efe3 | |
net.osmand.srtmPlugin.paid.apk | c7dd9b418933ceea723527487bd94268 | |
org.broeuschmeul.android.gps.bluetooth.provider.apk | cf1d9aa2d5eec5a8e0af76d9708a8da0 | |
com.intense.pub1.sbgs.apk | e272df5c9abd7d4c03982bb506922428 | 15% |
tgr.kitach.messenger.apk | cd4acd78cf29adf56837e944c0ea3791 | |
com.github.lamarios.clipious.apk | 0e728b50b101456d74329f97552ea2db | 94% |
com.ctbcad.cnove01.apk | 782216c3d9db96da2ef0285daddbdcdb | |
in.ac.iitb.cse.cartsbusboarding.apk | ee83d9a3c3fcffbd833f1b73d28d28cd | 2% |
de.reimardoeffinger.quickdic.apk | 8e5e7cc0e581fac6c5d83802dadc0095 | 98% |
com.fastcleaner.forphoneandroid.freenoads.apk | c31ca58e67d55bb20a06e0f986cf04c1 | 92% |
com.gh4a.apk | 22556b8c3b0f4196b0db777d64cac5ee | |
nznm.qfvxs.apk | a827ee829d6067eda9c19f1dee15b9af | |
com.freezingwind.animereleasenotifier.apk | c0786ccbcfe7cb57f82f36a66040d452 | |
ogjp.otmyswhz.apk | ef3c97b748088019dc986dce53ae0755 | |
com.scare.obscure.apk | b11e72c94d810958df65d8716d853bc3 | 46% |
org.smc.inputmethod.indic.apk | c9eeb111666c723e3a4f78e2e11ab10d | |
com.blame.annual.apk | 376fc34c1eb64a348311156b1f22763e | 45% |
org.xapek.andiodine.apk | 923df6854199e999fdd274729b28a1ad | 5% |
ir.PluTus.pluto.apk | dc9f73c8ec88a8b493a15a3cbcb36f15 | 33% |
org.sufficientlysecure.viewer.apk | dcb35395a9a3fa0aea0bd9c876c4fadc | |
ir.shz.shzkisi.apk | 7ec247424733c287c3322fc49f1a7766 | |
com.mimic.left.apk | 4076db4387eb8ddf8f2010e3db8c8b07 | 59% |
com.igllc.reign.apk | bb78d33aac9b1c0c741b9e66d1ad9710 | |
org.tuxpaint.apk | 5f1d4d542004efd946a40a26166aed00 | |
Adliran.ir.apk | 3c0cccf2790ba49a122d0235225dbceb | 26% |
com.believe.blouse.apk | 768ec2246d2c92330ba8fafe6513963e | |
Rahbar.Api.apk | 2f1570b5b5723d3f4ddd615905e8c08f | 27% |
net.everythingandroid.smspopup.apk | 1e5d955dabdd0ee548054c8cdc223653 | |
com.cointrend.apk | cb3726beeb870d96e2dd458da66af96b | 97% |
com.junjunguo.pocketmaps.apk | 0be11a3a032b35e2ce8021d32780cf32 | 21% |
com.kabood.koroshkabir.apk | 6129cc4392d2e10ffdb80db67ca2534b | 24% |
site.leos.setter.apk | 2f03d669939c74b508a3959838fbba4c | |
jp.co.qsdn.android.jinbei3d.apk | f25da1334e4db5d6c14c2361ba4defa8 | |
ir.game.co.apk | 9849247aef1aa1ae82c4dc06a638f29d | |
fr.xgouchet.texteditor.apk | a3f79b347a1c06140697326acb04581a | |
org.smssecure.smssecure.apk | a6dcb00ee7482256f8070b2d2eb23f62 | |
com.ebaschiera.triplecamel.apk | d36cd1850f8dfec7298c08e8eed3f997 | |
org.y20k.trackbook.apk | d4054bf60b2fbcfc152b32397cb861b0 | |
com.comfort.digital.apk | a32c36009a37893be90e4f385b26b5ee | 35% |
com.kylecorry.trail_sense.apk | 42501430e5b199df00f0068b3bd59db4 | |
com.helphomestickers.heartcarejingchat.apk | fec9d39eb80814e1eec29e52e0fede2d | |
de.markusfisch.android.pielauncher.apk | d0cf7f183b84ff040f237da0d7e89c58 | 90% |
org.xcsoar.apk | 35923a4197bcd2efd8d22a167af3f028 | |
com.takela.message.apk | 55774d1c8251ee3c12ce08af65000bd7 | 16% |
tech.bogomolov.incomingsmsgateway.apk | 85d0288b9b04c7d71bfd8185a916490b | |
com.rmowa.wpamz.apk | 23e49cc28a5feeed4b9e362aa43e158a | 65% |
piste.security.path.vf.apk | 95d33595783ede50bd428a18823ca0a9 | 20% |
de.rwth_aachen.phyphox.apk | 0a3fa3b09980e629c6a983a2c33d0400 | |
com.brief.blouse.apk | be9d61e3363c3399b55a44895fd1cf60 | 47% |
xjl.lrl.jzk.xkbnif.apk | f140ec3c051717491aac1a477c0f453a | 44% |
net.goroid.maya.apk | 9b1de8718bb348e74ecde66dfa7332a8 | 19% |
eu.polarclock.apk | c3c6f8ba040f1715d32ac7563d7d9b0c | |
tube.chikichiki.sako.apk | d79144a6e4aad73e78bc25af25e8f8d1 | |
org.dyndns.fules.ck.apk | 7c1e243288ff30b602976d2ce634b0f3 | |
com.nima.demomusix.apk | 93a79a8f1b2ad1eb2b670782e571107d | |
aps.js.piste.asd.apk | b1e0ad60b4113ecfdf74e930848dcab4 | |
com.tutpro.baresip.apk | 702d0800421413f73f0f3d65a577986e | |
iroj.jnafjk.apk | d0118fe80f1af4cf2fad4579fa7f8741 | |
de.monocles.mail.apk | 21ce417bd40a12c2333ab505a0095891 | |
com.example.myapplication.apk | 52a5b10ae074459fbbeb1a0e8c297eac | |
com.piolang.transltor.voice.apk | c4c0982149feaf5266d6b2a9c4634858 | 84% |
net.sourceforge.kid3.apk | 7bff47951d893d50b7bf1bb151225006 | |
com.burtonben.goodlauncher.apk | d7ffbdf8e491f0c3e53901cf830f10b2 | 9% |
com.howwatchfunsms.locktextmessage.apk | d59b366ab1870d17f9abdd4824461327 | |
free.vpn.unblock.proxy.turbovpn.apk | 1fd53adfc1ff5f6262567592dfc88fd4 | 70% |
com.yshlhh.com.apk | f0c84c3ffcc77a88ce344e7f632afb2d | 67% |
com.feis.bphealthy.blood.apk | 6e05b674fb8725a4f1faae9d39be1b94 | 14% |
org.servalproject.apk | 8b2df68517574eb0c7d1b42858403695 | |
plus.H59300BC9.apk | 889e1c52bdebe6e1ae952bcc38b5daf1 | 11% |
mon.suxzgi.apk | b48f43a3c6b7c4ef07b7f87b62f64d61 | |
com.seleuco.easshs.apk | 013a0f9ddc9db42f06ae2cd1b6228c8f | 31% |
com.vicman.toonmeapp.apk | f724e92bdf978fb3bbdac308d4ba800c | 73% |
com.hugo.apk | 6320c822ba4ce417ffb82746dbf6f6f8 | |
org.segin.bfinterpreter.apk | 69d3cd2ef0e619193f145c89b22ce920 | |
de.jonasbernard.tudarmstadtmoodlewrapper.apk | 29bf40b35ce52d6e44c61304fdd8561a | |
com.belt.space.apk | 71e293f29e636112e0a00ebac8cf3eb8 | 7% |
center.bestlinks.samuraivpn.apk | f6e5f704bf5910b4d0aff44df2a77a8b | 91% |
com.dev.xavier.tempusromanum.apk | 1d51ef04566cc66661358f7708c0a9d3 | |
com.zanghh.pdfreader.apk | e9133a533614dafee5780d50b29484c3 | |
org.avmedia.gshockGoogleSync.apk | f942cf3de1107400be084ddd596016d9 | |
com.github.igrmk.smsq.apk | 72dfae851b1c93838094fe3b059ac5b1 | |
com.ljechbei.apk | 87118a9b63adebe8ad642509ff76818b | |
org.courville.nova.apk | 7041af61162329c4e2022d82939a2d2d | |
com.cliambrown.easynoise.apk | 8755ffdd6fe155593af77536bc8d1da1 | |
net.mullvad.mullvadvpn.apk | 956659e2df6362a79e110fac0fda3534 | |
nl.eduvpn.app.apk | aa2099699b3c8b68aa33925899ad9e84 | |
com.cheogram.android.apk | 4987ea46c3679a191434c1546231bade | |
io.pslab.apk | 37f9a2a3e4c906bf2cc3c14895620b1e | |
ru.yanus171.feedexfork.apk | 742aebc4c88564678e78276dbf29e935 |
本文讨论的都是针对标识符重命名的混淆检测,相同的办法可以应用到字符串检测上。但是不能应用到控制流混淆检测。AndrODet 的结果在这方面的表现也不尽如人意。未来我们会针对控制流检测专门设计新的模型。
与 AndrODet 相比,我们的模型需要相对更多的时间来确定 APK 是否被混淆,因为它需要单独检测每个类。虽然可以批量检测,但 APK 可能包含数千甚至数万个类。然而,在生产环境中,这是可以接受的,因为分析 APK 涉及静态分析、动态分析等各个方面,需要更长的时间来执行。因此,在我们的产品中,混淆检测的等待时间是合理的。此外,这个时间也可以通过并行架构处理来缓解。
结论
我们提出了一种基于文本分类的方法来检测 APK 是否被混淆。这种方法以前在现有研究中没有应用过,可以扩展到其他软件中的混淆检测以及字符串加密检测。此外,我们建议 APK 中混淆的检测应该在类级别进行,因为这样可以达到基本 100% 的准确率。
我们已经在正式生产环境中实现了这种方法。
Appendix
[ 1 ] https://0m1d.com/software/AndrODet
[ 2 ] https://drive.google.com/file/d/1OYYegY7MP7nGgfMORz_M7L4c3QFEjJW0/view?usp=sharing
源地址:https://www.liansecurity.com/#/main/news/HPMR8ogBE2npFSfFmiR_/detail