Cache side channel attacks: CPU Design as a security problem

 

End of May I had the opportunity to present my research on cache side channel attacks at the “Hack In The Box” conference. After my presentation with Nishat Herath last year at black hat I published my private comments to that slide deck and that was well received. I had decided to do that again for “Hack In The Box”, unfortunately it took me a little longer to translate my comments into something human readable. But here they are. Since the comments relate directly to a specific slide in the slide deck you’ll probably want to have the slide deck open when reading this blog post. You can find them here: https://conference.hitb.org/hitbsecconf2016ams/materials/D2T1%20-%20Anders%20Fogh%20-%20Cache%20Side%20Channel%20Attacks.pdf

Cache side channel attacks: CPU Design as a security problem

The title of the presentation took quite a while to figure out because I wanted a title that fairly and accurately described the content of the presentation, but one that was also slightly catchy. I like what I came up with.

Here I told how I got into cache side channel attacks as an introduction. I was working on a talk about row hammer detection, when Daniel Gruss tweeted he’d been able to row hammer in Java script. Consequently, I had to figure out how he did it, so that I could speak with confidence. Everything pointed towards the cache side channel attack literature, so I dug in and 4 hours later produced my first cache side channel attack. This side channel attack triggered my row hammer detection and that let me into a year worth of playing with CPU caches.

 

Agenda

When I start doing slides, I always think about what I want to come across to the listener well knowing that most people will have forgotten most two hours later.

1)      I wanted to point out that safe software running on unsafe hardware is unsafe – something I think is too often forgotten. Further I wanted to make the point that we are not talking about a “bug” in the sense that an intel engineer made a mistake. Rather the cache system generally works as designed – though this design has unintended consequences: cache side channel attacks. Specifically:

  1. Attacker can manipulate the cache: Shared L3 (between cores & trust zones) + Inclusive cache hierarchy
  2. The cache state can be queried and give back a lot of valuable information: Timing attacks (on access & clflush), Shared L3, N-Way-Set associative cache, complex addressing function for L3 that application access to sets.

2)      Here I just wanted to point out that this isn’t just an academic issue. In many ways cache side channel attacks, can be a real world alternative to VM breakout and privilege escalation attacks – or even a method to support either of those.

3)      I wanted to make the point that we can do something about these critters – even when the attacker adopts.

Introduction

  • The most important things I wanted to get across was CSCs are an attack methodology and not an attack. Further that the cache design is not a requirement to be an x86, that is the cache could be designed differently and be less useful for cache side channel attacks without causing software incompatibility.
  • The bandwidth of the side channel is essentially the bandwidth of the cache and thus a lot of valuable data can be leaked. The size of the caches makes the retention time of the information high and thus allows us to actually read out the data in most cases (say compare to D’Atoine’s attack on instruction reordering where the information is lost immediately if not queried). Finally, software cannot really avoid using the cache and thus leak information.
  • Here I wanted to point out that intel is unlikely to provide a fix. They won’t replace old processors, micro code update is unlikely and Intel have brought out CPU’s for a while without fixing. Leading us towards software fixes for a hardware problem. This is a situation which is always suboptimal, but short to medium term the only option. It was my intention to show that while suboptimal entirely within the realm of the possible.

Scope

Litterature: ARM: [11], TLB[9], RowBuffer[10]

L3 is not small

Point here was to give a sense of scale on the importance of the L3 cache in the CPU. Also it’s kind of neat you can actually see slices of the L3 cache in a die shot.

Why is this interesting

The point of this slide was to illustrate the flexibility and power of CSC’s. Important to notice here: CSC’s are always attack on software implementation – not algorithms. An RSA implementation might leak it’s private key, another implementation may not.

Literature: Covert channels [13], RSA[4], AES[6], ECDSA[5],Keyboard[7],Mouse[8], KASRL[9]

How the data cache works on Intel + Important cache features

Here I wanted to introduce the design features that allows the attacker to manipulate the cache hierarchy. The second slide is just a summary slide.

 

How memory is stored in L3 + N-Way Set Associative L3

