“Android APP二次打包”则是盗版正规Android APP,破解后植入恶意代码从新打包。无论从性能、用户体验、外观它都跟正规APP如出一辙可是背后它确悄悄运行着可怕的程序,它会在不知不觉中浪费手机电量、流量,恶意扣费、偷窥隐私等等行为。java
二次打包问题只是Android应用安全风险中的一部分, 通常是经过反编译工具向应用中插入广告代码与相关配置,再在第三方应用市场、论坛发布。react
对于打包党对于移动App带来的危害有如下几种:android
上述恶意行为严重危害移动产品和用户利益,同时也影响企业口碑。面试
关于移动App破解、数据泄露风险问题,以金融行业为例:众所周知数据是金融类应用产品重要资源之一,关乎企业生存与发展、但移动应用常常被破解、数据被抓包,致使本地存储数据以及用户名、密码等重要信息泄露。下面举例说明数据泄露案例。算法
金融类本地存储数据泄漏react-native
数据抓包,泄漏用户名和密码安全
面对二次打包很多公司都有本身的防范措施,知名公司的APP几乎都是本身在程序内部作过处理防止其APP被二次打包,一旦打包后从新运行则程序自动退出。接下来,我就来详解一下如何防止APP被二次打包。数据结构
### 如何解决移动App安全风险问题?app
基于多年的移动安全经验积累,网易云易盾在移动APP安全风险问题上,从起始的开发阶段、中间的测试阶段再到结尾发布阶段,针对移动APP全生命周期进行安全防御。工具
开发阶段——移动应用开发时接入安全组件,保护数据安全。其中,针对安全通讯方面,实现数据高强度加密,结合传统的对称、非对称加密算法和hash算法,客户端加密数据只有认证服务端才能解密,从而防止了数据泄漏、数据窃取和篡改。另外,为了实现增强数据的安全强度,安全组件结合自适应特征算法和随机切换算法,保证不一样时间、不一样终端的算法和密钥的差别性。
测试阶段——对移动应用进行人工渗透测试,发现漏洞解决产品修复相关问题,包括:APP渗透测试和服务端渗透测试。
发布阶段——APP上架以前针对应用作安全加固,提升安全防御等级,上架以后作盗版监测。网易云易盾可针对dex文件进行加固防御,防止被静态反编译获取代码逻辑;保护应用在被非法二次打包后不能正常运行;防止经过使用调试器工具对应用进行非法破解;提供自研高稳定的设备指纹,防止潜在的刷单风险;加密资源文件,防止apk资源文件被破解;对so文件进行加固保护,防止native代码被逆向分析;对游戏提供加固保护,让游戏免受破解、外挂等威胁。
要实现代码内部防止APP被二次打包首先得了解APK的机器识别原理,APK的惟一识别是依靠包名和签名来作鉴定的,相似豌豆夹的洗白白、360手机卫士等安全软件对APK的山寨识别,他们就是依赖包名来肯定APK而后经过签名来肯定其是否山寨。因此说本身的程序内部在启动的时候能够经过获取APK自己的签名而后和正确的签名作对比来识别本身是否被二次打包。
经过PackageManag对象能够获取APK自身的签名。
过对签名的码的分解获得一串20左右的字符串,此字符串则是APK的签名的MD5值,经过获取的签名MD5值与正确的MD5值进行对比,就能够识别其APK是否被盗版。
下图是一些已作过保护的APP的代码块分析:
上图是“XX省电王“的防止二次打包的关键代码
上图是”XX电池管家”的防止二次打包的关键代码
以上两处都是smali层的代码,以上2处代码的截图都是下载量很是高的APP所作的防止二次打包的处理,其处理的代码确定会使用到的关键代码是
Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature。
此方法可以起到必定的安全做用,通常的打包党面对它是迫不得已的,若是你了解一些smali语法它的做用就等于0了。
### Android 应用加固的技术细节
此外,针对如何加固的技术细节问题,网易云资深安全工程师钟亚平在安卓巴士全球开发者论坛的活动中也作过《安卓App逆向与保护》的主题演讲:
安卓App安全包含不少内容,包括混淆代码、总体Dex加固、拆分 Dex 加固、虚拟机加固等方面。事实上,这些内容也是国内近几年Android App安全保护的一种主要趋势。
Java代码是很是容易反编译的,做为一种跨平台的、解释型语言,Java 源代码被编译成中间“字节码”存储于class文件中。因为跨平台的须要,这些字节码带有许多的语义信息,很容易被反编译成Java源代码。为了很好地保护Java源代码,开发者每每会对编译好的class文件进行混淆处理。
混淆就是对发布出去的程序进行从新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即便反编译成功也很可贵出程序的真正语义。ProGuard就是一个混淆代码的开源项目,可以对字节码进行混淆、缩减体积、优化等处理。
Proguard处理流程图以下所示,包含压缩、优化、混淆、预检四个主要环节:
混淆代码逆向分析
若是想要反编译混淆代码,钟亚平分享了一个国外的工具DEGUADR,它可以经过统计的方式来解混淆。虽然这个工具的正确率达不到100%,可是能在必定程度上帮助反编译代码。
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
为了增强Android保护强度,随着安全技术的发展,又出现了新型的“加固技术”。Dex加固是对Dex文件进行加壳防御,防止被静态反编译工具破解而泄露源码,最刚开始出现的是总体加固技术方案。
总体加固技术的原理如上所示,包括替换application/classes.dex、解密/动态加载原classes.dex、调用原application相关方法、将原application对象/名称设置到系统内部相关变量四大环节。其中最为关键的一步就是解密/动态加载原classes.dex,经过加密编译好的最终ex源码文件,而后在一个新项目中用新项目的application启动来解密原项目代码并加载到内存中,再把当前进程替换为解密后的代码,可以很好地隐藏源码并防止直接性的反编译。
总体Dex加固逆向分析
总体Dex加固逆向分析有两种经常使用的方法。其一是在内存中暴力搜索 dexn035,再 dump。如下是在32位系统中的效果示例:
另外一种方法就是经过Hook dvmDexFileOpenPartial(void addr, int len, DvmDex*)。
随着业务规模发展到必定程度,不断地加入新功能、添加新的类库,代码在急剧膨胀的同时,相应的apk包的大小也急剧增长,那么简单的总体加固方案就不能很好地知足安全需求,在总体加固方案以外又出现了拆分加固的技术方案。
可是如上所示,Dex文件在加固时,针对中间缺失的一部分数据会以解密后的数据来替换,有的时候这种拆分替换也会致使数据不许确。那么到底应该拆分什么样的数据呢?就须要了解一下Dex文件的数据结构。
Dex文件结构极为复杂,如下图示选取了其中较为重要的内容。事实上,Dex文件是一个以class为核心组装起来的文件,其中最重要的是classdata和classcode两部分,有其特定的接口和指令数据,选取这两部分来拆分的话,即便拆分出来也不会泄露class数据和字节码数据,反编译出来也不完整,安全性较高。
拆分Dex加固逆向分析
对于Dex拆分加固的逆向分析,以下所示,能够用classdata替换从而组装成新的Dex文件,虽然和原来的Dex文件不会彻底一致,但也在必定程度上复原了被拆分数据的样子。
但要注意的是,这种方法仅适用于被拆分出去的数据变形一次性完成,也就是说,在有其余保护思路的状况下尽可能避免使用,并且即便有须要也尽可能选在用到这个类的时候才去恢复。
此外还有一个更底层一些的工具dexhunter,这个工具较为前卫,但同时也有一些局限性,譬如部分指令数据会被优化,造成的代码界面不是很美观等等。
虚拟机加固也属于Dex拆分加固的一种,它是对字节作了一些变化处理。以下所示,这是一个正常安卓系统中的代码,在其中进行了虚拟机加固操做:
以add-int v0, v1, v二、sub-int v0, v1, v二、mul-int v0, v1, v2这三条指令进行替换,而后进行加固编译,这样子操做后,即便把替换后的数据恢复了,也不会以add-int v0, v1, v二、sub-int v0, v1, v二、mul-int v0, v1, v2这三条指令进行替换,而后进行加固编译,这样子操做后,即便把替换后的数据恢复了,也不会变造成为以前的字节码,安全系数较高。
虚拟机加固逆向分析—HOOK JNI 接口
这种方式下的逆向分析,一方面能够经过HOOK JNI 接口来实现,它有两种实现方式。
其一是类成员/静态变量操做相关接口,好比:
(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代码不被逆向分析
Android应用作不到彻底的防止二次打包。
一、简单型
最简单的就像签名验证。验证编译以后的dex签名,md5等数据。
二、微有点技术含量型
由native在运行时释放class到内存。释放bytes数据直接喂给classloader。
三、难度型
对native自己再进行一些加固,加逆向坑(暗桩)增长破解难度。
四、较难度型
Java代码执行代码的时候调用native操做,实现破解必须破解native部分。
最后若是须要,部分必要算法转移到云端执行,最大限度的去保证防被破解和二次打包
做者:yijian2595
连接:https://www.jianshu.com/p/b6c...
在这里得到的不只仅是技术!