Monthly Archives: May 2012

Why Usermode Hooking Sucks – Bypassing Comodo Internet Security

Abstract

This post discusses the issues that arise from the reliance on user-mode control flow monitoring techniques for the implementation of systems such as Host Based Intrusion Detection Systems, Sandboxes, Function Tracers, etc. It focuses on a single HIPS product offered by Comodo [1], a well respected company that helps the community by offering a number of their products free of charge. However, the techniques used by this product are not completely bulletproof and can be exploited by malicious agents to disable its protection barriers or circumvent Operating System protections and deliver an unwanted payload.

Throughout the next paragraphs we will briefly analyze the techniques used by the Comodo Internet Security Premium product to install the HIPS technology for monitoring a single application as well as the environmental effects it has inside the processes’ address space. We shall then introduce the dangers and attack vectors this technique creates and eventually provide an example proof of concept technique to stop the monitor’s installation.

Additionally, we will illustrate that the changes made by this software to the address space of a process can eventually allow the creation of external attack vectors that enable the exploitation of a specific software vulnerabilities that was previously thought to be improbable due to operating system protection barriers.

Finally, we shall introduce a proof of concept program that automatically applies the example technique to an arbitrary executable file in order to automate the process of evading the HIPS installation therefore, illustrating how malicious programs can implement this technique to improve the infection and propagation phases of their attack.

Introduction

Numerous security applications rely on the modification of user-mode memory locations for installing hooks to circumvent the code execution flow to an injected library or memory page for various security or statistical reasons. However, malicious software that are aware of such hooks can essentially overcome them and execute without any interruptions. It all comes down to the permissions available by the malicious software to control it’s own address space.

We may classify such programs, for the purpose of this post, in the following categories based on the techniques used to bypass security blockades.

  • Smart-Malware
  • Targeted-Malware

The term Smart-Malware,  refers to malicious pieces of software that are capable of understanding the execution environment by disassembling instructions and identifying possible hooks. Such malware can then reconstruct the original code execution flow thus bypassing security software. Malicious agents of this kind can be considered to be the next step in malware evolution.

Targeted-Malware refers to malicious software that target a single or a set of security products by disabling or bypassing their protections. The proof of concept program introduced in this post targets the Comodo Internet Security Premium product by modifying malicious executables in such a way thus allowing them by disable the HIPS security protections enforced to them as a process.

User-mode hook “security” modifications that fall under a processes’ address space, where an executable module retains the ability to read and write from and to them, create a false sense of security to the end user. Security products such as Comodo, that employ such techniques can essentially be bypassed by Smart-Malware and Targeted-Malware agents.

The following sections of this post, will abstractly introduce the technique used by Comodo to install a Host Based Intrusion Prevention System whose purpose is to monitor the behavior of, by default, untrusted applications and assess their maliciousness or report back to the user querying him/her whether to continue execution or not. Additionally, we shall briefly cover the attack vectors created by this product and their effects in the overall system security.

Next, we shall introduce our research results, that illustrate why such techniques should not be employed by software products. We will go through a real-life example process of modifying a malicious software to disable alerts generate by the Comodo HIPS.

Comodo HIPS Hook Installation

The technique used by Comodo to install the HIPS on a newly created process involves placing a hook prior to the initial execution of the main module. This hook diverts the execution flow towards a code page which contains a set of obfuscated assembly instructions that load the monitoring library into the process address space. This occurs when executing an application on any Windows OS version and processor architecture.

How the code section is created or what exactly does it do falls outside our scope of research, however an initial analysis has shown numerous other issues with the algorithm’s logic. It is worth noting that the code page is loaded at a constant address throughout all Operating System versions that Comodo Internet Security supports.

Disclosure Timeline

30 November 2011 – Notified vendor.

1 December 2011 – Notified vendor.

16 December 2011 – Attempted to notify vendor.

Research Laboratory

Our laboratory setup for this specific research contains the following Operating Systems:

