Jan Biemond

95 papers A 1B 1C 7Misc 27Journal 31Unranked 27
YearRankTypeTitle / Venue / Authors
2011 J jnl
IEEE J. Sel. Top. Signal Process.
Dan Schonfeld, Jan Biemond, Gerard de Haan, André Kaup
2005 J jnl
EURASIP J. Adv. Signal Process.
Andrei Rares, Marcel J. T. Reinders, Jan Biemond
2005 J jnl
IEEE Trans. Image Process.
Andrei Rares, Marcel J. T. Reinders, Jan Biemond
2003 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Bang Jun Lei, Li-Qun Xu, Emile A. Hendriks, Jan Biemond
2002 conf
ICIP (2)
Andrei Rares, Marcel J. T. Reinders, Reginald L. Lagendijk, Jan Biemond
2002 conf
3DPVT
André Redert, Emile A. Hendriks, Jan Biemond
2002 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Peter M. B. van Roosmalen, Reginald L. Lagendijk, Jan Biemond
2002 Misc conf
ICASSP
Andrei Rares, Marcel J. T. Reinders, Jan Biemond
2002 conf
EUSIPCO
Andrei Rares, Marcel J. T. Reinders, Jan Biemond
2001 A conf
ICME
Alan Hanjalic, Geerd Kakes, Reginald L. Lagendijk, Jan Biemond
2001 conf
ICIP (1)
Andrei Rares, Marcel J. T. Reinders, Jan Biemond
2001 conf
Storage and Retrieval for Media Databases
Alan Hanjalic, Geerd Kakes, Reginald L. Lagendijk, Jan Biemond
2001 J jnl
J. Electronic Imaging
Alan Hanjalic, Geerd Kakes, Reginald L. Lagendijk, Jan Biemond
2001 J jnl
Int. J. Image Graph.
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
2000 J jnl
IEEE Trans. Circuits Syst. Video Technol.
André Redert, Emile A. Hendriks, Jan Biemond
2000 J jnl
Signal Process. Image Commun.
Reginald L. Lagendijk, Emmanuel D. Frimout, Jan Biemond
1999 C conf
MMSP
Frank H. P. Spaan, Inald Lagendijk, Jan Biemond
1999 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
1999 conf
VISUAL
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
1999 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Peter M. B. van Roosmalen, Reginald L. Lagendijk, Jan Biemond
1999 J jnl
IEEE Signal Process. Mag.
André Redert, Emile A. Hendriks, Jan Biemond
1999 conf
ICIP (3)
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
1999 Misc conf
ICASSP
Peter M. B. van Roosmalen, Anil C. Kokaram, Jan Biemond
1999 Misc conf
ICASSP
Jan Biemond, Peter M. B. van Roosmalen, Reginald L. Lagendijk
1999 conf
Storage and Retrieval for Image and Video Databases (SPIE)
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
1999 conf
Security and Watermarking of Multimedia Contents
Gerhard C. Langelaar, Reginald L. Lagendijk, Jan Biemond
1998 ch.
Image Databases and Multi-Media Search
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
1998 conf
ICIP (3)
Frank H. P. Spaan, Reginald L. Lagendijk, Jan Biemond
1998 conf
ECMAST
Frank H. P. Spaan, Reginald L. Lagendijk, Jan Biemond
1998 conf
EUSIPCO
Peter M. B. van Roosmalen, Anil C. Kokaram, Jan Biemond
1998 J jnl
J. Vis. Commun. Image Represent.
Gerrit C. Langelaar, Reginald L. Lagendijk, Jan Biemond
1998 conf
EUSIPCO
Gerrit C. Langelaar, Reginald L. Lagendijk, Jan Biemond
1998 J jnl
J. Electronic Imaging
Jan Biemond, Edward J. Delp
1998 conf
ICIP (3)
Alan Hanjalic, Reginald L. Lagendijk, Jan Biemond
1997 conf
ICIP (1)
Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1997 J jnl
IEEE Trans. Image Process.
Richard P. Kleihorst, Reginald L. Lagendijk, Jan Biemond
1997 conf
Storage and Retrieval for Image and Video Databases (SPIE)
Alan Hanjalic, Marco Ceccarelli, Reginald L. Lagendijk, Jan Biemond
1997 Misc conf
ICASSP
Anil C. Kokaram, Peter J. W. Rayner, Peter M. B. van Roosmalen, Jan Biemond
1997 conf
ICIP (1)
Frank H. P. Spaan, Reginald L. Lagendijk, Jan Biemond
1997 conf
Human Vision and Electronic Imaging
Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1997 Misc conf
ICASSP
André Redert, Emile A. Hendriks, Jan Biemond
1996 Misc conf
ICASSP
Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1996 conf
EUSIPCO
Reginald L. Lagendijk, Jan Biemond, Cor P. Quist
1996 conf
ICIP (1)
Peter M. B. van Roosmalen, Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1996 conf
Human Vision and Electronic Imaging
Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1996 conf
EUROSIM
Sándor Bozóki, Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1996 conf
ICIP (1)
Frances Jane Hampson, R. E. H. Franich, Jean-Christophe Pesquet, Jan Biemond
1995 J jnl
IEEE Trans. Image Process.
Richard P. Kleihorst, Reginald L. Lagendijk, Jan Biemond
1995 Misc conf
ICASSP
Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1995 B conf
ICIP
Stefan J. P. Westen, Reginald L. Lagendijk, Jan Biemond
1995 J jnl
IEEE Trans. Image Process.
Shlomo Koch, Howard Kaufman, Jan Biemond
1994 conf
ICIP (1)
Richard P. Kleihorst, Reginald L. Lagendijk, Jan Biemond
1994 conf
ICIP (2)
R. E. H. Franich, Reginald L. Lagendijk, Jan Biemond
1994 J jnl
IEEE Trans. Image Process.
Ricardo A. F. Belfor, Marc P. A. Hesp, Reginald L. Lagendijk, Jan Biemond
1993 conf
ICASSP (5)
Frank Bosveld, Reginald L. Lagendijk, Jan Biemond
1993 C conf
VCIP
Herjan J. Barnard, Jos H. Weber, Jan Biemond
1993 C conf
VCIP
Emmanuel D. Frimout, Jan Biemond, Reginald L. Lagendijk
1993 conf
ICASSP (5)
Richard P. Kleihorst, Reginald L. Lagendijk, Jan Biemond
1993 C conf
VCIP
Ruggero E. H. Franich, Reginald L. Lagendijk, Jan Biemond
1992 J jnl
Signal Process.
Frank Bosveld, Reginald L. Lagendijk, Jan Biemond
1992 J jnl
Signal Process. Image Commun.
Frank Bosveld, Reginald L. Lagendijk, Jan Biemond
1992 Misc conf
ICASSP
Frank Bosveld, Reginald L. Lagendijk, Jan Biemond
1992 J jnl
IEEE Trans. Signal Process.
Peter H. Westerink, Jan Biemond, Dick E. Boekee
1991 J jnl
IEEE Trans. Signal Process.
Aggelos K. Katsaggelos, Jan Biemond, Ronald W. Schafer, Russell M. Mersereau
1991 Misc conf
ICASSP
Reginald L. Lagendijk, Jan Biemond
1991 J jnl
J. Vis. Commun. Image Represent.
Johannes N. Driessen, Lilla Böröczky, Jan Biemond
1990 C conf
VCIP
Lilla Böröczky, Johannes N. Driessen, Jan Biemond
1990 J jnl
Multidimens. Syst. Signal Process.
N. K. Bose, Jan Biemond, Marwan A. Simaan
1990 Misc conf
ICASSP
Reginald L. Lagendijk, Jan Biemond, Dick E. Boekee
1990 Misc conf
ICASSP
Jan Biemond, Frank Bosveld, Reginald L. Lagendijk
1990 J jnl
IEEE Trans. Acoust. Speech Signal Process.
Reginald L. Lagendijk, Jan Biemond, Dick E. Boekee
1990 C conf
VCIP
Reginald L. Lagendijk, Jan Biemond
1990 C conf
VCIP
Frank Bosveld, Reginald L. Lagendijk, Jan Biemond
1990 J jnl
Signal Process. Image Commun.
Peter H. Westerink, Jan Biemond, Frank Müller
1989 Misc conf
ICASSP
Johannes N. Driessen, Jan Biemond, Dick E. Boekee
1989 Misc conf
ICASSP
Reginald L. Lagendijk, Jan Biemond, Dick E. Boekee
1989 Misc conf
ICASSP
Peter H. Westerink, Jan Biemond, Dick E. Boekee
1988 Misc conf
ICASSP
Peter H. Westerink, Jan Biemond, Dick E. Boekee
1988 Misc conf
ICASSP
Reginald L. Lagendijk, Aggelos K. Katsaggelos, Jan Biemond
1988 J jnl
IEEE Trans. Acoust. Speech Signal Process.
Reginald L. Lagendijk, Jan Biemond, Dick E. Boekee
1988 J jnl
IEEE Trans. Commun.
Peter H. Westerink, Dick E. Boekee, Jan Biemond, John W. Woods
1987 Misc conf
ICASSP
Reginald L. Lagendijk, Russell M. Mersereau, Jan Biemond
1987 Misc conf
ICASSP
Peter H. Westerink, Jan Biemond, Dick E. Boekee
1986 Misc conf
ICASSP
Jan Biemond, F. G. van der Putten, John W. Woods
1986 Misc conf
ICASSP
Jan Biemond, Reginald L. Lagendijk
1985 Misc conf
ICASSP
Aggelos K. Katsaggelos, Jan Biemond, Russell M. Mersereau, Ronald W. Schafer
1985 Misc conf
ICASSP
R. H. J. M. Plompen, B. F. Schuurink, Jan Biemond
1985 Misc conf
ICASSP
John W. Woods, Jan Biemond, A. Murat Tekalp
1985 Misc conf
ICASSP
Jan Biemond, F. G. van der Putten
1985 Misc conf
ICASSP
Aggelos K. Katsaggelos, Jan Biemond, Russell M. Mersereau, Ronald W. Schafer
1984 Misc conf
ICASSP
Aggelos K. Katsaggelos, Jan Biemond, Russell M. Mersereau, Ronald W. Schafer
1984 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
John W. Woods, Jan Biemond
1982 Misc conf
ICASSP
Jan Biemond
1979 J jnl
IEEE Trans. Syst. Man Cybern.
Jan Biemond, Jan J. Gerbrands
1979 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Leo H. Links, Jan Biemond
redb/ext/spoof_check.py
← Index redb/ext/spoof_check.py python
import copy
import struct
from enum import Enum

