本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78237571

1.调用Debug.isDebuggerConnected函数这种反调试的Android加固比较少,主要是因为Debug.isDebuggerConnected这种方法的反调试作用不大,过掉也比较容易。百度的Android应用加固使用了调用Debug.isDebuggerConnected函数检测程序被调试的反调试方法。

2.绕过基于Debug.isDebuggerConnected函数检测进行反调试的方法整理:

【1】.对基于Debug.isDebuggerConnected函数检测进行反调试的百度加固的Android应用使用Apktool工具进行解包处理,在解包后的所有smali文件中全局搜索关键字符串“isDebuggerConnected”,查找到Debug.isDebuggerConnected函数检测反调试的smali汇编代码的位置,修改smali代码检测位置处的判断条件
绕过Debug.isDebuggerConnected函数检测的反调试,使用Apktool工具对解包修改后的百度加固的Android应用的smali文件进行重新打包和签名处理,推荐使用AndroidKiller工具进行这所有的操作。

【2】.在 Dalvik模式下 进行百度加固的Andorid应用的动态so库文件调试时,使用IDA脚本IDC文件 Hook VMDebug.isDebuggerConnected函数的Native层实现函数dvmDbgIsDebuggerConnected,修改dvmDbgIsDebuggerConnected函数的返回值(基于VMDebug.isDebuggerConnected函数的Nativev层的函数dvmDbgIsDebuggerConnected)并且dvmDbgIsDebuggerConnected函数在libdvm.so库文件中还是导出函数,具体的原理参考《在百度加固中正确使用ida的姿势》。

Hook dvmDbgIsDebuggerConnected函数的IDA脚本(至于脚本中,第一次r0寄存器的值为1的时候为什么不改成0 ,需要参考一下Android源码的实现才能理解)。

from idaapi import *
from idc import * debug_addr = LocByName("_Z25dvmDbgIsDebuggerConnectedv")
end = FindFuncEnd(debug_addr) - 0x02
count = 0; class DumpHook(DBG_Hooks):
def dbg_bpt(self,tid,ea):
global count
r0 = GetRegValue('r0')
if r0 == 1:
count = count + 1
if count == 2:
SetRegValue(0,"r0")
ResumeProcess()
return 0 AddBpt(end)
debug = DumpHook()
debug.hook() print "hook"

dalvik虚拟机模式 下,VMDebug.isDebuggerConnected函数最终调用的是Native函数 dvmDbgIsDebuggerConnected

函数dvmDbgIsDebuggerConnected
libdvm.so库文件 中的导出函数

art虚拟机模式 下,VMDebug.isDebuggerConnected函数最终调用的是Native函数art::Dbg::IsDebuggerActive

函数art::Dbg::IsDebuggerActive
libart.so库文件 中的导出函数

【3】.解包百度加固的Android应用,把百度加固的 libbaiduprotect.so 库文件单独拿出来,自己编写一个dalvik虚拟机模式下的 loader程序 调用百度加固的 libbaiduprotect.so 库文件中的JNI_Onload函数bypass掉壳代码和反调试,具体的方法可以参考看雪论坛的文章《百度加固逆向分析》。

#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <jni.h> int main()
{
JavaVM* vm;
JNIEnv* env;
jint res; JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=.";
vm_args.version=0x00010002;
vm_args.options=options;
vm_args.nOptions =1;
vm_args.ignoreUnrecognized=JNI_TRUE; printf("[+] dlopen libdvm.so\n");
// RTLD_LAZY RTLD_NOW
void *handle = dlopen("/system/lib/libdvm.so", RTLD_LAZY);
if(!handle) { printf("[-] dlopen libdvm.so failed!!\n");
return 0;
} // 先创建一个java虚拟机。因为JNI_ONload函数参数第一个参数为JavaVM。
typedef int (*JNI_CreateJavaVM_Type)(JavaVM**, JNIEnv**, void*);
JNI_CreateJavaVM_Type JNI_CreateJavaVM_Func = (JNI_CreateJavaVM_Type)dlsym(handle, "JNI_CreateJavaVM");
if(!JNI_CreateJavaVM_Func) { printf("[-] dlsym failed\n");
return 0;
} // 创建java虚拟机
res = JNI_CreateJavaVM_Func(&vm, &env, &vm_args)
void* si = dlopen("/data/local/tmp/libbaiduprotect.so", RTLD_LAZY);
if(si == NULL) { printf("[-] dlopen err!\n");
return 0;
} typedef jint (*FUN)(JavaVM* vm, void* res);
FUN func_onload = (FUN)dlsym(si, "JNI_OnLoad");
// 将断点下在了这里可以正好获取到JNI_Onload的函数地址。
if(func_οnlοad==NULL)
return 0; // 调用JNI_Onload函数
func_onload(vm,NULL);
return 0;
}

