如何防止 Android 应用被二次打包?

论坛 期权论坛 期权     
匿名用户   2018-10-20 23:02   8567   8
提示: 作者被禁止或删除 内容自动屏蔽
分享到 :
0 人收藏

8 个回复

倒序浏览
2#
网易云  5级知名 | 2018-10-20 23:02:19
对于题主的问题,我们专门咨询了网易云易盾安全专家卓辉,以下为卓辉的解答:
二次打包问题只是Android应用安全风险中的一部分, 一般是通过反编译工具向应用中插入广告代码与相关配置,再在第三方应用市场、论坛发布。
对于打包党对于移动App带来的危害有以下几种:


1. 插入自己广告或者删除原来广告;
2. 恶意代码, 恶意扣费、木马等;
3. 修改原来支付逻辑。


上述恶意行为严重危害移动产品和用户利益,同时也影响企业口碑。


关于移动App破解、数据泄露风险问题,以金融行业为例:众所周知数据是金融类应用产品重要资源之一,关乎企业生存与发展、但移动应用经常被破解、数据被抓包,导致本地存储数据以及用户名、密码等重要信息泄露。下面举例说明数据泄露案例。



                                             金融类本地存储数据泄漏

                                        数据抓包,泄漏用户名和密码


[h1]如何解决移动App安全风险问题?[/h1]

基于多年的移动安全经验积累,网易云易盾在移动APP安全风险问题上,从起始的开发阶段、中间的测试阶段再到结尾发布阶段,针对移动APP全生命周期进行安全防护。





开发阶段——移动应用开发时接入安全组件,保护数据安全。其中,针对安全通信方面,实现数据高强度加密,结合传统的对称、非对称加密算法和hash算法,客户端加密数据只有认证服务端才能解密,从而防止了数据泄漏、数据窃取和篡改。另外,为了实现加强数据的安全强度,安全组件结合自适应特征算法和随机切换算法,保证不同时间、不同终端的算法和密钥的差异性。


测试阶段——对移动应用进行人工渗透测试,发现漏洞解决产品修复相关问题,包括:APP渗透测试和服务端渗透测试。


发布阶段——APP上架之前针对应用做安全加固,提高安全防护等级,上架之后做盗版监测。网易云易盾可针对dex文件进行加固防护,防止被静态反编译获取代码逻辑;保护应用在被非法二次打包后不能正常运行;防止通过使用调试器工具对应用进行非法破解;提供自研高稳定的设备指纹,防止潜在的刷单风险;加密资源文件,防止apk资源文件被破解;对so文件进行加固保护,防止native代码被逆向分析;对游戏提供加固保护,让游戏免受破解、外挂等威胁。





[h1]Android 应用加固的技术细节[/h1]

此外,针对如何加固的技术细节问题,网易云资深安全工程师钟亚平在安卓巴士全球开发者论坛的活动中也做过《安卓App逆向与保护》的主题演讲:


安卓App安全包含很多内容,包括混淆代码、整体Dex加固、拆分 Dex 加固、虚拟机加固等方面。事实上,这些内容也是国内近几年Android App安全保护的一种主要趋势。


一、混淆代码


Java代码是非常容易反编译的,作为一种跨平台的、解释型语言,Java 源代码被编译成中间“字节码”存储于class文件中。由于跨平台的需要,这些字节码带有许多的语义信息,很容易被反编译成Java源代码。为了很好地保护Java源代码,开发者往往会对编译好的class文件进行混淆处理。


混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。ProGuard就是一个混淆代码的开源项目,能够对字节码进行混淆、缩减体积、优化等处理。


Proguard处理流程图如下所示,包含压缩、优化、混淆、预检四个主要环节:





1. 压缩(Shrink):检测并移除代码中无用的类、字段、方法和特性(Attribute);


2. 优化(Optimize):对字节码进行优化,移除无用的指令。优化代码,非入口节点类会加上private/static/final,没有用到的参数会被删除,一些方法可能会变成内联代码;


3. 混淆(Obfuscate):使用a、b、c、d这样简短而无意义的名称,对类、字段和方法进行重命名;


4. 预检(Preveirfy):在Java平台上对处理后的代码进行预检,确保加载的class文件是可执行的。


