Linux下的反调试技术

2014年01月30日 ⁄ 综合 ⁄ 共 2669字 ⁄ 字号 小 中 大 ⁄ 评论关闭

转自  http://wangcong.org/blog/archives/310

如何防止自己的程序被调试器跟踪,这是一个很有趣的话题,也是反逆向工程中的一个重要话题。这里简单介绍一下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
void handler(int signo)
{} int main(void)
{
signal(SIGTRAP, handler);
__asm__("nop\n\t"
"int3\n\t");
printf("Hello from main!\n");
return 0;
}

二. 文件描述符

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

#include
#include
#include
int main(void)
{
if(close(3) == -1) {
printf("OK\n");
} else {
printf("traced!\n");
exit(-1);
}
return 0;
}

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

三. 利用getppid

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

#include
#include
#include
#include
#include
#include
#include
#include
#include int get_name_by_pid(pid_t pid, char* name)
{
int fd;
char buf[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);
return 0;
} int main(void)
{
char name[1024];
pid_t ppid = 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");
else if (strcmp(name, "gdb") == 0 ||
strcmp(name, "strace") == 0 ||
strcmp(name, "ltrace") == 0)
printf("Traced!\n");
else
printf("Unknown! Maybe traced!\n"); return 0;
}

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

#include
#include
#include int main(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"); return 0;
}

四. 利用环境变量

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 int main( int argc, 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");
return 0;
}

五. 利用ptrace

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

#include
#include
#include int main(void)
{
if ( ptrace(PTRACE_TRACEME, 0, 1, 0) < 0 ) {
printf("traced!\n");
return 1;
}
printf("OK\n");
return 0;
}

Linux下的反调试技术的更多相关文章

  1. 基于TLS的反调试技术

    TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...

  2. 反调试技术常用API,用来对付检测od和自动退出程序

    在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...

  3. Windows 反调试技术——OpenProcess 权限过滤 - ObRegisterCallback

    转载: https://blog.xpnsec.com/anti-debug-openprocess/ 看雪翻译:https://bbs.pediy.com/thread-223857.htm 本周我 ...

  4. linux下多进程的调试

    linux下多进程的调试:  (1)follow-fork-mode           set follow-fork-mode [parent | child] ---- fork之后选择调试父进 ...

  5. Linux下用Xdebug调试php

    Linux下用Xdebug调试php 博客分类: php PHPLinuxZendEclipseC# 为了调试PHP程序,安装一下xdebug. 官方网址: http://www.xdebug.org ...

  6. Ubuntu\Linux 下编写及调试C\C++

    一.在Ubuntu\Linux 下编写及调试C\C++需要配置基本的环境,即配置gcc编译器.安装vim编译器,具体配置安装步骤我在这里就不多说了. 二.基本环境配置完了我们就可以进入自己的程序编写了 ...

  7. Windows反调试技术(上)

    写在前面 在逆向工程中为了防止破解者调试软件,通常都会在软件中采用一些反调试技术来防破解.下面就是一些在逆向工程中常见的反调试技巧与示例. BeingDebuged 利用调试器加载程序时调试器会通过C ...

  8. Windows反调试技术(下)

    OD的DBGHELP模块 检测DBGHELP模块,此模块是用来加载调试符号的,所以一般加载此模块的进程的进程就是调试器.绕过方法也很简单,将DBGHELP.DLL改名. #include <Wi ...

  9. Linux驱动设计—— 驱动调试技术

    参考博客与书籍: <Linux设备驱动开发详解> <Linux设备驱动程序> http://blog.chinaunix.net/uid-24219701-id-2884942 ...

随机推荐

  1. python3存入redis是bytes

    在python3 中使用redis存储数据,存进去的是bytes >>> import redis >>> import time >>> imp ...

  2. SpringBoot(十)-- 整合MyBatis

    1.pom.xml 配置maven依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <ar ...

  3. Lua脚本和C++交互(一)

    现在,越来越多的C++服务器和客户端融入了脚本的支持,尤其在网游领域,脚本语言已经渗透到了方方面面,比如你可以在你的客户端增加一个脚本,这个脚本将会帮你在界面上显示新的数据,亦或帮你完成某些任务,亦或 ...

  4. Android 自定义 View 浅析

    Android 自定义 View 浅析 概括 说到自定义 View ,就一定得说说 android 系统的UI绘制流程.再说这个流程之前,我们先看一下在每一个 activity 页面中我们的布局 ui ...

  5. FastCGI在nginx中的参数

    FastCGI参数 fastcgi主要用于http调用外部解释器的接口,采用c/s结构,可以将http服务器和脚本解析器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程.当HTTP服务器每 ...

  6. vim 正则替换【转】

    :[range]s/from/to/[flags] range:搜索范围,如果没有指定范围,则作用于但前行. :1,10s/from/to/ 表示在第1到第10行(包含第1,第10行)之间搜索替换: ...

  7. 【Spring系列】Spring IoC

    前言 IoC其实有两种方式,一种是DI,而另一种是DL,即Dependency Lookup(依赖查找),前者是当前软件实体被动接受其依赖的其他组件被IOc容器注入,而后者是当前软件实体主动去某个服务 ...

  8. 【问题记录系列】the resource is not on the build path of a java project

    在eclipse中新建了一个maven项目搭建Spring源码阅读环境,创建一个bean生产getter和setter方法的时候报错“the resource is not on the build ...

  9. MIME类型列表

    A Multipurpose Internet Mail Extensions (MIME) type is a standard that indicates the nature and form ...

  10. OpenStack入门之【OpenStack-havana】之单网卡-All In One 安装(基于CentOS6.4)

    这篇文章是自己的一篇老文,分享下,请君慢用.... =========================================== [特别申明]:经过了一段时间的不断学习加不断的测试得出本文, ...