Statistics

Members: 1928
News: 293
Web Links: 1
Visitors: 5960300

Who's Online

We have 11 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
Anti-debugging and Anti-emulation Techniques
User Rating: / 21
PoorBest 
Written by A. Danielescu   


Malware is code written with the intent to cause annoyance, to retrieve sensitive information about individuals, to cause data loss, or for other similar purposes. Antivirus companies are constantly trying to detect malware and to lessen or stop these damaging effects. This causes an ongoing struggle between antivirus companies and virus writers. Anti-debugging and anti-emulation techniques have been devised by virus writers to counteract the efforts of antivirus companies to detect and remove malicious code. To further detect and stop malware, these techniques must be understood. This paper attempts to identify current anti-debugging and anti-emulation techniques and to provide code samples to allow for the identification of malicious code.

1. Introduction

 

To deter or slow down analysts from reverse-engineering malware, virus writers employ anti-debugging and anti-emulation techniques.  These techniques slow down the reverse-engineering process by attempting to avoid detection when a virus is being run in an emulator or debugger.  Several different methods are employed by malware to fool dynamic detection and other analysis mechanisms such as emulators and debuggers.  Each virus usually employs one to many of these techniques. 

This paper discusses those methods virus writers employ to slow down reverse-engineering of their viruses.  It also provides examples of these methods.  This paper is intends to provide an overview of the various anti-debugging and anti-emulation techniques for those that want to protect against these defenses.  

The paper is split into several sections.  Section 2 addresses anti-emulation techniques, followed by anti-debugging techniques in section 3, and other anti-detection techniques that do not fall into the first two categories are discussed in section 4.  Examples of viruses that combine all of the techniques are discussed in section 5, while section 6 is the conclusion.

 

2.  Anti-emulation

 

            An emulator provides a restricted environment (an image of an operating system that is installed on top of a host operating system) in which one can dynamically analyze a program.   For example, a machine running Linux can have a virtual machine installed on it running Windows XP.  An emulator will also include CPU and memory emulation, hardware emulation, and an emulation controller [1].  This provides a safe way to dynamically analyze programs without the possibility of causing damage to the underlying operating system.                 

                There are also drawbacks to this system.  First, the more time spent emulating, the longer the user has to wait to get any analysis back on the program.  Second, emulation is slow due to the overhead required to monitor the program and to emulate the operating system and hardware.  QEMU, a hardware and operating system emulator, has between a factor of 4 to 10 slowdown in hardware emulation and a factor of 2 slowdown on emulation of the software memory management unit [2].  QEMU does not have any dynamic monitoring, which would further increase the slowdown.  A final drawback is that malware employs different anti-emulation techniques to fool the emulator.  These techniques fall into three categories: Outlasting, outsmarting, or overextending the emulator.

               

2.1 Outlasting the emulator

 

                Since emulation is expensive, emulators only run a couple hundred instructions of code to detect malware before terminating.  On an Intel x86 system, it is believed that running around 1000 instructions is enough to detect malicious code while maintaining a short runtime [1].  If the code does nothing considered malicious during that time, the emulator will not detect the code as malware.  Outlasting the emulator can be done by replicating based on a specific probability, by running benign code for a specific time frame before running the malicious code, or by entry point obfuscation.

 

2.1.1 Probabilistic Replication

                Some malware will only replicate a certain percentage of the time.  This means that an emulator would have to run the code several times in order to accurately detect the malicious code.  An example of this is a virus that runs benign code 90% of executions and malicious code only 10%.

 

2.1.2 Running Benign Code

                Other malware will run benign code every time on startup for a specific time frame and then run the malicious code.  The purpose of this is to allow the emulator to run for the given number of instructions and pretend that the code does nothing malicious in this time frame.  It then goes on to replicate and cause damage to a system.

 

2.1.3 Entry Point Obfuscation

Entry point obfuscation (EPO) is a method that includes attaching malicious code to a specific section of a file. Instead of the malicious code executing first, the code can look for calls to the ExitProcess() API function and overwrite those calls with a jump to the malicious code.  This way the code runs on exit, not entry of an executable.  It can also look for a specific sequence of code to overwrite with the malicious code itself, or with a jump to the malicious code.  Entry point obfuscation, therefore, has the added advantage of giving the virus the ability to run the code later by copying the code to a new location before actually overwriting it [1]. 

 

