当前位置:Linux教程 - Linux - Unix系统平台下的Anti-Debugging技术简介

Unix系统平台下的Anti-Debugging技术简介

目  录
----

一、前 言
二、欺骗反汇编代码
三、监视断点
四、设置伪断点
五、检测调试跟踪


一、前 言
-----

Silvio Cesare早在1999年就已发表了一篇关于在Linux系统平台下如何对抗反汇编技术的文章。虽然早已看过多遍,但总觉得对于大力倡导Open Source的Unix系统平台,对抗反汇编的实际需求和意义并不甚大,所以一直没有把它翻译和整理出来。后来逐渐发觉汇编与对抗反汇编的技术在某些方面是可以运用在网络安全领域的,例如攻击者可以通过在其攻击代码、后门代码等处使用对抗反汇编的技术,达到更难以被查觉和分析的目的,而对于某些不允许公开技术细节(例如政府机密部门或军方)的安全软件,也可利用这些技术使其他人无法用反汇编技术窥探其功能实现。当然在病毒的编写中自然也是可以使用这些技术的。

本文较为简单,仅介绍了四种比较容易实现的技术原理,即使是给出的例子也非常简单。至于如何在实际中运用它们,如何同时把这几种技术混和起来,甚至还能不能发现其它更高级的对抗反汇编的技术,就留给各位有兴趣的朋友自己去尝试了。

本文的实验环境为:NetBSD 1.5 for i386 和 Red Hat Linux 6.2 for i386


二、欺骗反汇编代码
---------

这种技术就是当在用反汇编程序或调试工具进行反汇编时,列出的反汇编代码具有欺骗性。最简单的方法就是使程序跳到指令“之中”执行。也就是说真实的代码是从某条指令“之中”开始的,但在反汇编时由于是针对整条指令而不能列出真正被运行的汇编指令代码。

例如以下程序:

/* anti1.c
* Anti-Debugging technique #1: False Disassembly
*
* Compile: gcc -o anti1 anti1.c
* Tested: NetBSD 1.5 for i386
*
* Author: Silvio Cesare
* Modified: backend
* Date: June 7, 2001
*
*/

int main()
{
__asm__("
jmp antidebug1 + 2
antidebug1:
.short 0xc606
call reloc
reloc:
popl %esi
jmp antidebug2
antidebug2:
addl $(data - reloc),%esi
movl 0(%esi),%edi
pushl %esi
jmp *%edi
data:
.long 0
");
}

如果使用objdump或gdb等反汇编工具对编译后的二进制程序代码进行反汇编时,会得到如下结果:

[root@netbsd /root/nsfocus]# gcc -o anti1 anti1.c
[root@netbsd /root/nsfocus]# objdump -d anti1

anti1: file format elf32-i386

...
...
...

080487c4 :
80487c4: 55 pushl %ebp
80487c5: 89 e5 movl %esp,%ebp
80487c7: eb 02 jmp 80487cb

080487c9 :
80487c9: 06 pushl %es
80487ca: c6 e8 00 movb $0x0,%al
80487cd: 00 00 addb %al,(%eax)
...

080487d0 :
80487d0: 5e popl %esi
80487d1: eb 00 jmp 80487d3

080487d3 :
80487d3: 81 c6 0f 00 00 addl $0xf,%esi
80487d8: 00
80487d9: 8b 7e 00 movl 0x0(%esi),%edi
80487dc: 56 pushl %esi
80487dd: ff e7 jmp *%edi

080487df :
80487df: 00 00 addb %al,(%eax)
80487e1: 00 00 addb %al,(%eax)
80487e3: c9 leave
80487e4: c3 ret
80487e5: 90 nop
80487e6: 90 nop
80487e7: 90 nop

可以看到这种输出所得到的指令和实际运行的指令已经完全不同了!


三、监视断点
------

当定义一个断点时,实际上是将断点地址处的指令内容用int3的机器码0xcc替换了。当一个程序被跟踪调试时,int3中断会使进程停止执行。此时程序的控制权就交给其父进程(调试进程)。要使被调试进程继续执行,调试器会将被int3机器码替换的断点地址内容恢复回原样。因此,要监视某处是否被设置了断点,程序只要在运行时检查是否有int3机器码(0x33)就能知道了。另一种方法是计算某代码段的校验和。如果校验和不一致,则说明代码被修改了,很可能是在该代码段的某处被设置了断点。

程序例子如下:

/* anti2.c
* Anti-Debugging technique #2: Detecting Breakpoints
*
* Compile: gcc -o anti2 anti2.c
* Tested: NetBSD 1.5 for i386
*
* Author: Silvio Cesare
* Modified: backend
* Date: June 7, 2001
*
*/

void foo()
{
printf("Hellon");
}

int main()
{
if ((*(volatile unsigned *)((unsigned)foo + 3) & 0xff) == 0xcc) {
printf("BREAKPOINTn");
exit(1);
}
foo();
}

[root@netbsd /root/nsfocus]# gcc -o anti2 anti2.c
[root@netbsd /root/nsfocus]# gdb
GNU gdb 4.17
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386--netbsd".
(gdb) file anti2
Reading symbols from anti2...(no debugging symbols found)...done.
(gdb) br foo
Breakpoint 1 at 0x80487fb
(gdb) r
Starting program: /root/nsfocus/anti2
BREAKPOINT
(no debugging symbols found)...(no debugging symbols found)...
Program exited with code 01.
(gdb) q
[root@netbsd /root/nsfocus]# ./anti2
Hello
[root@netbsd /root/nsfocus]#


四、设置伪断点
-------

正如前面已经提到的,断点的设置实际上是用int3机器码(0xcc)替换该地址内容。要设置一个伪断点,只需在代码中插入一条int3指令即可。这条指令会触发SIGTRAP信号,因此只要我们的代码中有该信号的处理函数,就能够在触发该信号后仍能正常执行,前提条件当然是没有在调试器中运行。;)

