ANDROID调试检测技术汇编

上传人:n**** 文档编号:45911142 上传时间:2018-06-20 格式:PDF 页数:23 大小:572.11KB
返回 下载 相关 举报
ANDROID调试检测技术汇编_第1页
第1页 / 共23页
ANDROID调试检测技术汇编_第2页
第2页 / 共23页
ANDROID调试检测技术汇编_第3页
第3页 / 共23页
ANDROID调试检测技术汇编_第4页
第4页 / 共23页
ANDROID调试检测技术汇编_第5页
第5页 / 共23页
点击查看更多>>
资源描述

《ANDROID调试检测技术汇编》由会员分享,可在线阅读,更多相关《ANDROID调试检测技术汇编(23页珍藏版)》请在金锄头文库上搜索。

1、ANDROID调试检测技术汇编1 调试器调试端口2 调试器进程名3 父进程名检测4 自身进程名检测5 apk线程检测6 apk进程fd文件检测7 安卓系统自带调试检测函数8 ptrace检测9 函数hash值检测10 断点指令检测11 系统源码修改检测12 单步调试陷阱13 利用IDA先截获信号特性的检测14 利用IDA解析缺陷反调试15 五种代码执行时间检测16 三种种进程信息结构检测17 Inotify事件监控dump1. IDA调试端口检测原理: 调试器远程调试时,会占用一些固定的端口号。做法: 读取/proc/net/tcp,查找IDA远程调试所用的23946端口,若发现说明进程正在被

2、IDA调试。(也可以运行netstat apn结果中搜索23946端口)void CheckPort23946ByTcp() FILE* pfile=NULL; char buf0x1000=0; / 执行命令 char* strCatTcp= “cat /proc/net/tcp |grep :5D8A“; /char* strNetstat=“netstat |grep :23946“; pfile=popen(strCatTcp,“r“); if(NULL=pfile) LOGA(“CheckPort23946ByTcp popen打开命令失败!n“); return; / 获取结果 w