OS Version Bypass Protection Other Vulnerabilities/Issues
Windows 7 64bit Yes on all SysWoW64 Processes ( 32 bit ) Yes
Windows 7 32bit No Yes
Windows XP 32bit No Yes

Software:

  • OllyDBG (Any version would do)
  • C Compiler

 Low Level Analysis

As mentioned in the previous paragraphs the code page contains the code to load and execute the monitor library. The name of this library is guard32.dll or guard64.dll depending on the operating system version and application. It is located at:

OS Version Path Description
Windows 64bit C:\Windows\system32\guard64.dll All 64bit Windows versions on 64bit applications
Windows 64bit C:\Windows\SysWOW64\guard32.dll All 64bit Windows versions on 32bit applications
Windows 32bit C:\Windows\system32\guard32.dll All 32bit Windows versions on 32bit applications

Recent updates have installed an additional layer of protection that sets guard32.dll and guard64.dll libraries as AppInit_DLLs in the following registry keys, however an application can uninstall them without alerting the user of malicious attempts.

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows]
“AppInit_DLLs”=”C:\Windows\SysWOW64\guard32.dll”

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows]
“AppInit_DLLs”=” C:\\Windows\\system32\\guard64.dll”

If we open a 32bit process in OllyDBG on a 64bit Windows version and set it so that we stop at the Entry Point of the application then we will come across the following image:

Figure 1: SysWoW64 Process Entry Point Hook

In 32bit Windows versions the above JMP instruction is located in ntdll.dll at the entry of the ZwTestAlert function as shown below:

Figure 2: Windows 32bit Process ZwTestAlert Hook

In a similar way 64bit Windows versions running 64bit native applications contain an identical JMP instruction in the ntdll library ZwTestAlert function as shown below:

Figure 3: Windows 64bit Process ZwTestAlert Hook

This instruction acts as a trampoline instruction to the statically allocated memory page which, as mentioned before, loads the monitor library. There are three major issues that arise from the above technique:

  1. A statically allocated executable memory location ( 0x71B00000 ) introduces an attack vector where 3rd party application vulnerabilities such as buffer overflows, that satisfy certain conditions, can be exploited on ASLR enabled systems without having to worry about address randomization!
  2. The technique used in SysWoW64 applications does not take into consideration the fact that an application has the same access rights to modify it’s address space, thus uninstalling any hooks!
  3. Incorrect assumptions are made in regards to the exact execution process of a thread. In other words, the Entry Point and the call to ZwTestAlert from the Windows loader are not necessarily executed prior to the execution of the target application.

An analysis of the code located in the statically allocated memory page reveals a number of instructions that might allow, in certain cases, the successful exploitation of vulnerabilities due to the fact that no randomization takes place. For example, the CALL ECX instruction located at address 0x71B0000A could be proven useful in a buffer overflow situation where ECX happens to point in an attacker controlled executable location.

Figure 4: Call ECX

Another set of instructions that might be proven useful in a similar scenario are the instructions that begin at location 0x71B002A6 or even 0x71B002A9 and end with the RETN instruction at 0x71B002AA as shown below. These can be used in a case where right after the overflow EBP+4 points to an attacker controlled location thus returning to it. Additionally, the attacker can also take advantage of the POP/RETN instructions to create a ROP algorithm that exhausts ( or pops out ) values inside the stack, therefore walking through each value until a pointer to an attacker controlled memory location is reached and returned to.

Figure 5: Possible ROP Block

The above situations, are rather remote and quite rare. However, we cannot avoid the fact that they are still there. We believe that it is unacceptable that this problem is introduced into the system by a product which is supposed to be protecting it from such malicious attacks.

Another issue that arises from the current implementation of Comodo HIPS or any other usermode hooking security products is the fact that applications can modify any memory page in their private allocated address space. Doing so in applications running on Windows 32bit version appears to have no effect in evading the HIPS system where Comodo appears to be filtering requests from the kernel side. The following hooks were identified in a process running on a Windows 32bit system:

Figure 6: Windows 32bit guard32.dll Hooks