程序实例如下:

/* anti3.c
* Anti-Debugging technique #3: Setting Up False Breakpoints
*
* Compile: gcc -o anti3 anti3.c
* Tested: NetBSD 1.5 for i386
*
* Author: Silvio Cesare
* Modified: backend
* Date: June 7, 2001
*
*/

#include

void handler(int signo)
{
/* Do something you like here which can not
be executed in dubuggers. :) */
}

int main()
{
signal(handler, SIGTRAP);
__asm__("
int3
");
printf("Hellon");
}

[root@netbsd /root/nsfocus]# gdb
GNU gdb 4.17
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386--netbsd".
(gdb) file anti3
Reading symbols from anti3...(no debugging symbols found)...done.
(gdb) r
Starting program: /root/nsfocus/anti3
(no debugging symbols found)...(no debugging symbols found)...
Program received signal SIGTRAP, Trace/breakpoint trap.
0x8048847 in main ()
(gdb) c
Continuing.
Hello

Program exited with code 06.
(gdb) q
[root@netbsd /root/nsfocus]# ./anti3
Hello
[root@netbsd /root/nsfocus]#


五、检测调试跟踪
--------

(backend:此方法对Linux有效,但对NetBSD无效!!!)

这种技术是在程序中检测是否正被strace或gdb之类的调试器或跟踪工具执行。其基本原理是在Linux系统中,一个进程只能成功调用一次ptrace的PTRACE_TRACEME请求(PTRACE_TRACEME是ptrace系统调用中唯一由被调用进程执行的ptrace请求。详细资料可查阅ptrace的手册页(man 2 ptrace))。所有调试器和程序跟踪工具都使用这个调用请求设置对进程的调试跟踪。

程序实例如下:

/* anti4.c
* Anti-Debugging technique #4: Detecting Debugging
*
* Compile: gcc -o anti4 anti4.c
* Tested: Red Hat Linux 6.2 for i386
*
* Author: Silvio Cesare
* Modified: backend
* Date: June 7, 2001
*
*/

#include

int main()
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
printf("DEBUGGING... Byen");
return 1;
}
printf("Hellon");
return 0;
}

[root@redhat62 /root/nsfocus]# gcc -o anti4 anti4.c
[root@redhat62 /root/nsfocus]# gdb
GNU gdb 19991004
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux".
(gdb) file anti4
Reading symbols from anti4...done.
(gdb) r
Starting program: /root/nsfocus/anti4
DEBUGGING... Bye

Program exited with code 01.
(gdb) q
[root@redhat62 /root/nsfocus]# ./anti4
Hello
[root@redhat62 /root/nsfocus]#