3、hile(fgets(buf,sizeof(buf),pfile) / 执行到这里,判定为调试状态 LOGA(“执行cat /proc/net/tcp |grep :5D8A的结果:n“); LOGB(“%s“,buf); /while pclose(pfile); 2. 调试器进程名检测原理: 远程调试要在手机中运行android_server gdbserver gdb等进程。做法: 遍历进程,查找固定的进程名,找到说明调试器在运行。void SearchObjProcess() FILE* pfile=NULL; char buf0x1000=0; / 执行命令 /pfile=popen

4、(“ps | awk print $9“,“r“); / 部分不支持awk命令 pfile=popen(“ps“,“r“); if(NULL=pfile) LOGA(“SearchObjProcess popen打开命令失败!n“); return; / 获取结果 LOGA(“popen方案:n“); while(fgets(buf,sizeof(buf),pfile) / 打印进程 LOGB(“遍历进程:%sn“,buf); / 查找子串 char* strA=NULL,strB=NULL,strC=NULL,strD=NULL; strA=strstr(buf,“android_serve

5、r“); strB=strstr(buf,“gdbserver“); strC=strstr(buf,“gdb“); strD=strstr(buf,“fuwu“); if(strA | strB |strC | strD) / 执行到这里,判定为调试状态 LOGB(“发现目标进程:%sn“,buf); /if /while pclose(pfile); 3 父进程名检测原理: 有的时候不使用apk附加调试的方法进行逆向,而是写一个.out可执行文件直接加载so进行调试,这样程序的父进程名和正常启动apk的父进程名是不一样的。测试发现: (1)正常启动的apk程序:父进程是zygote (2)

6、调试启动的apk程序:在AS中用LLDB调试发现父进程还是zygote (3)附加调试的apk程序:父进程是zygote (4)vs远程调试 用可执行文件加载so:父进程名为gdbserver 结论:父进程名非zygote的,判定为调试状态。做法: 读取/proc/pid/cmdline,查看内容是否为zygotevoid CheckParents() / / 设置buf char strPpidCmdline0x100=0; snprintf(strPpidCmdline, sizeof(strPpidCmdline), “/proc/%d/cmdline“, getppid(); / 打开

7、文件 int file=open(strPpidCmdline,O_RDONLY); if(filed_name0 d_name0 = 0) +Count; LOGB(“%d 线程名称:%sn“,Count,pde-d_name); LOGB(“线程个数为:%d“,Count); if(1=Count) / 此处判定为调试状态. LOGA(“调试状态!n“); int i=0; return; 6 apk进程fd文件检测原理: 根据/proc/pid/fd/路径下文件的个数差异,判断进程状态。 (apk启动的进程和非apk启动的进程fd数量不一样) (apk的debug启动和正常启动,进程fd

8、数量也不一样)代码: 略7 安卓系统自带调试检测函数/ android.os.Debug.isDebuggerConnected() 原理: 分析android自带调试检测函数isDebuggerConnected()在native的实现, 尝试在native使用。做法: (1)dalvik模式下: 找到进程中libdvm.so中的dvmDbgIsDebuggerConnected()函数, 调用他就能得知程序是否被调试。 dlopen(/system/lib/libdvm.so) dlsym(_Z25dvmDbgIsDebuggerConnectedv)(2)art模式下: art模式下,结

9、果存放在libart.so中的全局变量gDebuggerActive中, 符号名为_ZN3art3Dbg15gDebuggerActiveE。 但是貌似新版本android不允许使用非ndk原生库,dlopen(libart.so)会失败。 所以无法用dalvik那样的方法了。 有一种麻烦的方法,手动在内存中搜索libart模块,然后手工寻找该全局变量符号。/ 只写了dalvik的代码,art的就不写了 typedef unsigned char wbool; typedef wbool (*PPP)(); void NativeIsDBGConnected() void* Handle=NU

10、LL; Handle=dlopen(“/system/lib/libdvm.so“, RTLD_LAZY); if(NULL=Handle) LOGA(“dlopen打开libdvm.so失败!n“); return; PPP Fun = (PPP)dlsym(Handle, “_Z25dvmDbgIsDebuggerConnectedv“); if(NULL=Fun) LOGA(“dlsym获取_Z25dvmDbgIsDebuggerConnectedv失败!n“); return; else wbool ret = Fun(); if(1=ret) / 此处判定为调试模式 LOGA(“da

11、lvikm模式,调试状态!n“); return; return; 8 ptrace检测原理: 每个进程同时刻只能被1个调试进程ptrace,再次p自己会失败。做法: 1 主动ptrace自己,根据返回值判断自己是否被调试了。 2 或者多进程ptrace。/ 单线程ptrace void ptraceCheck() / ptrace如果被调试返回值为-1,如果正常运行,返回值为0 int iRet=ptrace(PTRACE_TRACEME, 0, 0, 0); if(-1 = iRet) LOGA(“ptrace失败,进程正在被调试n“); return; else LOGB(“ptrace

12、的返回值为:%dn“,iRet);return; 9 函数hash值检测原理: so文件中函数的指令是固定,但是如果被下了软件断点,指令就会发生改变(断点地址被改写为bkpt断点指令),可以计算内存中一段指令的hash值进行校验,检测函数是否被修改或被下断点。代码: 略10 断点指令检测原理: 上面说了,如果函数被下软件断点,则断点地址会被改写为bkpt指令, 可以在函数体中搜索bkpt指令来检测软件断电。/ IDA 6.8 断点扫描 / 参数1:函数首地址 参数2:函数size typedef uint8_t u8; typedef uint32_t u32; void checkbkpt(

13、u8* addr,u32 size) / 结果 u32 uRet=0; / 断点指令 / u8 armBkpt4=0xf0,0x01,0xf0,0xe7; / u8 thumbBkpt2=0x10,0xde; u8 armBkpt4=0; armBkpt0=0xf0; armBkpt1=0x01; armBkpt2=0xf0; armBkpt3=0xe7; u8 thumbBkpt2=0; thumbBkpt0=0x10; thumbBkpt1=0xde; / 判断模式 int mode=(u32)addr%2; if(1=mode) LOGA(“checkbkpt:(thumb mode)该

14、地址为thumb模式n“); u8* start=(u8*)(u32)addr-1); u8* end=(u8*)(u32)start+size); / 遍历对比 while(1) if(start = end) uRet=0; LOGA(“checkbkpt:(no find bkpt)没有发现断点.n“); break; if( 0=memcmp(start,thumbBkpt,2) ) uRet=1; LOGA(“checkbkpt:(find it)发现断点.n“); break; start=start+2; /while /if else LOGA(“checkbkpt:(arm

15、mode)该地址为arm模式n“); u8* start=(u8*)addr; u8* end=(u8*)(u32)start+size); / 遍历对比 while(1) if (start = end) uRet = 0; LOGA(“checkbkpt:(no find)没有发现断点.n“); break; if (0 = memcmp(start,armBkpt , 4) uRet = 1; LOGA(“checkbkpt:(find it)发现断点.n“); break; start = start + 4; /while /else return; 11 系统源码修改检测原理: 安卓native下最流行的反调试方案是读取进程的status或stat来检测tracepid,原理是调试状态下的进程tracepid不为0。对于这种调试检测手段,最彻底的绕过方式是修改系统源码后重新编译,让tracepid永远为0。对抗这种bypass手段,我们可以创建一个子进程,让子进程主动ptrace自身设为调试状态,此时正常情况下,子进程的tracepid应该不为0。此时我们检测子进程的tracepid是否为

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 电子/通信 > 综合/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号