• Stars
    star
    341
  • Rank 123,998 (Top 3 %)
  • Language
    C++
  • License
    MIT License
  • Created almost 4 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

UnhookMe is an universal Windows API resolver & unhooker addressing problem of invoking unmonitored system calls from within of your Red Teams malware

UnhookMe - Dynamically unhooking imports resolver

In the era of intrusive AVs and EDRs that introduce hot-patches to the running processes for their enhanced optics requirements, modern adversaries must have a robust tool to slide through these watchguards. The propsed implementation of dynamic imports resolver that would be capable of unhooking used functions in-the-fly is yet another step towards strengthening adversary resilience efforts.

The solution I'm proposing here is to switch from using linker-resolved WinAPI imports, staying visibile in compiled executable's PE headers (Import Address Table specifically) to favor fully-dynamic approach insisting on resolving imports only in a dynamic fashion. Such dynamical resolver can be equipped with unhooking logic happening in the background, without any sort of guidance from the operator's side.


Simplest usage example

This is how you can ensure to call MessageBoxW unhooked, unmonitored:

    RESOLVE(user32, MessageBoxW);
    _MessageBoxW(0, L"Look Ma! I'm unhooked!", L"Third - Unhooked", 0);

All the magic happens within RESOLVE macrodefintion, that constructs ImportResolver<T> object named _MessageBoxW.


Showcase

Unhookme showcase animation

Here's how UnhookMe example works:

  1. It presents us with the first MessageBoxW that is not subject for hooking
  2. Then we hook MessageBoxW prologue ourselves to make it always return 0 without displaying it's message
  3. Finally, we resolve MessageBoxW dynamically using the UnhookingImportResolver resolver, which will detect applied prologue patches and restore original bytes, effectively unhooking MessageBoxW functionality.

In the meantime of popping message boxes, these are the loglines printed to console's stdout:

[~] Resolved symbol kernel32.dll!CreateFileA
[~] Resolved symbol kernel32.dll!ReadProcessMemory
[~] Resolved symbol kernel32.dll!MapViewOfFile
[~] Resolved symbol kernel32.dll!VirtualProtectEx
[#] Found trampoline hook in symbol: MessageBoxW . Restored original bytes from file.
[~] Resolved symbol user32.dll!MessageBoxW

How to use it?

There are in total 5 C++ source code/header files that your solution need to include. However your main program file needs to include only two required headers, as detailed below.

  • resolver.h - header containing most of the UnhookingImportResolver implementation and handy macrodefinitions
  • resolver.cpp - source code with global options defined
  • usings.h - a one big and nasty header file containing tens of using type definitions for commonly used WinAPIs
  • PE.cpp - custom PE parser source code file
  • PE.h - custom PE parser header file

Required headers

Your program will require only two headers being included:

#include "usings.h"
#include "resolver.h"

Global options

There are couple of global options that can be changed affecting the way in which Resolver works or reports it's activity. These are defined in the very beginning of resolver.cpp file:

Resolver global options:

  • globalQuietOption - set to true if you don't want to have any sort of output
  • globalVerboseOption - set to true if you want to have detailed verbose output
  • globalAntiSplicingOption - unhook resolved functions if they're hooked.
  • globalLogFilePath - where to redirect output log lines. If empty, pick stdout.
bool globalQuietOption = false;
bool globalVerboseOption = true;
bool globalAntiSplicingOption = true;

wchar_t globalLogFilePath[MAX_PATH] = L"";

Custom API type specification

In order to use Resolver a function pointer type must be first declared with using statement of strict form:

    using fn_FunctionName = ReturnType WINAPI (
        ParamType1 paramName1,
        ...,
        ParamTypeN paramNameN,
    );

This repository comes with usings.h header file containing predefined using types for tens of popular Windows APIs.

The FunctionName will correspond to the WinAPI that we want to have ImportResolver resolve and that function pointer must be marked as having WINAPI call convention ( __stdcall on x86 and __fastcall on x64). The ReturnType must precede WINAPI type modifier.

Function resolution and usage

Having function pointer type defined like specified above, we will be able to use it in the following manner:

    RESOLVE(libraryName, FunctionName);
    ReturnType output = _FunctionName(param1, ..., paramN);

The macro RESOLVE takes care of instantiating ImportResolver templated object and adjust specifed library's name.

Resolver introduces several more Macrodefinitions offering easy to use in various circumstances constructor invocation:

#define RESOLVE(mod, func)                    RESOLVE_PARAMETERIZED(mod, func, ::globalVerboseOption, ::globalAntiSplicingOption)
#define RESOLVE_NO_UNHOOK(mod, func)          RESOLVE_PARAMETERIZED(mod, func, ::globalVerboseOption, false)

#define RESOLVE_VERBOSE_UNHOOK(mod, func)     RESOLVE_PARAMETERIZED(mod, func, true, true)
#define RESOLVE_VERBOSE_NOUNHOOK(mod, func)   RESOLVE_PARAMETERIZED(mod, func, true, false)
#define RESOLVE_NOVERBOSE_UNHOOK(mod, func)   RESOLVE_PARAMETERIZED(mod, func, false, true)
#define RESOLVE_NOVERBOSE_NOUNHOOK(mod, func) RESOLVE_PARAMETERIZED(mod, func, false, false)

Resolver's constructor:

    template<typename Ret, typename ...Args>
    ImportResolver<Ret WINAPI(Args...)>(
            std::string dllName,
            std::string funcName,
            bool _verbose = false,
            bool _unhook = false,
            bool *_wasItHooked = nullptr
        )

How does it work?

The underlaying resolver leverages custom PE headers parser, that processes every referenced DLL module to map their exports and verify that module's PE headers integrity as well as integrity of referenced function's stub bytes.

The idea is following:

  1. Firstly we issue LoadLibrary to load referenced by the user library (the one specified as first parameter for RESOLVE macro) if it could not be reached through GetModuleHandle.

  2. Then we process loaded/referenced library's PE headers, map its exports, retrieve array of exports addresses as well as compute these addresses ourselves for cross-verification.

  3. If address of a routine defined in DLL's Export Address Table doesn't correspond to what we would expect, the export is considered EAT hooked. The same goes if our Executable Import Address Table (IAT) entry for that function was altered and no longer points to the correct spot in DLL's code section - then the function is considered to be IAT hooked.

  4. Assuming no hooks were found so far, we fetch first N bytes of the function's prologue and compare them to what's in DLL's file stored in disk. If there is miscrepancy between bytes fetched from memory and from file - we consider function was inline patched (hot-patched).

  5. If the function was considered hooked - we return original export's address (the one we computed ourselves) and/or unhook the entry. If there were patch bytes in place, we'll restore them.

  6. Finally, in order to optimize resolver's performance impact - we cache all of the loaded modules imagebases and resolved functions addresses and return them from a cache (being std::map ) during subsequent hits.

Among the problems such dynamically-unhooking resolver faced are the issues with traversing forwarded APIs (a DLL may contain Export thunk saying that this function is not implemented in this module, but it is in another one) - which although this implementation has support for, sometimes it brokes its traversal logic.


β˜• Show Support β˜•

This and other projects are outcome of sleepless nights and plenty of hard work. If you like what I do and appreciate that I always give back to the community, Consider buying me a coffee (or better a beer) just to say thank you! πŸ’ͺ


Author

   Mariusz Banach / mgeeky, 21
   <mb [at] binary-offensive.com>
   (https://github.com/mgeeky)

More Repositories

1

Penetration-Testing-Tools

A collection of more than 170+ tools, scripts, cheatsheets and other loots that I've developed over years for Red Teaming/Pentesting/IT Security audits purposes.
PowerShell
2,514
star
2

ThreadStackSpoofer

Thread Stack Spoofing - PoC for an advanced In-Memory evasion technique allowing to better hide injected shellcode's memory allocation from scanners and analysts.
C++
1,035
star
3

cobalt-arsenal

My collection of battle-tested Aggressor Scripts for Cobalt Strike 4.0+
PowerShell
1,033
star
4

RedWarden

Cobalt Strike C2 Reverse proxy that fends off Blue Teams, AVs, EDRs, scanners through packet inspection and malleable profile correlation
Python
922
star
5

ShellcodeFluctuation

An advanced in-memory evasion technique fluctuating shellcode's memory protection between RW/NoAccess & RX and then encrypting/decrypting its contents
C++
922
star
6

ProtectMyTooling

Multi-Packer wrapper letting us daisy-chain various packers, obfuscators and other Red Team oriented weaponry. Featured with artifacts watermarking, IOCs collection & PE Backdooring. You feed it with your implant, it does a lot of sneaky things and spits out obfuscated executable.
PowerShell
869
star
7

PackMyPayload

A PoC that packages payloads into output containers to evade Mark-of-the-Web flag & demonstrate risks associated with container file formats. Supports: ZIP, 7zip, PDF, ISO, IMG, CAB, VHD, VHDX
Python
853
star
8

decode-spam-headers

A script that helps you understand why your E-Mail ended up in Spam
Python
558
star
9

Stracciatella

OpSec-safe Powershell runspace from within C# (aka SharpPick) with AMSI, Constrained Language Mode and Script Block Logging disabled at startup
C#
494
star
10

ElusiveMice

Cobalt Strike User-Defined Reflective Loader with AV/EDR Evasion in mind
C
417
star
11

tomcatWarDeployer

Apache Tomcat auto WAR deployment & pwning penetration testing tool.
Python
409
star
12

SharpWebServer

Red Team oriented C# Simple HTTP & WebDAV Server with Net-NTLM hashes capture functionality
C#
279
star
13

AzureRT

AzureRT - A Powershell module implementing various Azure Red Team tactics
PowerShell
227
star
14

expdevBadChars

Bad Characters highlighter for exploit development purposes supporting multiple input formats while comparing.
Python
202
star
15

msidump

MSI Dump - a tool that analyzes malicious MSI installation packages, extracts files, streams, binary data and incorporates YARA scanner.
Python
191
star
16

RobustPentestMacro

This is a rich-featured Visual Basic macro code for use during Penetration Testing assignments, implementing various advanced post-exploitation techniques.
VBScript
144
star
17

Exploit-Development-Tools

A bunch of my exploit development helper tools, collected in one place.
Python
140
star
18

VisualBasicObfuscator

Visual Basic Code universal Obfuscator intended to be used during penetration testing assignments.
Python
135
star
19

msi-shenanigans

Proof of Concept code and samples presenting emerging threat of MSI installer files.
Python
77
star
20

PE-library

Lightweight Portable Executable parsing library and a demo peParser application.
C++
72
star
21

HEVD_Kernel_Exploit

Exploits pack for the Windows Kernel mode driver HackSysExtremeVulnerableDriver written for educational purposes.
C++
63
star
22

procmon-filters

SysInternals' Process Monitor filters repository - collected from various places and made up by myself. To be used for quick Behavioral analysis of testing specimens. Inspired and based on Lenny Zeltser's collection.
58
star
23

PhishingPost

PHP Script intdended to be used during Phishing campaigns as a credentials collector linked to backdoored HTML <form> action parameter
PHP
56
star
24

burpContextAwareFuzzer

BurpSuite's payload-generation extension aiming at applying fuzzed test-cases depending on the type of payload (integer, string, path; JSON; XML; GWT; binary) and following encoding-scheme applied originally.
Python
39
star
25

CustomXMLPart

A PoC weaponising CustomXMLPart for hiding malware code inside of Office document structures.
VBA
37
star
26

dirbuster

wfuzz, SecLists and john -based dirbusting / forceful browsing script intended to be used during web pentest assingments
Shell
34
star
27

ntfs-journal-viewer

Utterly simple NTFS Journal dumping utility. Handy when it comes to Computer Forensics and Malware Forensics Ops.
C
33
star
28

digitalocean-app-redirector

Reverse-HTTP Redirector via DigitalOcean Apps Platform
Python
27
star
29

LISET

Light System Examination Toolkit (LISET) - logs & activity & configuration gathering utility that comes handy in fast Windows incident response (either forensic or malware oriented).
Batchfile
27
star
30

RPISEC-MBE-Solutions

Solutions to the RPISEC MBE / Modern Binary Exploitation VM & course.
Python
19
star
31

prc_xchk

User-mode process cross-checking utility intended to detect naive malware hiding itself by hooking IAT/EAT.
C++
17
star
32

PEInfo

Another Portable Executable files analysing stuff
C++
17
star
33

mgeeky

9
star
34

stegano1

College project implementing some of the compression and image steganographic algorithms.
C++
5
star
35

DISASM

Simple disassembling library (currently only x86)
C++
4
star
36

linux-utils

Some linux utils I've coded and decided to share.
C
2
star
37

Symulacja-Reaktora-Jadrowego

(Polish only) Program przygotowywany na uczelnie w ramach kursu "Symulacje Komputerowe". Przedstawia hipotetyczna prace reaktora jadrowego w roznych stanach i konfiguracjach.
MATLAB
1
star