2.2 Outsmarting the emulator

 

                To outsmart the emulator some malware uses time based triggers, or other conditionals, or it uses different decryption techniques if it is encrypted malware.  Time based triggers can be anything as simple as running the malicious code only on 3 pm or only on a specific day.  The malware can also check conditions such as checking to see if it is being debugged or emulated.  If it is, it executes benign code.

                Decryption techniques that can be used include spreading the decryption loop throughout the code or having multiple decryption passes [1].  Multiple decryption layers are used by W32/Harrier, W32/Coke and W32/Zelly where the first decryptor will decrypt the second, the second will decrypt the third, etc [9].  Malware can also only decrypt blocks of code as needed in order to outsmart the emulator [1]. 

The RDA.Fighter virus uses brute force decryption.  This means that the virus does not store the decryption key so it must try all possible decryption keys in order to decrypt itself.  This is useful because it is then difficult for anti-virus companies to decrypt the virus without using the same brute force method, which takes a large amount of emulation instructions.  It is likely, then, that the virus will not decrypt itself while the emulator is running.  Below is the code for the decryption code of the RDA Fighter virus [6].

 
setup:
        xor ebx,ebx
 
iterate:
       mov esi,[ebp + hostOffset]
       mov edi,esi
       mov ecx,[ebp + host_size]
       inc ebx
decrypt:
       lodsb
       xor al,bl
       stosb
       loop decrypt
 
check:
       mov esi,[ebp + hostOffset]
       push esi
       mov ecx,[ebp + host_size]
       push ecx
       mov eax,[ebp + __ADDR_CheckSum]  ; whatever this happens to be
       call eax
       test eax,eax
       jnz iterate
       mov esi,[ebp + hostOffset]
       jmp esi

 

In the above example we see that the setup block sets ebx to zero and is only run once.  Iterate then sets esi and edi to the beginning of the encrypted code, sets ecx to the size of the encrypted code, and also increments ebx by one.  The decrypt basic block goes through the ecrypted code byte by byte and xors the byte with the key in ebx.  This loop terminates when ecx becomes zero.  The check basic block then checks to see if the current code matches a predetermined checksum.  If it does, then the code has been decrypted.  If it hasn’t been, it goes back to the iterative loop and tries again with the next largest key. If it has been decrypted then it jumps to the newly decrypted code.    

W95/Fono uses a nonlinear decryption algorithm, meaning that the encrypted portion of the virus is not decrypted linearly as expected.  Since the virus body is not decrypted one byte after the other, it can confuse emulators.  W95/Fono uses a key table and the decryptor performs substitutions based on this table.  Each symbol in the plaintext alphabet corresponds to another symbol in the ciphertext.  For example:  A corresponds with L, Z corresponds with F, etc. Therefore, by using this encryption method, each piece of the virus is decrypted in semi-random order and every position is only hit once.  W95/Drill and {W32, Linux}/Simile.D use nonlinear decryption as well.

W95/Silcer and W95/Resure force the Windows Loader to relocate the infected program images when they are loaded to memory.  Relocating the images is responsible for decrypting the virus body because the virus puts in special relocations for the decryption [9].  W95/Resurrel is a virus written after W95/Resure.  This virus sets the base address of the newly infected file to a value of  0xBFxxxxxx (the xxxxxx is a random value returned by the GetTickCount() API call).  Then it adds a relocation entry for each DWORD value of its own code section and encrypts each DWORD by adding the base address value to the DWORD of the code section and then subtracting 0x400000.  When the application is executed the image of the program cannot be loaded into memory as is because the base address is wrong or an address in KERNEL32.DLL.  Therefore, the system loader will relocate the code to a valid address, decrypting the virus as it does so.  The difficulty in decrypting the virus makes it hard to detect [10].    

 

