读懂Android中的代码混淆

合集下载

Android代码混淆的写法总结

Android代码混淆的写法总结

Android代码混淆的写法总结Apk⽂件被反编译出来能被获取到⾥⾯的代码。

对于这种情况,我们可以对项⽬代码进⾏混淆,随机⽣成难理解的类名,⽅法名,让代码难以阅读,加⼤功能被盗取的难度。

混淆可以起到压缩Apk,混淆⽂件,预检,优化的作⽤。

1. 使⽤⽅式,在gradle⽂件中设置minifyEnabled为true即可开启混淆buildTypes {release {minifyEnabled ture //是否开启代码混淆proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}混淆内容在proguard-android.txt⽂件中写。

2. 混淆设置参数-optimizationpasses 4 代码混淆的压缩⽐例,值介于0-7-dontusemixedcaseclassnames 混淆后类型都为⼩写-dontskipnonpubliclibraryclasses 不去忽略⾮公共的库类-dontoptimize 不优化输⼊的类⽂件-dontpreverify 不做预校验的操作-ignorewarnings 忽略警告-verbose 混淆时是否记录⽇志-keepattributes Annotation 保护注解-printmapping proguardMapping.txt ⽣成原类名和混淆后的类名的映射⽂件-optimizations !code/simplification/cast,!field/ ,!class/merging/ 指定混淆是采⽤的算法3. 保持不被混淆的设置保持实体类不混淆-keep class 你的实体类所在的包.** { *; }保持四⼤组件,Application,Fragment不混淆-keep public class * extends android.app.Application-keep public class * extends android.app.Activity-keep public class * extends android.app.Fragment-keep public class * extends android.support.v4.app.Fragment-keep public class * extends android.app.Fragment-keep public class * extends android.app.Service-keep public class * extends android.content.BroadcastReceiver-keep public class * extends android.content.ContentProvider-keep public class * extends android.preference.Preference保持 native ⽅法不被混淆-keepclasseswithmembernames class * {native <methods>;}保持枚举enum类不被混淆-keepclassmembers enum * {public static **[] values();public static ** valueOf(ng.String);}保持 Parcelable 不被混淆-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;}保持第三⽅包不混淆,⽐如这⾥⽤到微信、⽀付宝⽀付第三⽅#⽀付宝混淆-keep class com.alipay.android.app.IAlixPay{*;}-keep class com.alipay.android.app.IAlixPay$Stub{*;}-keep class com.alipay.android.app.IRemoteServiceCallback{*;}-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}-keep class com.alipay.sdk.app.PayTask{ public *;}-keep class com.alipay.sdk.app.AuthTask{ public *;}#微信⽀付混淆-keep class com.tencent.mm.opensdk.** {*;}-keep class com.tencent.wxop.** {*;}-keep class com.tencent.mm.sdk.** {*;}4. 完整混淆⽰例:#指定代码的压缩级别-optimizationpasses 5#包名不混合⼤⼩写-dontusemixedcaseclassnames#不去忽略⾮公共的库类-dontskipnonpubliclibraryclasses#优化不优化输⼊的类⽂件-dontoptimize#预校验-dontpreverify#混淆时是否记录⽇志-verbose#忽略警告-ignorewarning#保护注解-keepattributes *Annotation*-keep public class * extends android.app.Application-keep public class * extends android.app.Activity-keep public class * extends android.app.Fragment-keep public class * extends android.support.v4.app.Fragment-keep public class * extends android.app.Fragment-keep public class * extends android.app.Service-keep public class * extends android.content.BroadcastReceiver-keep public class * extends android.content.ContentProvider-keep public class * extends android.preference.Preference-keepclasseswithmembernames class * {native <methods>;}-keepclassmembers class * extends android.app.Activity {public void *(android.view.View);}-keepclassmembers enum * {public static **[] values();public static ** valueOf(ng.String);}-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;}-keepclassmembers class **.R$* {*;}-keep class * extends android.view.View{*;}-keep class * extends android.app.Dialog{*;}-keep class * implements java.io.Serializable{*;}#butterknife-keep class butterknife.** { *; }-dontwarn butterknife.internal.**-keep class **$$ViewBinder { *; }#volley-dontwarn com.android.volley.**-keep class com.android.volley.**{*;}#fastjson-dontwarn com.alibaba.fastjson.**-keep class com.alibaba.fastjson.**{*;}#happy-dns-dontwarn com.qiniu.android.dns.**-keep class com.qiniu.android.dns.**{*;}#okhttp-dontwarn com.squareup.okhttp.**-keep class com.squareup.okhttp.**{*;}-keep class okio.**{*;}-keep class .**{*;}-keep class com.android.internal.http.multipart.**{*;}-keep class org.apache.**{*;}-keep class com.qiniu.android.**{*;}-keep class android.support.annotation.**{*;}-keep class com.squareup.wire.**{*;}-keep class com.ant.liao.**{*;}#腾讯-keep class com.tencent.**{*;}-keep class u.aly.**{*;}#ImageLoader-keep class com.nostra13.universalimageloader.**{*;}#友盟-dontwarn com.umeng.**-keep class com.umeng.**{*;}#pulltorefresh-keep class com.handmark.pulltorefresh.** { *; }-keep class android.support.v4.** { *;}-keep public class * extends android.support.v4.**{public protected *;}-keep class android.support.v7.** {*;}⾃⼰试着⽤⼀个简单的项⽬加⼊混淆,打个包试试效果吧。

Android项目的代码混淆,Androidproguard使用说明

Android项目的代码混淆,Androidproguard使用说明

Android项⽬的代码混淆,Androidproguard使⽤说明简单介绍Java代码是⾮常easy反编译的。

为了⾮常好的保护Java源码,我们往往会对编译好的class⽂件进⾏混淆处理。

ProGuard是⼀个混淆代码的开源项⽬。

它的主要作⽤就是混淆,当然它还能对字节码进⾏缩减体积、优化等,但那些对于我们来说都算是次要的功能。

原理Java 是⼀种跨平台的、解释型语⾔,Java 源码编译成中间”字节码”存储于 class ⽂件⾥。

因为跨平台的须要,Java 字节码中包括了⾮常多源码信息,如变量名、⽅法名,⽽且通过这些名称来訪问变量和⽅法,这些符号带有很多语义信息,⾮常easy被反编译成 Java 源码。

为了防⽌这样的现象,我们能够使⽤ Java 混淆器对 Java 字节码进⾏混淆。

混淆就是对公布出去的程序进⾏⼜⼀次组织和处理,使得处理后的代码与处理前代码完毕同样的功能,⽽混淆后的代码⾮常难被反编译,即使反编译成功也⾮常难得出程序的真正语义。

被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执⾏结果也与混淆前⼀样。

仅仅是混淆器将代码中的全部变量、函数、类的名称变为简短的英⽂字母代号。

在缺乏对应的函数名和程序凝视的况下,即使被反编译。

也将难以。

同⼀时候混淆是不可逆的,在混淆的过程中⼀些不影响正常执⾏的信息将永久丢失。

这些信息的丢失使程序变得更加难以理解。

混淆器的作⽤不仅仅是保护代码。

它也有精简编译后程序⼤⼩的作⽤。

因为以上介绍的缩短变量和函数名以及丢失部分信息的原因。

编译后 jar ⽂件体积⼤约能降低25% ,这对当前费⽤较贵的⽆线⽹络传输是有⼀定意义的。

语法-include {filename} 从给定的⽂件⾥读取配置參数-basedirectory {directoryname} 指定基础⽂件夹为以后相对的档案名称-injars {class_path} 指定要处理的应⽤程序jar,war,ear和⽂件夹-outjars {class_path} 指定处理完后要输出的jar,war,ear和⽂件夹的名称-libraryjars {classpath} 指定要处理的应⽤程序jar,war,ear和⽂件夹所须要的程序库⽂件-dontskipnonpubliclibraryclasses 指定不去忽略⾮公共的库类。

Android开发中的应用反编译和代码混淆保护(五)

Android开发中的应用反编译和代码混淆保护(五)

Android开发中的应用反编译和代码混淆保护Android应用的开发和发布是一个复杂且竞争激烈的过程。

开发者经过数月甚至数年的努力,编写出一个功能强大、用户友好的应用程序,但不幸的是,他们的劳动成果很容易被他人复制、篡改甚至盗窃。

为了保护开发者的利益和应用程序的安全性,应用反编译和代码混淆成为了Android开发中不可忽视的重要环节。

一、应用反编译的风险和挑战在Android开发中,应用的APK文件是一个包含了可执行代码和资源文件的压缩包。

由于APK文件的本质,这使得它容易被反编译,进而暴露应用程序的源代码和敏感信息。

一旦黑客获得了应用的源代码,他们就可以轻易地篡改应用的功能,嵌入恶意代码或者窃取用户的隐私信息。

因此,应用反编译是一项必要的任务,以保障代码的安全性和应用的可靠性。

然而,应用反编译并不是一项容易的任务。

当开发者上传应用到Google Play商店之后,APK文件将自动被Google Play进行代码验证和防护,这使得大多数的简单反编译方法无法成功。

而且,应用反编译也需要一定的技术水平和耐心。

反编译的过程中,黑客们需要了解和掌握DEX文件格式、Dalvik虚拟机指令集等相关知识。

因此,开发者需要采取一些措施来提高应用的防护性。

二、代码混淆保护的必要性和原理代码混淆是一种在编译过程中对应用程序代码进行变形、重组和操纵的技术。

通过代码混淆,开发者可以使得应用程序的逻辑和结构变得模糊,以干扰和困惑那些试图进行反编译的黑客。

代码混淆可以对变量、类、方法、字符串等进行重命名、删除无效代码、修改控制流等操作,使得应用程序的源代码变得难以阅读和理解。

代码混淆保护对于Android应用开发者来说是必要的。

通过混淆代码,开发者可以最大程度地降低黑客反编译并篡改应用程序的可能性。

在遭受沉重打击的黑客面前,应用的安全性将得到有效的保护。

三、常用的代码混淆技术代码混淆是一项技术性较强的工作,以下是一些常用的代码混淆技术供开发者参考:1.变量与方法重命名:通过将变量和方法改名为无意义的随机字符串,使得应用代码变得难以理解和阅读。

android对app代码混淆

android对app代码混淆

android对app代码混淆接到新任务。

现有项⽬的代码混淆。

在此之前混淆了⼀些理解,但还不够具体和全⾯,我知道有些东西混起来相当棘⼿。

但幸运的是,现在这个项⽬是不是太复杂(对于这有些混乱)。

提前完成~~这是总结。

第⼀部分介绍下操作流程(eclipse):1、打开混淆器:找到项⽬根⽂件夹下的project.properties⽂件,将“#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”这⾏前的“#”删除就可以;2、改动混淆配置⽂件:找到项⽬根⽂件夹下的proguard-project.txt⽂件。

改动当中代码,这部分是最关键;3、保存相关⽂件供以后出错时使⽤:主要有导出的apk⽂件、项⽬根⽂件夹下的proguard⽂件夹下的⽂件(基本的是mapping.txt)和项⽬源代码;4、项⽬执⾏过程出错处理:依据错误信息和第3步中保存的mapping定位错误位置。

知道这些之后。

我们对其进⾏展开。

打开eclipse然后新建⼀个项⽬,默认会创建proguard-project.txt和project.properties。

编写我们的代码。

然后将proguard-project.txt的“#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”这⾏前的“#”删除,最后导出就可以实现对代码的混淆,即使我们没有去编写proguard-project.txt中的内容。

以下是我的測试代码:public class MainActivity extends Activity {private String mName;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);mName = "ttdevs";getString(mName);setName(mName);showDialog();// testError();}public String getString(String name) {return "hello " + name;}public void setName(String name) {System.out.println("I'm " + name);}private void showDialog() {new Handler().postDelayed(new Runnable() {@Overridepublic void run() {ScoreAlertDialog.showDialog(MainActivity.this);}}, 2000);}public static class ScoreAlertDialog {public static void showDialog(final Activity activity) {if (activity.isFinishing()) {return;}try {AlertDialog.Builder builder = new AlertDialog.Builder(activity);builder.setTitle("alert_title");builder.setNegativeButton("cancel", null);builder.setPositiveButton("submit", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {try {Toast.makeText(activity, "Welcome", Toast.LENGTH_LONG).show();} catch (Exception e) {e.printStackTrace();}}});builder.show();} catch (Exception e) {e.printStackTrace();}}}private void testError() {try {int error = 1 / 0;} catch (Exception e) {e.printStackTrace();}}}打包,反编译,最后我们得到例如以下的代码:分析上⾯的代码我们会发现,⾃⼰定义的⽅法名都被替换成⽆特殊意义的短字母,⽽activity的onCreate()⽅法却没变;最后⼀个testError()⽅法因为我们没有调⽤也被剔除掉了。

android混淆原则

android混淆原则

android混淆原则Android 混淆是一种对代码进行加密和混淆处理,以保护代码的安全性和增加逆向工程的难度。

在编写Android应用程序时,经常会使用一些开源库或者框架,这就需要进行混淆,以避免泄露源代码以及反编译出应用的详细信息。

本文将介绍Android混淆的原则和一些常用的混淆规则。

1.不混淆应用程序入口类入口类通常是指具有主函数的类,混淆这些类会导致应用无法启动。

因此,入口类通常不应混淆。

2.混淆关键类和方法名关键类和方法通常是应用程序的核心逻辑和功能所在,为保护代码的安全性和增加逆向工程的难度,这些类和方法通常需要进行混淆处理。

3. 不混淆Android SDK和第三方库的类和方法Android SDK和第三方库的类和方法通常已经经过充分测试和优化,进行混淆可能会导致应用程序运行异常或者功能失效。

因此,这些类和方法通常不应混淆。

4.不混淆资源文件和布局文件的名称资源文件和布局文件通常根据其名称在代码中进行引用,混淆这些名称会导致代码无法正确引用资源和布局文件。

因此,资源文件和布局文件的名称通常不应混淆。

5.对于内部类和内部方法,根据需要进行混淆内部类和内部方法通常是在对外部不可见的情况下被调用,因此,根据实际需求,可以选择对其进行混淆来增加代码的安全性。

6.混淆类和方法的参数、变量和属性名混淆参数、变量和属性名可以增加代码的安全性和逆向工程的难度。

通常情况下,开发者可以使用一些自动化工具来进行混淆,这些工具可以自动生成随机的名称并将其替换原有的名称。

7.混淆代码中的字符串代码中的字符串通常包含了一些敏感信息或者关键字,混淆这些字符串可以增加代码的安全性。

在混淆过程中,可以将字符串进行拼接、加密以及将其存储在其他文件中,从而增加逆向工程的难度。

8.使用混淆规则文件进行混淆混淆规则文件可以指定需要混淆的类、方法、参数、变量和属性名等信息,以及不需要进行混淆的一些类和方法。

在进行混淆前,可以编写混淆规则文件并告诉混淆工具使用这些规则文件进行混淆,从而更加灵活和精细地控制混淆的过程。

详解Android的反编译和代码混淆

详解Android的反编译和代码混淆

详解Android的反编译和代码混淆前⾔包括以下内容1. 要反编译apk需要下⾯3个⼯具2. 反编译资源⽂件3. 反编译类⽂件4. 代码混淆要反编译apk需要下⾯3个⼯具1、apktool(资源⽂件获取)作⽤:资源⽂件获取,可以提取图⽚⽂件和布局⽂件进⾏使⽤查看2、dex2jar(源⽂件获取)作⽤:将APK反编译成java源码(classes.dex转化成jar⽂件)3、jd-gui作⽤:查看APK中classes.dex转化成的jar⽂件,即源码⽂件下⾯进⾏反编译资源⽂件和类⽂件:反编译资源⽂件资源⽂件:包括图⽚资源、布局资源、动画、样式等其他资源这样资源⽂件都可以看得到了。

反编译类⽂件⽅式⼀:反编译得到Java类1.下载并解压dex2jar-2.0,得到dex2jar-2.0⽂件夹,⾥⾯包含dex2jar.bat及其⽂件2.将apk⽂件改为xx.zip⽂件,并解压得到classes.dex⽂件,并将其复制到dex2jar-2.0⽂件夹中3⽣成⼀个classes-dex2jar.jar⽂件,使⽤jd-gui.exe打开⽣成的classes-dex2jar.jar⽂件⽅式⼆:直接使⽤smali2java⼯具什么是smali?smali是将Android字节码⽤可阅读的字符串形式表现出来的⼀种语⾔,可以称之为Android字节码的反汇编语⾔。

代码混淆只能混淆java类,不能混淆资源⽂件。

系统定义的组件不能混淆。

必须是导出的apk。

如何实现代码混淆混淆类⽂件修改module:app下的build.gradlebuildTypes {release {//是否需要混淆,默认false代表不混淆,true代表混淆minifyEnabled true//混淆需要⽤到的⼀个⼯具:proguard,对应的⼀个⽂件是:proguard-android.txt(这个⽂件在android-sdk \tools\proguard⽬录下)//proguard是⼀个压缩、优化和混淆Java字节码⽂件的免费⼯具proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}在proguard-rules.pro中添加:把下⾯代码,放⼊proguard-rules.pro⽂末:#指定代码的压缩级别-optimizationpasses 5#包明不混合⼤⼩写-dontusemixedcaseclassnames#不去忽略⾮公共的库类-dontskipnonpubliclibraryclasses#优化不优化输⼊的类⽂件-dontoptimize#预校验-dontpreverify#混淆时是否记录⽇志-verbose# 混淆时所采⽤的算法-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*#保护注解-keepattributes *Annotation*# 保持哪些类不被混淆-keep public class * extends android.app.Fragment-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 * extends android.app.backup.BackupAgentHelper-keep public class * extends android.preference.Preference-keep public class com.android.vending.licensing.ILicensingService#如果有引⽤v4包可以添加下⾯这⾏-keep public class * extends android.support.v4.app.Fragment#忽略警告-ignorewarning##记录⽣成的⽇志数据,gradle build时在本项⽬根⽬录输出###apk 包内所有 class 的内部结构-dump class_files.txt#未混淆的类和成员-printseeds seeds.txt#列出从 apk 中删除的代码-printusage unused.txt#混淆前后的映射-printmapping mapping.txt########记录⽣成的⽇志数据,gradle build时在本项⽬根⽬录输出-end###### #####混淆保护⾃⼰项⽬的部分代码以及引⽤的第三⽅jar包library########-libraryjars libs/umeng-analytics-v5.2.4.jar#三星应⽤市场需要添加:sdk-v1.0.0.jar,look-v1.0.1.jar#-libraryjars libs/sdk-v1.0.0.jar#-libraryjars libs/look-v1.0.1.jar#如果不想混淆 keep 掉-keep class com.lippi.recorder.iirfilterdesigner.** {*; }#友盟-keep class com.umeng.**{*;}#项⽬特殊处理代码#忽略警告-dontwarn com.lippi.recorder.utils**#保留⼀个完整的包-keep class com.lippi.recorder.utils.** {*;}-keep class com.lippi.recorder.utils.AudioRecorder{*;}#如果引⽤了v4或者v7包-dontwarn android.support.**####混淆保护⾃⼰项⽬的部分代码以及引⽤的第三⽅jar包library-end####-keep public class * extends android.view.View {public <init>(android.content.Context);public <init>(android.content.Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSet, int);public void set*(...);}#保持 native ⽅法不被混淆-keepclasseswithmembernames class * {native <methods>;}#保持⾃定义控件类不被混淆-keepclasseswithmembers class * {public <init>(android.content.Context, android.util.AttributeSet);}#保持⾃定义控件类不被混淆-keepclassmembers class * extends android.app.Activity {public void *(android.view.View);}#保持 Parcelable 不被混淆-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;}#保持 Serializable 不被混淆-keepnames class * implements java.io.Serializable#保持 Serializable 不被混淆并且enum 类也不被混淆-keepclassmembers class * implements java.io.Serializable {static final long serialVersionUID;private static final java.io.ObjectStreamField[] serialPersistentFields;!static !transient <fields>;!private <fields>;!private <methods>;private void writeObject(java.io.ObjectOutputStream);private void readObject(java.io.ObjectInputStream);ng.Object writeReplace();ng.Object readResolve();}#保持枚举 enum 类不被混淆如果混淆报错,建议直接使⽤上⾯的 -keepclassmembers class * implements java.io.Serializable即可#-keepclassmembers enum * {# public static **[] values();# public static ** valueOf(ng.String);#}-keepclassmembers class * {public void *ButtonClicked(android.view.View);}#不混淆资源类-keepclassmembers class **.R$* {public static <fields>;}#避免混淆泛型如果混淆报错建议关掉#–keepattributes Signature#移除log 测试了下没有⽤还是建议⾃⼰定义⼀个开关控制是否输出⽇志#-assumenosideeffects class android.util.Log {# public static boolean isLoggable(ng.String, int);# public static int v(...);# public static int i(...);# public static int w(...);# public static int d(...);# public static int e(...);#}#如果⽤⽤到Gson解析包的,直接添加下⾯这⼏⾏就能成功混淆,不然会报错。

android 混淆规则

android 混淆规则一、什么是Android混淆Android混淆(obfuscation)是一种优化工具,它可以将代码以及相关的文件有效地进行混淆和加密,从而使代码更难被人理解和阅读,从而保护软件的源代码安全,避免在破解者的手里泄露。

二、Android混淆的目的Android混淆的目的是保护软件的源代码,使其难以被破解或者恶意的使用。

Android 混淆的过程是根据可执行文件的程序、类、变量、函数等内容自动生成。

通过混淆,将源代码混淆之后,破解者不可能识别其中的原理、内部结构和工作原理。

三、Android混淆规则1、改变代码中原来的函数、变量和类名。

2、为固定的字符串添加不可读的字符。

3、移除代码中没有使用的字符。

4、将可执行文件和可执行程序之间的依赖关系混淆掉。

5、将可执行文件中的特定字段替换成更加难识别的字段。

6、移除设置中的不必要的零件或者信息。

7、添加混淆代码和模块,拦截破解者的识别行为。

8、对代码进行优化,精简注释,增加可执行文件的体积。

9、删除在编译期间产生的辅助文件,如调试文件和日志文件。

10、利用安全技术,如数据加密、数字签名和令牌机制,保护应用程序不被恶意修改。

四、Android混淆的优缺点优点:1、可以减少文件的体积,改善APP的性能,减少使用的带宽等。

2、有效的加密防止恶意破解,提高应用程序的安全性。

3、有效可以防止程序泄漏。

4、可以提高APP程序的开发周期。

缺点:1、Android混淆过程会使软件变得复杂,从而影响软件及其依赖库的更新。

2、Android混淆后,APP可能不稳定,可能会造成应用程序出现崩溃等问题。

3、混淆可能会影响APP程序的索引,从而影响APP在市场上的发布和推广。

Android proguard代码混淆

Android proguard代码混淆代码混淆并不是让代码无法被反编译,而是将代码中的类、方法、变量等信息进行重命名,将它们改成一些毫无意义的名字,譬如A类的b()方法等。

所以说代码混淆可以在不影响程序正常运行的前提下让破解者很头疼,从而大大提升了程序的安全性。

我们的Android项目可以使用Android Studio来创建,也可以使用Eclipse创建。

下面我们分别针对这两种情况对项目代码实现混淆。

创建项目首先新建一个MyFragment类,代码如下所示:public class MyFragment extends Fragment {private String message = "(watson) global variable in MyFragment";@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(yout.fragment_my, container, false);methodWithGlobalVariable();methodWithLocalVariable();return view;}public void methodWithGlobalVariable() {message = message.toUpperCase();System.out.println(message);}public void methodWithLocalVariable() {String message2 = "(watson) local variable in MyFragment";message2 = message2.toUpperCase();System.out.println(message2);}}MyFragment继承自Fragment,onCreateView()方法中调用了methodWithGlobalVariable()和methodWithLocalVariable()方法,这两个方法的内部分别引用了一个全局变量和一个局部变量。

Android开发中的应用反编译和代码混淆保护(三)

Android开发中的应用反编译和代码混淆保护在如今移动应用开发领域的竞争激烈环境下,应用程序的安全性变得越来越重要。

Android作为一款流行的移动操作系统,其应用开发者面临着应用反编译的风险。

为了保护应用程序代码的安全性,开发者需要采取适当的措施进行代码混淆和反编译保护。

本文将探讨Android开发中的应用反编译问题,并介绍一些常用的代码混淆和保护技术。

1. 应用反编译的风险随着技术的不断发展,越来越多的人学会了如何反编译Android 应用程序。

应用反编译使得黑客可以轻松获取源代码,从而发现应用程序中可能存在的漏洞。

这些漏洞可能包括密码存储不安全、网络请求不加密等问题,给应用程序的安全性带来了严重威胁。

2. 代码混淆保护代码混淆是一种常用的保护应用程序的技术。

通过代码混淆,开发者可以将源代码中的变量、方法名和类名进行重命名,使得反编译后的源代码难以理解和修改。

代码混淆可以有效地增加应用程序的安全性,防止黑客通过反编译获取源代码。

3. 常用的代码混淆工具在Android开发中,有许多可以实现代码混淆的工具。

其中,ProGuard是应用广泛的一种代码混淆工具。

ProGuard能够对Android 应用程序的字节码进行缩小、优化和混淆。

通过删除无用的代码、重命名变量名和方法名,并对代码流进行修改,ProGuard可以使反编译后的源代码难以理解和修改。

4. 自定义代码混淆规则除了使用常用的代码混淆工具外,开发者还可以通过自定义代码混淆规则进一步提高应用程序的安全性。

通过定义自己的规则,开发者可以更加灵活地对代码进行混淆。

例如,可以定义规则使得一些关键函数和类名无法被反编译,或者在代码中添加一些虚假的逻辑,以混淆黑客对应用程序的分析。

5. 其他防护措施除了代码混淆外,还有一些其他的防护措施可以加强应用程序的安全性。

例如,开发者可以在应用程序中使用加密算法对敏感数据进行加密,以防止数据泄漏。

另外,应用程序可以使用数字签名来验证应用的完整性,防止黑客篡改应用程序的代码。

移动应用开发中常见的代码混淆与反编译保护技术(七)

移动应用开发中常见的代码混淆与反编译保护技术在移动应用开发领域,代码混淆与反编译保护技术是非常重要的,它们可以有效地保护应用程序免受恶意攻击和盗用。

本文将介绍移动应用开发中常见的代码混淆与反编译保护技术,以及它们的原理与应用。

一、代码混淆的原理与应用代码混淆是指通过修改代码的结构和逻辑,使得代码难以阅读和理解,从而增加了反编译的难度。

常见的代码混淆技术包括变量和方法名的重命名、代码重写与逻辑转换、无用代码和控制流混淆等。

1. 变量和方法名的重命名通过将变量和方法名替换为无意义的名称,如将“username”替换为“a”,可以使得代码更难以被理解。

这种技术通常需要配合自动化工具来实现,以确保代码的修改不会破坏程序的功能。

2. 代码重写与逻辑转换通过重写代码的结构和逻辑,可以使得代码不易于被理解和分析。

例如,可以将原本的if-else语句转换为switch语句,或者使用随机数和无用代码生成方法来替换原有的代码逻辑。

3. 无用代码和控制流混淆向代码中插入一些无用的代码,如死循环和无效的判断语句,可以使得反编译者在阅读和理解代码时感到困惑。

此外,控制流混淆技术还可以修改代码的控制流程,使得代码的执行路径难以预测,从而增加反编译的难度。

代码混淆技术可以有效地防止反编译和逆向工程,从而保护应用程序的知识产权和机密信息。

虽然代码混淆并不能完全阻止反编译,但它可以使得反编译者花费更多的时间和精力来理解和分析代码,从而减少了盗用和恶意攻击的风险。

二、反编译保护技术的原理与应用除了代码混淆之外,还有一些其他的技术可以用来保护应用程序不被反编译,如加密和动态加载等。

1. 加密加密是指对应用程序的代码进行加密处理,使得反编译者无法直接获取到明文的代码。

常见的加密算法包括对称加密算法和非对称加密算法,可以通过密钥管理和安全存储技术来保护密钥的安全性。

2. 动态加载动态加载是指将应用程序的一部分代码放在服务器端,通过网络加载到客户端执行。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

读懂Android中的代码混淆本文为本人的一些实践总结,介绍一些混淆的知识和注意事项。

希望可以帮助大家更好的学习和使用代码混淆。

作者:技术小黑屋来源:知乎|2017-03-02 13:05收藏分享本文为本人的一些实践总结,介绍一些混淆的知识和注意事项。

希望可以帮助大家更好的学习和使用代码混淆。

什么是混淆关于混淆维基百科上该词条的解释为代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。

代码混淆影响到的元素有∙类名∙变量名∙方法名∙包名∙其他元素混淆的目的混淆的目的是为了加大反编译的成本,但是并不能彻底防止反编译.如何开启混淆∙通常我们需要找到项目路径下app目录下的build.gradle文件∙找到minifyEnabled这个配置,然后设置为true即可.一个简单的示例如下1. buildTypes {2.3. release {4.5. minifyEnabled true6.7. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'proguard是什么Java官网对Proguard的定义ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions. It renames the remaining classes, fields, and methods using short meaningless names. Finally, it preverifies the processed code for Java 6 or higher, or for Java Micro Edition.∙Proguard是一个集文件压缩,优化,混淆和校验等功能的工具∙它检测并删除无用的类,变量,方法和属性∙它优化字节码并删除无用的指令.∙它通过将类名,变量名和方法名重命名为无意义的名称实现混淆效果.∙最后它还校验处理后的代码混淆的常见配置-keepKeep用来保留Java的元素不进行混淆. keep有很多变种,他们一般都是∙-keep∙-keepclassmembers∙-keepclasseswithmembers一些例子保留某个包下面的类以及子包1. -keep public class .widget.**保留所有类中使用otto的public方法1. # Otto2.3. -keepclassmembers class ** {4.5. @com.squareup.otto.Subscribe public *;6.7. @com.squareup.otto.Produce public *;8.9. }保留Contants类的BOOK_NAME属性1. -keepclassmembers class com.example.admin.proguardsample.Constants {2.3. public static ng.String BOOK_NAME;4.5. }更多关于Proguard keep使用,可以参考官方文档-dontwarndontwarn是一个和keep可以说是形影不离,尤其是处理引入的library时.引入的library可能存在一些无法找到的引用和其他问题,在build时可能会发出警告,如果我们不进行处理,通常会导致build中止.因此为了保证build继续,我们需要使用dontwarn处理这些我们无法解决的library的警告.比如关闭Twitter sdk的警告,我们可以这样做1. -dontwarn com.twitter.sdk.**其他混淆相关的介绍,都可以通过访问官方文档获取.哪些不应该混淆反射中使用的元素如果一些被混淆使用的元素(属性,方法,类,包名等)进行了混淆,可能会出现问题,如NoSuchFiledException或者NoSuchMethodException等.比如下面的示例源码1. //Constants.java2.3. public class Constants {5. public static String BOOK_NAME = "book_name";6.7. }8.9. //MainActivity.java10.11. Field bookNameField = null;12.13. try {14.15. String fieldName = "BOOK_NAME";16.17. bookNameField = Constants.class.getField(fieldName);18.19. Log.i(LOGTAG, "bookNameField=" + bookNameField);20.21. } catch (NoSuchFieldException e) {22.23. e.printStackTrace();24.25. }如果上面的Constants类进行了混淆,那么上面的语句就可能抛出NoSuchFieldException.想要验证,我们需要看一看混淆的映射文件,文件名为mapping.txt,该文件保存着混淆前后的映射关系.1. com.example.admin.proguardsample.Constants -> com.example.admin.proguardsample.a:2.3. ng.String BOOK_NAME -> a4.5. void <init>() -> <init>6.7. void <clinit>() -> <clinit>8.9. com.example.admin.proguardsample.MainActivity -> com.example.admin.proguardsample.MainActivity:10.11. void <init>() -> <init>12.13. void onCreate(android.os.Bundle) -> onCreate从映射文件中,我们可以看到∙Constants类被重命名为a.∙Constants类的BOOK_NAME重命名了a然后,我们对APK文件进行反编译一探究竟.推荐一下这个在线反编译工具decompile Android .apk ✓ONLINE ✓注意,使用jadx decompiler后,会重新命名,正如下面注释/* renamed from: com.example.admin.proguardsample.a */所示.1. package com.example.admin.proguardsample;2.3. /* renamed from: com.example.admin.proguardsample.a */4.5. public class C0314a {6.7. public static String f1712a;8.9. static {10.11. f1712a = "book_name";12.13. }14.15. }而MainActivity的翻译后的对应的源码为1. try {2.3. Log.i("MainActivity", "bookNameField=" + C0314a.class.getField("BOOK_NAME"));4.5. } catch (NoSuchFieldException e) {6.7. e.printStackTrace();8.9. }MainActivity中反射获取的属性名称依然是BOOK_NAME,而对应的类已经没有了这个属性名,所以会抛出NoSuchFieldException.注意,如果上面的filedName使用字面量或者字符串常量,即使混淆也不会出现NoSuchFieldException异常。

因为这两种情况下,混淆可以感知外界对filed的引用,已经在调用出替换成了混淆后的名称。

GSON的序列化与反序列化GSON是一个很好的工具,使用它我们可以轻松的实现序列化和反序列化.但是当它一旦遇到混淆,就需要我们注意了.一个简单的类Item,用来处理序列化和反序列化1. public class Item {2.3. public String name;4.5. public int id;6.7. }序列化的代码1. Item toSerializeItem = new Item();2.3. toSerializeItem.id = 2;4.5. = "Apple";6.7. String serializedText = gson.toJson(toSerializeItem);8.9. Log.i(LOGTAG, "testGson serializedText=" + serializedText);开启混淆之后的日志输出结果1. I/MainActivity: testGson serializedText={"a":"Apple","b":2}属性名已经改变了,变成了没有意思的名称,对我们后续的某些处理是很麻烦的.反序列化的代码1. Gson gson = new Gson();2.3. Item item = gson.fromJson("{\"id\":1, \"name\":\"Orange\"}", Item.class);4.5. Log.i(LOGTAG, "testGson item.id=" + item.id + ";=" + );对应的日志结果是1. I/MainActivity: testGson item.id=0;=null可见,混淆之后,反序列化的属性值设置都失败了.为什么呢?因为反序列化创建对象本质还是利用反射,会根据json字符串的key作为属性名称,value则对应属性值.如何解决∙将序列化和反序列化的类排除混淆∙使用@SerializedName注解字段@SerializedName(parameter)通过注解属性实现了∙序列化的结果中,指定该属性key为parameter的值.∙反序列化生成的对象中,用来匹配key与parameter并赋予属性值.一个简单的用法为1. public class Item {2. @SerializedName("name")3. public String name;4. @SerializedName("id")5. public int id;枚举也不要混淆枚举是Java 5 中引入的一个很便利的特性,可以很好的替代之前的常量形式.枚举使用起来很简单,如下1. public enum Day {2. MONDAY,3. TUESDAY,4. WEDNESDAY,5. THURSDAY,6. FRIDAY,7. SATURDAY,8. SUNDAY9. }这里我们这样使用枚举1. Day day = Day.valueOf("monday");2. Log.i(LOGTAG, "testEnum day=" + day);运行上面的的代码,通常情况下是没有问题的,是否说明枚举就可以混淆呢?其实不是.为什么没有问题呢,因为默认的Proguard配置已经处理了枚举相关的keep操作.1. # For enumeration classes, see /manual/examples.html#enumerations2.3. -keepclassmembers enum * {4.5. public static **[] values();6.7. public static ** valueOf(ng.String);8.9. }如果我们手动去掉这条keep配置,再次运行,一个这样的异常会从天而降.1. E AndroidRuntime: Process: com.example.admin.proguardsample, PID: 172462.3. E AndroidRuntime: ng.AssertionError: impossible4.5. E AndroidRuntime: at ng.Enum$1.create(Enum.java:45)6.7. E AndroidRuntime: at ng.Enum$1.create(Enum.java:36)8.9. E AndroidRuntime: at libcore.util.BasicLruCache.get(BasicLruCache.java:54)10.11. E AndroidRuntime: at ng.Enum.getSharedConstants(Enum.java:211)12.13. E AndroidRuntime: at ng.Enum.valueOf(Enum.java:191)14.15. E AndroidRuntime: at com.example.admin.proguardsample.a.a(Unknown Source)16.17. E AndroidRuntime: at com.example.admin.proguardsample.MainActivity.j(Unknown Source)18.19. E AndroidRuntime: at com.example.admin.proguardsample.MainActivity.onCreate(Unknown Source)20.21. E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:6237)22.23. E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)24.25. E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)26.27. E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)28.29. E AndroidRuntime: at android.app.ActivityThread.-wrap11(ActivityThread.java)30.31. E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)32.33. E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)35. E AndroidRuntime: at android.os.Looper.loop(Looper.java:148)36.37. E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5417)38.39. E AndroidRuntime: at ng.reflect.Method.invoke(Native Method)40.41. E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)42.43. E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)44.45. E AndroidRuntime: Caused by: ng.NoSuchMethodException: values []46.47. E AndroidRuntime: at ng.Class.getMethod(Class.java:624)48.49. E AndroidRuntime: at ng.Class.getDeclaredMethod(Class.java:586)50.51. E AndroidRuntime: at ng.Enum$1.create(Enum.java:41)52.53. E AndroidRuntime: ... 19 more好玩的事情来了,我们看一看为什么会抛出这个异常1.首先,一个枚举类会生成一个对应的类文件,这里是Day.class. 这里类里面包含什么呢,看一下反编译的结果1. proguardsample javap Day2.3. Warning: Binary file Day contains com.example.admin.proguardsample.Day4.5. Compiled from"Day.java"6.7. public final class com.example.admin.proguardsample.Day extends ng.Enum<com.example.admin.proguardsample.Day> {8.9. public static final com.example.admin.proguardsample.Day MONDAY;10.11. public static final com.example.admin.proguardsample.Day TUESDAY;12.13. public static final com.example.admin.proguardsample.Day WEDNESDAY;14.15. public static final com.example.admin.proguardsample.Day THURSDAY;16.17. public static final com.example.admin.proguardsample.Day FRIDAY;18.19. public static final com.example.admin.proguardsample.Day SATURDAY;21. public static final com.example.admin.proguardsample.Day SUNDAY;22.23. public static com.example.admin.proguardsample.Day[] values();24.25. public static com.example.admin.proguardsample.Day valueOf(ng.String);26.27. static {};28.29. }∙枚举实际是创建了一个继承自ng.Enum的类∙java代码中的枚举类型最后转换成类中的static final属性∙多出了两个方法,values()和valueOf().∙values方法返回定义的枚举类型的数组集合,即从MONDAY到SUNDAY这7个类型.2.找寻崩溃轨迹其中Day.valueOf(String)内部会调用Enum.valueOf(Class,String)方法1. public static com.example.admin.proguardsample.Day valueOf(ng.String);2.3. Code:4.5. 0: ldc #4 // class com/example/admin/proguardsample/Day6.7. 2: aload_08.9. 3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;10.11. 6: checkcast #4 // class com/example/admin/proguardsample/Day12.13. 9: areturn而Enum的valueOf方法会间接调用Day.values()方法,具体步骤是∙Enum.value调用Class.enumConstantDirectory方法获取String到枚举的映射∙Class.enumConstantDirectory方法调用Class.getEnumConstantsShared获取当前的枚举类型∙Class.getEnumConstantsShared方法使用反射调用values来获取枚举类型的集合.混淆之后,values被重新命名,所以会发生NoSuchMethodException.关于调用轨迹,感兴趣的可以自己研究一下源码,不难.四大组件不建议混淆Android中四大组件我们都很常用,这些组件不能被混淆的原因为∙四大组件声明必须在manifest中注册,如果混淆后类名更改,而混淆后的类名没有在manifest注册,是不符合Android组件注册机制的.∙外部程序可能使用组件的字符串类名,如果类名混淆,可能导致出现异常注解不能混淆注解在Android平台中使用的越来越多,常用的有ButterKnife和Otto.很多场景下注解被用作在运行时反射确定一些元素的特征.为了保证注解正常工作,我们不应该对注解进行混淆.Android工程默认的混淆配置已经包含了下面保留注解的配置1. -keepattributes *Annotation*关于注解,可以阅读这篇文章了解.详解Java中的注解其他不该混淆的∙jni调用的java方法∙java的native方法∙js调用java的方法∙第三方库不建议混淆∙其他和反射相关的一些情况stacktrace的恢复Proguard混淆带来了很多好处,但是也会导致我们收集到的崩溃的stacktrace变得更加难以读懂,好在有补救的措施,这里就介绍一个工具,retrace,用来将混淆后的stacktrace还原成混淆之前的信息.retrace脚本Android 开发环境默认带着retrace脚本,一般情况下路径为./tools/proguard/bin/retrace.shmapping映射表Proguard进行混淆之后,会生成一个映射表,文件名为mapping.txt,我们可以使用find工具在Project下查找1. find . -name mapping.txt2.3. ./app/build/outputs/mapping/release/mapping.txt一个崩溃stacktrace信息一个原始的崩溃信息是这样的.1. E/AndroidRuntime(24006): Caused by: ng.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()'on a null object reference2.3. E/AndroidRuntime(24006): at com.example.admin.proguardsample.a.a(Utils.java:10)4.5. E/AndroidRuntime(24006): at com.example.admin.proguardsample.MainActivity.onCreate(MainActivity.java:22)6.7. E/AndroidRuntime(24006): at android.app.Activity.performCreate(Activity.java:6106)8.9. E/AndroidRuntime(24006): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)10.11. E/AndroidRuntime(24006): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2566)12.13. E/AndroidRuntime(24006): ... 10 more对上面的信息处理,去掉E/AndroidRuntime(24006):这些字符串retrace才能正常工作.得到的字符串是1. Caused by: ng.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()'on a null object reference2. at com.example.admin.proguardsample.a.a(Utils.java:10)3. at com.example.admin.proguardsample.MainActivity.onCreate(MainActivity.java:22)4. at android.app.Activity.performCreate(Activity.java:6106)5. at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)6. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2566)7. ... 10 more将上面的stacktrace保存成一个文本文件,比如名称为npe_stacktrace.txt.开搞1. ./tools/proguard/bin/retrace.sh /Users/admin/Downloads/ProguardSample/app/build/outputs/mapping/release/mapping.txt /tmp/npe_stacktrace.txt得到的易读的stacktrace是1. Caused by: ng.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()'on a null object reference2.3. at com.example.admin.proguardsample.Utils.int getBitmapWidth(android.graphics.Bitmap)(Utils.java:10)4.5. at com.example.admin.proguardsample.MainActivity.void onCreate(android.os.Bundle)(MainActivity.java:22)6.7. at android.app.Activity.performCreate(Activity.java:6106)8.9. at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)10.11. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2566)12.13. ... 10 more注意:为了更加容易和高效分析stacktrace,建议保留SourceFile和LineNumber属性1. -keepattributes SourceFile,LineNumberTable关于混淆,我的一些个人经验总结就是这些.希望可以对大家有所帮助.【编辑推荐】1.Android避免内存溢出(Out of Memory)方法总结2.科技帖如何将AI原生的应用到Android系统3.iOS与Android开发——我们该如何选择?4.Android Studio小技巧5.如何构建Android MVVM应用程序。

相关文档
最新文档