Detecting debugging

检测调试器的方法很多, 比如检测进程名之类. 这里我们介绍一种方法, 就是通过检测一些函数的调用情况来分析程序当前是否处于被调试状态

int main()
{
	if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
		printf("DEBUGGING... Bye\n");
		return 1;
	}
	printf("Hello\n");
	return 0;
}

一个进程只能被一个进程ptrace, 如果你自己调用ptrace, 那么其它程序就无法通过ptrace调试或向你的程序注入代码.

如果程序当前被gdb调试, 那么ptrace函数就会返回错误, 也就侧面表明了检测到了调试器的存在.

绕过方法1

显然ptrace只能作用于使用ptrace的调试器, 我们可以用不使用ptrace的调试器.

我们也可以通过打补丁的方式将ptrace函数擦除, 更简单就是将ptrace的调用代码或是之后的校验给擦除了.

如果可执行文件(实际情况下不太可能)在编译时并没有启用-s选项(-s 选项能移除所有的符号表信息和重定位信息), 那么情况会变得简单很多. 我们从这个简单的情况来分析

# objdump -t test_debug | grep ptrace
080482c0 	F *UND* 	00000075 	ptrace@@GLIBC_2.0

ptrace在0x080482c0位置被调用

那要是有启用-s选项, 该怎么处理呢? 这时我们需要使用gdb

我们简单地断在了ptrace处, 现在输入finish执行到当前函数返回, 回到main函数里

将函数返回结果eax修改为正确的返回结果, 就可以了

绕过方法2

方法2就是编写自己的ptrace函数

如前几篇所述, LD_PRELOAD环境变量可以将可执行文件指向我们自己的ptrace函数.

我们写一个ptrace函数并生成目标文件

我们接下来就可以通过设置环境变量LD_PRELOAD来使用我们自己的ptrace函数, 当然这里是可以在gdb中进行设置

可以看到程序无法检测到调试器了.

Reference: Beginners Guide to Basic Linux Anti Anti Debugging Techniques

Last updated