def MakeGenericParamRow():
    return construct.Struct('GenericParamRow',
        construct.ULInt16('Number'),
        construct.ULInt16('Flags'),
        MDTag.TypeOrMethodDef.parse('Owner'),
        MDTag.StringHeapRef.parse('Name')
    )
def MakeMethodRow():
    return construct.Struct('MethodRow',
        MakeRva('RVA'),
        construct.ULInt16('ImplFlags'),
        construct.ULInt16('Flags'),
        MDTag.StringHeapRef.parse('Name'),
        MDTag.BlobHeapRef.parse('Signature'),
        MDTag.ParamRef.parse('ParamList')
    )
def MakeAssemblyRefRow():
    return construct.Struct('AssemblyRefRow',
        construct.ULInt16('MajorVersion'),
        construct.ULInt16('MinorVersion'),
        construct.ULInt16('BuildNumber'),
        construct.ULInt16('RevisionNumber'),
        construct.ULInt32('Flags'),
        MDTag.BlobHeapRef.parse('PublicKeyOrToken'),
        MDTag.StringHeapRef.parse('Name'),
        MDTag.StringHeapRef.parse('Culture'),
        MDTag.BlobHeapRef.parse('HashValue')
    )
def ReadVtableFixups(ClrHeader):
    VTableFixup = construct.Struct('VTableFixup',
        MakeRva('RVA'),
        construct.ULInt16('Count'),
        construct.FlagsEnum(construct.ULInt16('Type'),
            COR_VTABLE_32BIT                           = 0x01, # V-table slots are 32-bits in size.
            COR_VTABLE_64BIT                           = 0x02, # V-table slots are 64-bits in size.
            COR_VTABLE_FROM_UNMANAGED                  = 0x04, # If set, transition from unmanaged.
            COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN = 0x08, # If set, transition from unmanaged with keeping the current appdomain.
            COR_VTABLE_CALL_MOST_DERIVED               = 0x10, # Call most derived method described by
        )
    )
    numFixups = ClrHeader.VTableFixups.Size / VTableFixup.sizeof()
    VTableFixups = construct.Array(numFixups, VTableFixup)
    if numFixups == 0: return []
    return VTableFixups.parse(idc.get_bytes(ClrHeader.VTableFixups.VA, int(VTableFixups.sizeof())))
def MakeImplMapRow():
    return construct.Struct('ImplMapRow',
        construct.ULInt16('MappingFlags'),
        MDTag.MemberForwarded.parse('MemberForwarded'),
        MDTag.StringHeapRef.parse('ImportName'),
        MDTag.ModuleRefRId.parse('ImportScope')
    )
def MakeModuleRow():
    return construct.Struct('ModuleRow',
        construct.ULInt16('Generation'),
        MDTag.StringHeapRef.parse('Name'),
        MDTag.GuidHeapRef.parse('MVId'),
        MDTag.GuidHeapRef.parse('EnCId'),
        MDTag.GuidHeapRef.parse('EnCBaseId')
    )
def MakeMethodSemanticsRow():
    return construct.Struct('MethodSemanticsRow',
        construct.ULInt16('Flags'),
        MDTag.MethodRId.parse('Method'),
        MDTag.HasSemantics.parse('Association')
    )
def MakePropertyRow():
    return construct.Struct('PropertyRow',
        construct.ULInt16('Flags'),
        MDTag.StringHeapRef.parse('Name'),
        MDTag.BlobHeapRef.parse('Type')
    )
def MakeEventRow():
    return construct.Struct('EventRow',
        construct.ULInt16('EventFlags'),
        MDTag.StringHeapRef.parse('Name'),
        MDTag.TypeDefOrRef.parse('EventType')
    )
def MakeClassLayoutRow():
    return construct.Struct('ClassLayoutRow',
        construct.ULInt16('PackingSize'),
        construct.ULInt32('ClassSize'),
        MDTag.TypeDefRId.parse('Parent')
    )
def MakeDeclSecurityRow():
    return construct.Struct('DeclSecurityRow',
        construct.ULInt16('Action'),
        MDTag.HasDeclSecurity.parse('Parent'),
        MDTag.BlobHeapRef.parse('PermissionSet')
    )
def MakeParamRow():
    return construct.Struct('ParamRow',
        construct.ULInt16('Flags'),
        construct.ULInt16('Sequence'),
        MDTag.StringHeapRef.parse('Name')
    )
def MakeFieldRow():
    return construct.Struct('FieldRow',
        construct.ULInt16('Flags'),
        MDTag.StringHeapRef.parse('Name'),
        MDTag.BlobHeapRef.parse('Signature')
    )
#!/usr/bin/env python3
# TODO apply native method type information
import construct_legacy as construct
import ida_entry
import idaapi
import idautils
import idc
import io
import struct

ImageFileHeader = construct.Struct('ImageFileHeader',
    construct.Enum(construct.ULInt16('Machine'),
        IMAGE_FILE_MACHINE_I386  = 0x014c,
        IMAGE_FILE_MACHINE_AMD64 = 0x8664,
        IMAGE_FILE_MACHINE_ARMNT = 0x01c4
    ),
    construct.ULInt16('NumberOfSections'),
    construct.ULInt32('TimeDateStamp'),
    construct.ULInt32('PointerToSymbolTable'),
    construct.ULInt32('NumberOfSymbols'),
    construct.ULInt16('SizeOfOptionalHeader'),
    construct.ULInt16('Characteristics')
)

def MakeRva(name):
    return construct.Embed(construct.Struct('EmbeddedRva',
        construct.ULInt32(name),
        construct.Value('VA', lambda ctx: idaapi.get_imagebase() + ctx[name])
    ))

def MakeImageDataDirectory(name):