Here I wanted to introduce how the cache stores data. This is further back ground for manipulation, but also serves as a back ground for getting information from the cache. The “intel’s problem” is a so called fully associative cache on bytes. Essentially cache line concept limits accuracy of the attacks and the N-Way set associative cache allows an attacker to work on much smaller units making attacks practical. Further it allows an attacker to deduct information from cache-set congruence, something that is supported by the complex addressing function for the cache. I avoided the complex addressing function deliberately to avoid complexity and just mentioned that “the colors are not clumped together, but spread out”. Cache side channel attacks has historically only approximated this complex addressing function by doing a simple timing attack – loading N+1 addresses from the same set will cause one not to be cached and thus accessing it will be slow. The complex addressing function for cache sets has been reverse engineered resonantly for most intel CPU’s.

 

Example code to attack

The example code I use to explain the attacks is inspired by a function in the GDK library which is significantly more complex than this. I wanted to underline that code as well as data can be attacked and that branches matter. I wanted to speak about the big 3 attacks in the following slides by highlight some differences in a concrete example. The GDK library was first attacked by [7].

Common for all CSC

Here the goal was to introduce timing attack and all the cache manipulation primitives of the big 3 caches. Evict is just accessing enough cache lines congruent to a cache set to cause all previously stored information to be evict. Prime is a variation on Evict – where you carefully access cache lines congruent to a cache set in a way that the attacker knows what is in the cache set. The flush primitive is simply the clflush instruction, that removes a specific cache line from the cache hierarchy.

 

Big 3 Cache side channel Attacks

I wanted to comment that the 3 attacks and the variants of them make up most CSC’s and that they are all fairly similar in structure. Also I wanted to point back to the primitives described in the previous slide.

Literature: Evict+Time[1], Prime+Probe[2], Flush+Reload[3]

“The 4 slides on the attacks”

In these slides I wanted to highlight some advantages and disadvantages for each attack. The Evict+Time does not give any temporal resolution – which I call “post mortem analysis”, but you don’t need to worry about synchronizing with victim. Synchronizing can be done by any means including a separated CSC, a function call or any other information leak. Or even spying constantly. Though the accuracy is cache congruence it should probably be noted that prime and probe is disturbed by any cache set congruent memory operation whereas Evict+Time is only disturbed by those who evict exactly those cache lines used by the function. However, calling a function tends to bring more non-relevant code into play and thus noise. Noise is a more complex topic that the impression the overview slide gives.

Shared memory

I heard the „nobody shares memory“comment one too many times and wanted to raise a flag that it isn’t that uncommon. Finally, I wanted to warn against shared memory – particularly as it’s introduced through deduplication as that’s the most common vector in VM environments. Flush+Reload is just an example of the problems with dedublication, but one can can pile on with D’Antoine’s instruction reordering attack, dedublication attacks, more speculatively row hammer can become a practical cross VM vector with deduplication, row buffer side channel attacks etc. etc.

 

Noise

I wanted to point out that CSC’s are noisy. Usually the noise is due to contention with irrelevant code running on multicore CPU’s or contention in other subsystem than the cache. Also the hardware prefetcher can destroy things for an attacker. Of these effects only the effect of the hw prefetcher cannot be eliminated by repeating the attack – though obviously not all attacks lend themselves to be repeated (you cannot ask a user for his password 10k times). Sometimes you get good results in the first attempt. I had an Evict+Time attack that required more than 10k attempts to give satisfying results.

 

Performance counters

My „agenda“on my blackhat talk last year was to communicate that performance Counters can be an important tool for security related weirdness in the CPU. Part of this slide is an attempt to repeat that message. The important part was to introduce performance counters, performance counter interrupt and setting up the counter as they form an important part of my work on detecting cache side channel attacks.

Flush + Reload code

Here the Clflush is used as a “manipulate cache to a known state primitive”.

The Mov instruction (which could be replaced by most memory access instructions) is the reload phase. The RDTSC(P) does the actual timing of the reload phase and the mfence instructions prevents that the CPU reorder the instructions to do the reload phase outside the rdtsc(p) bracket.

My comments read that I should explain that cache side channel attacks like flush+reload is in a race condition with the process being spied upon.–Say if we’re attacking keyboard input we’ll be less visible if we wait a few milliseconds per iteration because nobody types that fast whereas for crypto we almost always need much higher temporal resolution and usually wouldn’t wait at all.

Detecting flush+reload

My original suggestion was to see how long a given count of cache misses would take. If too fast we had a cache side channel attack. [12] and [13] improved on that. All works fairly well.

Row hammer was flush + reload

