so层反调试方法以及部分反反调试的方法
1.检测ida远程调试所占的常用端口23946,是否被占用
//检测idaserver是否占用了23946端口
void CheckPort23946ByTcp() {
FILE* pfile=NULL;
char buf[0x1000]={0};
//执行命令
char* strCatTcp="cat /proc/net/tcp | grep :5D8A";
//char* strNetstat="netstat -apn | grep :23946"
pfile=popen(strCatTcp,"r");
//说明是没有被调试
if(NULL==pfile)
{
return;
}
//获取执行命令后的结果,并存入buf字符数组中
while(fgets(buf,sizeof(buf),pfile))
{
printf("执行 cat /proc/net/tcp | grep :5D8A的结果:\n");
printf("%s",buf);
}
pclose(pfile);
}
上面的netstat -apn | grep 23946 那个-apn是必须加的,之前看大佬的pdf好像漏了
反反调试方法:
1.直接nop掉
2.汇编级直接改寄存器值绕过
3. 既然是检测23946端口,那我就不运行在23946端口了,换一个端口运行
二.调试器进程名检测
原理: android调试时需要运行androidserver,androidserver64,gdb,gdbserver等进程
反调试代码:
void SerachObjectProcess()
{
FILE* pfile=NULL;
char buf[0x1000]={0};
//执行命令
//pfile=popen("ps | awk'{print $9}'","r");
pfile=popen("ps","r");
if(pfile==NULL) {
printf("命令打开失败");
return;
}
//获取查询结果
while(fgets(buf,sizeof(buf),pfile))
{
//打印进程
printf("遍历进程:%s\n",buf);
//查找子串
char* strA=NULL;
char *strB = NULL;
char *strC=NULL;
char *strD=NULL;
//IDA检测
strA=strstr(buf,"android_server");
//gdb检测
strB=strstr(buf,"gdbserver");
strC=strstr(buf,"gdb");
strD=strstr(buf,"fuwu");
if(strA||strB||strC||strD) {
printf("被调试了,%s\n", buf);
return;
}
}
pclose(pfile); }
反反调试:
直接修改调试器server的名字,运行的话./自定义的server名字 -p xxxx(自定义端口)
三.父进程名检测
原理:附加调试时,父进程名都为zygote,有时候调试会使用可执行文件直接加载so文件进行调试,所以如果父进程名非zygote的话,必然是被调试的,充分非必要条件
反调试代码:
void CheckParents()
{
char strPpidCmdline[0x100]={0};
snprintf(strPpidCmdline, sizeof(strPpidCmdline),"proc/%d/cmdline",getppid());
int file=open(strPpidCmdline,O_RDONLY);
if(file<0)
{
printf("打开文件错误");
return;
}
//初始化一下
memset(strPpidCmdline,0, sizeof(strPpidCmdline));
//将文件内容读入内存中,方便比较
ssize_t ret=read(file,strPpidCmdline, sizeof(strPpidCmdline));
if(-1==ret)
{
printf("读入内存失败");
return;
}
char* sRet=strstr(strPpidCmdline,"zygote");
if(sRet==NULL)
{
printf("被调试了");
return;
}
int i=0;
return;
}
反反调试:
那就直接附加调试呗,其他方法暂时我也不知道233
四.自身进程名检测
原理: 和上文一样如果用可执行文件加载so配合脱壳的话,进程名也会发生改变,检测是否是apk那种com.xxx.xx
五:检测线程的数量
原理: 正常apk启动时是要有许多进程要启动的,而如果用可执行文件加载so文件,那么必然只有一个线程
反调试代码:
void CheckTaskCount()
{
char buf[0x100]={0};
char* str="/proc/%d/task";
snprintf(buf,sizeof(buf),str,getpid());
//打开目录
DIR* pdir=opendir(buf);
if(!pdir)
{
perror("CheckTaskCount open() fail.\n");
return;
}
//查看目录下文件的个数
struct dirent* pde=NULL;
int count=0;
while((pde=readdir(pdir)))
{
//字符过滤,每个文件都是一个线程id
if((pde->d_name[0]<='9')&&(pde->d_name[0]>='0'))
{
count++;
printf("%d 线程名称:%s\n",count,pde->d_name);
}
if(count<=1)
{
//说明被调试了
printf("被调试了");
}
return;
} }
https://blog.csdn.net/qq_40732350/article/details/81986548
六:apk进程的fd文件数量差异检测
原理:/proc/pid/fd目录下文件数,调试与非调试fd文件数量不同
七.安卓系统自带的检测函数
android.os.Debug.isDebuggerConnected(),这个函数是在java层中直接调用就行,
但是如果在native层使用这个也是有办法的,
1. dvm下的方式
找到进程中的libdvm.so中的dvmDbgIsDebuggerConnect()函数,调用它,通过返回值来判断程序是否被调试
dlopen(/system/lib/libdvm.so)
dlsym(_Z25dvmDbgIsDebuggerConnect())
typedef unsigned char wbool;
typedef wbool (*ppp)();
void NativeIsDBGConnected()
{
void* Handle=NULL;
Handle=dlopen("/system/lib/libdvm.so",RTLD_LAZY);
if(Handle==NULL)
{
return;
}
ppp Fun=(ppp)dlsym(Handle,"_Z25dvmDbgIsDebuggerConnect"); //根据动态链接库的句柄和符号名,返回地址
if(Fun==NULL) {
printf("获取函数地址失败");
return;
} else
{
wbool ret=Fun();
if(ret==1)
{
printf("被调试了");
return;
}
}
}
2.art模式
结果存放在libart.so中的全局变量gDebuggerActive中,符号名
void checkPtrace()
{
int iRet;
iRet=ptrace(PTRACE_TRACEME,0,0,0);
if(iRet==-1)
{
//说明父进程调试失败,说明进程已经被别的进程ptrace了
printf("已经被调试了!");
return;
} else
{
printf("还没被调试");
}
}
反反调试:
1. 修改系统源码,将ptrace返回值直接返回0
2. hook ptrace
3.nop这个函数,或者汇编级修改寄存器绕过
九.函数hash值检测
原理:文件的函数指令一般固定,如果被下了断点,指令会发生改变(bkpt断点指令),可以计算内存中一段指令的hash值,做校验
十.断点指令检测
和上文一样,如果被下了断点的话,指令会被替换成(bkpt断点指令),那么在内存搜索一下不就完事了吗,注意arm和thumb指令有所区别
反调试代码:
void checkbkpt(u8* addr,u32 size)
{
//结果
u32 uRet=0;
//断点指令
u8 armBkpt[4]={0xf0,0x01,0xf0,0xe7};
u8 thumbBkpt[2]={0x10,0xde};
int mode=(u32)addr%2;
if(1==mode)
{
u8* start=(u8*)((u32)addr-1);
u8* end=(u8*)((u32)start+size);
while(1)
{
if(start>=end)
{
uRet=0;
return;
}
if(0==memcmp(start,thumbBkpt,2))
{
uRet=1;
break;
}
start=start+2;
}
} else{
//arm
u8* start=(u8*)addr;
u8* end=(u8*)((u32)start+size);
while (1)
{
if(start>=end)
{
uRet=0;
return;
}
if(0==memcmp(start,armBkpt,4))
{
uRet=1;
break;
}
start=start+4;
} }
}
十一.安卓系统源码修改反调试
原理: 直接通过修改安卓源码修改,ptrace的返回值,使其永远为零,那么我们可以先自身trace自身,然后再通过子进程再trace一遍,如果还返回为0,说明就有问题。
反调试代码:
未完
so层反调试方法以及部分反反调试的方法的更多相关文章
- 为Eclipse添加反编译插件,更好的调试
为Eclipse添加反编译插件,更好的调试 一般来说,我们的项目或多或少的都会引用一些外部jar包,如果可以查看jar包的源代码,对于我们的调试可以说是事半功倍. 1.下载并安装jad.exe.将ja ...
- dex方法隐藏后的反编译和运行时 效果
隐藏smali方法后 java源码: int b = fun2(); baksmali解释为: invoke-virtual {v1}, <int MainAc ...
- Windows7下驱动开发与调试体系构建——5.实战反调试标记位(NtGlobalFlag)
目录/参考资料:https://www.cnblogs.com/railgunRG/p/14412321.html <加密与解密>P670中,介绍了检查程序是否被调试的第二种方法:查看进程 ...
- 【反编译系列】一、反编译代码(dex2jar + jd-gui)和反编译资源(apktool)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! [反编译系列]二.反编译代码(jeb) [反编译系列]三.反编译神器(jadx) [反编译系列]四.反编译so文件(IDA_Pro) 概述 ...
- PHPstorm破解方法及xdebug的断点调试
原文地址:http://www.php.cn/php-weizijiaocheng-381903.html 相信用PHPstorm的程序员肯定很多,令人头疼的是下载的PHPstorm是有使用期限的,小 ...
- Android开发调试无法连接到夜神模拟器的解决方法
Android开发调试无法连接到夜神模拟器的解决方法: 一般原因是adb的版本不一致造成的!!!!!换成一样的就可以了. 在网上看到的方法,特记录下来: 1.任务管理器里看下,adb.exe以及nox ...
- flask中重定向所涉及的反推:由视图函数反推url
flask中重定向所涉及的反推:由视图函数反推url 例如有视图index() 反推 url的/default # -*- coding: utf-8 -*- from flask import Fl ...
- java远程调试(断点)程序/tomcat( eclipse远程调试Tomcat方法)
tomcat远程调试: 1.Linux中配置tomcat在catalina.sh中添加如下CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_soc ...
- 深入理解为什么Java中方法内定义的内部类可以访问方法中的局部变量
好文转载:http://blog.csdn.net/zhangjg_blog/article/details/19996629 开篇 在我的上一篇博客 深入理解Java中为什么内部类可以访问外部类的成 ...
- 微信调试、API、AJAX的调试 SocketLog
SocketLog适合Ajax调试和API调试, 举一个常见的场景,用SocketLog来做微信调试, 我们在做微信API开发的时候,如果API有bug,微信只提示"改公众账号暂时无法提供服 ...
随机推荐
- Nginx下配置Https 配置文件(vue)
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...
- Web前端自动化测试Cypress实践总结
本文主要首先主要介绍了什么是自动化测试,接着对常用的自动化测试框架进行了对比分析,最后,介绍了如果将自动化测试框架Cypress运用在项目中. 一.自动化测试概述 为了保障软件质量,并减少重复性的测试 ...
- AIFramework基本概念整理
AIFramework基本概念整理 本文介绍: 对天元 MegEngine 框架中的 Tensor, Operator, GradManager 等基本概念有一定的了解: 对深度学习中的前向传播.反向 ...
- Java真的是白天鹅
前言 我最近越来越真切的感受到,Java真的是白天鹅. 这真的是一种羡慕嫉妒恨的感受. 今天和一个Java技术Leader聊天,我告诉他敏捷开发是以人为本,他居然跟我说敏捷开发在行业内有规范,规范是死 ...
- swagger 注解使用
@Api() 用于类:表示标识这个类是swagger的资源 tags–表示说明 value–也是说明,可以使用tags替代 但是tags如果有多个值,会生成多个list @ApiOperation() ...
- mybatis之Param注解
一.作用 使用@Param注解表示给参数命名,名称就是括号中的内容.给参数命名,然后在映射文件中就能根据名称获取参数值了.在mybatis中我们常常要使用到多个参数,但是在xml中的parameter ...
- UiPath中恢复依赖项失败的解决方法
目录 序言 正文 什么是依赖包? 如何查看项目使用了哪些版本的依赖包? 一.项目内查看 二.查看项目的 JSON 文件 问题根源 解决方法 一.「等」字诀 二.切换网络环境(根治) 三.手动复制依赖包 ...
- fiddler抓取手机APP包相关的设置
一.设置手机的代理服务器 1.前提:手机与电脑用的是同一个网络 2.fiddler设置允许远程连接,并设置好端口 3.查询电脑所在网络的ip地址(windows下,命令行窗口使用:ipconfig进行 ...
- 【模拟7.19】那一天我们许下约定(组合数学,DP)
看了题目名字深切怀疑出题人是不是失恋了,然后出题折磨我们.然后这题就愉快的打了个暴力,最后莫名其妙wa20,伤心..... 其实这题正解不是很难想,如果说把暴力的DP搞出来,正解也差不到哪去了, 我们 ...
- 『无为则无心』Python基础 — 9、Python字符串的编码与转义
目录 1.查看变量类型 2.转义字符 (1)转义字符说明 (2)示例 (3)常用转义字符对照表 3.字符编码 (1)字符编码介绍 (2)Python中的字符编码 (3)编码格式应用于不同场景 提示:上 ...