关于Android系统上dalvik虚拟机模式下java虚拟机的创建方法,可以参考书籍《Android框架揭秘》102页~110页中,关于dalvik虚拟机模式下java虚拟机创建的代码分析。

Dalvik虚拟机模式下,java虚拟机的创建可以参考Andorid 4.4.4 r1的源码文件 /dalvik/vm/Jni.cpp  中的代码。

http://androidxref.com/4.4.4_r1/xref/dalvik/vm/Jni.cpp#3424

Art虚拟机模式下,java虚拟机的创建可以参考Android 4.4.4 r1的源码文件 /art/runtime/jni_internal.cc 中的代码。

http://androidxref.com/4.4.4_r1/xref/art/runtime/jni_internal.cc#2888

【4】.自己编写个简单的Android程序,自定义加载百度加固的动态库文件libbaiduprotect.so,然后在这个Android应用的基础上进行百度加固动态库文件libbaiduprotect.so的动态调试。

3.这里再介绍一种 手动绕过百度加固Debug.isDebuggerConnected反调试的方法,比较实用也比较简单不需要太多的操作。在介绍这种手动过掉Debug.isDebuggerConnected函数反调试的方法之前,先了解一下Debug.isDebuggerConnected函数的执行流程,以Android
4.4.4 r1的源码为分析基础。

【1】.Debug.isDebuggerConnected函数是在Android 4.4.4 r1源码的文件 /frameworks/base/core/java/android/os/Debug.java 中实现的,该函数最终调用的是VMDebug.isDebuggerConnected函数。

http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/os/Debug.java#isDebuggerConnected

【2】.VMDebug.isDebuggerConnected函数是在Native层实现的,在Android 4.4.4 r1源码的文件 /libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
中,到这里Debug.isDebuggerConnected函数的java层实现已经基本完成了,接下来是Debug.isDebuggerConnected函数在Native层的实现,由于Android系统可以运行在Dalvik虚拟机模式下或者Art虚拟机模式下,因此在Dalvik虚拟机模式下和Art虚拟机模式下,Debug.isDebuggerConnected函数底层的具体实现会有有所不同,需要分开来分析和学习。

http://androidxref.com/4.4.4_r1/xref/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java#122

【3】.在dalvik虚拟机模式下,VMDebug.isDebuggerConnected函数是在Android 4.4.4 r1源码的文件/dalvik/vm/native/dalvik_system_VMDebug.cpp
中实现的,具体就是对应Native层的函数Dalvik_dalvik_system_VMDebug_isDebuggerConnected

http://androidxref.com/4.4.4_r1/xref/dalvik/vm/native/dalvik_system_VMDebug.cpp#Dalvik_dalvik_system_VMDebug_isDebuggerConnected

Dalvik_dalvik_system_VMDebug_isDebuggerConnected函数的实现,Dalvik_dalvik_system_VMDebug_isDebuggerConnected最终调用的是libdvm.so库文件的导出函数dvmDbgIsDebuggerConnected

【4】.dvmDbgIsDebuggerConnected函数是在Android 4.4.4 r1源码的文件 /dalvik/vm/Debugger.cpp 中实现的,最终Debug.isDebuggerConnected函数的返回值是由全局对象gDvm的成员变量gDvm.debuggerActive决定的。

http://androidxref.com/4.4.4_r1/xref/dalvik/vm/Debugger.cpp#443