Just noting here that if we remove the information acquisition and do it for two addresses at once we have the original row hammer code. It’s then easy to see that row hammer was a flush+reload attack. The “was” word was carefully chosen. Others has shown that the movnti instruction is a vector for row hammer too, and that vector is not a row hammer related attack. To round off my introduction I hope I mentioned that rowhammer.js was a flush+reload variation that I (and others) usually call Evict+Reload using the eviction primitive I discussed in a previous slide.

 

Flush + Flush

The back story here is I’d figured that clflush would leak information about the cache state and when approached by Daniel Gruss and Clementiné Maurice about detecting a cache attack that causes less cache misses I immediately knew, what they were talking about. Instead of competing to publish I did not do more work in this direction. I did get to review their wonderful paper though.

Flush+flush works with replacing the mov instruction in flush+reload with a clflush but is otherwise identical. The clflush instruction is probably faster when the cache line parameter isn’t in the cache because it’s able to shortcut actually flushing the cache.

Flush+flush has an advantage beyond stealthiness: clflush is faster than mov on uncached memory. Also it leaves the cache in a known state which means the first line of code can be skipped when iterating the attack. This attack is probably the fastest CSC. Also the clflush instruction introduces less problems with the hardware prefetchers. Literature: [13]

Why is flush+flush Stealth

Clflush does not cause cache misses! However, the victim still incurs cache misses due to flush and reload. This usually isn’t sufficient for the flush+reload detection I outline in previous slides to get decent detection rates without incurring significant amount of false positives.

 

Detecting flush+flush

The first point is an assumption that we’re not talking about a cross VM attack. My opinion is that cross VM flush+flush attacks should be foiled by not using dedublication. It’s also an assumption that I need. In a cross VM attack the attacker could use ring 0 to attack and thus bypass the CR4.TSD access violation. However, it is worth noting that even in this scenario it would make flush+flush more difficult.

The other 3 points are just the technology I use to catch flush+flush with.

Stage 1

This is actually a revamped version of my “Detecting flush+flush” blog post. After posting that I had some private conversations where my method got criticized for being too costly performance wise. So I first tried to find a better performance counter. There was an event that actually mentioned CLFLUSH in the offcore counters, unfortunately it was only available on a small subset of microarchitectures that I deemed too small to be worthwhile. I actually tried to see if intel just changed documentation and it appears they really revamped that event for other purposes. Then I played around with the CBO events in the cache system, though I could get better than cache-ref it was at the cost of being gameable from an attacker view point. So instead I decided to make a two stage approach – first detect the bracket and then detect clflush instruction. I had two reasons for this approach. The first is to deal with the performance impact of the second stage which can be quite severe. The second is I have a feeling that we’ll see other instruction-timing attacks in the months to come and this two stage model maps well to defending this kind of problem. The reason why this two stage works better is that the RDTSC instruction itself is rare, but in pairs spaced close enough for an attacker to not drown in noise is so rare that I’ve not seen a single benign application causing this in my testing.

Problems?

Using CR4.TSD to make rdtsc privileged affects performance two fold. First it causes a very significant slowdown on the RDTSC instruction with emulating it in an exception handler. However, the RDTSC is rarely used – in particularly rarely used in a fashion where it makes up a significant part of the total execution time and thus I think the performance penalty is acceptable. Much worse is that the RDTSC instruction becomes less accurate which might cause issues. Short of profiling code, I’ve yet to come up with a benign case where such accuracy would be required. I may be wrong though.

The detection obviously hinges strongly around the RDTSC being used as a timer. I’ve yet to come up with a good alternative to rdtsc, but that doesn’t mean it doesn’t exists.

 

Omissions

The Gory details left out is mostly eviction policy and complex addressing function related stuff. Such as finding eviction sets and priming the cache. There are many suggestions for mitigation – not sharing memory being one that’s very good but incomplete as it doesn’t work for evict+time and prime+probe. There are different ways of adding noise or making the timer less accurate – all in my opinion fundamentally flawed as noise or less timer accuracy can be defeated by law of large numbers. The Cache Allocation Technology can be used to protect against CSC’s – here I’m not a fan because it requires software to be reauthored to be protected and that it has limited coverage. Finally, it’s worth mentioning writing branch-free-cache-set-aware code which actually works, but is difficult and we’re unlikely to be able to demand that all affected software does so.

Presenting PeNet: a native .NET library for analyzing PE Headers with PowerShell

