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,微信只提示"改公众账号暂时无法提供服 ...
随机推荐
- 程序"三高"解决方案
0. 程序三高 1. 缓存 2. 预处理和延后处理 3. 池化 3.1 内存池 3.2 线程池 3.3 连接池 4. 异步(回调) 5. 消息队列 5.1 服务解耦 5.2 异步处理 5.3 流量削峰 ...
- minikube与kubectl版本不一致问题
在使用minikube学习的时候,会出现你在mac上安装的minikube默认是最新版本,但是实际情况是需要安装低一些版本.可以按照k8s官方文档安装的时候指定不同安装版本,如果很慢或者无法访问直接走 ...
- kubernetes技能图谱
深入剖析Kubernetes-张磊(Kubernetes社区资深成员与项目维护者) Kubernetes集群搭建 ver1.20.5
- android设置时钟
<TextClock android:id="@+id/timeText" android:layout_width="match_pa ...
- 详述盒子模型(包含padding、border、margin的详细用法和描述)
提起盒子模型,我想无论是对于一个前端资深开发人员还是前端入门开发人员来说都不陌生,这是CSS最基础的知识. 但是惭愧地说,我之前理解的盒子模型,只是文字上的理解.我知道定义一个元素的宽度和高度时,设置 ...
- Win10 安装 Python3 (上)
Python3 For Windows 10 installer 参考 The full installer 安装 随后可以看到,installer 在用户环境变量PATH中,添加了三项: 卸载 使用 ...
- 对狂神的shiro的学习总结
1.shiro的10分钟快速开始 导入依赖 新建一个普通的maven项目,然后new一个hello-shiro(moudle)作为第一个测试项目 具体框架如下: 导入对应的依赖在pom.xml文件里 ...
- uwsgi启动Django应用
uwsgi启动Django应用 uWSGI是一个Web服务器,它实现了WSGI协议.uwsgi.http等协议. WSGI / uwsgi / uWSGI 三者区别: WSGI是一种通信协议,Fl ...
- C# 尝试还原程序包是出错:找不到“XXXXX”版本的程序包“XXXXXX”
在C#管理程序包的时候有时会出现找不到某某版本的程序包 如果出现这样的情况,解决办法是在你当前项目获取当前类库下的packages.config里去删除一段配置就可以解决! 我的缺少的是版本为9.0. ...
- CVPR2020:点云分析中三维图形卷积网络中可变形核的学习
CVPR2020:点云分析中三维图形卷积网络中可变形核的学习 Convolution in the Cloud: Learning Deformable Kernels in 3D Graph Con ...