Yara Windows

The Event Log coupled with Windows Event Forwarding and Sysmon can be extremely powerful in the hands of defenders, allowing them to detect attackers every step of the way. Obviously this is an issue for the attackers. Before privilege escalation it is limited what we can do to evade event logging, but once privileges have been elevated it is an equal playing field.

YARA is a tool aimed at (but not limited to) helping malware researchers to identify and classify malware samples. With YARA you can create descriptions of malware families (or whatever you want to describe) based on textual or binary patterns. YARA in a nutshell. YARA is a tool aimed at (but not limited to) helping malware researchers to identify and classify malware samples. With YARA you can create descriptions of malware families (or whatever you want to describe) based on textual or binary patterns. Each description, a.k.a rule, consists of a set of strings and a boolean expression which determine its logic.

In the past I have released a method to evade this logging by loading a malicious kernel driver and hooking the NtTraceEvent syscall. This method is effective but has two issues. The main issue is the risk associated with loading a kernel driver and patching syscalls as there is the potential to cause a BSOD on the machine which for obvious reasons a very bad thing. The other issue is that it will simply stop all events from being reported, so while the hook is active that machine will no longer be sending events to the SOC or SIEM. It is a real possibility that defenders would notice this sudden lack of events. So is there a way to only filter out the events caused by an attacker while also remaining completely inside usermode? Yes.

A couple of years ago @hlldz released Invoke-Phant0m. It would find the event log process and then kill all the threads running from wevtsvc.dll. This is because wevtsvc.dllis the event log service so by killing the threads associated with it will disable the logging. It works well but still has the same issue that ghost in the logs does, all events are stopped from being reported. To solve this issue I wanted to make a tool that will be similar to Invoke-Phant0m but will allow an attacker to apply a filter to the events being reported so they can only block events related to there malicious actions.

Reversing the event log service.

After opening wevtsvc.dll in cutter and looking around I noticed that it will open a tracing session via OpenTraceW.

OpenTraceW takes the EVENT_TRACE_LOGFILEW structure as an argument. This structure has the value EventRecordCallback which points to the callback function that will be given the event.

With a bit of digging about in windbg I found the callback function is wevtsvc!EtwEventCallback

Looking at the disassembly of the callback we can see that it does not look like a function, but rather is just a bit of assembly that will call EventCallback.

Setting a breakpoint on wevtsvc!EtwEventCallback we are able to dig a bit more into how this callback works. It will receive the event in the EVENT_RECORD structure which looks like;

The EVENT_HEADER structure will contain more info about the event including the provider which is reporting the event. With a little windbg magic we are able to grab this providers GUID.

Now that we have the providers GUID we can look it up using the logman.exe utility, and see that the provider was Microsoft-Windows-Sysmon.

Now we know we are looking in the right place we can patch this function with a ret instruction. This will stop all the events from being reported.

Below you can see that I cleared the event log at 7:01 then added a new user at 7:04 but this event was not reported because of our ret in the callback is causing all events system wide to be dropped.

Applying the hook

Now that we have a PoC working in windbg its time to start writing the code. I'm going to skip the injection side as there is loads of good explanations on that and go straight into how EvtMuteHook.dll will work.

Yara

The first thing we need to do is find the offset of wevtsvc!EtwEventCallback so we know where to place the hook. The first step in doing that is locating the base address of wevtsvc.dll the code below will do that and store it in the dwBase variable.

Since we do not know the exact location of EtwEventCallback we will need to search memory for it. We know that it is in the address space of wevtsvc.dll which is why we had to find it's base address.

We can use the disassembly from windbg to see the bytes at the start of the callback. We can then scan memory until we find these bytes. Once we have we will know where to place the hook.

This code will search 0xfffff bytes past the base address of wevtsvc.dll for the pattern 4883ec384c8b0d

Windows

Once we have the offset we will make a copy of the bytes located there with a call to memcpy

Then apply a hook to redirect all the calls to EtwEventCallback to EtwCallbackHook

I'm going to skip going into details about parsing EventRecord->UserData as it could be a whole blog post on its own, but if you are interested you can see my implementation here.

Now having hooked the callback is good, but we still need to be able to report events we don't want to block. This means we are going to also have to restore and run the callback so the event is reported, then re-hook it so we can catch the next event.

Using a typedef makes doing this pretty straight forward.

Yara windows example

After doing all of the we are now able to find the offset of the ETW callback, hook it to our own and parse the data. Then unpatch the callback and report the event.

Below you can see what the parsed event looks like in the windbg window.

Pattern matching with YARA

Now that we have the event in a clear format, its time to implement filters. I decided to use YARA rules for two reasons, The first being that I love the irony of using a popular defensive tool offensively. The second reason is that it is actually perfect for this use case as it has a very well documented C API and will work completely inside memory.

It is also worth pointing out that I have defined the following macros to keep consistency in the code style

The below example shows how you can create a yara rule object that can be used in YRRulesScanMem

Once the rule object has been created we can start scanning memory. The below example will scan the StringBuffer variable which contains the formatted event and will pass the result to the yara callback function ToReportOrNotToReportThatIsTheQuestion which in turn will either set the dwReport variable to 0 or 1 depending on if the rule matched or not. There is also a hard baked check for if the PIPE_NAME variable is present in the event. The reason for this is EvtMuteHook.dll will use a named pipe to dynamically update the current rule, this will cause events to be generated so this check will ensure that these events are never reported.