Windows 64bit SysWoW64 processes are a completely different story. In this case the guard32.dll library is responsible for installing all possible hooks in usermode in order to implement the same functionality for the HIPS. The following hooks were identified in a SysWoW64 process :

Figure 7: Windows SysWoW64 guard32.dll Hooks (Click for complete image)

A textual representation of the list can be found by clicking the link below:

Click To View The complete List…

If a SysWoW64 application would detect all hooks to guard32.dll and recover the original code then it would be able to execute malicious code without detection. However, this technique is quite inefficient since in order to maintain cross-compatibility with various operating system versions, the application would have to load each library file in memory, locate the original code, apply any pointer relocations and finally uninstall the hook.

An additional issue that arises from this hooking technique, is the forceful reallocation of Copy-on-Write memory pages that are commonly shared between multiple processes in order to save up memory. For example, in pure systems the ntdll.dll module is loaded once and shared between all processes. If one of those processes alters a page, then that page is duplicated and a unique instance is given to that process. What Comodo HIPS does is to ask every process to alter the memory pages containing the above hooked functions, leading to numerous private copies that waste a huge amount of memory in the system.

The next issue with Comodo Internet Security, the most serious one, falls in the category of incorrect assumptions about the operating system environment. The hooks in Figure 1 and Figure 2 have a single purpose. To jump within the memory page at 0x71B00000 and load the guard32.dll. How these hooks are placed in new processes is of no concern to this post. In short, Comodo just modifies the parent process and hooks process creation functions such as CreateProcessA. When you double click on an executable in Windows explorer, the explorer process essentially creates a new process for you using those functions, therefore allowing Comodo to modify the newly created address space before the main thread begins executing.

Now the problem exists in a vector that was not considered by the Comodo programmers and designers. That is the implementation of Thread Local Storage on Windows that can allow, certain executable files that declare static shared variables, to specify constructor or destructor functions for local threads. For a more detailed information on TLS you can refer to the Microsoft PE and COFF Specification [2] document. Since constructor functions have to be executed when a thread is created, as specified by the specification in order to initialize the TLS, the execution flow passes first from them and then to the main executable. It happens to be that ZwTestAlert is also executed after the execution of all constructor functions. Therefore, a malicious application could essentially execute a small piece of code that uninstalls the initial installation hook.

In order to achieve evasion from Comodo Internet Security using this methodology, the following steps need to be implemented:

  1. Allocate a location to place the TLS Directory structure defined as _IMAGE_TLS_DIRECTORY32.
  2. Fill in the addresses for callback functions ( our supposed constructors ).
  3. Allocate a location to place the code for the TLS callback functions.
  4. Write code that uninstalls the initial hooks from the EP or ZwTestAlert.
  5. Modify the PE Header’s DataDirectory to use the newly created TLS Directory.

The first step is to find a location to place the TLS Directory. The structure is defined in winnt.h header file as follows:

typedef struct _IMAGE_TLS_DIRECTORY32 {
DWORD   StartAddressOfRawData;
DWORD   EndAddressOfRawData;
DWORD   AddressOfIndex;             // PDWORD
DWORD   AddressOfCallBacks;         // PIMAGE_TLS_CALLBACK *
DWORD   SizeOfZeroFill;
DWORD   Characteristics;
} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;

It’s size is 6 x DWORD elements of size 4 bytes each which makes us 24 bytes. For the purposes of this research and the proof of concept code, we are creating a brand new PE section in the executable file. Lets say that we decide to add a new section of roughly about 100 bytes. We create a new IMAGE_SECTION_HEADER structure and write it to the end of the last section in the PE executable. This is done by the AddNewPESection function of the POC code which has the following prototype:

PIMAGE_SECTION_HEADER AddNewPESection(
PFILE_IN_MEMORY lpFile,
char * lpszSectionName,
int nSectionSize,
DWORD dwCharacteristics )

We can name the new section “.tls” and set the following characteristics:

  • IMAGE_SCN_CNT_CODE
  • IMAGE_SCN_MEM_READ
  • IMAGE_SCN_MEM_WRITE
  • IMAGE_SCN_CNT_INITIALIZED_DATA