"""
Checks that the metadata within a file's Rich header does not contradict the
other metadata contained within it.

References:
    https://gist.github.com/skochinsky/07c8e95e33d9429d81a75622b5d24c8b
    https://www.sec.in.tum.de/i20/publications/finding-the-needle-a-study-of-
    the-pe32-rich-header-and-respective-malware-triage
"""

KNOWN_PRODUCT_IDS = {
    0: "Unknown",
    1: "Import0",
    2: "Linker510",
    3: "Cvtomf510",
    4: "Linker600",
    5: "Cvtomf600",
    6: "Cvtres500",
    7: "Utc11_Basic",
    8: "Utc11_C",
    9: "Utc12_Basic",
    10: "Utc12_C",
    11: "Utc12_CPP",
    12: "AliasObj60",
    13: "VisualBasic60",
    14: "Masm613",
    15: "Masm710",
    16: "Linker511",
    17: "Cvtomf511",
    18: "Masm614",
    19: "Linker512",
    20: "Cvtomf512",
    21: "Utc12_C_Std",
    22: "Utc12_CPP_Std",
    23: "Utc12_C_Book",
    24: "Utc12_CPP_Book",
    25: "Implib700",
    26: "Cvtomf700",
    27: "Utc13_Basic",
    28: "Utc13_C",
    29: "Utc13_CPP",
    30: "Linker610",
    31: "Cvtomf610",
    32: "Linker601",
    33: "Cvtomf601",
    34: "Utc12_1_Basic",
    35: "Utc12_1_C",
    36: "Utc12_1_CPP",
    37: "Linker620",
    38: "Cvtomf620",
    39: "AliasObj70",
    40: "Linker621",
    41: "Cvtomf621",
    42: "Masm615",
    43: "Utc13_LTCG_C",
    44: "Utc13_LTCG_CPP",
    45: "Masm620",
    46: "ILAsm100",
    47: "Utc12_2_Basic",
    48: "Utc12_2_C",
    49: "Utc12_2_CPP",
    50: "Utc12_2_C_Std",
    51: "Utc12_2_CPP_Std",
    52: "Utc12_2_C_Book",
    53: "Utc12_2_CPP_Book",
    54: "Implib622",
    55: "Cvtomf622",
    56: "Cvtres501",
    57: "Utc13_C_Std",
    58: "Utc13_CPP_Std",
    59: "Cvtpgd1300",
    60: "Linker622",
    61: "Linker700",
    62: "Export622",
    63: "Export700",
    64: "Masm700",
    65: "Utc13_POGO_I_C",
    66: "Utc13_POGO_I_CPP",
    67: "Utc13_POGO_O_C",
    68: "Utc13_POGO_O_CPP",
    69: "Cvtres700",
    70: "Cvtres710p",
    71: "Linker710p",
    72: "Cvtomf710p",
    73: "Export710p",
    74: "Implib710p",
    75: "Masm710p",
    76: "Utc1310p_C",
    77: "Utc1310p_CPP",
    78: "Utc1310p_C_Std",
    79: "Utc1310p_CPP_Std",
    80: "Utc1310p_LTCG_C",
    81: "Utc1310p_LTCG_CPP",
    82: "Utc1310p_POGO_I_C",
    83: "Utc1310p_POGO_I_CPP",
    84: "Utc1310p_POGO_O_C",
    85: "Utc1310p_POGO_O_CPP",
    86: "Linker624",
    87: "Cvtomf624",
    88: "Export624",
    89: "Implib624",
    90: "Linker710",
    91: "Cvtomf710",
    92: "Export710",
    93: "Implib710",
    94: "Cvtres710",
    95: "Utc1310_C",
    96: "Utc1310_CPP",
    97: "Utc1310_C_Std",
    98: "Utc1310_CPP_Std",
    99: "Utc1310_LTCG_C",
    100: "Utc1310_LTCG_CPP",
    101: "Utc1310_POGO_I_C",
    102: "Utc1310_POGO_I_CPP",
    103: "Utc1310_POGO_O_C",
    104: "Utc1310_POGO_O_CPP",
    105: "AliasObj710",
    106: "AliasObj710p",
    107: "Cvtpgd1310",
    108: "Cvtpgd1310p",
    109: "Utc1400_C",
    110: "Utc1400_CPP",
    111: "Utc1400_C_Std",
    112: "Utc1400_CPP_Std",
    113: "Utc1400_LTCG_C",
    114: "Utc1400_LTCG_CPP",
    115: "Utc1400_POGO_I_C",
    116: "Utc1400_POGO_I_CPP",
    117: "Utc1400_POGO_O_C",
    118: "Utc1400_POGO_O_CPP",
    119: "Cvtpgd1400",
    120: "Linker800",
    121: "Cvtomf800",
    122: "Export800",
    123: "Implib800",
    124: "Cvtres800",
    125: "Masm800",
    126: "AliasObj800",
    127: "PhoenixPrerelease",
    128: "Utc1400_CVTCIL_C",
    129: "Utc1400_CVTCIL_CPP",
    130: "Utc1400_LTCG_MSIL",
    131: "Utc1500_C",
    132: "Utc1500_CPP",
    133: "Utc1500_C_Std",
    134: "Utc1500_CPP_Std",
    135: "Utc1500_CVTCIL_C",
    136: "Utc1500_CVTCIL_CPP",
    137: "Utc1500_LTCG_C",
    138: "Utc1500_LTCG_CPP",
    139: "Utc1500_LTCG_MSIL",
    140: "Utc1500_POGO_I_C",
    141: "Utc1500_POGO_I_CPP",
    142: "Utc1500_POGO_O_C",
    143: "Utc1500_POGO_O_CPP",
    144: "Cvtpgd1500",
    145: "Linker900",
    146: "Export900",
    147: "Implib900",
    148: "Cvtres900",
    149: "Masm900",
    150: "AliasObj900",
    151: "Resource900",
    152: "AliasObj1000",
    154: "Cvtres1000",
    155: "Export1000",
    156: "Implib1000",
    157: "Linker1000",
    158: "Masm1000",
    170: "Utc1600_C",
    171: "Utc1600_CPP",
    172: "Utc1600_CVTCIL_C",
    173: "Utc1600_CVTCIL_CPP",
    174: "Utc1600_LTCG_C ",
    175: "Utc1600_LTCG_CPP",
    176: "Utc1600_LTCG_MSIL",
    177: "Utc1600_POGO_I_C",
    178: "Utc1600_POGO_I_CPP",
    179: "Utc1600_POGO_O_C",
    180: "Utc1600_POGO_O_CPP",
    183: "Linker1010",
    184: "Export1010",
    185: "Implib1010",
    186: "Cvtres1010",
    187: "Masm1010",
    188: "AliasObj1010",
    199: "AliasObj1100",
    201: "Cvtres1100",
    202: "Export1100",
    203: "Implib1100",
    204: "Linker1100",
    205: "Masm1100",
    206: "Utc1700_C",
    207: "Utc1700_CPP",
    208: "Utc1700_CVTCIL_C",
    209: "Utc1700_CVTCIL_CPP",
    210: "Utc1700_LTCG_C ",
    211: "Utc1700_LTCG_CPP",
    212: "Utc1700_LTCG_MSIL",
    213: "Utc1700_POGO_I_C",
    214: "Utc1700_POGO_I_CPP",
    215: "Utc1700_POGO_O_C",
    216: "Utc1700_POGO_O_CPP",
    219: "Cvtres1200",
    220: "Export1200",
    221: "Implib1200",
    222: "Linker1200",
    223: "Masm1200",
    # Speculation
    224: "AliasObj1200",
    237: "Cvtres1210",
    238: "Export1210",
    239: "Implib1210",
    240: "Linker1210",
    241: "Masm1210",
    # Speculation
    242: "Utc1810_C",
    243: "Utc1810_CPP",
    244: "Utc1810_CVTCIL_C",
    245: "Utc1810_CVTCIL_CPP",
    246: "Utc1810_LTCG_C ",
    247: "Utc1810_LTCG_CPP",
    248: "Utc1810_LTCG_MSIL",
    249: "Utc1810_POGO_I_C",
    250: "Utc1810_POGO_I_CPP",
    251: "Utc1810_POGO_O_C",
    252: "Utc1810_POGO_O_CPP",
    255: "Cvtres1400",
    256: "Export1400",
    257: "Implib1400",
    258: "Linker1400",
    259: "Masm1400",
    260: "Utc1900_C",
    261: "Utc1900_CPP",
    # Speculation
    262: "Utc1900_CVTCIL_C",
    263: "Utc1900_CVTCIL_CPP",
    264: "Utc1900_LTCG_C ",
    265: "Utc1900_LTCG_CPP",
    266: "Utc1900_LTCG_MSIL",
    267: "Utc1900_POGO_I_C",
    268: "Utc1900_POGO_I_CPP",
    269: "Utc1900_POGO_O_C",
    270: "Utc1900_POGO_O_CPP",
}