Where's all the logs gone?

You can grab the latest versions of EvtMute from here. EvtMuteHook.dll contains the core functionality, once it is injected it will apply a temporary filter which will allow all events to be reported, this filter can be dynamically updated without having to re-inject.

I've written SharpEvtMute.exe which is a C# assembly that can easily run via execute in shad0w or execute-assembly in cobalt strike. I will be writing a native version in C for a more stealthy option.

Disabling Logging

A trivial use case would be to disable event logging system wide. To do this we can use the following yara rule.

We will need to start by injecting the hook into the event service.

Now that the hook is placed we can add the filter.

Now all events will be dropped by the event service.

Complex Filters

Filters can be dynamically changed without having to re-inject a hook. This makes it quick and easy to update the active filter.

An example of a more complex filter is shown below. It is capable of blocking the events related to a lsass memory dump from being reported by sysmon.

With a complex rule like this it is much harder to condense it into a single line. This is why I added the ability to give base64 encoded rules.

The rule can easily be converted to base64 from a linux command line.

Then using the --Encoded flag we can pass it as a filter

Opsec Considerations

When injecting the hook SharpEvtMute.exe will call CreateRemoteThread this call is made before the hook is placed so it will be reported by Sysmon. This is because the injection feature of SharpEvtMute.exe should only be used as a PoC. I recommend manually injecting EvtMuteHook.dll into the event logging service when stealth is important.

It's PID can be found by running SharpEvtMute.exe --Pid. The hook can be placed by manually injecting the shellcode (run make in EvtMuteBin) via your C2 framework of choice, e.g shinject in shad0w.

It is also worth mentioning that the hook will use a named pipe to update filters. The named pipe is called EvtMuteHook_Rule_Pipe (this named can be changed easily). There is a rule hard baked into the hook to ensure that any events including this name will be dropped automatically but it will still be an IOC having it listening, so I recommend changing it.

Community Filters

If you create some useful filters feel free to make a pull request to the YaraFilters directory. It would be cool to have a good collection of filters to hide common actions that everyone can benefit from.

Thanks for reading and if you have any questions feel free to hit me up on twitter @batsec

YARA is a multi-platform program running on Windows, Linux and Mac OS X. You canfind the latest release at https://github.com/VirusTotal/yara/releases.

Compiling and installing YARA¶

Download the source tarball and get prepared for compiling it:

Make sure you have automake, libtool, make and gcc installedin your system. Ubuntu and Debian users can use:

If you plan to modify YARA’s source code you may also need flex andbison for generating lexers and parsers:

Compile and install YARA in the standard way:

Run the test cases to make sure that everything is fine:

Some of YARA’s features depend on the OpenSSL library. Those features areenabled only if you have the OpenSSL library installed in your system. If not,YARA is going to work fine but you won’t be able to use the disabled features.The configure script will automatically detect if OpenSSL is installed ornot. If you want to enforce the OpenSSL-dependent features you must pass--with-crypto to the configure script. Ubuntu and Debian users can usesudoapt-getinstalllibssl-dev to install the OpenSSL library.

The following modules are not compiled into YARA by default:

  • cuckoo
  • magic
  • dotnet

If you plan to use them you must pass the corresponding --enable-<modulename> arguments to the configure script.

For example:

Modules usually depend on external libraries, depending on the modules youchoose to install you’ll need the following libraries:

  • cuckoo:
    Depends on Jansson for parsing JSON.Some Ubuntu and Debian versions already include a package namedlibjansson-dev, if sudoapt-getinstalllibjansson-dev doesn’twork for you then get the source code fromits repository.
  • magic:
    Depends on libmagic, a library used by the Unix standard programfile.Ubuntu, Debian and CentOS include a packagelibmagic-dev. The source code can be foundhere.

Installing on Windows¶

Yara Windows

Yara Windows Command Line

Compiled binaries for Windows in both 32 and 64 bit flavors can be found in thelink below. Just download the version you want, unzip the archive, and put theyara.exe and yarac.exe binaries anywhere in your disk.

Yara Windows 7

To install the yara-python extension download and execute the installercorresponding to the version of Python you’re using.

Installing on Mac OS X with Homebrew¶

To install YARA using Homebrew, simply typebrewinstallyara.

Installing yara-python¶

Yara Windows

If you plan to use YARA from your Python scripts you need to install theyara-python extension. Please refer to https://github.com/VirusTotal/yara-pythonfor instructions on how to install it.

Running YARA for the first time¶

Now that you have installed YARA you can write a very simple rule and use thecommand-line tool to scan some file:

Yara Windows Defender

Don’t get confused by the repeated my_first_rule in the arguments toyara, I’m just passing the same file as both the rules and the file tobe scanned. You can pass any file you want to be scanned (second argument).

If everything goes fine you should get the following output:

Which means that the file my_first_rule is matching the rule named dummy.

Yara Windows Github

If you get an error like this:

It means that the loader is not finding the libyara library which islocated in /usr/local/lib. In some Linux flavors the loader doesn’t look forlibraries in this path by default, we must instruct it to do so by adding/usr/local/lib to the loader configuration file /etc/ld.so.conf: