赞
踩
反编译地址及使用方法:
找到Android软件安装包中的class.dex:
把apk文件改名为.zip,然后解压缩其中的class.dex文件,它就是java文件编译再通过dx工具打包成的。
工具准备:
1、把dex文件反编译为jar文件的工具。(dex2jar)
http://code.google.com/p/dex2jar/downloads/list
2、把jar反编译为java的工具。(JD-GUI)
http://java.decompiler.free.fr/?q=jdgui
反编译步骤:
1、把class.dex拷贝到dex2jar.bat所在目录。运行dex2jar.bat class.dex,生成classes.dex.dex2jar.jar。
2、运行JD-GUI工具(它是绿色无须安装的),打开上面的jar文件,即可看到源代码。
如何防止反编译:
在eclipse下的混淆
在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt。
如果需要对项目进行全局混码,只需要进行一步操作:
将project.properties的中
“# proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”的“#”去掉就可以了。
在android studio下的混淆
1.首先要在build.gradle中开启混淆,也就是minifyEnabled true,我用的build.gradle具体如下所示:
buildTypes {
release {
minifyEnabled true//最小化资源包
shrinkResources true//去掉无用资源
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
}
2.project.properties文件中加上你的混淆文件申明了,如下:
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
3.接下来是 蛋疼的 配置的是项目中app下的proguard-rules.pro
混淆器(ProGuard)
混淆器通过删除从未用过的代码和使用晦涩名字重命名类、字段和方法,对代码进行压缩,优化和混淆。结果是一个比较小的.apk文件,该文件比较难进行逆向工程。因此,当你的应用程序对安全敏感(要求高),例如当你授权应用程序的时候,混淆器是一种重要的保护手段。
当你在发布模式下,或者通过运行ant release,或者通过使用Eclipse中的Export Wizard构建你的应用程序的时候,构建系统都会自动地去检查proguard.config属性是否被设置了。如果被设置了,混淆器在把所有东西打包成.apk文件之前,自动地对应用程序字节码进行混淆处理。而在调试模式中构建则不会调用混淆器,因为那样调试会更加繁重。
运行混淆器之后输出的文件有:
dump.txt 描述.apk包中所有class文件的内部结构。
mapping.txt 列出了源代码与混淆后的类,方法和属性名字之间的映射。这个文件对于在构建之后得到的bug报告是有用的,因为它把混淆的堆栈跟踪信息反翻译为源代码中的类,方法和成员名字。更多信息,查看解码混淆过的堆栈跟踪信息。
seeds.txt 列出那些未混淆的类和成员。
usage.txt 列出从.apk中剥离的代码。
这些文件放在以下目录中:
<project_root>/bin/proguard 当你使用Ant时
<project_root>/proguard 当你使用Eclipse时
混淆器配置(proguard config)
某些情况下,proguard.cfg文件的缺省配置可以满足需求了。但是,对于混淆器来说,大多数情况做出正确的分析是困难的,并且它或许会删除在它看来是无用的,但对于程序来说却确实需要的代码。一些例子如下:
一个仅引用于AndroidManifest.xml文件的类。
一个通过JNI调用的方法。
动态引用的属性和方法。
缺省的proguard文件试图覆盖普通的情况,但是你可能碰到类似ClassNotFoundException的异常,这个异常出现在当你的程序去访问一个被混淆器移除了的类的时候。
你可以在proguard.cfg文件中添加-keep这一行来修复这些错误。例如:
-keep public class <MyClass>
4.1 首先这里 有一份混淆模板,大家直接复制即可(大神可自定义)
############################################# # # 对于一些基本指令的添加 # ############################################# # 代码混淆压缩比,在0~7之间,默认为5,一般不做修改 -optimizationpasses 5 # 混合时不使用大小写混合,混合后的类名为小写 -dontusemixedcaseclassnames # 指定不去忽略非公共库的类 -dontskipnonpubliclibraryclasses # 这句话能够使我们的项目混淆后产生映射文件 # 包含有类名->混淆后类名的映射关系 -verbose # 指定不去忽略非公共库的类成员 -dontskipnonpubliclibraryclassmembers # 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。 -dontpreverify # 保留Annotation不混淆 -keepattributes *Annotation*,InnerClasses # 避免混淆泛型 -keepattributes Signature # 抛出异常时保留代码行号 -keepattributes SourceFile,LineNumberTable # 指定混淆是采用的算法,后面的参数是一个过滤器 # 这个过滤器是谷歌推荐的算法,一般不做更改 -optimizations !code/simplification/cast,!field/*,!class/merging/* ############################################# # # Android开发中一些需要保留的公共部分 # ############################################# # 保留我们使用的四大组件,自定义的Application等等这些类不被混淆 # 因为这些子类都有可能被外部调用 -keep public class * extends android.app.Activity -keep public class * extends android.app.Appliction -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 * extends android.view.View -keep public class com.android.vending.licensing.ILicensingService # 保留support下的所有类及其内部类 -keep class android.support.** {*;} # 保留继承的 -keep public class * extends android.support.v4.** -keep public class * extends android.support.v7.** -keep public class * extends android.support.annotation.** # 保留R下面的资源 -keep class **.R$* {*;} # 保留本地native方法不被混淆 -keepclasseswithmembernames class * { native <methods>; } # 保留在Activity中的方法参数是view的方法, # 这样以来我们在layout中写的onClick就不会被影响 -keepclassmembers class * extends android.app.Activity{ public void *(android.view.View); } # 保留枚举类不被混淆 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } # 保留我们自定义控件(继承自View)不被混淆 -keep public class * extends android.view.View{ *** get*(); void set*(***); public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); } # 保留Parcelable序列化类不被混淆 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } # 保留Serializable序列化的类不被混淆 -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); java.lang.Object writeReplace(); java.lang.Object readResolve(); } # 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆 -keepclassmembers class * { void *(**On*Event); void *(**On*Listener); } # webView处理,项目中没有使用到webView忽略即可 -keepclassmembers class fqcn.of.javascript.interface.for.webview { public *; } -keepclassmembers class * extends android.webkit.webViewClient { public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); public boolean *(android.webkit.WebView, java.lang.String); } -keepclassmembers class * extends android.webkit.webViewClient { public void *(android.webkit.webView, jav.lang.String); } # 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用 # 记得proguard-android.txt中一定不要加-dontoptimize才起作用 # 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制 #-assumenosideeffects class android.util.Log { # public static int v(...); # public static int i(...); # public static int w(...); # public static int d(...); # public static int e(...); #} ############################################# # # 项目中特殊处理部分 # ############################################# #-----------处理反射类--------------- #-----------处理js交互--------------- #-----------处理实体类--------------- #-----------处理第三方依赖库---------
4.2 关于第三方依赖库的处理,仅做参考~
# AndroidEventBus -keep class org.simple.** { *;} -keep interface org.simple.** { *;} -keepclassmembers class * { @org.simple.eventbus.Subscriber <methods>; } # 百度地图(jar包换成自己的版本,记得签名要匹配) -libraryjars libs/baidumapapi_v2_1_3.jar -keep class com.baidu.** {*;} -keep class vi.com.** {*;} -keep class com.sinovoice.** {*;} -keep class pvi.com.** {*;} -dontwarn com.baidu.** -dontwarn vi.com.** -dontwarn pvi.com.** # Bugly -dontwarn com.tencent.bugly.** -keep class com.tencent.bugly.** {*;} # ButterKnife -keep class butterknife.** { *;} -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *;} -keepclasseswithmembernames class * { @butterknife.* <fields>; } -keepclasseswithmembernames class * { @butterknife.* <methods>; } # EventBus -keepattributes *Annotation* -keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *;} # Glide -keep public class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; } # Gson -keepattributes Signature-keepattributes *Annotation* -keep class sun.misc.Unsafe { *;} -keep class com.google.gson.stream.** { *;} # 使用Gson时需要配置Gson的解析对象及变量都不混淆。不然Gson会找不到变量。 # 将下面替换成自己的实体类 -keep class com.example.bean.** { *;} # 极光推送 -dontoptimize -dontpreverify -dontwarn cn.jpush.** -keep class cn.jpush.** { *;} # Retrofit -dontwarn retrofit2.** -keep class retrofit2.** { *;} -keepattributes Signature -keepattributes Exceptions # Retrolambda -dontwarn java.lang.invoke.* # RxJava RxAndroid -dontwarn sun.misc.** -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { long producerIndex; long consumerIndex; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { rx.internal.util.atomic.LinkedQueueNode producerNode; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode; } # 微信支付 -dontwarn com.tencent.mm.** -dontwarn com.tencent.wxop.stat.** -keep class com.tencent.mm.** {*;} -keep class com.tencent.wxop.stat.**{*;} # 友盟统计分析 -keepclassmembers class * { public <init>(org.json.JSONObject);} -keepclassmembers enum com.umeng.analytics.** { public static **[] values(); public static ** valueOf(java.lang.String); } # 友盟自动更新 -keepclassmembers class * { public <init>(org.json.JSONObject);} -keep public class cn.irains.parking.cloud.pub.R$*{ public static final int *;} -keep public class * extends com.umeng.** -keep class com.umeng.** { *;} # 支付宝钱包 -dontwarn com.alipay.** -dontwarn HttpUtils.HttpFetcher -dontwarn com.ta.utdid2.** -dontwarn com.ut.device.** -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.alipay.mobilesecuritysdk.* -keep class com.ut.*
4.编译, 解决错误,然后打包.
我们可以重新来反编译项目得到源码,看是否自己的类中得到混淆,例如方法名成为了a,b,c等,如果是就说明编译成功了.
应用的签名
我们知道Android中的每个应用都是有一个唯一的签名。但是这个签名在之前是可以被伪造,并实现为此打包的。为了防止应用被二次打包,或者是需要破解我们的apk的操作,在入口处添加签名验证,如果发现应用的签名不正确就立即退出程序,我们可以在应用启动的时候获取应用的签名值,然后和正规的签名值作比对,如果不符合就直接退成程序即可。
public static String getSign(){ Context context= StockApplication.getInstance(); try { PackageInfo packageInfo=context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); Signature[] signatures=packageInfo.signatures; StringBuilder builder=new StringBuilder(); for (Signature signature:signatures){ builder.append(signature.toCharsString()); } return builder.toString(); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return ""; }
我们可以在application启动的时候,如果不是我们app的签名,那么app直接退出
private void checkSign() {
if (!Utils.isMyApp()){
//直接退出
}
}
public static boolean isMyApp(){
String signStr=getSign();
return SIGN.equals(signStr);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。