2.3 Overextending the emulator

               

                Overextending the emulator is defined as executing a set of instructions that will cause the emulator to crash or that may indicate that an emulator is running.  Calling undocumented instructions that an emulator may not support is one way to cause the emulator to throw an exception and stop running. One such example is the undocumented CPU Instruction SALC that is used in W95/Vulcano [9].  Another way to detect emulation or to crash the emulator currently running, if there is one, is to try to access large portions of memory at once [1].  This is usually not effective though because most operating systems, as well as emulators, will impede the program. 

                A way to detect whether an emulator is running is to call a function twice that should return two different values.  An example of this would be calling any of the time functions twice, and verifying that there is a difference between two return values.  In Windows this can be achieved through kernel32!QueryPerformanceCounter which wraps ZwQueryPerformaceCounter, kernel32!GetTickCounter, or by querying the current number of CPU cycles executed since the machine started using the RDTSC (read time stamp counter) instruction.  An example of the latter is below [15].


push offset handler
push dword ptr fs:[0]
mov fs:[0],esp
rdtsc
push eax
xor eax, eax
div eax ;trigger exception
rdtsc
sub eax, [esp] ;ticks delta
add esp, 4
pop fs:[0]
add esp, 4
cmp eax, 10000h ;threshold
jb @not_debugged
@debugged:
...
@not_debugged:
...
handler:
mov ecx, [esp+0Ch]
add dword ptr [ecx+0B8h], 2 ;skip div
xor eax, eax
ret

 

The example above shows how the RDTSC instruction can be used to detect whether a debugger is present.  In this case, RDTSC is called twice and the difference of the two values returned is found.  This difference is then compared to a threshold (in this example it is 10000h).  If the difference is greater, than a debugger is present and a jump away from the malicious code is executed. 

Importing obscure libraries may not actually cause the emulator to stop running, but if the library is not imported, the malware code itself may not run. 

                Malware can also look for webpages to see if it has access to the internet.  This is something that can also cause the virus code to not execute on a machine that is not currently connected to the internet, but also stops execution when an emulator is running since most emulators do not allow internet access [1].

                Using coprocessor FPU instructions is another way to overextend the emulator because most emulators do not emulate the FPU instructions.  Prizzy polymorphic engine (PPE) can generate 43 different coprocessor instructions for the use of its polymorphic decryptor.  If these FPU instructions are not provided, the decryption on Prizzy does not execute.

                Along the same lines, malware can use MMX instructions.  This instruction set adds 8 new registers to the architecture. The malware will check to see if MMX support exists by using the CPUID instruction.  Examples of malware that use this technique are W32/Legacy and W32/Thorin.

Malware will also setup an exception handler, execute a garbage block of code, and then indirectly execute its own handler to transfer control to another part of the polymorphic decryptor.  This is done in hopes that the emulator cannot handle the exception [9].  An example that is similar to this technique is shown in section 3.7.

 

3.  Anti-debugging 

 

                Anti-debugging techniques are usually any attempt of the malware to monitor its own code to detect debugging.  To do this, the malware can examine its own code for breakpoints or check for a debugger directly through system calls.

 

3.1 Breakpoints

 

                To examine its code for breakpoints, the malware can look for the 0xcc opcode instruction, which raises a SIGTRAP.  This is the instruction the debugger will use to gain control from the malware at a breakpoint.  The malware can also set false breakpoints if the malware code itself has a signal handler.  This way it can continue to execute instructions after the breakpoint that it set.

Malware can also try to overwrite the breakpoints.  W95/Marburg virus uses a backwards decryption loop for the virus to overwrite the breakpoint. The viruses in the Yankee_doodle family, on the other hand, use hamming code to self correct their code.  Hamming code allows programs to detect and correct errors, but in this case allows the virus to detect and remove breakpoints in its code [9].

 

3.2 Calculating the checksum

 

                Malware can also checksum its own code.  If the checksum has changed, then the virus can assume that it is being debugged and there have been breakpoints placed within the code [3].  VAMPiRE is an anti-anti debugging tool that gets around the detection of breakpoints [12].  VaMPiRE accomplishes this by keeping a table of breakpoints in memory to maintain a list of the breakpoints that have been set.  The program consists of a page-fault handler (PFH), a general protection fault handler (GPFH), a single-step handler and a framework API.  When a breakpoint is triggered either the PFH (handles breakpoints set on code, data, or memory mapped I/O) or the GPFH (handles legacy I/O breakpoints) receives control.  The single-step handler is used for breakpoint persistence, allowing breakpoints to be used more than once.

 