screen1The last years have seen a strong rise in PowerShell and .NET malware, so in this article we go native and show how PowerShell and the PeNet library can be leveraged to analyze Portable Executable (PE) headers of Windows executables, motivated by, but not limited to .NET binaries. PeNet is published under Apache License Version 2.0 and maintained by the author. Find an API description for C#, VB, C++ and F# in the PeNet API Reference.

Why PowerShell

PowerShell is an object-oriented programming language with full access to all .NET and Windows libraries. This is one of the reasons why PowerShell became more and more popular in malware and exploitation. The syntax makes it easy to use for everyone familiar with C/C++ or an equivalent modern programming language. Since most malware analysis is done automated to process huge amounts of malicious executables, a scripting language comes handy in this context. As every Windows PC has PowerShell and an IDE for it installed, it is easy to start coding and you can be sure that your code runs basically on every computer running Windows.

About PeNet Library

The PeNet library is a .NET library written in C# which parses PE headers of Windows executables. It can show and interpret values, flags, resources and so on, and is also capable of changing the values. The library is under the Apache 2 license and can be used by everyone in their projects.

Analyzing a PE Header

In the following section we walk through and example to demonstrate how to analyze the PE header of a Windows executable using PeNet. 

First, we need to import the PeNet library in PowerShell:

# Import the PeNet DLL

