News: CFTIRC Online Bulletin Board Launched (Pentesting & DFIR Miner).
Please register an account to access our community's posts.

Login  |  Register

Author Topic: A New Approach to Generically Bypass User-Space EDR Hooking  (Read 371 times)

BigBrother

  • Administrator
  • Sr. Member
  • *****
  • Posts: 408
  • Karma: 2000
  • You Posted! You Posted! : Earned for posting at least 1 time.
    Have something to say! Have something to say! : Earned for posting at least 10 times.
    Talkative! Talkative! : Earned for posting at least 100 times.
A New Approach to Generically Bypass User-Space EDR Hooking
« on: August 18, 2020, 11:44:43 am »

Introduction

During red team engagements, it is not uncommon to encounter Endpoint Defence & Response (EDR) / Prevention (EDP) products that implement user-land hooks to gain insight in to a process’ behaviour and monitor for potentially malicious code. Some great work has been done in bypassing these checks in the past, including from our friends at Outflank who demonstrated this using direct system calls (recommended reading, HT to @Cneelis). However, in this blog post we will illustrate a new, generic approach for circumventing user-land EDR hooks.

Our technique involves tracing into code which may invoke hooked functions, detecting the hooks and redirecting execution to the original code (usually migrated into a small thunk elsewhere in memory) circumventing the layer of defence which may otherwise be implemented.

In practice there are some minor shortcoming to address to make this approach maximally useful, however it is hoped that this post will provide a good starting point and that the more general concept could form the basis for further ideas and research.

A Brief Introduction to Function Hooking

Function hooking is a technique used to intercept function calls at the point of execution, providing an application with the opportunity to examine, modify or replace the behaviour of the hooked function at runtime. Function hooks are usually installed on functions for which the source code is not available to the developer, otherwise (language supported) techniques can be employed to more achieve the desired level of augmentation.

There are several approaches which can be used to hook functions. One such approach involves redirecting entries within the Import Address Table (IAT) to point to an associated function hook, which then in turn calls the original function as required. This approach involves walking the Import Directory for an application at runtime and enumerating imported functions by name (or by ordinal) until the desired function is identified and then overwriting the associated IAT entry with a pointer to the hook.

This approach is however not the approach usually favoured by developers of hooking libraries because there is a risk that not every call to the hooked function will be intercepted. For example – in the event that the application has cached a pointer to the original function before the hook is installed, once called the original function will be invoked and the hook will be bypassed. Similarly if other means of locating the target function are employed (for example, by using the Windows API GetProcAdress the pointer to the original function will be returned, rather than the hook). Hooking imported functions by name also works only for functions which are exported by some other DLL (rather than – say – internal functions).

Due to these shortcomings the preferred approach to function hooking involves direct rewriting of the target function. With this approach the first few instructions of the target are copied out of the function into executable memory and are replaced with a jmp to the hook. Directly following the copied instructions a jmp instruction is added to return back to the original function at the point which follows the copied instructions. This has the effect of seamlessly redirecting the function call – parameters and registers intact – to the hook function. The hook function then is free to examine and modify parameters as required and may then choose to invoke the original function by calling the newly allocated executable memory address containing the original instructions and jmp as previously mentioned.

This approach is preferable because – since it overwrites the function being hooked itself rather than a pointer to the function – this approach should succeed in intercepting every call to the hooked function rather than just those relying on the IAT for a particular module. This technique for function hooking makes much more sense therefore when implementing – for example – anti-malware/EDR software which depends on the ability to detect and examine usage of particular functions.

To implement a function hooking library great care is required to ensure that modification of the target function does not crash the application. Problems which may arise within a poorly implemented library may include – race conditions (between rewriting the function prologue versus another thread attempting to execute the prologue), breaking instructions (making incorrect assumptions about the format of the hooked function prologue may lead to an incorrect number of instructions being copied and overwritten), and calling convention mismatch (assuming the calling convention used by a particular function may lead to the hook target implementing parameter management and stack cleanup incorrectly, leading to a crash – this is however more the responsibility of the hook developer than the library itself).

Read the full article @ https://www.mdsec.co.uk/2020/08/firewalker-a-new-approach-to-generically-bypass-user-space-edr-hooking/
--
Best Regards
CFTIRC Admin
https://www.acfti.org/cftirc-community