# MemberRef hash

The MemberRef hash is a purely experimental hash method and hasn't been tested yet. The idea was to create a hash method that also works with obfuscated malware. The MemberRef table contains mostly .NET runtime constructs like methods, properties, fields and so on, which can't be easily obfuscated. This could be a more reliable hash method than for example TypeRef hash, but still has to be proven.

The MemberRef hash uses the referenced member name of the table rows and the table names (Name) of the corresponding classes (Class). This <TableNameOfBelongingClass>-<MemberName> string pair is added to a list and the hash value is calculated at the end, so basically the same procedure as in the TypeRef hash. The class always belongs to one of the five tables TypeDef, TypeRef, ModuleRef, MethodDef or TypeSpec.

The list of table and member names can be sorted alphabetically after the reference names before being hashed. Strings are used case-sensitive.

# Malware example

Hash (SHA-256): 6f30280da560a30bbe25835f00d881dad94e5a7641b63e028080628c1f82a992

This is an unobfuscated .NET EXE malware with the following MemberRef table:

MemberRef table content of the malware
MemberRef table content of the malware

As can be seen that the majority of referenced member names are present in cleartext. There's only a small amount of strings which are obfuscated.

We can calculate the different MemberRef hash possibilities with the following example code:

# Import class DotNetPE from module dotnetfile
from dotnetfile import DotNetPE

# Create an instance of DotNetPE with the file path as a parameter
dotnet_file = DotNetPE('/Users/<username>/6f30280da560a30bbe25835f00d881dad94e5a7641b63e028080628c1f82a992')

# Check if the "MemberRef" table exists and print out MemberRef hashes
if dotnet_file.metadata_table_exists('MemberRef'):
    print(f'MemberRef hash (unsorted): {dotnet_file.TypeRef.get_typeref_hash()} (SHA-256)')
    print(f'MemberRef hash (sorted) {dotnet_file.MemberRef.get_memberref_hash(strings_sorted=True)} (SHA-256)')

The result is as follows:

MemberRef hash (unsorted): 580bf8658b52f3e9f9ec56e7ca0182dfcbd5b5afc0e5ba7a33fde9391d600e2c (SHA-256)
MemberRef hash (sorted): b5704580aca9c5d42c06eeaaacc76ca6f581e24839f90dba14c20689af758495 (SHA-256)

Which combination makes more sense is up to you, if you want to use this hash method.

As an example of how the list of <TableNameOfBelongingClass>-<MemberName> name pairs looks like before it gets hashed, the following list excerpt shows the unsorted version:

...
TypeRef-InitializeArray
TypeRef-set_Key
TypeRef-set_IV
TypeRef-CreateDecryptor
TypeRef-Write
TypeRef-GetManifestResourceStream
TypeRef-get_BaseStream
TypeRef-set_Position
TypeRef-ReadBytes
TypeRef-GetPublicKeyToken
TypeRef-set_Mode
TypeRef-CreateDecryptor
TypeRef-FlushFinalBlock
TypeRef-Close
TypeRef-get_MainModule
TypeRef-get_BaseAddress
...