Neel Nanda

93 papers A* 17Journal 74Unranked 2
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
János Kramár, Joshua Engels, Zheng Wang, Bilal Chughtai, Rohin Shah, Neel Nanda, Arthur Conmy
2026 J jnl
CoRR
Helena Casademunt, Bartosz Cywinski, Khoi Tran, Arya Jakkli, Samuel Marks, Neel Nanda
2026 J jnl
CoRR
Anna Soligo, Edward Turner, Senthooran Rajamanoharan, Neel Nanda
2026 J jnl
CoRR
Elias Kempf, Simon Schrodi, Bartosz Cywinski, Thomas Brox, Neel Nanda, Arthur Conmy
2026 J jnl
CoRR
Jim Maar, Denis Paperno, Callum McDougall, Neel Nanda
2025 J jnl
CoRR
Rohin Shah, Alex Irpan, Alexander Matt Turner, Anna Wang, Arthur Conmy, David Lindner, Jonah Brown-Cohen, Lewis Ho, Neel Nanda, Raluca Ada Popa, Rishub Jain, Rory Greig, Samuel Albanie, Scott Emmons, Sebastian Farquhar, Sébastien Krier, Senthooran Rajamanoharan, Sophie Bridgers, Tobi Ijitoye, Tom Everitt, Victoria Krakovna, Vikrant Varma, Vladimir Mikulik, Zachary Kenton, Dave Orr, Shane Legg, Noah D. Goodman, Allan Dafoe, Four Flynn, Anca D. Dragan
2025 A* conf
ICML
Subhash Kantamneni, Joshua Engels, Senthooran Rajamanoharan, Max Tegmark, Neel Nanda
2025 J jnl
CoRR
Subhash Kantamneni, Joshua Engels, Senthooran Rajamanoharan, Max Tegmark, Neel Nanda
2025 J jnl
CoRR
Constantin Venhoff, Iván Arcuschin, Philip Torr, Arthur Conmy, Neel Nanda
2025 J jnl
CoRR
Been Kim, John Hewitt, Neel Nanda, Noah Fiedel, Oyvind Tafjord
2025 J jnl
CoRR
Tomek Korbak, Mikita Balesni, Elizabeth Barnes, Yoshua Bengio, Joe Benton, Joseph Bloom, Mark Chen, Alan Cooney, Allan Dafoe, Anca D. Dragan, Scott Emmons, Owain Evans, David Farhi, Ryan Greenblatt, Dan Hendrycks, Marius Hobbhahn, Evan Hubinger, Geoffrey Irving, Erik Jenner, Daniel Kokotajlo, Victoria Krakovna, Shane Legg, David Lindner, David Luan, Aleksander Madry, Julian Michael, Neel Nanda, Dave Orr, Jakub Pachocki, Ethan Perez, Mary Phuong, Fabien Roger, Joshua Saxe, Buck Shlegeris, Martín Soto, Eric Steinberger, Jasmine Wang, Wojciech Zaremba, Bowen Baker, Rohin Shah, Vladimir Mikulik
2025 J jnl
CoRR
Iván Arcuschin, Jett Janiak, Robert Krzyzanowski, Senthooran Rajamanoharan, Neel Nanda, Arthur Conmy
2025 J jnl
CoRR
Anna Soligo, Edward Turner, Senthooran Rajamanoharan, Neel Nanda
2025 J jnl
CoRR
Lewis Smith, Bilal Chughtai, Neel Nanda
2025 A* conf
ICLR
Javier Ferrando, Oscar Balcells Obeso, Senthooran Rajamanoharan, Neel Nanda
2025 J jnl
CoRR
Bartosz Cywinski, Emil Ryd, Rowan Wang, Senthooran Rajamanoharan, Neel Nanda, Arthur Conmy, Samuel Marks
2025 J jnl
CoRR
Constantin Venhoff, Ashkan Khakzar, Sonia Joseph, Philip Torr, Neel Nanda
2025 A* conf
ICML
Patrick Leask, Neel Nanda, Noura Al Moubayed
2025 J jnl
CoRR
Patrick Leask, Neel Nanda, Noura Al Moubayed
2025 J jnl
CoRR
Dmitrii Troitskii, Koyena Pal, Chris Wendler, Callum McDougall, Neel Nanda
2025 J jnl
CoRR
Nick Jiang, Xiaoqing Sun, Lisa Dunlap, Lewis Smith, Neel Nanda
2025 A* conf
ICML
Bart Bussmann, Noa Nabeshima, Adam Karvonen, Neel Nanda
2025 J jnl
CoRR
Bart Bussmann, Noa Nabeshima, Adam Karvonen, Neel Nanda
2025 J jnl
CoRR
Edward Turner, Anna Soligo, Mia Taylor, Senthooran Rajamanoharan, Neel Nanda
2025 J jnl
CoRR
Julian Minder, Clément Dumas, Stewart Slocum, Helena Casademunt, Cameron Holmes, Robert West, Neel Nanda
2025 J jnl
CoRR
Lee Sharkey, Bilal Chughtai, Joshua Batson, Jack Lindsey, Jeff Wu, Lucius Bushnaq, Nicholas Goldowsky-Dill, Stefan Heimersheim, Alejandro Ortega, Joseph Isaac Bloom, Stella Biderman, Adrià Garriga-Alonso, Arthur Conmy, Neel Nanda, Jessica Rumbelow, Martin Wattenberg, Nandi Schoots, Joseph Miller, Eric J. Michaud, Stephen Casper, Max Tegmark, William Saunders, David Bau, Eric Todd, Atticus Geiger, Mor Geva, Jesse Hoogland, Daniel Murfet, Tom McGrath
2025 J jnl
Trans. Mach. Learn. Res.
Lee Sharkey, Bilal Chughtai, Joshua Batson, Jack Lindsey, Jeffrey Wu, Lucius Bushnaq, Nicholas Goldowsky-Dill, Stefan Heimersheim, Alejandro Ortega, Joseph Isaac Bloom, Stella Biderman, Adrià Garriga-Alonso, Arthur Conmy, Neel Nanda, Jessica Rumbelow, Martin Wattenberg, Nandi Schoots, Joseph Miller, William Saunders, Eric J. Michaud, Stephen Casper, Max Tegmark, David Bau, Eric Todd, Atticus Geiger, Mor Geva, Jesse Hoogland, Daniel Murfet, Tom McGrath
2025 J jnl
CoRR
Oscar Obeso, Andy Arditi, Javier Ferrando, Joshua Freeman, Cameron Holmes, Neel Nanda
2025 J jnl
CoRR
Jake Ward, Chuqiao Lin, Constantin Venhoff, Neel Nanda
2025 J jnl
CoRR
Farnoush Rezaei Jafari, Oliver Eberle, Ashkan Khakzar, Neel Nanda
2025 J jnl
CoRR
Julian Minder, Clément Dumas, Caden Juang, Bilal Chugtai, Neel Nanda
2025 A* conf
ICML
Adam Karvonen, Can Rager, Johnny Lin, Curt Tigges, Joseph Isaac Bloom, David Chanin, Yeu-Tong Lau, Eoin Farrell, Callum McDougall, Kola Ayonrinde, Demian Till, Matthew Wearden, Arthur Conmy, Samuel Marks, Neel Nanda
2025 J jnl
CoRR
Adam Karvonen, Can Rager, Johnny Lin, Curt Tigges, Joseph Isaac Bloom, David Chanin, Yeu-Tong Lau, Eoin Farrell, Callum McDougall, Kola Ayonrinde, Matthew Wearden, Arthur Conmy, Samuel Marks, Neel Nanda
2025 A* conf
ICML
Dmitrii Kharlapenko, Stepan Shabalin, Arthur Conmy, Neel Nanda
2025 J jnl
CoRR
Dmitrii Kharlapenko, Stepan Shabalin, Fazl Barez, Arthur Conmy, Neel Nanda
2025 J jnl
CoRR
Atticus Wang, Joshua Engels, Oliver Clive-Griffin, Senthooran Rajamanoharan, Neel Nanda
2025 A* conf
ICLR
Patrick Leask, Bart Bussmann, Michael T. Pearce, Joseph Isaac Bloom, Curt Tigges, Noura Al Moubayed, Lee Sharkey, Neel Nanda
2025 J jnl
CoRR
Patrick Leask, Bart Bussmann, Michael T. Pearce, Joseph Isaac Bloom, Curt Tigges, Noura Al Moubayed, Lee Sharkey, Neel Nanda
2025 J jnl
CoRR
Tim Tian Hua, Andrew Qin, Samuel Marks, Neel Nanda
2025 J jnl
CoRR
Helena Casademunt, Caden Juang, Adam Karvonen, Samuel Marks, Senthooran Rajamanoharan, Neel Nanda
2025 J jnl
CoRR
Paul C. Bogdan, Uzay Macar, Neel Nanda, Arthur Conmy
2025 J jnl
CoRR
Uzay Macar, Paul C. Bogdan, Senthooran Rajamanoharan, Neel Nanda
2025 J jnl
CoRR
Constantin Venhoff, Ashkan Khakzar, Sonia Joseph, Philip Torr, Neel Nanda
2025 A* conf
ICLR
Aleksandar Makelov, Georg Lange, Neel Nanda
2025 J jnl
CoRR
Bartosz Cywinski, Emil Ryd, Senthooran Rajamanoharan, Neel Nanda
2025 J jnl
CoRR
Constantin Venhoff, Iván Arcuschin, Philip Torr, Arthur Conmy, Neel Nanda
2024 J jnl
CoRR
János Kramár, Tom Lieberum, Rohin Shah, Neel Nanda
2024 J jnl
CoRR
Bart Bussmann, Patrick Leask, Neel Nanda
2024 A* conf
NeurIPS
Alessandro Stolfo, Ben Wu, Wes Gurnee, Yonatan Belinkov, Xingyi Song, Mrinmaya Sachan, Neel Nanda
2024 J jnl
CoRR
Alessandro Stolfo, Ben Wu, Wes Gurnee, Yonatan Belinkov, Xingyi Song, Mrinmaya Sachan, Neel Nanda
2024 J jnl
CoRR
Javier Ferrando, Oscar Obeso, Senthooran Rajamanoharan, Neel Nanda
2024 J jnl
CoRR
Adam Karvonen, Can Rager, Samuel Marks, Neel Nanda
2024 A* conf
ICML
Cody Rushing, Neel Nanda
2024 J jnl
CoRR
Cody Rushing, Neel Nanda
2024 J jnl
CoRR
Tom Lieberum, Senthooran Rajamanoharan, Arthur Conmy, Lewis Smith, Nicolas Sonnerat, Vikrant Varma, János Kramár, Anca D. Dragan, Rohin Shah, Neel Nanda
2024 J jnl
CoRR
Stefan Heimersheim, Neel Nanda
2024 J jnl
CoRR
Senthooran Rajamanoharan, Arthur Conmy, Lewis Smith, Tom Lieberum, Vikrant Varma, János Kramár, Rohin Shah, Neel Nanda
2024 A* conf
NeurIPS
Senthooran Rajamanoharan, Arthur Conmy, Lewis Smith, Tom Lieberum, Vikrant Varma, János Kramár, Rohin Shah, Neel Nanda
2024 J jnl
CoRR
Connor Kissane, Robert Krzyzanowski, Joseph Isaac Bloom, Arthur Conmy, Neel Nanda
2024 A* conf
ICLR
Aleksandar Makelov, Georg Lange, Atticus Geiger, Neel Nanda
2024 J jnl
CoRR
Senthooran Rajamanoharan, Tom Lieberum, Nicolas Sonnerat, Arthur Conmy, Vikrant Varma, János Kramár, Neel Nanda
2024 A* conf
NeurIPS
Andy Arditi, Oscar Obeso, Aaquib Syed, Daniel Paleka, Nina Panickssery, Wes Gurnee, Neel Nanda
2024 J jnl
CoRR
Andy Arditi, Oscar Obeso, Aaquib Syed, Daniel Paleka, Nina Rimsky, Wes Gurnee, Neel Nanda
2024 J jnl
CoRR
Bilal Chughtai, Alan Cooney, Neel Nanda
2024 A* conf
ICLR
Fred Zhang, Neel Nanda
2024 J jnl
CoRR
Aleksandar Makelov, Georg Lange, Neel Nanda
2024 J jnl
CoRR
Jacob Dunefsky, Philippe Chlenski, Neel Nanda
2024 A* conf
NeurIPS
Jacob Dunefsky, Philippe Chlenski, Neel Nanda
2024 J jnl
CoRR
Wes Gurnee, Theo Horsley, Zifan Carl Guo, Tara Rezaei Kheirkhah, Qinyi Sun, Will Hathaway, Neel Nanda, Dimitris Bertsimas
2024 J jnl
Trans. Mach. Learn. Res.
Wes Gurnee, Theo Horsley, Zifan Carl Guo, Tara Rezaei Kheirkhah, Qinyi Sun, Will Hathaway, Neel Nanda, Dimitris Bertsimas
2023 J jnl
CoRR
Bilal Chughtai, Lawrence Chan, Neel Nanda
2023 A* conf
ICML
Bilal Chughtai, Lawrence Chan, Neel Nanda
2023 J jnl
CoRR
Callum McDougall, Arthur Conmy, Cody Rushing, Thomas McGrath, Neel Nanda
2023 J jnl
CoRR
Tom Lieberum, Matthew Rahtz, János Kramár, Neel Nanda, Geoffrey Irving, Rohin Shah, Vladimir Mikulik
2023 conf
BlackboxNLP@EMNLP
Neel Nanda, Andrew Lee, Martin Wattenberg
2023 J jnl
CoRR
Neel Nanda, Andrew Lee, Martin Wattenberg
2023 J jnl
CoRR
Wes Gurnee, Neel Nanda, Matthew Pauly, Katherine Harvey, Dmitrii Troitskii, Dimitris Bertsimas
2023 J jnl
Trans. Mach. Learn. Res.
Wes Gurnee, Neel Nanda, Matthew Pauly, Katherine Harvey, Dmitrii Troitskii, Dimitris Bertsimas
2023 J jnl
CoRR
Aleksandar Makelov, Georg Lange, Neel Nanda
2023 J jnl
CoRR
Curt Tigges, Oskar John Hollinsworth, Atticus Geiger, Neel Nanda
2023 J jnl
CoRR
Alex Foote, Neel Nanda, Esben Kran, Ioannis Konstas, Fazl Barez
2023 J jnl
CoRR
Alex Foote, Neel Nanda, Esben Kran, Ioannis Konstas, Shay B. Cohen, Fazl Barez
2023 A* conf
ICLR
Neel Nanda, Lawrence Chan, Tom Lieberum, Jess Smith, Jacob Steinhardt
2023 J jnl
CoRR
Neel Nanda, Lawrence Chan, Tom Lieberum, Jess Smith, Jacob Steinhardt
2023 J jnl
CoRR
Fred Zhang, Neel Nanda
2023 J jnl
CoRR
Lucia Quirke, Lovis Heindrich, Wes Gurnee, Neel Nanda
2022 J jnl
J. Mach. Learn. Res.
Michael K. Cohen, Marcus Hutter, Neel Nanda
2022 J jnl
CoRR
Catherine Olsson, Nelson Elhage, Neel Nanda, Nicholas Joseph, Nova DasSarma, Tom Henighan, Ben Mann, Amanda Askell, Yuntao Bai, Anna Chen, Tom Conerly, Dawn Drain, Deep Ganguli, Zac Hatfield-Dodds, Danny Hernandez, Scott Johnston, Andy Jones, Jackson Kernion, Liane Lovitt, Kamal Ndousse, Dario Amodei, Tom Brown, Jack Clark, Jared Kaplan, Sam McCandlish, Chris Olah
2022 conf
FAccT
Deep Ganguli, Danny Hernandez, Liane Lovitt, Amanda Askell, Yuntao Bai, Anna Chen, Tom Conerly, Nova DasSarma, Dawn Drain, Nelson Elhage, Sheer El Showk, Stanislav Fort, Zac Hatfield-Dodds, Tom Henighan, Scott Johnston, Andy Jones, Nicholas Joseph, Jackson Kernian, Shauna Kravec, Ben Mann, Neel Nanda, Kamal Ndousse, Catherine Olsson, Daniela Amodei, Tom B. Brown, Jared Kaplan, Sam McCandlish, Christopher Olah, Dario Amodei, Jack Clark
2022 J jnl
CoRR
Deep Ganguli, Danny Hernandez, Liane Lovitt, Nova DasSarma, Tom Henighan, Andy Jones, Nicholas Joseph, Jackson Kernion, Benjamin Mann, Amanda Askell, Yuntao Bai, Anna Chen, Tom Conerly, Dawn Drain, Nelson Elhage, Sheer El Showk, Stanislav Fort, Zac Hatfield-Dodds, Scott Johnston, Shauna Kravec, Neel Nanda, Kamal Ndousse, Catherine Olsson, Daniela Amodei, Dario Amodei, Tom B. Brown, Jared Kaplan, Sam McCandlish, Chris Olah, Jack Clark
2022 J jnl
CoRR
Yuntao Bai, Andy Jones, Kamal Ndousse, Amanda Askell, Anna Chen, Nova DasSarma, Dawn Drain, Stanislav Fort, Deep Ganguli, Tom Henighan, Nicholas Joseph, Saurav Kadavath, Jackson Kernion, Tom Conerly, Sheer El Showk, Nelson Elhage, Zac Hatfield-Dodds, Danny Hernandez, Tristan Hume, Scott Johnston, Shauna Kravec, Liane Lovitt, Neel Nanda, Catherine Olsson, Dario Amodei, Tom B. Brown, Jack Clark, Sam McCandlish, Chris Olah, Benjamin Mann, Jared Kaplan
2021 J jnl
CoRR
Neel Nanda, Jonathan Uesato, Sven Gowal
2021 J jnl
CoRR
Michael K. Cohen, Marcus Hutter, Neel Nanda
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