混淆代码逆向分析


如果想要反编译混淆代码,钟亚平分享了一个国外的工具DEGUADR,它能够通过统计的方式来解混淆。虽然这个工具的正确率达不到100%,但是能在一定程度上帮助反编译代码。


使用DEGUADR解混淆的示例:





com.xxxxx.common.util.CryptoUtil网站也提供了一种反编译服务,如下所示:


java.lang.String a(byte[]) -> encodeToString


java.lang.String a(byte[],boolean,java.lang.String) ->a


byte[] a(byte[],byte[]) -> encrypt


byte[] b(byte[]) -> getKey


byte[] b(byte[],byte[]) -> decrypt


byte[] d(java.lang.String) -> getKey


java.lang.String a(byte,char[]) -> a


java.lang.String a(java.io.File) -> getHash


java.lang.String a(java.lang.String) -> c


java.lang.String b(java.lang.String) -> encode


二、整体Dex加固


为了加强Android保护强度,随着安全技术的发展,又出现了新型的“加固技术”。Dex加固是对Dex文件进行加壳防护,防止被静态反编译工具破解而泄露源码,最刚开始出现的是整体加固技术方案。





整体加固技术的原理如上所示,包括替换application/classes.dex、解密/动态加载原classes.dex、调用原application相关方法、将原application对象/名称设置到系统内部相关变量四大环节。其中最为关键的一步就是解密/动态加载原classes.dex,通过加密编译好的最终ex源码文件,然后在一个新项目中用新项目的application启动来解密原项目代码并加载到内存中,再把当前进程替换为解密后的代码,能够很好地隐藏源码并防止直接性的反编译。


整体Dex加固逆向分析


整体Dex加固逆向分析有两种常用的方法。其一是在内存中暴力搜索 dex\n035,再 dump。以下是在32位系统中的效果示例:



另一种方法就是通过Hook dvmDexFileOpenPartial(void* addr, int len, DvmDex**)。


三、拆分Dex加固


随着业务规模发展到一定程度,不断地加入新功能、添加新的类库,代码在急剧膨胀的同时,相应的apk包的大小也急剧增加,那么简单的整体加固方案就不能很好地满足安全需求,在整体加固方案之外又出现了拆分加固的技术方案。





但是如上所示,Dex文件在加固时,针对中间缺失的一部分数据会以解密后的数据来替换,有的时候这种拆分替换也会导致数据不准确。那么到底应该拆分什么样的数据呢?就需要了解一下Dex文件的数据结构。


Dex文件结构极为复杂,以下图示选取了其中较为重要的内容。事实上,Dex文件是一个以class为核心组装起来的文件,其中最重要的是classdata和classcode两部分,有其特定的接口和指令数据,选取这两部分来拆分的话,即使拆分出来也不会泄露class数据和字节码数据,反编译出来也不完整,安全性较高。







拆分Dex加固逆向分析


对于Dex拆分加固的逆向分析,如下所示,可以用classdata替换从而组装成新的Dex文件,虽然和原来的Dex文件不会完全一致,但也在一定程度上复原了被拆分数据的样子。





但要注意的是,这种方法仅适用于被拆分出去的数据变形一次性完成,也就是说,在有其他保护思路的情况下尽量避免使用,而且即使有需要也尽量选在用到这个类的时候才去恢复。


此外还有一个更底层一些的工具dexhunter,这个工具较为前卫,但同时也有一些局限性,譬如部分指令数据会被优化,形成的代码界面不是很美观等等。







四、虚拟机加固


虚拟机加固也属于Dex拆分加固的一种,它是对字节做了一些变化处理。如下所示,这是一个正常安卓系统中的代码,在其中进行了虚拟机加固操作:





以add-int v0, v1, v2、sub-int v0, v1, v2、mul-int v0, v1, v2这三条指令进行替换,然后进行加固编译,这样子操作后,即使把替换后的数据恢复了,也不会以add-int v0, v1, v2、sub-int v0, v1, v2、mul-int v0, v1, v2这三条指令进行替换,然后进行加固编译,这样子操作后,即使把替换后的数据恢复了,也不会变形成为之前的字节码,安全系数较高。


虚拟机加固逆向分析—HOOK JNI 接口