class Result(Enum):
    VALID = 0
    INVALID = 1
    UNABLE_TO_PARSE = 2


def _rol(val, num):
    """Rotates val to the left by num bits."""
    return ((val << (num % 32)) & 0xFFFFFFFF) | (val >> (32 - (num % 32)))


def checksum_test(pe, rich_header):
    """Tests that the Rich header checksum is valid.

    Computes what the Rich header checksum should be. If the Rich header
    contains a different checksum value, this function returns INVALID
    This indicates that either the Rich header or MS-DOS stub has been modified

    The Rich header checksum is computed from the following:
        Length of the MS-DOS stub
        Contents of the MS-DOS stub, with e_lfanew zeroed out
        Rich header @Comp.IDs and lowest 5 bits of each count
    """
    if rich_header is None:
        rich_header = {}
    # Checksum stored in Rich header
    rich_checksum = rich_header.get("checksum", None)

    # Get DOS header data
    if pe.DOS_HEADER.e_lfanew > len(pe.__data__):
        return Result.UNABLE_TO_PARSE
    data = pe.__data__[: pe.DOS_HEADER.e_lfanew]

    # Get start marker
    mask = 0x536E6144  # DanS (little-endian)
    start_marker = struct.pack(
        "<LLLL", rich_checksum ^ mask, rich_checksum, rich_checksum, rich_checksum
    )
    if not len(start_marker):
        return Result.UNABLE_TO_PARSE

    # Get index of start marker
    start_index = data.find(start_marker)
    if start_index == -1:
        return Result.UNABLE_TO_PARSE

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.UNABLE_TO_PARSE

    # Compute cd as MS-DOS stub portion of checksum
    # Zero out e_lfanew from 0x3c to 0x3f
    cd = 0
    for i in range(start_index):
        if i >= 0x3C and i <= 0x3F:
            cd += _rol(0, i)
        else:
            cd += _rol(data[i], i)

    # Compute cd as Rich header portion of checksum
    cr = 0
    while len(rich_fields):
        compid = rich_fields.pop(0)
        count = rich_fields.pop(0)
        cr += _rol(compid, count & 0x1F)

    # Compute checksum from MS-DOS stub start index, cd, cr
    # Only keep lowest 32 bits
    checksum = (start_index + cd + cr) & 0xFFFFFFFF

    # Compare computed checksum with the checksum in the Rich header
    if checksum != rich_checksum:
        return Result.INVALID
    else:
        return Result.VALID