3.3 Detecting the debugger

 

                A very simple way of detecting a debugger on a Linux system is to simply call Ptrace, since Ptrace can’t be called in succession more than once for a specific process [3].  In Windows, the system call isDebuggerPresent will return 1 if the program is being debugged and 0 otherwise.  This system call simply checks a flag that has been set by the debugger if it is running.  This check can be done directly by checking the second byte in the Process Environment Block.  The following code is an example of this technique.

 

mov eax, fs:[30h]

move eax, byte [eax+2]

test eax, eax    

jne @DdebuggerDetected

 

                As the above example shows, eax is set to the PEB (Process Environment Block) and the second byte of that block is then accessed and the contents moved into eax.  A check is done to see whether eax is zero.  If it is, then there is no debugger present, if not, then there is a debugger. 

When a process is created with a debugger already running, the system sets certain flags for the heap manipulation routines in the Windows dll ntdll.dll.  These flags are FLG_HEAP_ENABLE_TAIL_CHECK, FLG_HEAP_ENABLE_FREE_CHECK, and FLG_HEAP_VALIDATE_PARAMETERS.  These flags can be checked using the following code:

 

mov eax, fs:[30h]
mov eax, [eax+68h]
and eax, 0x70
test eax, eax
jne @DebuggerDetected

 

In the above example, we again access the PEB and then get the start of the flags for the heap manipulation routine by adding 68h as an offset to the address of the PEB.  The flags are then checked to see if a debugger is present. 

Checking flags within heap headers such as the ForceFlags is another way to detect whether a debugger is running or not.  Here is an example [15]:

 

mov eax, fs:[30h]
mov eax, [eax+18h] ;process heap
mov eax, [eax+10h] ;heap flags
test eax, eax
jne @DebuggerDetected

 

                The above example shows how the process heap and the heap flags can be accessed from the offset of the PEB.   These are then tested to see if the Force Flags were previously set by a debugger currently running. 

        Another possible way to detect the debugger is through the use of the NtQueryInformationProcess syscall.  This function can be called with ProcessInformationClass set to 7, which refers to the ProcessDebugPort, and the function will return -1 if the process is being debugged.  Below is an example [15].

 

push 0

push 4

push offset isdebugged

push 7 ;ProcessDebugPort

push -1

call NtQueryInformationProcess

test eax, eax

jne @ExitError

cmp isdebugged, 0

jne @DebuggerDetected

 

In this example, the parameters for the  NtQueryInformationProcess syscall are first pushed onto the stack.  These parameters are as follows: the first is the handle (in this case 0), the second is the process information length (4 bytes in this example),  the following is the process information class (in this case 7, specifying the ProcessDebugPort), the next is the variable used to return whether or not there is a debugger present.  If this value is non-zero then the process is being run under a debugger.   If not, then all is well.  The last parameter is the return length.  NtQueryInformationProcess is then called with these parameters and a return value is placed in isdebugged.  This is later tested to see if it equals zero, or not.

Other simple ways of detecting the debugger is by checking to see if the device list contains the name of a debugger, by checking the registry keys for a debugger, or by scanning memory to detect the debugger’s code in memory [9]. 

Another method, similar to the EPO method, is to instruct the PE loader that the entry point of the program is referenced in the Thread Local Storage (TLS) entry in the PE header.  This has the effect of causing the code in the TLS to execute first instead of the read entry point of the program.  Therefore, the TLS can perform anti-debugging checks before the program even starts [15].  Starting on the TLS also allows the virus to begin execution before the debugger starts, since some debuggers break on the main entry point of the program [9].

 

3.4 Checking for single stepping

 

                Other ways that the malware can detect a debugger is to check for single stepping.  Checking for single stepping can be done by adding a value above the stack pointer and then checking to see if the value is still there.  If the value is there, this means that the code is being single stepped.  When a debugger is single stepping a process, it will push instructions onto the stack when it takes control and pop them back off the stack before it executes the next instruction.  So if the value is still there that means that something other than the running process has been using the stack [1].  Below is a code example of how malware can detect single stepping by using the stack state [9]:

 

mov bp, sp ; pick stack pointer

push ax ; store any ax mark on the stack

pop ax ; pick the value from the stack

cmp word ptr [bp-2], ax ; compare against stack

jne debug ; if different, debugger detected.  

 