[System.Reflection.Assembly]::LoadFrom(“C:\PeNet.dll”| Out-Null

Now, we define a path to an executable and a new object which represents the PE header.

# Windows Executable to analyze

$executable ‘C:\Windows\System32\calc.exe’

# Create a new PE header object with PeNet

$peHeader New-Object PeNet.PeFile -ArgumentList $executable

The $peHeader object contains all information we can get from the PeNet library. 

Basic File Information

Now, let us check, if the file we are analyzing is a PE file or not and display some information about the PE file.

Write-Host “Is PE File`t” $peHeader.IsValidPeFile

Write-Host “Is 32 Bit`t”  $peHeader.Is32Bit

Write-Host “Is 64 Bit`t”  $peHeader.Is64Bit

Write-Host “Is DLL`t`t”   $peHeader.IsDLL

Write-Host “File Size`t”  $peHeader.FileSize “Bytes”

 

These lines are accessing flags and properties of the $peHeader object. The output for these lines is:

Is PE File    True

Is 32 Bit     False

Is 64 Bit     True

Is DLL        False

File Size     32768 Bytes

The output shows that the executable we are analyzing is a 64 Bit PE file and an executable but no DLL. The file size is 32768 bytes. To identify files, hashes are common in malware analysis, so let us display the most common hashes.

Write-Host “SHA-1`t”   $peHeader.SHA1

Write-Host “SHA-256`t” $peHeader.SHA256

Write-Host “MD5`t`t”   $peHeader.MD5

Output:

SHA-1         7270d8b19e3b13973ee905f89d02cc2f33a63aa5

SHA-256       700ee0e9c1e9dc18114ae2798847824577e587813c72b413127fb70b9cb042dd

MD5           c4cb4fdf6369dd1342d2666171866ce5

One more interesting hash is the Import-Hash (ImpHash), which is a hash over the imported functions of the PE file. The ImpHash can be used to identify similar malware, since the same ImpHash is a strong indicator for similar behavior, or at least the same packer.

Write-Host “ImpHash`t” $peHeader.ImpHash

Output:

ImpHash 251a86d312a56bf3a543b34a1b34d4cc

The ImpHash is used by VirusTotal, too, and besides the .NET implementation in PeNet, a Python library exists which can be used to compute the hash.

To check if the PE file is signed with a valid signature we can use the following PS code:

Write-Host “Signature Information” -ForegroundColor Yellow

Write-Host “Is Signed`t`t`t”        $peHeader.IsSigned

Write-Host “Is Chain Valid`t`t”     $peHeader.IsValidCertChain($True)

Write-Host “Is Signature Valid`t”  ([PeNet.Utility]::IsSignatureValid($executable))

The parameter $True indicates that PeNet should check the certificate chain online. If we set the parameter to $False, the check would be done offline, which could lead to outdated results.

The output for our example is:

Is Signed                   False

Is Chain Valid              False

Is Signature Valid          False

The executable isn’t signed at all, so obviously the chain and the signature are invalid.

DOS/NT Header

We have two options to get the values of each structure in the PE header. The first is
by value, where you can access every single structure member. The second methods
returns the whole structure with all value containing it as a string for easier representation in console output.

To access single values, let’s have a look how we can obtain the e_magic value from the
IMAGE_DOS_HEADER and how to access the Signature from the IMAGE_NT_HEADERS.

“e_magic`t {0:X0}” -f $peHeader.ImageDosHeader.e_magic

“NT signature {0:X0}” -f $peHeader.ImageNtHeaders.Signature

We start at the PE header and select the structure and value we want. The values are
printed to the console in hexadecimal.

Output:

e_magic        5A4D         

NT signature   4550

The PeNet library overrides a ToString() method for each PE structure. This means
that we can print the whole IMAGE_DOS_HEADER (and any other header) directly to
the console without caring for formatting or without the knowledge of the members of the structure.

Write-Host $peHeader.ImageDosHeader

Output:

IMAGE_DOS_HEADER

e_magic   :   5A4D

e_cblp    :   90

e_cp      :   3

e_crlc    :   0

e_cparhdr :   4

e_minalloc:   0

e_maxalloc:   FFFF

e_ss      :   0

e_sp      :   B8

e_csum    :   0

e_ip      :   0

e_cs      :   0

e_lfarlc  :   40

e_ovno    :   0

e_oemid   :   0

e_oeminfo :   0

e_lfanew  :   F8

File Header

The IMAGE_FILE_HEADER is a structure in the IMAGE_NT_HEADERS and can be accessed again as single values or as a whole.

For example, let’s access the machine type of the file header.

“Machine {0:X0}” -f $peHeader.ImageNtHeaders.FileHeader.Machine

Write-Host “Resolved Machine`t ([PeNet.Utility]::ResolveTargetMachine($peHeader.ImageNtHeaders.FileHeader.Machine))

In the first line, we print the machine field as a hex value. Since this value doesn’t
say much we can use the PeNet library to resolve the value to a meaningful
string as shown in the second line.

Output:

Machine              8664

Resolved Machine     AMD AMD64

Interesting in the file header are the file characteristics which can be accessed and
resolved like this:

“`nCharacteristics {0:X0}” -f $peHeader.ImageNtHeaders.FileHeader.Characteristics

Write-Host ([PeNet.Utility]::ResolveFileCharacteristics($peHeader.ImageNtHeaders.FileHeader.Characteristics))

The first line prints the file characteristics as a hex value and the second line resolves them to different flags. All flags can be access on their own, but we just print them all at once.

Output:

Characteristics 22

 

File Characteristics

RelocStripped                 :     False

ExecutableImage               :      True

LineNumbersStripped           :     False

LocalSymbolsStripped          :     False

AggressiveWsTrim              :     False

LargeAddressAware             :      True

BytesReversedLo               :     False

Machine32Bit                  :     False

DebugStripped                 :     False

RemovableRunFromSwap          :     False

NetRunFroMSwap                :     False

System                        :     False

DLL                           :     False

UpSystemOnly                  :     False

BytesReversedHi               :     False

And again to print the whole header just type:

Write-Host $peHeader.ImageNtHeaders.FileHeader

Output:

IMAGE_FILE_HEADER

Machine:                     8664

NumberOfSections:            6

TimeDateStamp:               5632D8CE

PointerToSymbolTable:        0

NumberOfSymbols:             0

SizeOfOptionalHeader:        F0

Characteristics:             22

Section Header

To access the sections of the executable we parse the section header and resolve the section characteristics to get an overview of the rights of each section.

$num = 1;

foreach($sec in $peHeader.ImageSectionHeaders)

{
    Write-Host “`nNumber:” $num

    Write-Host “Name:” ([PeNet.Utility]::ResolveSectionName($sec.Name))

    Write-Host $sec

    $flags ([PeNet.Utility]::ResolveSectionFlags($sec.Characteristics))

    Write-Host “Flags:” $flags 

    $num++;

}

The output for the first two sections with resolved name and resolved flags:

 

Number: 1

Name:  .text

IMAGE_SECTION_HEADER

PhysicalAddress:             16B0

VirtualSize:                 16B0

VirtualAddress:              1000

SizeOfRawData:               1800

PointerToRawData:            400

PointerToRelocations:        0

PointerToLinenumbers:        0

NumberOfRelocations:         0

NumberOfLinenumbers:         0

Characteristics:             60000020

 

Flags: IMAGE_SCN_CNT_CODE
IMAGE_SCN_MEM_EXECUTE IMAGE_SCN_MEM_READ

 

Number: 2

Name:  .rdata

IMAGE_SECTION_HEADER

PhysicalAddress:            151A

VirtualSize:                151A

VirtualAddress:             3000

SizeOfRawData:              1600

PointerToRawData:           1C00

PointerToRelocations:       0

PointerToLinenumbers:       0

NumberOfRelocations:        0

NumberOfLinenumbers:        0

Characteristics:            40000040

 

Flags:
IMAGE_SCN_CNT_INITIALIZED_DATA IMAGE_SCN_MEM_READ

Optional Header / Data Directory

The Optional Header is, like the File Header, a structure in the NT header and can be accessed by each member or as a whole. In the following we just print the whole header. Since the Optional Header includes the Data Directory structure it is printed (cut off), too.

IMAGE_OPTIONAL_HEADER

Magic:                      20B

MajorLinkerVersion:         C

MinorLinkerVersion:         A

SizeOfCode:                 1800

SizeOfInitializedData:      6A00

SizeOfUninitializedData:    0

AddressOfEntryPoint:        22E0

BaseOfCode:                 1000

BaseOfData:                 0

ImageBase:                  140000000

SectionAlignment:           1000

FileAlignment:              200

MajorOperatingSystemVersion: A

MinorOperatingSystemVersion: 0

MajorImageVersion:          A

MinorImageVersion:          0

MajorSubsystemVersion:      A

MinorSubsystemVersion:      0

Win32VersionValue:          0

SizeOfImage:                D000

SizeOfHeaders:              400

CheckSum:                   FB66

Subsystem:                  2

DllCharacteristics:         C160

SizeOfStackReserve:         80000

SizeOfStackCommit:          2000

SizeOfHeapReserve:          100000

SizeOfHeapCommit:           1000

LoaderFlags:                0

NumberOfRvaAndSizes:        10

 

IMAGE_DATA_DIRECTORY

VirtualAddress:             0

Size:                       0

IMAGE_DATA_DIRECTORY

VirtualAddress:             3D68

Size:                       DC

IMAGE_DATA_DIRECTORY

VirtualAddress:             7000

Size:                       4718

IMAGE_DATA_DIRECTORY

VirtualAddress:             6000

Size:                       180

IMAGE_DATA_DIRECTORY

VirtualAddress:             0

Size:                       0

IMAGE_DATA_DIRECTORY

VirtualAddress:             C000

Size:                       48

IMAGE_DATA_DIRECTORY

VirtualAddress:             3590

Size:                       38

IMAGE_DATA_DIRECTORY

VirtualAddress:             0

Size:                       0

IMAGE_DATA_DIRECTORY…

 

Imports, Exports and Resources

We have seen how the Optional Header and the Data Directory can be accessed. The most interesting parts of the Data Directory are the Imports, Exports and Resources. PeNet parses all these directories for us and shows us the content.

Let’s start with the imports. Since listing all imported functions would be too much for this article we will have a look at all function imported from Kernel32.dll

foreach($import in $peHeader.ImportedFunctions)

{
    if($import.DLL -eq “KERNEL32.DLL”)

    {

        $import

    }

}

This code iterates over all imported functions and checks if the DLL from which the function should be imported is the Kernel32.dll. If so, the imported function is printed.

Output:

Name                        DLL          Hint

—-                        —          —-

GetLastError                KERNEL32.dll  599

CreateEventExW              KERNEL32.dll  179

WaitForSingleObject         KERNEL32.dll 1483

SetEvent                    KERNEL32.dll 1291

FindPackagesByPackageFamily KERNEL32.dll  395

QueryPerformanceCounter     KERNEL32.dll 1081

GetCurrentProcessId         KERNEL32.dll  529

GetCurrentThreadId          KERNEL32.dll  533

CloseHandle                 KERNEL32.dll  124

GetTickCount                KERNEL32.dll  765

RtlCaptureContext           KERNEL32.dll 1210

RtlLookupFunctionEntry      KERNEL32.dll 1217

RtlVirtualUnwind            KERNEL32.dll 1224

UnhandledExceptionFilter    KERNEL32.dll 1441

SetUnhandledExceptionFilter KERNEL32.dll 1377

GetCurrentProcess           KERNEL32.dll  528

TerminateProcess            KERNEL32.dll 1407

RaiseException              KERNEL32.dll 1103

GetSystemTimeAsFileTime     KERNEL32.dll  736

Since we are analyzing an executable and not a DLL there are most likely no exports, but to be sure let us check.

if($peHeader.ExportedFunctions -eq $null)

{
    “Image has no exports.”

}

else

{
    “Image has exports.”

}

Output:

Image has no exports.

Nothing to see here, let’s move on and check for resources. We print the root elements of this executable and no subdirectories to keep the output readable.

 

foreach($de in $peHeader.ImageResourceDirectory.DirectoryEntries)

{
    if($de.IsIdEntry -eq $True)

{

      Write-Host “ID Entry” $de.ID ” Resolved Name: “ ([PeNet.Utility]::ResolveResourceId($de.ID))

      }

    elseif($de.IsNamedEntry -eq $True)
{ 

        Write-Host “Named Entry: “ $de.ResolvedName
    }

}

Output:

ID Entry 3  Resolved Name:   Icon

ID Entry 14  Resolved Name:  GroupIcon

ID Entry 16  Resolved Name:  Version

ID Entry 24  Resolved Name:  Manifest

Again, we used a resolve function to map the IDs of directory entries to meaningful names.

Pattern-Matching

Often, we don’t search for a structure member to have a specific value, but instead want
to match some byte or string signature over samples. That’s why PeNet comes with a build-in Aho-Corasick pattern matching algorithm for byte arrays and strings.

The idea is to construct a trie containing all signatures once and to use this trie to match multiple executables against the signatures. We will see an example below.

$trie New-Object PeNet.PatternMatching.Trie

 

$trie.Add(“MicrosoftCalculator”, ([System.Text.Encoding]::ASCII), “pattern1”)

$trie.Add(“not in the binary”, ([System.Text.Encoding]::ASCII), “pattern2”)

$trie.Add(“<assemblyIdentity”, ([System.Text.Encoding]::ASCII), “pattern3”)

 

$matches = $trie.Find($peHeader.Buff)

 

foreach($match in $matches)

{
    Write-Host “Pattern” $match.Item1 “matched at offset” $match.Item2

}

 

A new trie object is created and then filled with some strings to search for. The encoding is of the string is given, because string in binaries are often in Unicode. The pattern2 is not in the binary and should not be found, the other two patterns should.

The output is:

Pattern pattern1 matched at offset 9410

Pattern pattern3 matched at offset 14498

Pattern pattern3 matched at offset 14725

We see that pattern1 matched once and pattern3 matched two times at different offsets.

Conclusion

We’ve seen how PE headers can be analyzed with PowerShell and PeNet. PeNet is a .NET library, i.e., any other .NET language can be used, too. The library is still under development and a lot of PE features are still missing, but they will follow soon. None the less, it’s a mighty tool for malware analysis, if building large-scale, automated analysis systems with the .NET framework is what you aim for. Feel free to contribute to the PeNet library or fork it at GitHub.

 

 

Cyber? WTF!

“The only real difficulties in programming are cache invalidation and naming things.” — Phil Karlton

Everything needs a name to go by, right? So did this blog. When we scrolled through the seemingly endless list of new TLDs, we stumbled upon .wtf and while it is all a bit of a blur looking back, our fingers must have developed a dynamic of their own and out came ‘whois cyber.wtf’, which was unregistered for whatever reason¹. During the several days of juggling alternative names – actually spending quite a few thoughts on ‘we probably shouldn’t do this’, anticipating what corporate communications and marketing might think of it – we kept returning to cyber.wtf. When you hear or read people prefixing ordinary, proper, and once actually useful nouns with ‘cyber’, what are your thoughts? We think that ‘WTF?’ might actually be the only appropriate letters to follow on ‘cyber‘. Anyway, this will be our home for the time being. Don’t expect a fixed post frequency, we don’t intend to post for the general sake of creating more bytes on the internet. Expect a post whenever there is both content and time for posting. Expect content that is mostly malware- and/or security-centric, the occasional nifty thing we find mixed in, and where we happen to give a talk. We’ll probably start out with the latter. Judge us by our content, naming is hard.

¹ which at that time actually resulted in

No whois server is known for this kind of object

because whois is pleasantly old-fashioned in its default. -h whois.donuts.co or the line

\.wtf$ whois.donuts.co

in your whois.conf catapults it into a part of the modern age of completely unnecessary but partially wonderful TLDs.