android 防止反编译的若干方法
第一种方式:混淆策略
混淆策略是每个应用必须增加的一种防护策略,同时他不仅是为了防护,也是为了减小应用安装包的大小,所以他是每个应用发版之前必须要添加的一项功能,现在混淆策略一般有两种:
对代码的混淆
我们在反编译apk之后,看到的代码类名,方法名,已经代码格式看起来不像正常的Android项目代码,那么这时候就会增加阅读难度,增加破解难度,像这样的代码混淆:
我们一般现在的破解查看Java层代码就是两种方式:
一种是直接先解压classes.dex文件出来,使用dex2jar工具转化成jar文件,然后再用jd-gui工具进行查看类结构
一种是使用apktool工具直接反编译apk,得到smali源码,阅读smali源码
不过这种代码混淆有时候在一定程度上能够增加混淆策略,但是有时候也不是很安全,因为我们知道我们在破解的过程中一般是找程序的入口,那么这些入口一般都是Application或者是MainActivity之类的,但是这些Android中的组件类是不能进行混淆的,所以我们还是有入口可寻,能够找到入口代码,然后进行跟踪。
2、对工程资源的混淆
我们上面说到了对代码的混淆能够增加一定的代码阅读难度,有时候我们为了防止资源的保护也是可以做混淆的,这个资源混淆原理这里就不多解释了,微信团队已经将这个功能开源,不了解的同学可以转战github查看:
https://github.com/shwenzhang/AndResGuard
主要是对资源的混淆
第二种方式:应用的签名
我们知道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);
}
第三种方式:修改Naitve函数名
这个方法其实不太常用,因为他的安全措施不是很强大的,但是也是可以起到一定的障眼法策略,在说这个知识点的时候,我们先来了解一下so加载的流程:
在Android中,当程序在java层运行System.loadLibrary("jnitest");这行代码后,程序会去载入libjnitest.so文件,与此同时,产生一个"Load"事件,这个事件触发后,程序默认会在载入的.so文件的函数列表中查找JNI_OnLoad函数并执行,与"Load"事件相对,当载入的.so文件被卸载时,“Unload”事件被触发,此时,程序默认会去在载入的.so文件的函数列表中查找JNI_OnUnload函数并执行,然后卸载.so文件。需要注意的是,JNI_OnLoad与JNI_OnUnload这两个函数在.so组件中并不是强制要求的,用户也可以不去实现,java代码一样可以调用到C组件中的函数,之所以在C组件中去实现这两个函数(特别是JNI_OnLoad函数),往往是做一个初始化工作或“善后”工作。可以这样认为,将JNI_ONLoad看成是.so组件的初始化函数,当其第一次被装载时被执行(window下的dll文件也可类似的机制,在_DLL_Main()函数中,通过一个swith
case语句来识别当前是载入还是卸载)。将JNI_OnUnload函数看成是析构函数,当其被卸载时被调用。由此看来,就不难明白为什么很多jni C组件中会实现JNI_OnLoad这个函数了。 一般情况下,在C组件中的JNI_OnLoad函数用来实现给VM注册接口,以方便VM可以快速的找到Java代码需要调用的C函数。(此外,JNI_OnLoad函数还有另外一个功能,那就是告诉VM此C组件使用那一个JNI版本,如果未实现JNI_OnLoad函数,则默认是JNI 1.1版本)。
应用层的Java类别通过VM而调用到native函数。一般是通过VM去寻找*.so里的native函数。如果需要连续呼叫很多次,每次都需要寻找一遍,会多花许多时间。此时,C组件开发者可以将本地函数向VM进行注册,以便能加快后续调用native函数的效率.可以这么想象一下,假设VM内部一个native函数链表,初始时是空的,在未显式注册之前此native函数链表是空的,每次java调用native函数之前会首先在此链表中查找需要查找需要调用的native函数,如果找到就直接使用,如果未找到,得再通过载入的.so文件中的函数列表中去查找,且每次java调用native函数都是进行这样的流程,因此,效率就自然会下降,为了克服这样现象,我们可以通过在.so文件载入初始化时,即JNI_OnLoad函数中,先行将native函数注册到VM的native函数链表中去,这样一来,后续每次java调用native函数时都会在VM中的native函数链表中找到对应的函数,从而加快速度
第四种方式:反调试异常检测
这种方式其实是为了应对现在很多破解者使用IDA进行动态方式调试so文件,从而获取重要的信息,如果还不知道如何使用IDA进行动态调试so文件的同学可以查看这篇文章:Android中使用IDA进行动态调试so文件 ,看完这篇文章之后,我们可以知道IDA进行so动态调试是基于进程的注入技术,然后使用Linux中的ptrace机制,进行调试目标进程的,那么ptrace机制有一个特点,就是如果一个进程被调试了,在他进程的status文件中有一个字段TracerPid会记录调试者的进程id值,比如:
查看文件:/proc/[myPid]/status
在第六行,有一个TracerPid字段,就是记录了调试者的进程id
那么我们就可以这么做来达到反调试的功效了,就是我们可以轮训的遍历自己进程的status文件,然后读取TracerPid字段值,如果发现他大于0,那么就代表着自己的应用在被人调试,所以就立马退出程序。原理知道了,代码实现也很简单,这里用pthread创建一个线程,然后进行轮训操作:
使用pthread_create创建一个线程,线程启动之后执行thread_function函数
看看thread_funcation函数:
开始轮训,读取TracerPid字段的值,发现大于0,就立马退出程序,我们运行结果看看:
android 防止反编译的若干方法的更多相关文章
- Android apk反编译基础(apktoos)图文教程
本文主要介绍了Android apk反编译基础,使用的工具是apktoos,我们将用图文的方式说明apktoos工具的使用方式,你可以参考这个方法反编译其它APK试试看了 很久有写过一个广工图书馆主页 ...
- Xamarin android如何反编译apk文件
Xamarin android 如何反编译 apk文件 这里推荐一款XamarinAndroid开发的小游戏,撸棍英雄,游戏很简单,的确的是有点大.等一下我们来翻翻译这个Xamarin Android ...
- 《Android逆向反编译代码注入》 - 逆向安全入门必看视频教程
适合人群: Android开发人员.逆向反编译开发人员.以及对Android逆向安全感兴趣的朋友. 视频地址: 51CTO学院:https://edu.51cto.com/course/24485 ...
- [Android]apk反编译方法
在学习Android开发的过程你,你往往会想去学习别人的apk是怎么开发的,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看.下面是我参考了一些 ...
- android app反编译
最新在反编译别人的apk,有时候看到别人的app有很炫的效果,就想知道别人是怎么样实现的,顺便自己参考,借鉴一下,下一次如果工作中碰到这个问题就知道怎么实现了.最近恰好放假三天,就研究了一下,一般别人 ...
- 【转】Android APK反编译就这么简单 详解(附图)
转载地址:http://blog.csdn.net/vipzjyno1/article/details/21039349 在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂 ...
- Android APK反编译详解(附图)
转载自http://blog.csdn.net/sunboy_2050/article/details/6727581 这段时间在学Android应用开发,在想既然是用Java开发的应该很好反编译从而 ...
- Android APK反编译easy 详解
在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用 ...
- Android APK反编译就这么简单 详解(附图)
在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用 ...
随机推荐
- 【学习笔记】启动Nginx、查看nginx进程、查看nginx服务主进程的方式、Nginx服务可接受的信号、nginx帮助命令、Nginx平滑重启、Nginx服务器的升级
1.启动nginx的方式: cd /usr/local/nginx ls ./nginx -c nginx.conf 2.查看nginx的进程方式: [root@localhost nginx] ...
- 分析MapReduce执行过程+统计单词数例子
MapReduce 运行的时候,会通过 Mapper 运行的任务读取 HDFS 中的数据文件,然后调用自己的方法,处理数据,最后输出.Reducer 任务会接收 Mapper 任务输出的数据,作为自己 ...
- 3.关于QT中的MainWindow窗口,MenuBar,ToolBar,QuickTip等方面的知识点
1 新建一个空Qt项目 编写12MainWindow.pro HEADERS += \ MyMainWindow.h \ MyView.h SOURCES += \ MyMainWindow.c ...
- Emojicon表情之快速应用于Android项目
最近在项目中遇到了一个问题,找了半天原因,最后发现是用户在昵称中输入了emojicon表情,导致服务器不识别出现错误,而项目中也未对emojicon表情作支持,因此不得不考虑对emojicon表情做下 ...
- RDD:基于内存的集群计算容错抽象
转载自:http://shiyanjun.cn/archives/744.html 摘要 本文提出了分布式内存抽象的概念--弹性分布式数据集(RDD,Resilient Distributed Dat ...
- 让 Google Test 出错时断点
Google Test 缺省是出错退出. 如果最后的出错行在系统库中,那就没什么帮助. 如果是调试运行,直接退出根本就不知道哪里出错了. 后来添加了一个运行参数: --gtest_break_on_f ...
- 【转载】图灵AngularJS入门教程
摘自图灵的AngularJS入门教程:http://www.ituring.com.cn/article/13471 感觉非常不错,所以推荐到首页一下! (一)Hello World! 开始学习Ang ...
- Android初级教程三个Dialog对话框小案例
这里把三个对话框形式写在一个项目程序里面,用三个按钮控制显示什么样式的对话框. 先看布局文件代码: <LinearLayout xmlns:android="http://schema ...
- 如何在Cocos2D游戏中实现A*寻路算法(六)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- Android的原始资源Raw和Assert资源的使用-android学习之旅(五十七)
代码示例 public class MainActivity extends Activity{ MediaPlayer mediaPlayer1,mediaPlayer2; @Override pr ...