扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
其实不要混淆的主旨就在于混淆会改变方法的名字,类的名字,但是对于外部的一些引用是通过名字找到对应的方法,类,这些可能是通过string找到方法,类,但是string里的字段是不会进行混淆,所以还是会保留原来的名字,这样混淆过后通过原来的名字去找混淆后的名字,是肯定找不到,所以就会报出nosuchfileException,(对于gson,反射,jsbridge,第三方库都是这个原因),至于说枚举类型,我还暂时没懂 为什么,还望共同学习,一起成长。
创新互联长期为上千客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为雷州企业提供专业的网站制作、做网站,雷州网站改版等技术服务。拥有十余年丰富建站经验和众多成功案例,为您定制开发。
文章是读了两篇博客写出来,也是自己总结,消化成自己的知识了,若有什么错误的地方,还望指出,相信读了这两篇文章之后你也会懂混淆,一个是如何混淆,一个是哪些该混淆,为什么不能混淆
-keepclasseswithmembernames class * { # 保持native方法不被混淆 native methods; }
-keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆 public static final Android.os.Parcelable$Creator *; }
发布一款应用除了设minifyEnabled为ture,你也应该设置zipAlignEnabled为true,像Google Play强制要求开发者上传的应用必须是经过zipAlign的,zipAlign可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。
原文:
其实不要混淆的主旨就在于混淆会改变方法的名字,类的名字,但是对于外部的一些引用是通过名字找到对应的方法,类,这些可能是通过string找到方法,类,但是string里的字段是不会进行混淆,所以还是会保留原来的名字,这样混淆过后通过原来的名字去找混淆后的名字,是肯定找不到,所以就会报出nosuchfileException,(对于gson,反射,jsbridge,第三方库都是这个原因),至于说枚举类型,我还暂时没懂 为什么,还望共同学习,一起成长。
文章是读了两篇博客写出来,也是自己总结,消化成自己的知识了,若有什么错误的地方,还望指出,相信读了这两篇文章之后你也会懂混淆,一个是如何混淆,一个是哪些该混淆,为什么不能混淆
混淆apk是一个很基础的工作,博客上也有一堆介绍,本文提供一下这类工作的解决思路。在安卓源码下面和android studio里面的做法差异不大,本文以android源码举例。
首先在对应mk文件里面添加proguard enabled的语句,系统有一个自带的build/core/proguard.flags,默认是使用这个文件,而且一般项目默认是关闭的,这也是有原因的。因为这里的proguard.flags是没有针对app的配置的,使用默认的混淆,app很有可能就不工作了。
添加了mk文件修改之后,在Android.mk同级根目录创建本app自有的proguard.flags。新增内容如下,这里需要注意,网上很多demo,基本分为三部分,一部是保留app基础功能部分的内容不混淆;2是保持app对外接口,例如get、set、isxx、AIDL、public、native层的接口或者类;3.是第三方jar包或接口。混淆的基本原理就是将上诉类或接口进行统一简单字母的替换,如果改变了这些对外接口的名字,很有可能被别人使用的时候就找不到对应哦接口
一些第三方的库如何不进行混淆,这个根据项目特点,可以自行搜索,比如百度的地图包什么的。
然后是如何验证和解决混淆过程遇到的问题,因为是对接口名进行替换,如果出现混淆问题的话,log里面一定会有类似
这个时候只需要对相关接口进行例外(-keep)即可,然后用android-studio,直接打开或者dex2jar进行反解可以看到相关的接口是否被简单替换。
android源码被混淆了还原方法为:
1、得到 classes.dex文件;直接用机器上的解压软件 打开 .apk 文件,解压出 classes.dex 文件。
2、还原.jar文件;这一步需要用到一个工具 dex2jar (谷歌的代码库里有)下载完了,解压,然后把第一步的 产物(即那个classes.dex文件)放到 dex2jar的解压目录(解压目录里 有 dex2jar.bat 文件,检查一下,没有的话说明目录不对)。
3、查看.jar文件;这一步就是传统的 反编译 了,需要工具辅助,这里用到的工具是jd-gui()下载系统对应的版本,解压,(xp系统)会看到一个 .exe文件,没错就是 单文件绿色版,双击,选择 第二步 生成的 .jar,即可。
2.3SDK的两个新特点:
1.刚安装上2.3时,查看sdk目录,发现在\tools下新增了一文件夹“proguard”,如下图,我就在想是不是Google终于官方对proguard考虑进去了。理论上,对java的混淆都是可以的,但关键在于如何编写proguard的混淆脚本。
2.使用SDK2.3后,新建的工程下和之前相比,都会多了一个文件“proguard.cfg”。一打开,相当惊喜,这就是混淆所需的proguard脚本啊。
如下图:
其代码如下:
view plaincopy to clipboardprint?
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations
!code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native ;
}
-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations
!code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native ;
}
-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public (android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
从脚本中可以看到,混淆中保留了继承自Activity、Service、Application、BroadcastReceiver、ContentProvider等基本组件。
并保留了所有的Native变量名及类名,所有类中部分以设定了固定参数格式的构造函数,枚举等等。(详细信息请参考\examples中的例子及注释。)
好了,进行得差不多了,下面就来看看如何真正的生成混淆APK吧。这儿又得提醒一下,SDK新的特性在文档里都是有的,所以文档很重要。
查看SDK2.3的文档,在路径“/docs/guide/developing/tools/proguard.html”的“Enabling
ProGuard ”中是这样描述的:
To enable ProGuard so that it runs as part of an Ant or Eclipse build, set
the proguard.config property in the /default.properties file. The path can be an
absolute path or a path relative to the project's root.
好的,那就这样做吧。
在工程的"default.properties"中添加这样一句话“proguard.config=proguard.cfg”,如下图:
这样就已经设置好ADT的混淆操作了。接下来就是正常的打包和签名了。。
下图是我混淆SDK Demo中自带的Notepad效果图:
注意要点:
1.混淆以后的包会比混淆前的包小一点,一定要注意这点.
如果混淆不成功,请在第2步,将proguard.config=proguard.cfg修改为proguard.config=E:\Mobile_Develop\Google_Android\publicGoldenBeach_new\proguard.cfg这种类似的用绝对路径,请注意绝对路径中的文件夹名不能含有空格,如果有空格请替换为"_".
2.android在用proguard混淆时,一般情况下使用系统自带的配置文件就可以保持大部分外部需要引用的类,比如Activity,view扩展等等,但是有些情况下一些引入的外部lib,如果被混淆也会出现各种各样的问题,如果不想混淆这些包,就要加上
-keep class packagename.** {*;}
这样就能完整保持原有class了
代码混淆(code obfuscation)是指将计算机程序的代码,转换成一种功能上等价,所谓功能上的等价是指其在变换前后功能相同或相近。其解释如下:程序P经过混淆变换为P‘,若P没有结束或错误结束,那么P’也不能结束或错误结束;而且P‘程序的结果应与程序P具有相同的输出。否则P’不是P的有效的混淆。
目前对于混淆的分类,普遍是以Collberg 的理论为基础,分为布局混淆(layout obfuscation)、数据混淆(data obfuscation)、控制混淆(control obfuscation)和预防混淆(preventive obfuscation)这四种类型。
1. 布局混淆
布局混淆是指删除或者混淆软件源代码或者中间代码中与执行无关的辅助文本信息,增加攻击者阅读和理解代码的难度。软件源代码中的注释文本、调试信息可以直接删除,用不到的方法和类等代码或数据结构也可以删除,这样即可以使攻击者难以理解代码的语义,也可以减小软件体积,提高软件装载和执行的效率。软件代码中的常量名、变量名、类名和方法名等标识符的命名规则和字面意义有利于攻击者对代码的理解,布局混淆通过混淆这些标识符增加攻击者对软件代码理解的难度。标识符混淆的方法有多种,例如哈希函数命名、标识符交换和重载归纳等。哈希函数命名是简单地将原来标识符的字符串替换成该字符串的哈希值,这样标识符的字符串就与软件代码不相关了;标识符交换是指先收集软件代码中所有的标识符字符串,然后再随机地分配给不同的标识符,该方法不易被攻击者察觉;重载归纳是指利用高级编程语言命名规则中的一些特点,例如在不同的命名空间中变量名可以相同,使软件中不同的标识符尽量使用相同的字符串,增加攻击者对软件源代码的理解难度。布局混淆是最简单的混淆方法,它不改变软件的代码和执行过程。
2. 数据混淆
数据混淆是修改程序中的数据域,而对代码段不作处理。常用的数据混淆方式有合并变量、分割变量、数组重组、字符串加密等。
合并变量是将几个变量合并为一个数据,原来的每个变量占据其中一个区域,类似于一个大的数据结构。分割变量则是将一个变量分割为两个变量,对分割前后提供一种映射关系,将对一个变量的操作转化为对分割后两个变量的操作。
数组重组有数组的分割、合并、折叠和平滑等几种方式。分割是将一个数组分成2个或多个相同维度的数组;合并则相反;折叠是增加数组的维数;平滑则是相反。
在ELF文件中,全局变量和常量字符串存放在数据段中,反汇编工具可以轻易查找到字符串与代码之间的引用关系。在软件破解中,通过一些字符串提示可以很方便的找到代码关键语句,从而破解软件。字符串加密则可以对这些明显的字符串进行加密存储,在需要时再进行解密。
3. 控制混淆
控制混淆也称流程混淆,它是改变程序的执行流程,从而打断逆向分析人员的跟踪思路,达到保护软件的目的。一般采用的技术有插入指令、伪装条件语句、断点等。伪装条件语句是当程序顺序执行从A到B,混淆后在A和B之间加入条件判断,使A执行完后输出TRUE或FALSE,但不论怎么输出,B一定会执行。
控制混淆采用比较多的还有模糊谓词、内嵌外联、打破顺序等方法。
模糊谓词是利用消息不对称的原理,在加入模糊谓词时其值对混淆者是已知的,而对反混淆者却很难推知。所以加入后将干扰反汇编者对值的分析。模糊谓词的使用一般是插入一些死的或不相关的代码(bogus code),或者是插入在循环或分支语句中,打断程序执行流程。
内嵌(in-line)是将一小段程序嵌入到被调用的每一个程序点,外联(out-line)是将没有任何逻辑联系的一段代码抽象成一段可被多次调用的程序。
打破顺序是指打破程序的局部相关性。由于程序员往往倾向于把相关代码放在一起,通过打破顺序改变程序空间结构,将加大破解者的思维跳跃。
4. 预防混淆
预防混淆一般是针对专用的反编译器设计的,目的就是预防被这类反编译器反编译。他是利用特定的反编译器或反混淆器的弱点进行专门设计。预防混淆对于特定的反编译器非常有效,所以在使用时要综合利用各种反编译器的特点进行设计。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流