这种方式下的逆向分析,一方面可以通过HOOK JNI 接口来实现,它有两种实现方式。


其一是类成员/静态变量操作相关接口,比如:


  • GetStaticDoubleField SetStaticDoubleField GetDoubleField SetDoubleField …


  • (byte, object, int, long…)


其二是反射调用类方法,比如:


  • CallVoidMethodA CallBooleanMethodA CallShortMethodA CallObjectMethodA …
  • CallStaticVoidMethodA CallStaticBooleanMethodA CallStaticShortMethodA CallStaticObjectMethodA …
  • (byte, int, long,double …)
  • CallObjectMethodA(JNIEnv* env, jobject object, jmethoID method, …)

通过HOOK JNI 接口实现虚拟机加固逆向分析通过HOOK JNI 接口不用逆向底层,就可以了解App大致的调用流程。但是对于复杂的调用过程,或者虚拟化方法数量较多的情况,这种逆向分析手段看起来会比较混乱;对于不需要返射到Java层执行的指令,如算术、逻辑运算等,则无法监控到。


虚拟机加固逆向分析—分析指令操作码映射


另一方面,也可以通过分析指令操作码映射来逆向分析。在同一加固版本,或者映射关系相同的情况下,可以采取以下所示的方法:



但在实际情况中,每次加固时的映射关系都是随机变化的,如下所示,这种情况下就无法直接建立映射关系。

不依赖于操作码的映射关系只与虚拟机结构有关,所以需要根据偏移关系建立映射关系,从而进行逆向分析。




安卓App逆向保护作为开发工作中的重要内容,一直是网易云易盾致力提供的应用服务。后续,我们将在SO加密保护方面进行更加深入地研究,对SO里面的逻辑进行分析,保护Native代码不被逆向分析。感兴趣的朋友可点击这里免费试用


更多详情请见:
知物由学 | 干货!一文了解安卓APP逆向分析与保护机制
网易云易盾卓辉:如何实现移动APP安全隐含规避?
3#
剑君  3级会员 | 2018-10-20 23:02:20
你可以不断升级版本
4#
搞事情  2级吧友 | 2018-10-20 23:02:22
1、为什么要防止二次打包
2、二次打包有哪些可能用到的技术
3、如何防止二次打包
关键代码用native c写,然后给so加壳,动态加载.
5#
丿奢望丨  2级吧友 | 2018-10-20 23:02:23
代码混淆加jni验证 包名  改包名就无法使用  不改包名  应用商店上不去
6#
李海  3级会员 | 2018-10-20 23:02:24
其实从移动应用安全角度来看的话,我们可以从如何提高破解成本,如何提高二次打包的难度的角度来考虑。首先我们来看二次打包会做哪些操作:
1)修改包名,但也有部分是不改包名的,直接把他想要的内容插进去
2)签名信息修改,由于修改了apk信息,需要重新签名,签名信息自然改了
3)修改原apk的部分功能或逻辑,因为要添加自己的代码嘛
4)修改资源,比如图标,字符串,app名等
其它还包括篡改服务器地址,去除广告等等。
那么从保护角度来看,要如何防止呢:
1)包名校验,一般校验前面几个字段,因为很多应用最后一个字段一般是渠道的
2)签名校验,这个应该是最有效最直接的,发现签名非法,不让运行
3)代码被篡改这块很难直接防,可以使用apk加固进行保护
4)资源文件校验也可以做,比如app名是否是目标名,图标什么的进行校验
这些校验建议可以放在so层来做,当然这个so本身又是app核心功能不能缺失的,然后再对so进行加固、混淆保护。
经过几上层层安全校验和保护,apk的安全性肯定是大大提高,起码可以经得起攻击了,而不是原来的不堪一击。
7#
席琴女  4级常客 | 2018-10-20 23:02:26
应用加固
8#
Plex  3级会员 | 2018-10-20 23:02:27
你试试二次打包QQ。
然后顺着这个思路走
9#
蒋帆  1级新秀 | 2018-10-20 23:02:28
所有的混淆编译,都是没什么用处的邪道,确保应用发布只有通过“数字签名”一条路,培养用户验证签名的习惯更重要
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:24326
精华:1
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP