Linux下的反调试技术
Linux下的反调试技术
转自 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下的反调试技术的更多相关文章
- 基于TLS的反调试技术
TLS(Thread Local Storage 线程局部存储) 一个进程中的每个线程在访问同一个线程局部存储时,访问到的都是独立的绑定于该线程的数据块.在PEB(进程环境块)中TLS存储槽共64个( ...
- 反调试技术常用API,用来对付检测od和自动退出程序
在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...
- Windows 反调试技术——OpenProcess 权限过滤 - ObRegisterCallback
转载: https://blog.xpnsec.com/anti-debug-openprocess/ 看雪翻译:https://bbs.pediy.com/thread-223857.htm 本周我 ...
- linux下多进程的调试
linux下多进程的调试: (1)follow-fork-mode set follow-fork-mode [parent | child] ---- fork之后选择调试父进 ...
- Linux下用Xdebug调试php
Linux下用Xdebug调试php 博客分类: php PHPLinuxZendEclipseC# 为了调试PHP程序,安装一下xdebug. 官方网址: http://www.xdebug.org ...
- Ubuntu\Linux 下编写及调试C\C++
一.在Ubuntu\Linux 下编写及调试C\C++需要配置基本的环境,即配置gcc编译器.安装vim编译器,具体配置安装步骤我在这里就不多说了. 二.基本环境配置完了我们就可以进入自己的程序编写了 ...
- Windows反调试技术(上)
写在前面 在逆向工程中为了防止破解者调试软件,通常都会在软件中采用一些反调试技术来防破解.下面就是一些在逆向工程中常见的反调试技巧与示例. BeingDebuged 利用调试器加载程序时调试器会通过C ...
- Windows反调试技术(下)
OD的DBGHELP模块 检测DBGHELP模块,此模块是用来加载调试符号的,所以一般加载此模块的进程的进程就是调试器.绕过方法也很简单,将DBGHELP.DLL改名. #include <Wi ...
- Linux驱动设计—— 驱动调试技术
参考博客与书籍: <Linux设备驱动开发详解> <Linux设备驱动程序> http://blog.chinaunix.net/uid-24219701-id-2884942 ...
随机推荐
- WPF依赖属性相关博客导航
1.一站式WPF--依赖属性(DependencyProperty)一(什么是依赖属性,依赖属性的由来) 2.一站式WPF--依赖属性(DependencyProperty)二(涉及依赖属性的使用) ...
- Explaining Delegates in C# - Part 5 (Asynchronous Callback - Way 2)
In this part of making asynchronous programming with delegates, we will talk about a different way, ...
- iOS开发-iOS7禁用手势返回
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // 禁用 iOS7 返回手势 if ([self.nav ...
- vc11(vs2012)下编译php源码
需要原料: vs2012.php源码 1.本机的mingw没搞定,参考网上文章尝试vs2012编译,借助vs2012自带的命令行工具: 需要去bison官网下载bison.exe放在“c:/windo ...
- sqlserver连接问题收集
问题1. 使用navicat连接本地sqlserver,报错“命名管道提供程序无法打开与 sql server 的连接 [2]” 解决: 参考本篇文章 <持续收集中>
- 处理i18n国际电话区号的代码实践
本文转载至 http://adad184.com/2015/08/18/practice-in-i18n-dialling-code/ 前言 上周在忙产品的国际化(i18n)的问题 其中一个很重要的地 ...
- codeforces水题100道 第九题 Codeforces Beta Round #63 (Div. 2) Young Physicist (math)
题目链接:http://www.codeforces.com/problemset/problem/69/A题意:给你n个三维空间矢量,求这n个矢量的矢量和是否为零.C++代码: #include & ...
- Android学习之Dialog
在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框; 实例如下: 1.效果图: 2.XML代码: ...
- Python学习(24):Python面向对象(2)
转自 http://www.cnblogs.com/BeginMan/p/3191037.html 一.类 类就是一个数据结构,封装了数据和操作. 类的声明与函数的声明十分类似: class newC ...
- ios设备唯一标识获取策略
In iOS 7 and later, if you ask for the MAC address of an iOS device, the system returns the value 02 ...