Android安全防护之旅---应用"反调试"操作的几种方案解析

移动开发
在之前介绍了很多破解相关的文章,在这个过程中我们难免会遇到一些反调试策略,当时只是简单的介绍了如何去解决反调试,其实在去年我已经介绍了一篇关于Android中的安全逆向防护之战的文章:Android安全逆向防护解析;那么这篇文章就来详细总结一下,现阶段比较流行的几种反调试解决方案。

一、前言

在之前介绍了很多破解相关的文章,在这个过程中我们难免会遇到一些反调试策略,当时只是简单的介绍了如何去解决反调试,其实在去年我已经介绍了一篇关于Android中的安全逆向防护之战的文章:Android安全逆向防护解析;那么这篇文章就来详细总结一下,现阶段比较流行的几种反调试解决方案。

二、反调试方案分析

***种:先占坑,自己附加

代码非常简单,在so中加上这行代码即可:ptrace(PTRACE_TRACEME, 0, 0, 0);其中PTRACE_TRACEME代表:本进程被其父进程所跟踪。其父进程应该希望跟踪子进程,一般一个进程只能被附加一次,我们在破解调试的时候都会附加需要调试应用的进程,如果我们先占坑,父进程附加自己,那么后面在附加调试就会失败。加上这段代码我们运行之后看一下效果:

 

我们在进行破解动态调试的时候都知道附加进程的status文件中的TracerPid字段就是被调试的进程pid,这里我们运行程序之后,查看进程对应的status文件,发现TracerPid值就是进程的父进程pid值。那么后面如果有进程在想附加调试就是会失败的。这种方式启动一定的调试作用,但是不是绝对安全的。关于解决这种反调试方案后面再说。

第二种:签名校验

其实签名校验,准备来说不算是反调试方案,但是也是一种安全防护策略,就在这里提一下了,而签名校验一般现在有很多用途,用意在于防止二次打包,一般方案有两种:

  • ***:直接在本地做防护,如果发现签名不一致直接退出应用。
  • 第二:将签名信息携带请求参数中参与加密,服务端进行签名校验,失败就返回错误数据即可。

而这两种方式也都不是最安全的防护,因为只要有签名校验的逻辑,在本地都可以进行过滤掉。而在之前的好几篇文章中都介绍了如何过滤这种签名校验的方法,不了解的同学可以去查看:Android中破解某应用的签名校验;而对于服务器签名校验以及将签名校验放到so中的文章后面会单独在介绍一篇。

第三种:调试状态检查

这种方式是纯属借助Android中的api进行检验,有两种方法:

***:检查应用是否属于debug模式

直接调用Android中的flag属性:ApplicationInfo.FLAG_DEBUGGABLE,判断是否属于debug模式:   

 

这个其实就是为了防止现在破解者为了调试应用将应用反编译在AndroidManifest.xml中添加:android:debuggable属性值,将其设置true。然后就可以进行调试。

 

添加这个属性之后,我们可以用 dumpsys package [packagename] 命令查看debug状态:

 

所以我们可以检查应用的AppliationInfo的flag字段是否为debuggable即可。不过这种方式也不是***的,后面会介绍如何解决这种反调试问题。

第二:检查应用是否处于调试状态

这个也是借助系统的一个api来进行判断:android.os.Debug.isDebuggerConnected();这个就是判断当前应用有没有被调试,我们加上这段代码之后,按照之前的那篇文章:脱掉360加固保护壳,其中有一个步骤进行jdb连接操作:

jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700,当连接成功之后,这个方法就会返回true,那么我们可以利用这个api来进行判断当前应用是否处于调试状态来进行反调试操作。但是这种方式不是***的,后面会介绍如何解决这种反调试问题。

第四种:循环检查端口

我们在之前破解逆向的时候,需要借助一个强大利器,那就是IDA,在使用IDA的时候,我们知道需要在设备中启动android_server作为通信,那么这个启动就会默认占用端口23946:

 

我们可以查看设备的tcp端口使用情况 cat /proc/net/tcp:

 

其中5D8A转化成十进制就是23946,而看到uid是0,因为我们运行android_server是root身份的,uid肯定是0了。所以我们可以利用端口检查方式来进行反调试策略,当然这种方式不是***的,后面会详细介绍如何解决这样的反调试方法。

第五种:循环检查TracerPid值

在***种方式中,我们简单的介绍了如果应用被调试了,那么他的TracerPid值就是调试进程的pid值,而在使用IDA进行调试的时候,需要在设备端启动android_server进行通信,那么被调试的进程就会被附加,这就是android_server进程的pid值了:

 

查看一下android_server的pid值:

 

所以我们可以在自己的应用中的native层加上一个循环检查自己status中的TracerPid字段值,如果非0或者是非自己进程pid(如果采用了***种方案的话,这里也是需要做一次过滤的);那么就认为被附加调试了。当然这里还有一种方案,就是可以检查进程列表中有没有android_server进程,不过这种方式都不是***的,后面会详细介绍如何解决这种反调试方案。

三、反调试方案总结

下面简单几句话总结这几种方案:

  • ***、自己附加进程,先占坑,ptrace(PTRACE_TRACEME, 0, 0, 0)!
  • 第二、签名校验不可或缺的一个选择,本地校验和服务端校验双管齐下!
  • 第三、借助系统api判断应用调试状态和调试属性,最基础的防护!
  • 第四、轮训检查android_server调试端口信息和进程信息,防护IDA的一种有效方式!
  • 第五、轮训检查自身status中的TracerPid字段值,防止被其他进程附加调试的一种有效方式!

上面就简单的介绍了现在流行的几种应用反调试策略方案,这几种方案可以全部使用,也可以采用几种使用,但是要记住一点:如果要做到更安全点,记得把反调试方案放到native层中,时机最早,一般在JNI_OnUnload函数里面,为了更安全点,native中的函数可以自己手动注册,函数名自己混淆一下也是可以的。具体可参见这篇文章:Android安全逆向防护解析。现在一些加固平台为了更有效的防护,启动的多进程之间的防护监听,多进程一起参与反调试方案,这种方式对于破解难度就会增大,但是也不是绝对安全的。文章中对于每种方式***都说到了,都不是***安全的,都有方法解决,而这内容放到下一篇来详细介绍了。

反调试方案策略代码下载:

https://github.com/fourbrother/android_anti_debug

四、总结

本文主要介绍了Android中应用在进行反调试反破解的几种方案,对于每种方案进行了详细原理分析,代码也给出了下载地址,可以自行运行看效果,而对于这几种反调试方案并非是绝对安全的,后面会再详细介绍如何解决这些反调试功能,但是为了应用安全,这几种方案也不可以不用,有总比没有好! 

责任编辑:庞桂玉 来源: 编码美丽
相关推荐

2011-01-06 10:58:40

2023-09-05 07:05:35

2010-12-24 12:47:20

2010-09-26 11:29:58

2010-12-21 17:17:21

2011-06-21 09:01:02

2024-10-31 12:15:04

2011-03-25 13:38:58

2010-10-27 14:35:24

2013-04-11 15:04:47

2015-05-12 16:02:32

2009-10-29 14:00:48

2011-03-25 13:35:36

2022-09-07 11:53:00

Web应用安全Web服务程序

2009-12-11 15:28:02

PHP安全防护

2019-10-21 09:02:23

邮件安全网络钓鱼电子邮件

2010-05-27 18:26:53

2010-08-09 12:13:54

2013-07-25 10:03:13

2012-01-13 13:15:56

点赞
收藏

51CTO技术栈公众号