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,微信只提示"改公众账号暂时无法提供服 ...
随机推荐
- MyBatis 延迟加载(十四)
什么是延迟加载 延迟加载又叫懒加载,也叫按需加载,也就是说先加载主表信息,需要的时候,再去加载从表信息.代码中有查询语句,当执行到查询语句时,并不是马上去数据库中查询,而是根据设置的延迟策略将查询向后 ...
- linux 创建网桥
由于最近项目需验证个问题,需求是要创建一个虚拟机网桥,在使用ifconfig命令查看时让docker0网桥不在第一个显示,因此,我们创建一个虚拟网桥让它排在第一位置 项目使用Centos7系统,因此使 ...
- IDEA中配置maven 全解析教程(Day_08)
每一个你讨厌的现在,都有一个不够努力的曾经. 一.选择一个maven的版本下载 本文中 maven 下载链接:(apache-maven-3.5.2.rar) https://files-cdn.cn ...
- Kubernetes-3.3:ETCD集群搭建及使用(https认证+数据备份恢复)
etcd集群搭建 环境介绍 基于CentOS Linux release 7.9.2009 (Core) ip hostname role 172.17.0.4 cd782d0a790b etcd1 ...
- Qt 圆角按钮,面版自动布局
一.前言 在部分界面开发中,有时需要动态添加控件或按钮到面板中,在不需要时又需要删除该控件,故模仿视频开发中的设置屏蔽词,通过自己绘制的按钮与排布面板控件实现. 实现效果如下: 说明: 1.输入框可设 ...
- Spring-Cloud之Feign原理剖析
Feign 主要是帮助我们方便进行rest api服务间的调用,其大体实现思路就我们通过标记注解在一个接口类上(注解上将包含要调用的接口信息),之后在调用时根据注解信息组装好请求信息,接下来基于rib ...
- Navicat Premium 15 linux 安装与激活 ArchLinux 2021
查看了很多教程花了半小时才弄好可真不容易 参考https://github.com/orginly/navicat-keygen 下载地址 http://www.navicat.com.cn/down ...
- Go语言的函数01---概念
package main import "fmt" /* 向某人致以问候 参数: name string类型,要问候的对象 n int类型,要问候的次数 返回值: string类型 ...
- Pptx的形状转为WPF的Geometry
本文是将演示如何解析pptx文件的形状到WPF当中,并且绘制显示出来 安装Openxml sdk 首先,我们先安装nuget的openxml sdk,下面两种方式都可以安装: nuget包管理器控制台 ...
- AIoT 2020 年分析
AIoT 2020 年分析 2020年,从智能手机到智能手表,从智能摄像头到智能汽车,随着AI.芯片.云计算.通信等基础技术的逐渐成熟,又一个行业来到了历史性的时刻--AIoT. 从"万物互 ...