def duplicate_test(pe, rich_header):
    """Checks for duplicate @Comp.IDs in the Rich header.

    If the Rich header contains duplicate entries, returns INVALID
    This indicates that the Rich header has been modified
    """
    if rich_header is None:
        rich_header = {}

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.UNABLE_TO_PARSE

    # Get a list of @Comp.IDs in rich_fields
    compids = []
    for i in range(len(rich_fields)):
        if i % 2 == 0:
            compids.append(rich_fields[i])

    # Check if any @Comp.IDs are duplicates
    if len(compids) != len(set(compids)):
        return Result.INVALID

    return Result.VALID


def linker_test(pe, rich_header):
    """Checks that the Rich and PE header linker versions do not conflict.

    Certain Rich Header ProdIDs correspond to linker versions
    Although they are undocumented, we have used prior research as well as our
    own to determine many of them
    There are likely more linker version ProdIDs that we have not identified

    If the linker versions conflict, this function returns INVALID
    This indicates that the Rich header or PE header has been modified
    """
    if rich_header is None:
        rich_header = {}

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.UNABLE_TO_PARSE

    # Get list of ProdIDs from rich_fields
    prodids = []
    for i in range(len(rich_fields)):
        if i % 2 == 0:
            prodids.append(rich_fields[i] >> 16)

    # Parse major and minor linker versions from PE header
    pe_major = pe.OPTIONAL_HEADER.MajorLinkerVersion
    pe_minor = pe.OPTIONAL_HEADER.MinorLinkerVersion

    # Iterate over Rich header ProdIDs
    found_linker = False
    for prodid in prodids:

        # Only interested in ProdIDs that correspond to linker versions
        if KNOWN_PRODUCT_IDS.get(prodid) is None:
            continue
        prodid_name = KNOWN_PRODUCT_IDS[prodid]
        if not prodid_name.startswith("Linker"):
            continue

        found_linker = True

        # Parse major and minor linker version from ProdID
        prodid_name = prodid_name[6:]
        if prodid_name.endswith("p"):
            prodid_name = prodid_name[:-1]
        rich_major = int(prodid_name[:-2])
        rich_minor = int(prodid_name[-2:])

        # Check whether the Rich and PE linker versions match
        if pe_major == rich_major and pe_minor == rich_minor:
            return Result.VALID

    if not found_linker:
        return Result.UNABLE_TO_PARSE

    return Result.INVALID


def import_count_test(pe, rich_header):
    """Checks that import0 does not conflict with the IAT import count.

    The Rich header contains a ProdID called import0
    It is related to the number of imports in the IAT, but we are unsure how
    It is never less than the number of imports in the IAT

    If import0 is less than IAT import count, this function returns INVALID
    This indicates that the Rich header or IAT has been modified
    """
    if rich_header is None:
        rich_header = {}

    # Check whether the file has an IAT
    if not hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
        return Result.UNABLE_TO_PARSE

    # Get the number of imports in the IAT
    iat_count = 0
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
        for imported_function in entry.imports:
            iat_count += 1

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.INVALID

    # Get @Comp.ID 65536 (ProdID Import0)
    import0_count = None
    while len(rich_fields):
        compid = rich_fields.pop(0)
        count = rich_fields.pop(0)
        if compid == 65536:
            import0_count = count

    # Legitimate files never have import0_count < iat_count
    if import0_count is None:
        return Result.VALID

    if import0_count < iat_count:
        return Result.INVALID

    return Result.VALID