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,微信只提示"改公众账号暂时无法提供服 ...
随机推荐
- kylin的rowkey优化之按维度分片
我们知道,系统会对cuboid的数据进行分片处理. 但是默认的分片策略是随机的,如果group by a,b 的查询命中了某个cuboid,但是a=1 and b=1 的两条数据在不同的机器上存储, ...
- XShell本地上传文件到Ubuntu上及从Ubuntu下载文件到本地
使用XShell本地上传文件到Ubuntu上及从Ubuntu下载文件到本地. 1.第一种方法是最常用的 :如果下载了Xshell和Xftp,Ctrl+Alt+F就可以选择文件的互传了!(虚拟机/云服务 ...
- Prometheus监控软件部署方法
背景:负责基于区块链的某公正项目的状态上报模块设计编码,基于Prometheus进行二次开发 1.说明Prometheus 是一个开源的服务监控软件,它通过 HTTP 协议从远程机器收集数据并存储在本 ...
- 学习Python中出现的错误集合(不定时更新)jupyter平台
出现的问题:1. 本图的错误,一个是line 7 init的两侧应该是是双下划线"__"导致所示错误 2. 本图的错误是 line 12 Student.student_tatal ...
- 自动驾驶传感器比较:激光雷达(LiDAR) vs. 雷达(RADAR)
自动驾驶传感器比较:激光雷达(LiDAR) vs. 雷达(RADAR) 据麦姆斯咨询报道,2032年全球范围内自动驾驶汽车的产量将高达2310万辆,未来该市场的复合年增长率(CAGR)高达58%.届时 ...
- 3D-camera结构光原理
3D-camera结构光原理 目前主流的深度探测技术是结构光,TOF,和双目.具体的百度就有很详细的信息. 而结构光也有双目结构光和散斑结构光等,没错,Iphone X 的3D深度相机就用 散斑结构光 ...
- GPU加速库AmgX
GPU加速库AmgX AmgX提供了一条简单的途径来加速NVIDIA GPU上的核心求解器技术.AmgX可以为模拟的计算密集型线性求解器部分提供高达10倍的加速度,特别适合于隐式非结构化方法. 它是一 ...
- 稀疏自编码器及TensorFlow实现
自动编码机更像是一个识别网络,只是简单重构了输入.而重点应是在像素级重构图像,施加的唯一约束是隐藏层单元的数量. 有趣的是,像素级重构并不能保证网络将从数据集中学习抽象特征,但是可以通过添加更多的约束 ...
- Ascend Pytorch算子适配层开发
Ascend Pytorch算子适配层开发 适配方法 找到和PyTorch算子功能对应的NPU TBE算子,根据算子功能计算出输出Tensor的size,再根据TBE算子原型构造对应的input/ou ...
- 深入理解Spring事务的那点事
Spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获 ...