Next we create an _IMAGE_TLS_DIRECTORY32 by filling in the values. Note that we will place this new structure at the start address of our new PE Section which we will refer to as new_section_va from now on. The suggested values are as follows:

Element Name Suggested Value
StartAddressOfRawData Virtual Address to a zeroed memory location. eg: new_section_va + 24
EndAddressOfRawData Virtual Address to a zeroed memory location. eg: new_section_va + 28
AddressOfIndex Virtual Address to a zeroed writable memory location. eg: new_section_va + 32
AddressOfCallBacks Virtual address to a void * array containing the virtual addresses of callback functions. This array ends with a NULL value to specify that there are no more entries available. We can use the location new_section_va + 36 for writing our callback function address and location new_section_va + 40 for the NULL terminating value
SizeOfZeroFill Not required and it is best to keep 0
Characteristics Reserved and set to 0

Note that the virtual addresses we’ve inserted need to be added to the relocation table in order to avoid any unexpected results when the executable gets loaded in a different base address. The next step is to write a set of assembly instructions that recover the original code and uninstall the hook placed by Comodo. We can use the following:

unsigned char ucCode[33] = {
0×56,                                       // PUSH ESI
0xE8, 0×00, 0×00, 0×00, 0×00,    // CALL $
0x5E,                                       // POP ESI
0×83, 0xC6, 0×12,                     // ADD ESI, 0×12
0x8B, 0x3E,                              // MOV EDI, DWORD [ESI]
0×83, 0xC6, 0×04,                     // ADD ESI, 4
0xB9, 0×05, 0×00, 0×00, 0×00,   // MOV ECX, 5
0xF3, 0xA4,                             // REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
0x5E,                                      // POP ESI
0xC3,                                      // RETN
0xC5, 0×15, 0×40, 0×00,            // Address to patch to (EP Address) container [24]
0xE8, 0x1E, 0×24, 0×00,    0×00 // Bytes to patch container [28]
};

Explanation:

PUSH ESI Spill the value of ESI into the stack
CALL $ Relative call 0 bytes ahead
POP ESI Pop the return address (which is the current address) from the stack, put there by the CALL instruction and store it in ESI
ADD ESI, 0×12 Add 18 bytes to ESI so that it will point to the EP Address container at the end of this code
MOV EDI, DWORD [ESI] Set EDI to the contents of ESI which is be the actual EP address
ADD ESI, 4 Skip 4 bytes ahead so that ESI would point to the Bytes to patch container
MOV ECX, 5 Set ECX counter to 5 bytes
REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI] Byte copy operation REP copies from ESI (Bytes to patch container) to EDI ( EP of executable ) an ECX number of bytes
POP ESI Recover the original value of ESI spilled at the begining of the function
RETN Return function

These assembly instructions are then patched to the .tls section and the array pointed to by the AddressOfCallBacks element from the TLS Directory is updated accordingly.

Finally, we update the DataDirectory from the PE Header of the executable to add the new TLS entry. Note that there is an additional change that needed to be done. That is the section that holds the EP of the executable needs to be marked as IMAGE_SCN_MEM_WRITE so that when the injected TLS code attempts to write to it no page exception is thrown.

Conclusions

To conclude with, we’d like to stress that we do not hate the Comodo HIPS product. The bypassing method presented in this post is rather remote and applies only on SysWoW64 ( 32bit ) applications running on a 64bit Windows version. Attached you will find a proof of concept application that automates the process of generating executable that can bypass the installation of hooks throughout the process address space. Thank you for reading.

Download: POC Comodo Bypass Application Creator (source and application)

Update: POC Video

References
  1. Free Internet Security Software Suite, Comodo, http://www.comodo.com/home/internet-security/free-internet-security.php
  2. Section 5.7, Microsoft PE and COFF Specification, Microsoft, September 2010, http://msdn.microsoft.com/library/windows/hardware/gg463125