Statistics

Members: 1925
News: 293
Web Links: 1
Visitors: 3823204

Who's Online

We have 2 guests online
Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home
Linux anti-debugging techniques (fooling the debugger)
User Rating: / 2
PoorBest 
Written by Silvio Cesare   


This article describes anti debugger techniques for x86/Linux (though some of these techniques are not x86 specific). That is techniques to either fool, stop, or modify the process of debugging the target program. This can be useful to the development of viruses and also to those implementing software protection.

False disassembly

This elegant technique produces false disassembly when listed. It produces this by jumping into the middle of instruction. The real code starts in the middle of this instruction, but the disassembly uses the entire instruction and thus continues disassembly not alligned to the real assembly.

        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 -d a.out
.
.
.
8048340:       55              pushl  %ebp
8048341:       89 e5           movl   %esp,%ebp
8048343:       eb 02           jmp    0x8048347
8048345:       06              pushl  %es
8048346:       c6 e8 00        movb   $0x0,%al
8048349:       00 00           addb   %al,(%eax)
804834b:       00 5e eb        addb   %bl,0xffffffeb(%esi)
804834e:       00 81 c6 0f 00  addb   %al,0xfc6(%ecx)
8048353:       00
8048354:       00 8b 7e 00 56  addb   %cl,0xff56007e(%ebx)
8048359:       ff
804835a:       e7 00           outl   %eax,$0x0
804835c:       00 00           addb   %al,(%eax)
804835e:       00 89 ec 5d c3  addb   %cl,0x90c35dec(%ecx)
8048363:       90
8048364:       90              nop
.
.
.

Detecting breakpoints

A breakpoint is defined by overwriting the breakpoint address with an int3 opcode (0xcc). If a program is being traced (man ptrace) then an int3 will cause the process to stop. This is when the parent process debugging takes over control. To continue processing it is up to the debugger to overwrite the int3 opcode with the original opcode. Thus to detect a breakpoint, the program simply has to check for an int3 opcode. Another solution is to checksum the code image. If the checksum fails, the code has been modified, and a breakpoint is probably the culprit.

void foo()
{
printf("Hello\n");
}
int main()
{
if ((*(volatile unsigned *)((unsigned)foo + 3) & 0xff) == 0xcc) {
printf("BREAKPOINT\n");
exit(1);
}
foo();
}
$ gdb
GDB is free software and you are welcome to 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.
GDB 4.16 (i586-debian-linux), Copyright 1996 Free Software Foundation, Inc.
(gdb) file a.out
Reading symbols from a.out...done.
(gdb) break foo
Breakpoint 1 at 0x8048373: file break.c, line 3.
(gdb) run
Starting program: /home/silvio/src/antidebug/a.out
BREAKPOINT
Program exited with code 01.
(gdb) quit
$ ./a.out
Hello
$

Setting up false breakpoints

As stated earlier, a breakpoint is created by overwriting the address with an int3 opcode (0xcc). To setup a false breakpoint then we simply insert an int3 into the code. This also raises a SIGTRAP, and thus if our code has a signal handler we can continue processing after the breakpoint.

#include <signal.h>
void handler(int signo)
{
}
int main()
{
signal(handler, SIGTRAP);
__asm__("
int3
");
printf("Hello\n");
}
$ gdb
GDB is free software and you are welcome to 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.
GDB 4.16 (i586-debian-linux), Copyright 1996 Free Software Foundation, Inc.
(gdb) file a.out
Reading symbols from a.out...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/silvio/src/antidebug/a.out
(no debugging symbols found)...(no debugging symbols found)...
Program received signal SIGTRAP, Trace/breakpoint trap.
0x80483c3 in main ()
(gdb) c
Continuing.
Hello
Program exited with code 06.
(gdb) quit
$ ./a.out
Hello
$

Detecting debugging

This is an elegant technique to detect if a debugger or program tracer such as strace or ltrace is being used on the target program. The premise of this technique is that a ptrace[PTRACE_TRACEME] cannot be called in succsession more than once for a process. All debuggers and program tracers use this call to setup debugging for a process.

int main()
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
printf("DEBUGGING... Bye\n");
return 1;
}
printf("Hello\n");
return 0;
}
$ gdb
GDB is free software and you are welcome to 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.
GDB 4.16 (i586-debian-linux), Copyright 1996 Free Software Foundation, Inc.
(gdb) file a.out
Reading symbols from a.out...done.
(gdb) run
Starting program: /home/silvio/src/antidebug/a.out
DEBUGGING... Bye
Program exited with code 01.
(gdb) quit
$ ./a.out
Hello
$