As the comments in this example show, a value is pushed onto the stack then popped off the stack.  If the debugger is present, then the value at the top of the stack pointer – 2 will be different than the value that was just popped off the stack and the appropriate action can be taken.  

 

3.5 Checking for slowdown in runtime

 

                By looking for slowdown in the runtime of the program, malicious code can also detect a debugger.  A significant slowdown in runtime likely means that the code is being single stepped.  So if the difference in the timestamp for 2 different calls is too great, the malware can act accordingly [1].  LTTng/LTTV Linux Trace Toolkit gets around the slowdown problem to trace a virus.  This is because LTTng/LTTV is a modular tool that traces the program without adding breakpoints or performing any analysis at the time of execution.  It also uses a lockless re-entry mechanism, meaning that it does not lock any portions of the Linux kernel code that the program being traced might need to use, and therefore does not cause the traced program to slow down and wait [4]. 

 

3.6 Instruction prefetching

 

                If the malicious code modifies the next instruction in a sequence and the new instruction is executed, then a debugger is running.  This is due to instruction prefetching; if the new instruction is prefetched, this means there was a break in the execution of the process.  Otherwise the original instruction would have been prefetched and executed [1].

 

3.7 Self modifying code

 

                The malware can also self-modify other code.  One example of this is HDSpoof.  This malware starts out with exception handlers and then removes them during execution.  That way, if anything goes wrong and an exception is thrown by the process during execution, the virus will terminate.  It also modifies the exception handlers at other times during execution by either removing or adding exception handlers.  Below is an example of HDSpoof removing all exception handlers except for the default one [7].

 

exception handlers before:
        0x77f79bb8 ntdll.dll:executehandler2@20 + 0x003a
        0x0041adc9 hdspoof.exe+0x0001adc9
        0x77e94809 __except_handler3
exception handlers after:
        0x77e94809 __except_handler3
 
0x41b770: 8b44240c       mov      eax,dword ptr [esp+0xc]
0x41b774: 33c9           xor      ecx,ecx               
0x41b776: 334804         xor      ecx,dword ptr [eax+0x4]
0x41b779: 334808         xor      ecx,dword ptr [eax+0x8]
0x41b77c: 33480c         xor      ecx,dword ptr [eax+0xc]
0x41b77f: 334810         xor      ecx,dword ptr [eax+0x10]
0x41b782: 8b642408       mov      esp,dword ptr [esp+0x8]
0x41b786: 648f0500000000 pop      dword ptr fs:[0x0]    
 