【5】.在art虚拟机模式下,VMDebug.isDebuggerConnected函数是在Android
4.4.4 r1源码的文件 /art/runtime/native/dalvik_system_VMDebug.cc 中实现的,具体就是实现函数VMDebug_isDebuggerConnected

【6】.VMDebug_isDebuggerConnected函数最终是调用的
Dbg::IsDebuggerActive
函数。

http://androidxref.com/4.4.4_r1/xref/art/runtime/native/dalvik_system_VMDebug.cc#117

【7】.Dbg::IsDebuggerActive
函数是在Android 4.4.4 r1源码文件 /art/runtime/debugger.cc 中实现的,具体就是获取全局变量gDebuggerActive的状态值。

http://androidxref.com/4.4.4_r1/xref/art/runtime/debugger.cc#578

4.Debug.isDebuggerConnected函数的底层实现已经分析差不多啦,下面就说下
Dalvik虚拟机模式下 手动Debug.isDebuggerConnected反调试的方法。关于Android应用so库文件的动态调试就不详细介绍了,网上的教程很多自己去看。

【A】.由于Dalvik虚拟机模式下,函数dvmDbgIsDebuggerConnectedlibdvm.so库文件
中的导出函数,因此在进行Dalvik虚拟机模式下的so库文件的

动态调试时,想要 过掉Debug.isDebuggerConnected函数的反调试 需要在 libdvm.so库文件 的dvmDbgIsDebuggerConnected函数开头和结尾的位置下断点进行拦截,然后修改dvmDbgIsDebuggerConnected函数的返回值为0即可。

【B】.由于Art虚拟机模式下,函数art::Dbg::IsDebuggerActivelibart.so库文件
中的导出函数,因此在进行Art虚拟机模式下的so库文件的

动态调试时,想要 过掉Debug.isDebuggerConnected函数的反调试 需要在libart.so库文件art::Dbg::IsDebuggerActive函数开头和结尾的位置下断点进行拦截,然后修改art::Dbg::IsDebuggerActive函数的返回值为0即可。

下面就以dalvik虚拟机模式下的百度加固的 libbaiduprotect.so 库文件动态调试为例,进行手动绕过百度加固Debug.isDebuggerConnected反调试的方法步骤说明。

【1】.百度加固的Android应用以调试模式启动等待调试以后,IDA Pro附加调试该百度加固的Android应用成功以后如下图设置IDA Pro的调试运行选项,并在libdvm.so库文件
的dvmDbgIsDebuggerConnected函数开头和结尾的位置下断点进行拦截,然后F9
运行当前被附加的Android应用程序几次,不过F9运行当前被附加的程序几次以后,该应用程序会断在dvmDbgIsDebuggerConnected函数的开头或者结尾的位置即当前函数断点被触发啦,没事,不用理会,继续做下面的操作即可。

【2】.另开启一个命令行终端Terminate,使用 jdb调试器 连接到被调试附加百度加固的Android应用,jdb调试器连接成功以后,dvmDbgIsDebuggerConnected函数开头的断点会被触发,断在dvmDbgIsDebuggerConnected函数开头的位置,再F9运行1次
断在dvmDbgIsDebuggerConnected函数结尾的位置,此时dvmDbgIsDebuggerConnected函数的返回值R0的值为1(不做任何操作继续F9运行),将第2次dvmDbgIsDebuggerConnected函数的返回值R0的值1修改为0
即可手动绕过百度加固Debug.isDebuggerConnected的反调试(千万记得:jdb附加之后,是修改dvmDbgIsDebuggerConnected函数第2次返回值1为0)。

