mirror of
https://github.com/dobin/avred
synced 2026-06-08 13:54:13 +00:00
1121 lines
48 KiB
Python
1121 lines
48 KiB
Python
"""
|
|
Part of dotnetfile
|
|
|
|
Copyright (c) 2016, 2021-2022 - Bob Jung, Yaron Samuel, Dominik Reichel
|
|
"""
|
|
|
|
import binascii
|
|
|
|
from math import log, floor
|
|
from typing import Dict, Optional, Any
|
|
|
|
from .logger import get_logger
|
|
from .util import BinaryStructure, FileLocation
|
|
from .constants import TABLE_ROW_VARIABLE_LENGTH_FIELDS
|
|
|
|
|
|
def get_blob_location_for_offset(pe, offset: int):
|
|
"""
|
|
This sort of just cheats and returns a DWORD for now since we haven't done the extra legwork in figuring out the
|
|
lengths of every single variable
|
|
"""
|
|
# I'm just going to go with 4 bytes for now...
|
|
blob_location_size = 4
|
|
|
|
blob_stream = pe.dotnet_stream_lookup.get(b'#Blob', None)
|
|
if blob_stream is not None:
|
|
blob_stream_rva = blob_stream.address - pe.address
|
|
blob_location_rva = blob_stream_rva + offset
|
|
blob_location_addr = blob_stream.address + offset
|
|
blob_location_bytes = pe.executable_bytes[blob_location_rva:blob_location_rva + blob_location_size]
|
|
|
|
if offset < blob_stream.size:
|
|
blob_location = FileLocation(blob_location_addr, blob_location_bytes, blob_location_size)
|
|
blob_location.string_representation = binascii.hexlify(blob_location_bytes)
|
|
return blob_location
|
|
|
|
return None
|
|
|
|
|
|
def get_guid_location_for_offset(pe, offset: int):
|
|
"""
|
|
"""
|
|
# I'm just going to go with 4 bytes for now...
|
|
guid_location_size = 4
|
|
guid_stream = pe.dotnet_stream_lookup.get(b'#GUID', None)
|
|
if guid_stream is not None:
|
|
guid_location_rva = guid_stream.address + offset
|
|
guid_location_bytes = pe.get_data(guid_location_rva, guid_location_size)
|
|
|
|
if offset < guid_stream.size:
|
|
guid_location = FileLocation(guid_location_rva, guid_location_bytes, guid_location_size)
|
|
guid_location.string_representation = binascii.hexlify(guid_location_bytes)
|
|
return guid_location
|
|
|
|
return None
|
|
|
|
|
|
def get_table_row_location(pe, table_name: str, table_index: int):
|
|
"""
|
|
given an index and a table name, this returns the metadata table row object
|
|
"""
|
|
if table_name in pe.metadata_tables_lookup:
|
|
|
|
metadata_table = pe.metadata_tables_lookup[table_name]
|
|
|
|
if table_index < len(metadata_table.table_rows):
|
|
metadata_row = metadata_table.table_rows[table_index]
|
|
# print 'got table row: %s 0x%x' % (table_name, table_index)
|
|
return metadata_row
|
|
|
|
return None
|
|
|
|
|
|
class METADATA_TABLE_ROW(BinaryStructure):
|
|
"""
|
|
This class represents a single metadata table row. It's a memory location that has fields.
|
|
"""
|
|
|
|
def __init__(self, pe, addr: int = None, string_representation: str = None, byte_buffer: bytes = None):
|
|
BinaryStructure.__init__(self, addr, string_representation, byte_buffer)
|
|
self.pe = pe
|
|
self.logger = get_logger('extended_pe_logger')
|
|
|
|
# Lookup of field name to the index in these streams
|
|
self.string_stream_references = {}
|
|
self.guid_stream_references = {}
|
|
self.blob_stream_references = {}
|
|
|
|
# Lookup of field name to the table name to the index in that table
|
|
self.table_references = {}
|
|
|
|
def create_string_stream_field_value(self, field_name: str):
|
|
"""
|
|
Used to define a reference to a string at an offset in the strings stream
|
|
"""
|
|
field_value = self.create_field_value(field_name, self.pe.dotnet_metadata_stream_header.string_offset_size,
|
|
self.pe.dotnet_metadata_stream_header.string_offset_struct_string)
|
|
|
|
self.string_stream_references[field_name] = field_value.value
|
|
|
|
return field_value
|
|
|
|
def create_guid_stream_field_value(self, field_name: str):
|
|
"""
|
|
Used to define a reference to a string at an offset in the guid stream
|
|
"""
|
|
field_value = self.create_field_value(field_name, self.pe.dotnet_metadata_stream_header.guid_offset_size,
|
|
self.pe.dotnet_metadata_stream_header.guid_offset_struct_string)
|
|
|
|
self.guid_stream_references[field_name] = field_value.value
|
|
|
|
return field_value
|
|
|
|
def create_blob_stream_field_value(self, field_name: str):
|
|
"""
|
|
Used to define a reference to a string at an offset in the blob stream
|
|
"""
|
|
field_value = self.create_field_value(field_name, self.pe.dotnet_metadata_stream_header.blob_offset_size,
|
|
self.pe.dotnet_metadata_stream_header.blob_offset_struct_string)
|
|
|
|
self.blob_stream_references[field_name] = field_value.value
|
|
|
|
return field_value
|
|
|
|
def create_table_reference(self, field_name: str, table_name: str):
|
|
"""
|
|
Creates a reference to a row in another table
|
|
"""
|
|
if table_name not in self.pe.dotnet_metadata_stream_header.table_size_lookup:
|
|
self.logger.debug(f'Table: {table_name} not defined in .NET header')
|
|
return None
|
|
|
|
field_size = 2
|
|
struct_string = 'H'
|
|
num_rows = self.pe.dotnet_metadata_stream_header.table_size_lookup[table_name]
|
|
if num_rows >= 65536:
|
|
field_size = 4
|
|
struct_string = 'I'
|
|
|
|
field_value = self.create_field_value(field_name, field_size, struct_string)
|
|
|
|
self.table_references[field_name] = (table_name, field_value.value)
|
|
|
|
return field_value
|
|
|
|
def create_variable_length_table_reference(self, field_name: str, type_name_param: Optional[str] = None):
|
|
"""
|
|
Go read ntcore's .NET tutorial and pay attention to "coded indexes"
|
|
"""
|
|
if type_name_param:
|
|
type_name = type_name_param
|
|
else:
|
|
type_name = field_name
|
|
|
|
field_size_info_tuple = self.pe.dotnet_field_size_info[type_name]
|
|
field_size = field_size_info_tuple[0]
|
|
struct_string = field_size_info_tuple[1]
|
|
|
|
table_names = TABLE_ROW_VARIABLE_LENGTH_FIELDS[type_name]
|
|
num_bits = int(floor(log(len(table_names) - 1, 2))) + 1
|
|
|
|
# print 'num bits: 0x%x' % num_bits
|
|
bit_mask = pow(2, num_bits) - 1
|
|
|
|
# print 'bitmask: 0x%x' % bit_mask
|
|
field_value = self.create_field_value(field_name, field_size, struct_string)
|
|
|
|
table_name_index = field_value.value & bit_mask
|
|
table_index = field_value.value >> num_bits
|
|
|
|
# print 'field_name: %s, type_name: %s, table_name_index: 0x%x table_index: 0x%x field_value: 0x%x
|
|
# bit_mask: 0x%x' % (field_name, type_name, table_name_index, table_index, field_value.value, bit_mask)
|
|
# print table_names
|
|
|
|
if table_name_index < len(table_names):
|
|
table_name = table_names[table_name_index]
|
|
else:
|
|
table_name = table_names[-1]
|
|
|
|
self.table_references[field_name] = (table_name, table_index)
|
|
|
|
return field_value
|
|
|
|
|
|
class MODULE_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
00 - Module Table
|
|
It's officially a one-row table, but there are ITW files with more than one row. It is representing the current
|
|
assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Generation (2-byte value, reserved, shall be zero)
|
|
Name (index into String heap)
|
|
Mvid (index into Guid heap; simply a Guid used to distinguish between two versions of the same module)
|
|
EncId (index into Guid heap, reserved, shall be zero)
|
|
EncBaseId (index into Guid heap, reserved, shall be zero)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Module', byte_buffer)
|
|
|
|
self.Generation = self.create_field_value('Generation', 2, 'H')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Mvid = self.create_guid_stream_field_value('Mvid')
|
|
self.EncId = self.create_guid_stream_field_value('EncId')
|
|
self.EncBaseId = self.create_guid_stream_field_value('EncBaseId')
|
|
|
|
|
|
class TYPE_REF_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
01 - TypeRef Table
|
|
Each row represents an imported class, its namespace and the assembly which contains it. It is documented in
|
|
ECMA-335.
|
|
|
|
Columns:
|
|
ResolutionScope (index into Module, ModuleRef, AssemblyRef or TypeRef tables, or null; more precisely, a
|
|
ResolutionScope coded index)
|
|
TypeName (index into String heap)
|
|
TypeNamespace (index into String heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'TypeRef', byte_buffer)
|
|
|
|
self.ResolutionScope = self.create_variable_length_table_reference('ResolutionScope', 'ResolutionScope')
|
|
self.TypeName = self.create_string_stream_field_value('TypeName')
|
|
self.TypeNamespace = self.create_string_stream_field_value('TypeNamespace')
|
|
|
|
|
|
class TYPE_DEF_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
02 - TypeDef Table
|
|
Each row represents a class in the current assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Flags (a 4-byte bitmask of type TypeAttributes)
|
|
TypeName (index into String heap)
|
|
TypeNamespace (index into String heap)
|
|
Extends (index into TypeDef, TypeRef or TypeSpec table; more precisely, a TypeDefOrRef coded index)
|
|
FieldList (index into Field table; it marks the first of a continguous run of Fields owned by this Type).
|
|
The run continues to the smaller of:
|
|
the last row of the Field table
|
|
the next run of Fields, found by inspecting the FieldList of the next row in this TypeDef table
|
|
MethodList (index into MethodDef table; it marks the first of a continguous run of Methods owned by this Type).
|
|
The run continues to the smaller of:
|
|
the last row of the MethodDef table
|
|
the next run of Methods, found by inspecting the MethodList of the next row in this TypeDef table
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'TypeDef', byte_buffer)
|
|
|
|
self.Flags = self.create_field_value('Flags', 4, 'I')
|
|
self.TypeName = self.create_string_stream_field_value('TypeName')
|
|
self.TypeNamespace = self.create_string_stream_field_value('TypeNamespace')
|
|
self.Extends = self.create_variable_length_table_reference('Extends', 'TypeDefOrRef')
|
|
self.FieldList = self.create_table_reference('FieldList', 'Field')
|
|
self.MethodList = self.create_table_reference('MethodList', 'MethodDef')
|
|
|
|
|
|
class FIELD_PTR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
03 - FieldPtr Table
|
|
Each row represents an index into the Field table. It is not documented in ECMA-335, but the definition can be
|
|
found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Field (index into Field table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Field', byte_buffer)
|
|
|
|
self.Field = self.create_table_reference('Field', 'Field')
|
|
|
|
|
|
class FIELD_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
04 - Field Table
|
|
Each row represents a field in a TypeDef class. The fields of one class are not stored casually: after the
|
|
fields of one class end, the fields of the next class begin. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Flags (a 2-byte bitmask of type FieldAttributes)
|
|
Name (index into String heap)
|
|
Signature (index into Blob heap)
|
|
"""
|
|
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Field', byte_buffer)
|
|
|
|
# Could parse out all the flags...
|
|
self.Flags = self.create_field_value('Flags', 2, 'H')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Signature = self.create_blob_stream_field_value('Signature')
|
|
|
|
|
|
class METHOD_PTR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
05 - MethodPtr Table
|
|
Each row represents an index into the MethodDef table. It is not documented in ECMA-335, but the definition can
|
|
be found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Method (index into MethodDef table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Method', byte_buffer)
|
|
|
|
self.Method = self.create_table_reference('Method', 'MethodDef')
|
|
|
|
|
|
class METHOD_DEF_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
06 - MethodDef Table
|
|
Each row represents a method in a specific class. The methods sequence follows the same logic of the fields one.
|
|
It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
RVA (a 4-byte constant)
|
|
ImplFlags (a 2-byte bitmask of type MethodImplAttributes)
|
|
Flags (a 2-byte bitmask of type MethodAttribute)
|
|
Name (index into String heap)
|
|
Signature (index into Blob heap)
|
|
ParamList (index into Param table). It marks the first of a contiguous run of Parameters owned by this method.
|
|
The run continues to the smaller of:
|
|
the last row of the Param table
|
|
the next run of Parameters, found by inspecting the ParamList of the next row in the MethodDef table
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'MethodDef', byte_buffer)
|
|
|
|
self.RVA = self.create_field_value('RVA', 4, 'I')
|
|
self.ImplFlags = self.create_field_value('ImplFlags', 2, 'H')
|
|
self.Flags = self.create_field_value('Flags', 2, 'H')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Signature = self.create_blob_stream_field_value('Signature')
|
|
self.ParamList = self.create_table_reference('ParamList', 'Param')
|
|
|
|
|
|
class PARAM_PTR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
07 - ParamPtr Table
|
|
Each row represents an index into the Param table. It is not documented in ECMA-335, but the definition can
|
|
be found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Param (index into Param table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Param', byte_buffer)
|
|
|
|
self.Param = self.create_table_reference('Param', 'Param')
|
|
|
|
|
|
class PARAM_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
08 - Param Table
|
|
Each row represents a method's param. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Flags (a 2-byte bitmask of type ParamAttributes)
|
|
Sequence (a 2-byte constant)
|
|
Name (index into String heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Param', byte_buffer)
|
|
|
|
self.Flags = self.create_field_value('Flags', 2, 'H')
|
|
self.Sequence = self.create_field_value('Sequence', 2, 'H')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
|
|
|
|
class INTERFACE_IMPL_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
09 - InterfaceImpl Table
|
|
Each row tells the framework a class that implements a specific interface. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Class (index into the TypeDef table)
|
|
Interface (index into the TypeDef, TypeRef or TypeSpec table; more precisely, a TypeDefOrRef coded index)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'InterfaceImpl', byte_buffer)
|
|
|
|
self.Class = self.create_table_reference('Class', 'TypeDef')
|
|
self.Interface = self.create_variable_length_table_reference('Interface', 'TypeDefOrRef')
|
|
|
|
|
|
class MEMBER_REF_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
10 - MemberRef Table
|
|
Also known as MethodRef table. Each row represents an imported method. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Class (index into the TypeRef, ModuleRef, MethodDef, TypeSpec or TypeDef tables; more precisely, a
|
|
MemberRefParent coded index)
|
|
Name (index into String heap)
|
|
Signature (index into Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'MemberRef', byte_buffer)
|
|
|
|
self.Class = self.create_variable_length_table_reference('Class', 'MemberRefParent')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Signature = self.create_blob_stream_field_value('Signature')
|
|
|
|
|
|
class CONSTANT_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
11 - Constant Table
|
|
Each row represents a constant value for a Param, Field or Property. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Type (a 1-byte constant, followed by a 1-byte padding zero).
|
|
Parent (index into the Param or Field or Property table; more precisely, a HasConstant coded index)
|
|
Value (index into Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Constant', byte_buffer)
|
|
|
|
self.Type = self.create_field_value('Type', 1, 'B')
|
|
self.Padding = self.create_field_value('Padding', 1, 'B')
|
|
self.Parent = self.create_variable_length_table_reference('Parent', 'HasConstant')
|
|
self.Value = self.create_blob_stream_field_value('Value')
|
|
|
|
|
|
class CUSTOM_ATTRIBUTE_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
12 - CustomAttribute Table
|
|
The best description is given by the SDK:
|
|
"The CustomAttribute table stores data that can be used to instantiate a Custom Attribute (more precisely,
|
|
an object of the specified Custom Attribute class) at runtime. The column called Type is slightly
|
|
misleading - it actually indexes a constructor method - the owner of that constructor method is the Type of
|
|
the Custom Attribute."
|
|
It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Parent (index into any metadata table, except the CustomAttribute table itself; more precisely, a
|
|
HasCustomAttribute coded index)
|
|
Type (index into the MethodDef or MethodRef table; more precisely, a CustomAttributeType coded index)
|
|
Value (index into Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'CustomAttribute', byte_buffer)
|
|
|
|
self.Parent = self.create_variable_length_table_reference('Parent', 'HasCustomAttribute')
|
|
self.Type = self.create_variable_length_table_reference('Type', 'CustomAttributeType')
|
|
self.Value = self.create_blob_stream_field_value('Value')
|
|
|
|
|
|
class FIELD_MARSHAL_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
13 - FieldMarshal Table
|
|
Each row tells the way a Param or Field should be treated when called from/to unmanaged code. It is documented
|
|
in ECMA-335.
|
|
|
|
Columns:
|
|
Parent (index into Field or Param table; more precisely, a HasFieldMarshal coded index)
|
|
NativeType (index into the Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'FieldMarshal', byte_buffer)
|
|
|
|
self.Parent = self.create_variable_length_table_reference('Parent', 'HasFieldMarshal')
|
|
self.NativeType = self.create_blob_stream_field_value('NativeType')
|
|
|
|
|
|
class DECL_SECURITY_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
14 - DeclSecurity Table
|
|
Security attributes attached to a class, method or assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Action (2-byte value)
|
|
Parent (index into the TypeDef, MethodDef or Assembly table; more precisely, a HasDeclSecurity coded index)
|
|
PermissionSet (index into Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'DeclSecurity', byte_buffer)
|
|
|
|
self.Action = self.create_field_value('Action', 2, 'H')
|
|
self.Parent = self.create_variable_length_table_reference('Parent', 'HasDeclSecurity')
|
|
self.PermissionSet = self.create_blob_stream_field_value('PermissionSet')
|
|
|
|
|
|
class CLASS_LAYOUT_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
15 - ClassLayout Table
|
|
Remember "#pragma pack(n)" for VC++? Well, this is kind of the same thing for .NET. It's useful when handing
|
|
something from managed to unmanaged code. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
PackingSize (a 2-byte constant)
|
|
ClassSize (a 4-byte constant)
|
|
Parent (index into TypeDef table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'ClassLayout', byte_buffer)
|
|
|
|
self.PackingSize = self.create_field_value('PackingSize', 2, 'H')
|
|
self.ClassSize = self.create_field_value('ClassSize', 4, 'I')
|
|
self.Parent = self.create_table_reference('Parent', 'TypeDef')
|
|
|
|
|
|
class FIELD_LAYOUT_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
16 - FieldLayout Table
|
|
Related with the ClassLayout. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Offset (a 4-byte constant)
|
|
Field (index into the Field table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'FieldLayout', byte_buffer)
|
|
|
|
self.Offset = self.create_field_value('Offset', 4, 'I')
|
|
self.Field = self.create_table_reference('Field', 'Field')
|
|
|
|
|
|
class STAND_ALONE_SIG_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
17 - StandAloneSig Table
|
|
Each row represents a signature that isn't referenced by any other table. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Signature (index into the Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'StandAloneSig', byte_buffer)
|
|
|
|
self.Signature = self.create_blob_stream_field_value('Signature')
|
|
|
|
|
|
class EVENT_MAP_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
18 - EventMap Table
|
|
List of events for a specific class. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Parent (index into the TypeDef table)
|
|
EventList (index into Event table). It marks the first of a contiguous run of Events owned by this Type. The run
|
|
continues to the smaller of:
|
|
the last row of the Event table
|
|
the next run of Events, found by inspecting the EventList of the next row in the EventMap table
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'EventMap', byte_buffer)
|
|
|
|
self.Parent = self.create_table_reference('Parent', 'TypeDef')
|
|
self.EventList = self.create_table_reference('EventList', 'Event')
|
|
|
|
|
|
class EVENT_PTR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
19 - EventPtr Table
|
|
Each row represents an index into the Event table. It is not documented in ECMA-335, but the definition can
|
|
be found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Event (index into Event table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Event', byte_buffer)
|
|
|
|
self.Param = self.create_table_reference('Event', 'Event')
|
|
|
|
|
|
class EVENT_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
20 - Event Table
|
|
Each row represents an event. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
EventFlags (a 2-byte bitmask of type EventAttribute)
|
|
Name (index into String heap)
|
|
EventType (index into TypeDef, TypeRef or TypeSpec tables; more precisely, a TypeDefOrRef coded index)
|
|
[this corresponds to the Type of the Event; it is not the Type that owns this event]
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Event', byte_buffer)
|
|
|
|
self.EventFlags = self.create_field_value('EventFlags', 2, 'H')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.EventType = self.create_variable_length_table_reference('EventType', 'TypeDefOrRef')
|
|
|
|
|
|
class PROPERTY_MAP_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
21 - PropertyMap Table
|
|
List of Properties owned by a specific class. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Parent (index into the TypeDef table)
|
|
PropertyList (index into Property table). It marks the first of a contiguous run of Properties owned by Parent.
|
|
The run continues to the smaller of:
|
|
the last row of the Property table
|
|
the next run of Properties, found by inspecting the PropertyList of the next row in this PropertyMap table
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'PropertyMap', byte_buffer)
|
|
|
|
self.Parent = self.create_table_reference('Parent', 'TypeDef')
|
|
self.PropertyList = self.create_table_reference('PropertyList', 'Property')
|
|
|
|
|
|
class PROPERTY_PTR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
07 - PropertyPtr Table
|
|
Each row represents an index into the Property table. It is not documented in ECMA-335, but the definition can
|
|
be found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Property (index into Property table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Property', byte_buffer)
|
|
|
|
self.Property = self.create_table_reference('Property', 'Property')
|
|
|
|
|
|
class PROPERTY_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
23 - Property Table
|
|
Each row represents a property. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Flags (a 2-byte bitmask of type PropertyAttributes)
|
|
Name (index into String heap)
|
|
Type (index into Blob heap) [the name of this column is misleading. It does not index a TypeDef or TypeRef
|
|
table - instead it indexes the signature in the Blob heap of the Property)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Property', byte_buffer)
|
|
|
|
self.Flags = self.create_field_value('Flags', 2, 'H')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Type = self.create_blob_stream_field_value('Type')
|
|
|
|
|
|
class METHOD_SEMANTICS_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
24 - MethodSemantics Table
|
|
Links Events and Properties to specific methods. For example one Event can be associated to more methods. A
|
|
property uses this table to associate get/set methods. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Semantics (a 2-byte bitmask of type MethodSemanticsAttributes)
|
|
Method (index into the MethodDef table)
|
|
Association (index into the Event or Property table; more precisely, a HasSemantics coded index)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'MethodSemantics', byte_buffer)
|
|
|
|
self.Semantics = self.create_field_value('Semantics', 2, 'H')
|
|
self.Method = self.create_table_reference('Method', 'MethodDef')
|
|
self.Association = self.create_variable_length_table_reference('Association', 'HasSemantics')
|
|
|
|
|
|
class METHOD_IMPL_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
25 - MethodImpl Table
|
|
Specifies details of how a method is implemented. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Class (index into TypeDef table)
|
|
MethodBody (index into MethodDef or MemberRef table; more precisely, a MethodDefOrRef coded index)
|
|
MethodDeclaration (index into MethodDef or MemberRef table; more precisely, a MethodDefOrRef coded index)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'MethodImpl', byte_buffer)
|
|
|
|
self.Class = self.create_table_reference('Class', 'TypeDef')
|
|
self.MethodBody = self.create_variable_length_table_reference('MethodBody', 'MethodDefOrRef')
|
|
self.MethodDeclaration = self.create_variable_length_table_reference('MethodDeclaration', 'MethodDefOrRef')
|
|
|
|
|
|
class MODULE_REF_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
26 - ModuleRef Table
|
|
Each row represents a reference to an external module. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Name (index into String heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'ModuleRef', byte_buffer)
|
|
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
|
|
|
|
class TYPE_SPEC_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
27 - TypeSpec Table
|
|
Each row represents a specification for a TypeDef or TypeRef. The only column indexes a token in the #Blob
|
|
stream. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Signature (index into the Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'TypeSpec', byte_buffer)
|
|
|
|
self.Signature = self.create_blob_stream_field_value('Signature')
|
|
|
|
|
|
class IMPL_MAP_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
28 - ImplMap Table
|
|
Quote: "The ImplMap table holds information about unmanaged methods that can be reached from managed code, using
|
|
PInvoke dispatch. Each row of the ImplMap table associates a row in the MethodDef table (MemberForwarded)
|
|
with the name of a routine (ImportName) in some unmanaged DLL (ImportScope).".
|
|
This means all the unmanaged functions used by the assembly are listed here. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
MappingFlags (a 2-byte bitmask of type PInvokeAttributes)
|
|
MemberForwarded (index into the Field or MethodDef table; more precisely, a MemberForwarded coded index. However,
|
|
it only ever indexes the MethodDef table, since Field export is not supported)
|
|
ImportName (index into the String heap)
|
|
ImportScope (index into the ModuleRef table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'ImplMap', byte_buffer)
|
|
|
|
self.MappingFlags = self.create_field_value('MappingFlags', 2, 'H')
|
|
self.MemberForwarded = self.create_variable_length_table_reference('MemberForwarded', 'MemberForwarded')
|
|
self.ImportName = self.create_string_stream_field_value('ImportName')
|
|
self.ImportScope = self.create_table_reference('ImportScope', 'ModuleRef')
|
|
|
|
|
|
class FIELD_RVA_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
29 - FieldRVA Table
|
|
Each row is an extension for a Field table. The RVA in this table gives the location of the initial value for a
|
|
Field. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
RVA (a 4-byte constant)
|
|
Field (index into Field table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'FieldRVA', byte_buffer)
|
|
|
|
self.RVA = self.create_field_value('RVA', 4, 'I')
|
|
self.Field = self.create_table_reference('Field', 'Field')
|
|
|
|
|
|
class ENC_LOG_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
30 - EncLog Table
|
|
Quote: "ENCLog and ENCMap, which occur in temporary images, generated during "Edit and Continue" or
|
|
"incremental compilation" scenarios, whilst debugging. Both table types are reserved for future use."
|
|
It is not documented in ECMA-335, but the definition can be found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Token (a 4-byte constant)
|
|
FuncCode (a 4-byte constant)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'EncLog', byte_buffer)
|
|
|
|
self.Token = self.create_field_value('Token', 4, 'I')
|
|
self.FuncCode = self.create_field_value('FuncCode', 4, 'I')
|
|
|
|
|
|
class ENC_MAP_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
31 - EncMap Table
|
|
Quote: "ENCLog and ENCMap, which occur in temporary images, generated during "Edit and Continue" or
|
|
"incremental compilation" scenarios, whilst debugging. Both table types are reserved for future use."
|
|
It is not documented in ECMA-335, but the definition can be found in metadata.c of the .NET runtime source code.
|
|
|
|
Columns:
|
|
Token (a 4-byte constant)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'EncMap', byte_buffer)
|
|
|
|
self.Token = self.create_field_value('Token', 4, 'I')
|
|
|
|
|
|
class ASSEMBLY_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
32 - Assembly Table
|
|
It's officially a one-row table, but there are ITW files with more than one row. It stores information about
|
|
the current assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
HashAlgId (a 4-byte constant of type AssemblyHashAlgorithm)
|
|
MajorVersion, MinorVersion, BuildNumber, RevisionNumber (2-byte constants)
|
|
Flags (a 4-byte bitmask of type AssemblyFlags)
|
|
PublicKey (index into Blob heap)
|
|
Name (index into String heap)
|
|
Culture (index into String heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'Assembly', byte_buffer)
|
|
|
|
self.HashAlgId = self.create_field_value('HashAlgId', 4, 'I')
|
|
self.MajorVersion = self.create_field_value('MajorVersion', 2, 'H')
|
|
self.MinorVersion = self.create_field_value('MinorVersion', 2, 'H')
|
|
self.BuildNumber = self.create_field_value('BuildNumber', 2, 'H')
|
|
self.RevisionNumber = self.create_field_value('RevisionNumber', 2, 'H')
|
|
self.Flags = self.create_field_value('Flags', 4, 'I')
|
|
self.PublicKey = self.create_blob_stream_field_value('PublicKey')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Culture = self.create_string_stream_field_value('Culture')
|
|
|
|
|
|
class ASSEMBLY_PROCESSOR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
33 - AssemblyProcessor Table
|
|
This table is ignored by the CLI and shouldn't be present in an assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Processor (a 4-byte constant)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'AssemblyProcessor', byte_buffer)
|
|
|
|
self.Processor = self.create_field_value('Processor', 4, 'I')
|
|
|
|
|
|
class ASSEMBLY_OS_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
34 - AssemblyOS Table
|
|
This table is ignored by the CLI and shouldn't be present in an assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
OSPlatformID (a 4-byte constant)
|
|
OSMajorVersion (a 4-byte constant)
|
|
OSMinorVersion (a 4-byte constant)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'AssemblyOS', byte_buffer)
|
|
|
|
self.OSPlatformID = self.create_field_value('OSPlatformID', 4, 'I')
|
|
self.OSMajorVersion = self.create_field_value('OSMajorVersion', 4, 'I')
|
|
self.OSMinorVersion = self.create_field_value('OSMinorVersion', 4, 'I')
|
|
|
|
|
|
class ASSEMBLY_REF_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
35 - AssemblyRef Table
|
|
Each row references an external assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
MajorVersion, MinorVersion, BuildNumber, RevisionNumber (2-byte constants)
|
|
Flags (a 4-byte bitmask of type AssemblyFlags)
|
|
PublicKeyOrToken (index into Blob heap - the public key or token that identifies the author of this Assembly)
|
|
Name (index into String heap)
|
|
Culture (index into String heap)
|
|
HashValue (index into Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'AssemblyRef', byte_buffer)
|
|
|
|
self.MajorVersion = self.create_field_value('MajorVersion', 2, 'H')
|
|
self.MinorVersion = self.create_field_value('MinorVersion', 2, 'H')
|
|
self.BuildNumber = self.create_field_value('BuildNumber', 2, 'H')
|
|
self.RevisionNumber = self.create_field_value('RevisionNumber', 2, 'H')
|
|
self.Flags = self.create_field_value('Flags', 4, 'I')
|
|
self.PublicKeyOrToken = self.create_blob_stream_field_value('PublicKeyOrToken')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Culture = self.create_string_stream_field_value('Culture')
|
|
self.HashValue = self.create_blob_stream_field_value('HashValue')
|
|
|
|
|
|
class ASSEMBLY_REF_PROCESSOR_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
36 - AssemblyRefProcessor Table
|
|
This table is ignored by the CLI and shouldn't be present in an assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Processor (4-byte constant)
|
|
AssemblyRef (index into the AssemblyRef table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'AssemblyRefProcessor', byte_buffer)
|
|
|
|
self.Processor = self.create_field_value('Processor', 4, 'I')
|
|
self.AssemblyRef = self.create_table_reference('AssemblyRef', 'AssemblyRef')
|
|
|
|
|
|
class ASSEMBLY_REF_OS_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
37 - AssemblyRefOS Table
|
|
This table is ignored by the CLI and shouldn't be present in an assembly. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
OSPlatformId (4-byte constant)
|
|
OSMajorVersion (4-byte constant)
|
|
OSMinorVersion (4-byte constant)
|
|
AssemblyRef (index into the AssemblyRef table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'AssemblyRefOS', byte_buffer)
|
|
|
|
self.OSPlatformID = self.create_field_value('OSPlatformID', 4, 'I')
|
|
self.OSMajorVersion = self.create_field_value('OSMajorVersion', 4, 'I')
|
|
self.OSMinorVersion = self.create_field_value('OSMinorVersion', 4, 'I')
|
|
self.AssemblyRef = self.create_table_reference('AssemblyRef', 'AssemblyRef')
|
|
|
|
|
|
class FILE_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
38 - File Table
|
|
Each row references an external file. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Flags (a 4-byte bitmask of type FileAttributes)
|
|
Name (index into String heap)
|
|
HashValue (index into Blob heap)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'File', byte_buffer)
|
|
|
|
self.Flags = self.create_field_value('Flags', 4, 'I')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.HashValue = self.create_blob_stream_field_value('HashValue')
|
|
|
|
|
|
class EXPORTED_TYPE_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
39 - ExportedType Table
|
|
Quote: "The ExportedType table holds a row for each type, defined within other modules of this Assembly, that is
|
|
exported out of this Assembly. In essence, it stores TypeDef row numbers of all types that are marked public in
|
|
other modules that this Assembly comprises.".
|
|
It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Flags (a 4-byte bitmask of type TypeAttributes)
|
|
TypeDefId (4-byte index into a TypeDef table of another module in this Assembly). This field is used as a hint
|
|
only. If the entry in the target TypeDef table matches the TypeName and TypeNamespace entries in this table,
|
|
resolution has succeeded. But if there is a mismatch, the CLI shall fall back to a search of the target
|
|
TypeDef table
|
|
TypeName (index into the String heap)
|
|
TypeNamespace (index into the String heap)
|
|
Implementation. This is an index (more precisely, an Implementation coded index) into either of the following
|
|
tables:
|
|
File table, where that entry says which module in the current assembly holds the TypeDef
|
|
ExportedType table, where that entry is the enclosing Type of the current nested Type
|
|
AssemblyRef table, where that entry says in which assembly the type may now be found (Flags must have
|
|
the IsTypeForwarder flag set).
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'ExportedType', byte_buffer)
|
|
|
|
self.Flags = self.create_field_value('Flags', 4, 'I')
|
|
self.TypeDefId = self.create_field_value('TypeDefId', 4, 'I')
|
|
self.TypeName = self.create_string_stream_field_value('TypeName')
|
|
self.TypeNamespace = self.create_string_stream_field_value('TypeNamespace')
|
|
|
|
self.Implementation = self.create_variable_length_table_reference('Implementation', 'Implementation')
|
|
|
|
|
|
class MANIFEST_RESOURCE_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
40 - ManifestResource Table
|
|
Each row references an internal or external resource. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Offset (a 4-byte constant)
|
|
Flags (a 4-byte bitmask of type ManifestResourceAttributes)
|
|
Name (index into the String heap)
|
|
Implementation (index into File table, or AssemblyRef table, or null; more precisely, an Implementation coded index)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'ManifestResource', byte_buffer)
|
|
|
|
self.Offset = self.create_field_value('Offset', 4, 'I')
|
|
self.Flags = self.create_field_value('Flags', 4, 'I')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
self.Implementation = self.create_variable_length_table_reference('Implementation', 'Implementation')
|
|
|
|
|
|
class NESTED_CLASS_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
41 - NestedClass Table
|
|
Each row represents a nested class. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
NestedClass (index into the TypeDef table)
|
|
EnclosingClass (index into the TypeDef table)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'NestedClass', byte_buffer)
|
|
|
|
self.NestedClass = self.create_table_reference('NestedClass', 'TypeDef')
|
|
self.EnclosingClass = self.create_table_reference('EnclosingClass', 'TypeDef')
|
|
|
|
|
|
class GENERIC_PARAM_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
42 - GenericParam Table
|
|
Quote: "The GenericParam table stores the generic parameters used in generic type definitions and generic
|
|
method definitions. These generic parameters can be constrained (i.e., generic arguments shall extend some
|
|
class and/or implement certain interfaces) or unconstrained.".
|
|
It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Number (the 2-byte index of the generic parameter, numbered left-to-right, from zero)
|
|
Flags (a 2-byte bitmask of type GenericParamAttributes)
|
|
Owner (an index into the TypeDef or MethodDef table, specifying the Type or Method to which this generic
|
|
parameter applies; more precisely, a TypeOrMethodDef coded index)
|
|
Name (a non-null index into the String heap, giving the name for the generic parameter. This is purely
|
|
descriptive and is used only by dotnetfile language compilers and by Reflection)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'GenericParam', byte_buffer)
|
|
|
|
self.Number = self.create_field_value('Number', 2, 'H')
|
|
self.Flags = self.create_field_value('Flags', 2, 'H')
|
|
self.Owner = self.create_variable_length_table_reference('Owner', 'TypeOrMethodDef')
|
|
self.Name = self.create_string_stream_field_value('Name')
|
|
|
|
|
|
class METHOD_SPEC_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
43 - MethodSpec
|
|
Contains information about generic method instantiations. It is documented in ECMA-335.
|
|
|
|
Columns:
|
|
Method (an index into the MethodDef or MemberRef table)
|
|
Instantiation (an index into the Blob heap, holding the signature of this instantiation)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'MethodSpec', byte_buffer)
|
|
|
|
self.Method = self.create_variable_length_table_reference('Method', 'MethodDefOrRef')
|
|
self.Instantiation = self.create_blob_stream_field_value('Instantiation')
|
|
|
|
|
|
class GENERIC_PARAM_CONSTRAINT_TABLE_ROW(METADATA_TABLE_ROW):
|
|
"""
|
|
44 - GenericParamConstraint Table
|
|
Contains information about inheritance and implementation constraints imposed on the generic parameters. It is
|
|
documented in ECMA-335.
|
|
|
|
Columns:
|
|
Owner (an index into the GenericParam table, specifying to which generic parameter this row refers)
|
|
Constraint (an index into the TypeDef, TypeRef, or TypeSpec tables, specifying from which class this generic
|
|
parameter is constrained to derive; or which interface this generic parameter is constrained to implement;
|
|
more precisely, a TypeDefOrRef coded index)
|
|
"""
|
|
def __init__(self, pe, addr: int = None, byte_buffer: bytes = None):
|
|
METADATA_TABLE_ROW.__init__(self, pe, addr, 'GenericParamConstraint', byte_buffer)
|
|
|
|
self.Owner = self.create_table_reference('Owner', 'GenericParam')
|
|
self.Constraint = self.create_variable_length_table_reference('Constraint', 'TypeDefOrRef')
|
|
|
|
|
|
"""
|
|
This is a lookup table that we can use to get the row types when we're parsing each table of metadata rows in the
|
|
metadata stream. There are several tables that are not documented in ECMA-335. However, the definitions can be found
|
|
in metadata.c of the .NET runtime dotnetfile code:
|
|
https://github.com/dotnet/runtime/blob/main/src/mono/mono/metadata/metadata.c
|
|
"""
|
|
METADATA_TYPE_LOOKUP: Dict[str, Any] = {
|
|
'Module': MODULE_TABLE_ROW,
|
|
'TypeRef': TYPE_REF_TABLE_ROW,
|
|
'TypeDef': TYPE_DEF_TABLE_ROW,
|
|
'FieldPtr': FIELD_PTR_TABLE_ROW, # Not documented in ECMA-335
|
|
'Field': FIELD_TABLE_ROW,
|
|
'MethodPtr': METHOD_PTR_TABLE_ROW, # Not documented in ECMA-335
|
|
'MethodDef': METHOD_DEF_TABLE_ROW,
|
|
'ParamPtr': PARAM_PTR_TABLE_ROW, # Not documented in ECMA-335
|
|
'Param': PARAM_TABLE_ROW,
|
|
'InterfaceImpl': INTERFACE_IMPL_TABLE_ROW,
|
|
'MemberRef': MEMBER_REF_TABLE_ROW,
|
|
'Constant': CONSTANT_TABLE_ROW,
|
|
'CustomAttribute': CUSTOM_ATTRIBUTE_TABLE_ROW,
|
|
'FieldMarshal': FIELD_MARSHAL_TABLE_ROW,
|
|
'DeclSecurity': DECL_SECURITY_TABLE_ROW,
|
|
'ClassLayout': CLASS_LAYOUT_TABLE_ROW,
|
|
'FieldLayout': FIELD_LAYOUT_TABLE_ROW,
|
|
'StandAloneSig': STAND_ALONE_SIG_TABLE_ROW,
|
|
'EventMap': EVENT_MAP_TABLE_ROW,
|
|
'EventPtr': EVENT_PTR_TABLE_ROW, # Not documented in ECMA-335
|
|
'Event': EVENT_TABLE_ROW,
|
|
'PropertyMap': PROPERTY_MAP_TABLE_ROW,
|
|
'PropertyPtr': PROPERTY_PTR_TABLE_ROW, # Not documented in ECMA-335
|
|
'Property': PROPERTY_TABLE_ROW,
|
|
'MethodSemantics': METHOD_SEMANTICS_TABLE_ROW,
|
|
'MethodImpl': METHOD_IMPL_TABLE_ROW,
|
|
'ModuleRef': MODULE_REF_TABLE_ROW,
|
|
'TypeSpec': TYPE_SPEC_TABLE_ROW,
|
|
'ImplMap': IMPL_MAP_TABLE_ROW,
|
|
'FieldRVA': FIELD_RVA_TABLE_ROW,
|
|
'EncLog': ENC_LOG_TABLE_ROW, # Not documented in ECMA-335
|
|
'EncMap': ENC_MAP_TABLE_ROW, # Not documented in ECMA-335
|
|
'Assembly': ASSEMBLY_TABLE_ROW,
|
|
'AssemblyProcessor': ASSEMBLY_PROCESSOR_TABLE_ROW,
|
|
'AssemblyOS': ASSEMBLY_OS_TABLE_ROW,
|
|
'AssemblyRef': ASSEMBLY_REF_TABLE_ROW,
|
|
'AssemblyRefProcessor': ASSEMBLY_REF_PROCESSOR_TABLE_ROW,
|
|
'AssemblyRefOS': ASSEMBLY_REF_OS_TABLE_ROW,
|
|
'File': FILE_TABLE_ROW,
|
|
'ExportedType': EXPORTED_TYPE_TABLE_ROW,
|
|
'ManifestResource': MANIFEST_RESOURCE_TABLE_ROW,
|
|
'NestedClass': NESTED_CLASS_TABLE_ROW,
|
|
'GenericParam': GENERIC_PARAM_TABLE_ROW,
|
|
'MethodSpec': METHOD_SPEC_TABLE_ROW,
|
|
'GenericParamConstraint': GENERIC_PARAM_CONSTRAINT_TABLE_ROW,
|
|
# 'Document': DOCUMENT_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'MethodDebugInformation': METHOD_DEBUG_INFORMATION_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'LocalScope': LOCAL_SCOPE_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'LocalVariable': LOCAL_VARIABLE_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'LocalConstant': LOCAL_CONSTANT_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'ImportScope': IMPORT_SCOPE_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'StateMachineMethod': STATE_MACHINE_METHOD_TABLE_ROW, # Not documented in ECMA-335
|
|
# 'CustomDebugInformation': CUSTOM_DEBUG_INFORMATION_TABLE_ROW # Not documented in ECMA-335
|
|
}
|
|
|
|
|
|
def get_metadata_row_class_for_table(table_name: str):
|
|
"""
|
|
maps between string represents a table name (such as "TypeRef") to
|
|
it appropriate class
|
|
:param table_name: string represents a table name
|
|
:return:
|
|
"""
|
|
return METADATA_TYPE_LOOKUP.get(table_name, None)
|