Below is code in which HDSpoof creates a new exception handler [7].

 
0x41f52b: add      dword ptr [esp],0x9ca
0x41f532: push     dword ptr [dword ptr fs:[0x0]
0x41f539: mov      dword ptr fs:[0x0],esp

 

3.8 Overwriting debugger information

 

                Some malware uses techniques that can override debugger information and therefore cause either the debugger or the virus itself to function improperly.

                By hooking the INT 1 and INT 3 ( INT3 is the 0xCC opcode byte that debuggers use) interrupts, malware can cause the debugger to lose its context.  This is harmless during normal execution of the virus.  Another option is to hook the interrupts and call another interrupt to run the virus code indirectly.  Below is the code to the Tequila virus that hooks INT 1.

 
new_interrupt_one:
   push bp
   mov bp,sp
   cs cmp b[0a],1      ;masm mod. needed
   je 0506             ;masm mod. needed
   cmp w[bp+4],09b4
   ja 050b             ;masm mod. needed
   push ax
   push es
   les ax,[bp+2]
   cs mov w[09a0],ax   ;masm mod. needed
   cs mov w[09a2],es   ;masm mod. needed
   cs mov b[0a],1
   pop es
   pop ax
   and w[bp+6],0feff
   pop bp
   iret

 

Normally the hook routine is set to IRET, as it is without a debugger installed.  V2Px uses hooks to decrypt its body with INT 1 and INT 3.  The INT 1 and INT 3 vectors are used continuously during execution of the code and calculations are done in the interrupt vector table.  

Some viruses also clear the contents of the debug registers (DRn) [9].  This can be done in one of two ways.  One way is to use the NtGetContextThread and NtSetContextThread syscalls.  Another way is to generate an exception, modify the thread context and then resume normal execution with the new context.  An example of this is below [15]. 


push offset handler
push dword ptr fs:[0]
mov fs:[0],esp
xor eax, eax
div eax ;generate exception
pop fs:[0]
add esp, 4
;continue execution
;...
handler:
mov ecx, [esp+0Ch] ;skip div
add dword ptr [ecx+0B8h], 2 ;skip div
mov dword ptr [ecx+04h], 0 ;clean dr0
mov dword ptr [ecx+08h], 0 ;clean dr1
mov dword ptr [ecx+0Ch], 0 ;clean dr2
mov dword ptr [ecx+10h], 0 ;clean dr3
mov dword ptr [ecx+14h], 0 ;clean dr6
mov dword ptr [ecx+18h], 0 ;clean dr7
xor eax, eax
ret

 

The first line of the above example pushes the offset of the handler onto the stack to make sure that its own handler will get control when the exception is thrown.  Then setup is done in for control to transfer to the handler, including setting eax to zero by XORing it with itself.  The div eax instruction generates and exception because eax is zero, so AX is being divided by zero.  The handler then skips the divide instruction, cleans dr0-dr7, sets eax to zero again, indicating that the exception was handled, and execution is resumed. 

 

3.9 Detaching the debugger thread

 

            Detaching the thread from the debugger can be done with the NtSetInformationThread syscall.  Calling this function with ThreadInformationClass set to 0x11 (ThreadHideFromDebugger), will detach the program’s thread from the debugger if there is a debugger present. The following code is an example [15]:

 

push 0
push 0
push 11h ;ThreadHideFromDebugger
push -2
call NtSetInformationThread

 

                In this example, the parameters for the NtSetInformationThread are first pushed onto the stack and then the function is called removing the program’s thread from the debugger.  This is done because 0 is passed in for the thread information length and thread information, -2 is passed on for the thread handle, and 11h is passed in for the thread information class which is the ThreadHideFromDebugger value.

 

3.10 Decryption

 

Decryption can be done in several different ways that also protect against debugging.  Some decryption depends upon a specific execution path.  If this execution path is not followed, due to a debugger being started at a specific point in the program, the value that the decryption algorithm uses may be incorrect.  Therefore, the program will not decrypt itself correctly.  HDSpoof uses this technique [7].

                Some viruses use the stack to decrypt their code.  Using a debugger on such a virus causes the decryption to fail, because the stack is used by INT 1 during debugging.  One example is the W95/SK virus that decrypts and builds its code on the stack.  Another example of this is the Cascade virus that uses the stack pointer register for one of the decryption keys.  Below is the code:

 

lea   si, Start   ; position to decrypt

mov   sp, 0682  ; length of encrypted body

 

Decrypt:

xor   [si], si    ; decryption key/counter 1

xor   [si], sp  ; decryption key/counter 2

inc   si    ; increment one counter

dec   sp    ; decrement the other

jnz   Decrypt   ; loop until all bytes are decrypted

 

Start:            ; Virus body

 

                The comments on the above example explain fairly well how the Cascade virus uses the stack pointer to decrypt the virus body.  The Cryptor virus, on the other hand, stores its encryption keys in the keyboard buffer, which is also destroyed by a debugger.  Tequila uses the decryptor’s code as the decryption key, so if the decryptor is modified with a debugger the virus will not be decrypted [9].  Below is the Tequila decryption code [13]:

 

perform_encryption_decryption:
   mov bx,0
   mov si,0960
   mov cx,0960
   mov dl,b[si]
   xor b[bx],dl
   inc si
   inc bx
   cmp si,09a0
   jb 0a61             ;masm mod. needed
   mov si,0960
   loop 0a52           ;masm mod. needed
   ret
 
the_file_decrypting_routine:
   push cs
   pop ds
   mov bx,4
   mov si,0964
   mov cx,0960
   mov dl,b[si]
   add b[bx],dl
   inc si
   inc bx
   cmp si,09a4
   jb 0a7e             ;masm mod. needed
   mov si,0964
   loop 0a6f           ;masm mod. needed
   jmp 0390            ;masm mod. needed

 

Research is being done on new anti-debugging methods that may be used in the future.  One such project works on a multiprocessor computer in which one processor is unused while debugging.  This new technique uses parallel processing of the decryption code [11].

 

4.  Other Anti-detection Techniques

               

4.1 Retroviruses

 

                Retroviruses try to disable the anti-virus software.  They do this by carrying a list of process names and killing the processes the program finds running.  Many retroviruses also take the process off of the startup list so the process no longer starts when the computer boots.   This type of malware may also try to starve the anti-virus software of CPU time or prevent the anti-virus software from connecting to the company’s servers to update its database [1].

 

5. Combining Techniques

 

The W32.Gobi virus is a polymorphic retrovirus that uses EPO and several anti-debugging techniques.  This virus opens a backdoor on TCP port 666 [8]

Simile (also known as Metaphor) is a very well known and complex virus that is approximately 14,000 lines of assembly [9].  This virus uses EPO by looking for the ExitProcess() API call.  It is also a metamorphic virus that uses polymorphic decryption [1].  About 90% of its code is spent on the polymorphic decryption.  The virus body and polymorphic decryptor are placed in a semi-random place in a newly infected file each time.  The first payload of Simile only activates during March, June, September or December.  Variants A and B display their message on the 17th of these months.  Variant C displays its message on the 18th.  The second payload activates on the 14th of May in variants A and B and on the 14th of July in variant C [9]. 

Ganda is a retrovirus that uses EPO.  It examines the list of startup processes and replaces the first instruction of each startup process with a return.  This renders any antivirus programs useless [1].

 

6.  Conclusion

 

Several techniques used by virus writers to slow down the reverse-engineering of their code have been presented.  This paper has given an overview of the anti-debugging and anti-emulation techniques that are found in current malware.  These techniques should to be understood in order to make dynamic detection and analysis of malware code more effective. 

 

References

 

1.       Aycock, John. Computer Viruses and Malware.  New York, NY: Springer, 2006.

 

2.       Bellard, Fabrice.  QEMU, a Fast and Portable Dynamic Translator.“ 2005 USENIX Annual Technical Conference, pp. 41-46, 2005 <http://www.usenix.org/event/usenix05/tech/freenix/full_papers/bellard/bellard_html/>.

 

3.       Cesare, Silvo.  “Linux anti-debugging techniques (fooling the debugger)”.  January 1999.  <http://vx.netlux.org/lib/vsc04.html>.

 

4.       Desnoyers, Mathieu, Michel R. Dagenais.  “The LTTng tracer: A low impact performance and behavior monitor for GNU/Linux” Ottawa Linux Symposium, 2006. <http://www.kernel.org/doc/ols/2006/ols2006v1-pages-209-224.pdf>.

 

5.       Detecting Complex Viruses. Ferrie, Peter, Frederic Perriot.  Security Focus.  25 January 2007. <http://www.securityfocus.com/infocus/1813>.

 

6.       Exploring RDA.  .aware eZine Alpha - Overground Hacking.  6 December 2007. <http://www.awarenetwork.org/etc/alpha/?x=3>.

 

7.       Reversing HDSpoof - A Tutorial.  8 February 2007.  < http://www.openrce.org/articles/full_view/14 >.

 

8.       Symantec Corp.  24 January 2007 <http://www.symantec.com/index.htm>.

 

9.       Szor, Peter. The Art of Computer Virus Research and Defense.  Maryland: Addison-Phoenix BookTech, 2005.

 

10.    Ször, Péter.  Tricky Relocations.” Virus Bulletin, 2001.

 

11.    Torrubia, Andres, Francisco J. Mora.  Information Security in Multiprocessor Systems Based on the X86 Architecture.” Computers & Security Vol.19, No.6, pp.559-563, 2000.

 

12.    Vasudevan, Amit, Ramesh Yerraballi, "Stealth Breakpoints," acsac, pp. 381-392,  21st Annual Computer Security Applications Conference (ACSAC'05),  2005. <http://doi.ieeecomputersociety.org/10.1109/CSAC.2005.52>.

 

13.    Virus Source Code Database :: VSCDB.  25 March 2007.  <http://www.totallygeek.com/vscdb/index.php>.

 

14.    VX Heavens.  7 February 2007.  <http://vx.netlux.org/>.

 

15.    Windows Anti-Debug ReferenceNicolas Falliere.  Security Focus.  27 September 2007 <http://www.securityfocus.com/infocus/1893>.