手动绕过百度加固Debug.isDebuggerConnected反调试的方法的更多相关文章

  1. 解决Android加固多进程ptrace反调试的思路整理

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/53613481 一.Android多进程反调试的原理代码 当ptrace附加目标进程 ...

  2. so层反调试方法以及部分反反调试的方法

    1.检测ida远程调试所占的常用端口23946,是否被占用 //检测idaserver是否占用了23946端口 void CheckPort23946ByTcp() { FILE* pfile=NUL ...

  3. C/C++ 程序反调试的方法

    C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...

  4. APP加固反调试(Anti-debugging)技术点汇总

    0x00 时间相关反调试 通过计算某部分代码的执行时间差来判断是否被调试,在Linux内核下可以通过time.gettimeofday,或者直接通过sys call来获取当前时间.另外,还可以通过自定 ...

  5. angr进阶(6)绕过反调试

    angr绕过反调试,一个是通过之前的方式,使用从特定位置开始测试的方法,还有一种通过hook进行反调试的方法. 其原理就在于angr能够符号化表示函数tumctf2016_zwiebe p.hook_ ...

  6. Windows 32位-调试与反调试

    1.加载调试符号链接文件并放入d:/symbols目录下. 0:000> .sympath srv*d:\symbols*http://msdl.microsoft.com/download/s ...

  7. 修改Android手机内核,绕过反调试

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/57086486 0x1.手机设备环境 Model number: Nexus 5 O ...

  8. 编译Android内核 For nexus 5 以及绕过Android的反调试

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/54880488 前面的博客中已经记录了Nexus 5手机的Android 4.4.4 ...

  9. 一种绕过PTRACE反调试的办法

    Linux 系统gdb等调试器,都是通过ptrace系统调用实现.Android加固中,ptrace自身防止调试器附加是一种常用的反调试手段. 调试时一般需要手工在ptrace处下断点,通过修改ptr ...

随机推荐

  1. Percona XtraDB Cluster之流量控制

    什么是流量控制? Percona XtraDB Cluster具有一种称为流控制的自调节机制.该机制有助于避免集群中最弱/最慢的成员明显落后于集群中其他成员的情况. 当集群成员在写数据很慢(同时又继续 ...

  2. Maven基础&&Spring框架阶段常用工具类整理

    常用工具类 1.密码加密工具类: package com.itheima.utils; import java.security.MessageDigest; import sun.misc.BASE ...

  3. 前端笔记:React的form表单全部置空或者某个操作框置空的做法

    1.全部置空的做法,一般在弹出框关闭后,需要重置该form所有表单: this.props.form.resetFields(); 2.针对某个操作框置空的做法 例如,form表单里有一个部门和一个张 ...

  4. centos系统mysql忘记密码

    安装 mysql 之后,注意添加软连接 mysql 忘记密码操作, vim /etc/my.cnf 在 [mysqld] 的段中加上一句:skip-grant-tables 重启 mysql 服务, ...

  5. P3388 【模板】割点(割顶) 题解 (Tarjan)

    题目链接 P3388 [模板]割点(割顶) 解题思路 最近学的东西太杂了,多写点博客免得自己糊里糊涂的过去了. 这个题求割点,感觉这篇文章写得挺好. 割点是啥?如果去掉这个点之后连通图变成多个不连通图 ...

  6. 利用kali系统制作最简单的OS

    制作最简单的OS 一.生成.bin文件 1.创建Boot.asm文件,输入相应的汇编代码 org 07c00h ; mov ax, cs mov ds, ax mov es, ax call Disp ...

  7. 07、列表list

    列表(list) 是一个有序且可变的容器,在里面可以存放多个不同类型的元素 list = ['阿斯顿','阿发师','收发室'] list = [98,88,66,-1] list = [1,True ...

  8. 《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口

    <C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户 ...

  9. 2021华为软件精英挑战赛(C/C++实现)-苦行僧的实现过程

    下面给出2021华为软件精英挑战赛参与的整个过程,虽然成绩不是很好,但是也是花了一些时间的,希望后面多多学习,多多进步. 代码已经上传到了Github上:https://github.com/myFr ...

  10. 【工程应用一】 多目标多角度的快速模板匹配算法(基于NCC,效果无限接近Halcon中........)

    愿意写代码的人一般都不太愿意去写文章,因为代码方面的艺术和文字中的美学往往很难兼得,两者都兼得的人通常都已经被西方极乐世界所收罗,我也是只喜欢写代码,让那些字母组成美妙的歌曲,然后自我沉浸在其中自得其 ...