如何防止自己的程序被调试器跟踪,这是一个很有趣的话题,也是反逆向工程中的一个重要话题。这里简单介绍一下Linux平台上的反调试技术。

(本文主要参考:http://blog.txipinet.com/2006/10/05/37-tecnicas-anti-debugging-sencillas-para-gnu-linux/。

做人要厚道,转载请指明出处!)

一. int3指令

Intel Software Developer’s Manual Volume 2A中提到:

The INT 3 instruction generates a special one byte opcode (CC) that is intended for

calling the debug exception handler. (This one byte form is valuable because it can be

used to replace the first byte of any instruction with a breakpoint, including other one

byte instructions, without over-writing other code).

int3是一个特殊的中断指令(从名字上也看得出来),专门用来给调试器使用。这时,我们应该很容易想到,要反调试,只要插入int3来迷惑调试器即可。不过,这会不会影响正常的程序?会!因为int3会在用户空间产生SIGTRAP。没关系,我们只要忽略这个信号就可以了。

#include

#include

voidhandler(intsigno)

{}

intmain(void)

{

signal(SIGTRAP,handler);

__asm__("nop\n\t"

"int3\n\t");

printf("Hello from main!\n");

return0;

}

二. 文件描述符

这是一个很巧妙的办法,不过它只对gdb之类的调试器有效。方法如下:

#include

#include

#include

intmain(void)

{

if(close(3)== -1){

printf("OK\n");

}else{

printf("traced!\n");

exit(-1);

}

return0;

}

gdb要调试这个程序时会打开一个额外的文件描述符来读这个可执行文件,而这个程序正是利用了这个“弱点”。当然,你应该能猜到,这个技巧对strace是无效的。

三. 利用getppid

和上面一个手法类似,不过这个更高明,它利用getppid来进行探测。我们知道,在Linux上要跟踪一个程序,必须是它的父进程才能做到,因此,如果一个程序的父进程不是意料之中的bash等(而是gdb,strace之类的),那就说明它被跟踪了。程序代码如下:

#include

#include

#include

#include

#include

#include

#include

intget_name_by_pid(pid_tpid,char*name)

{

intfd;

charbuf[1024]={0};

snprintf(buf,1024,"/proc/%d/cmdline",pid);

if((fd=open(buf,O_RDONLY))== -1)

return-1;

read(fd,buf,1024);

strncpy(name,buf,1023);

return0;

}

intmain(void)

{

charname[1024];

pid_tppid=getppid();

printf("getppid: %d\n",ppid);

if(get_name_by_pid(ppid,name))

return-1;

if(strcmp(name,"bash")==0||

strcmp(name,"init")==0)

printf("OK!\n");

elseif(strcmp(name,"gdb")==0||

strcmp(name,"strace")==0||

strcmp(name,"ltrace")==0)

printf("Traced!\n");

else

printf("Unknown! Maybe traced!\n");

return0;

}

同样的手法,一个更简单的方式是利用session id。我们知道,不论被跟踪与否,session id是不变的,而ppid会变!下面的程序就利用了这一点。

#include

#include

#include

intmain(void)

{

printf("getsid: %d\n",getsid(getpid()));

printf("getppid: %d\n",getppid());

if(getsid(getpid())!=getppid()){

printf("traced!\n");

exit(EXIT_FAILURE);

}

printf("OK\n");

return0;

}

四. 利用环境变量

bash有一个环境变量叫$_,它保存的是上一个执行的命令的最后一个参数。如果在被跟踪的状态下,这个变量的值是会发生变化的(为什么?)。下面列出了几种情况:

argv[0] getenv("_")

shell ./test ./test

strace ./test /usr/bin/strace

ltrace ./test /usr/bin/ltrace

gdb /home/user/test (NULL)

所以我们也可以据此来判断。

#include

#include

#include

intmain(intargc,char*argv[])

{

printf("getenv(_): %s\n",getenv("_"));

printf("argv[0]: %s\n",argv[0]);

if(strcmp(argv[0],(char*)getenv("_"))){

printf("traced!\n");

exit(-1);

}

printf("OK\n");

return0;

}

五. 利用ptrace

很简单,如果被跟踪了还再调用ptrace(PTRACE_TRACEME…)自然会不成功。

#include

#include

intmain(void)

{

if(ptrace(PTRACE_TRACEME,0,1,0)<0){

printf("traced!\n");

return1;

}

printf("OK\n");

return0;

}

Happy hacking!

linux反调试代码,linux反调试方法相关推荐

  1. linux简单重定向代码,Linux Shell编程(26)——代码块重定向

    像 while, until, 和 for 循环代码块, 甚至 if/then 测试结构的代码块都能做到标准输入的重定向. 即使函数也可以使用这种重定向的格式 .所有的这些依靠代码块结尾的 < ...

  2. 在linux下载github代码,linux 定时下载github最新代码

    场景:网站的代码在github上托管,静态网站部署在服务器上,每次自己修改完本地代码后,提交到github上,需要自己去服务器上执行git pull 拉取最新代码, 为了解决这种操作,自己再服务器上  ...

  3. Linux运行8086代码,* linux下编译,链接,运行,汇编程序

    当前使用的操作系统:ubuntu11.10 汇编程序由定义好的段构成,每个段都有不同的目的,三个最常用的段: 1)data 段 汇编程序data(数据)段是可选的. 数据段声明带有初始值的数据元素,这 ...

  4. linux创建根目录代码,Linux文件系统之目录的建立

    一:前言 在用户空间中,建立目录所用的API为mkdir().它在内核中的系统调用入口是sys_mkdir().今天跟踪一下 函数来分析linux文件系统中目录的建立过程. 二:sys_mkdir() ...

  5. linux运行软件代码,Linux软件安装-详细源码安装过程

    1.简介 软件的安装是linux学习时的重中之重,*nux上重要思维哲 学组合若干小功能进而成为一个可用可维护的系统平台.那么在 操作系统构建完成之时,除非内核等支持系统必需软件之外,可 拓展可维护的 ...

  6. linux内核定时器 代码,Linux内核计时器

    linxu内核中完成的许多功能都需要感知时间的行进,比如定期把页面缓存中的数据写入磁盘,定期进行进程调度,提供获得当前时间的系统调用,还有计划任务的实现,让系统在某段时间之后执行某个程序,或者在某个时 ...

  7. linux计算器界面代码,linux 日历,计算器,nano编辑器,开关机、重启,(示例代码)...

    1.查看文件下面所有的隐藏目录:ls -al 2.显示具体的年月日:date +%y/%m/%d 或date +%Y/%m/%d 3.显示这个月的日历: cal 显示某年日历:   cal 2017 ...

  8. linux mv编写代码,Linux命令--mv(示例代码)

    简介这篇文章主要介绍了Linux命令--mv(示例代码)以及相关的经验技巧,文章约4069字,浏览量253,点赞数7,值得推荐! Linux--mv mv经常被用来做备份 命令参数: -b :若需覆盖 ...

  9. linux aslr 关闭代码,Linux/ARM 禁用ASLR安全的代码[网络技术]

    赞助商链接 本文"Linux/ARM 禁用"ASLR安全"的代码[网络技术]"是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及 ...

最新文章

  1. 14.关于原子性的相关介绍
  2. 好程序员Web前端教程分享Vue学习心得
  3. 编译程序加不加 -lpthread 的区别【转】
  4. spring websocket源码分析续Handler的使用
  5. 十分钟搭建和使用ELK日志分析系统
  6. mysql模糊查询(详细的解析与例句)-建议收藏
  7. OpenFOAM算例报错,浮点溢出错误,Floating point exception【汇总】
  8. shiro学习(18):使用注解实现权限认证和后台管理三
  9. 我国共招过多少博士?多少硕士?数据来了!
  10. php 添加音乐,PHP网站插入音乐
  11. java查找网站在百度排名_百度网站快排系统 - 网站排名如何优化?
  12. python制作印刷体数据集:数字符号数据集(字符串转图片)
  13. c语言字符串与 浮点型,判断输入字符串是不是为浮点数
  14. Docker官方文档学习笔记(二):Docker Desktop入门
  15. 新家未来验房电子报告版本第三代更新,验房师专业电子报告
  16. 联想T460p加装固态硬盘
  17. 关于java.lang.ArithmeticException
  18. 利用range表单元素实现调色板
  19. Django-APIView
  20. 使用PyCharm进行接口测试

热门文章

  1. jtag引脚定义_硬件学习之通过树莓派操控 jtag
  2. PHP匹配函数怎么用,php preg_match_all函数怎么用
  3. 如何在python中构造时间戳参数
  4. oracle delete原理,如何恢复并理解oracle删除数据的原理
  5. D455 如何同时传输视频深度流和惯性单元IMU流?(双管道方法与调用回调方法)
  6. 图像识别中卷积神经网络“卷积”的作用
  7. numpy np.sort()函数(指定对某一轴进行排序,返回数组的排序副本)(成对数组不要用这个排,用哪个啥lexsort()或argsort()都行)
  8. Intel Realsense D435 Tensorlfow-yolov3 测试摄像头识别坐标转换成实际空间坐标的准确程度
  9. u盘读写测试_关于闪迪u盘cz880速度测试
  10. MultipartFile 文件上传