From 6e0f942f0fdd84c90a5b4c1491ce88d7afd84d80 Mon Sep 17 00:00:00 2001 From: MiniRML <134226498+MiniRML@users.noreply.github.com> Date: Mon, 12 Oct 2026 09:36:42 -0700 Subject: [PATCH 1/4] fix(nid): resolve PE reference exports through their ordinals --- core/libs/CMakeLists.txt | 2 + core/libs/nid/src/ExportExclusions.cpp | 11 ++++ core/libs/nid/tests/test_pe_references.py | 69 +++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 core/libs/nid/tests/test_pe_references.py diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index d094f39cf..d678c2910 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -163,6 +163,8 @@ if(BUILD_TESTING) endif() find_package(Python3 QUIET COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) + add_test(NAME nid_pe_references COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_pe_references.py $) add_test(NAME nid_patcher_macho COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_macho_nids.py $) endif() diff --git a/core/libs/nid/src/ExportExclusions.cpp b/core/libs/nid/src/ExportExclusions.cpp index 9c00d6b3e..9c2192699 100644 --- a/core/libs/nid/src/ExportExclusions.cpp +++ b/core/libs/nid/src/ExportExclusions.cpp @@ -49,7 +49,12 @@ std::unordered_set ReadPeExports(const std::vector& b if (!directory.VirtualAddress || directory.Size < sizeof(PeExportDirectory)) throw std::runtime_error("missing reference PE exports"); const auto sections = optional + optionalSize; RequireRange(binary, sections, std::uint64_t{sectionCount} * sizeof(PeSectionHeader)); + const auto headersSize = ReadValue(binary, optional + 60); const auto mapRva = [&](std::uint32_t rva, std::uint64_t size) -> std::uint64_t { + if (rva < headersSize && size <= headersSize - rva) { + RequireRange(binary, rva, size); + return rva; + } for (std::uint16_t index = 0; index < sectionCount; ++index) { const auto section = ReadValue(binary, sections + std::uint64_t{index} * sizeof(PeSectionHeader)); if (rva < section.VirtualAddress) continue; @@ -64,14 +69,20 @@ std::unordered_set ReadPeExports(const std::vector& b const auto table = ReadValue(binary, mapRva(directory.VirtualAddress, sizeof(PeExportDirectory))); if (!table.NumberOfNames) throw std::runtime_error("reference PE has no named exports"); const auto names = mapRva(table.AddressOfNames, std::uint64_t{table.NumberOfNames} * 4); + const auto ordinals = mapRva(table.AddressOfNameOrdinals, std::uint64_t{table.NumberOfNames} * 2); + const auto functions = mapRva(table.AddressOfFunctions, std::uint64_t{table.NumberOfFunctions} * 4); std::unordered_set result; for (std::uint32_t index = 0; index < table.NumberOfNames; ++index) { + const auto ordinal = ReadValue(binary, ordinals + std::uint64_t{index} * 2); + if (ordinal >= table.NumberOfFunctions) throw std::runtime_error("invalid reference PE export ordinal"); + if (!ReadValue(binary, functions + std::uint64_t{ordinal} * 4)) continue; const auto rva = ReadValue(binary, names + std::uint64_t{index} * 4); const auto offset = mapRva(rva, 1); auto name = ReadName(binary, offset, binary.size() - offset); mapRva(rva, name.size() + 1); if (!result.insert(name).second) throw std::runtime_error("duplicate reference export: " + name); } + if (result.empty()) throw std::runtime_error("reference PE has no named exports"); return result; } diff --git a/core/libs/nid/tests/test_pe_references.py b/core/libs/nid/tests/test_pe_references.py new file mode 100644 index 000000000..44cb4f974 --- /dev/null +++ b/core/libs/nid/tests/test_pe_references.py @@ -0,0 +1,69 @@ +import struct +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + +from test_macho_nids import build_dylib, exports_of, nid + + +def reference(*, headers=False, address=0x2000, ordinal=0): + image = bytearray(1280) + image[:2] = b"MZ" + struct.pack_into(" Date: Mon, 12 Oct 2026 09:57:43 -0700 Subject: [PATCH 2/4] test(nid): avoid competing hash test registration --- core/libs/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index d678c2910..85e1b872b 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -163,10 +163,10 @@ if(BUILD_TESTING) endif() find_package(Python3 QUIET COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) - add_test(NAME nid_pe_references COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_pe_references.py $) add_test(NAME nid_patcher_macho COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_macho_nids.py $) + add_test(NAME nid_pe_references COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_pe_references.py $) endif() add_test_executable(patched_libraries_tests tests/PatchedLibraries.cpp) add_dependencies(patched_libraries_tests libs) From 1c500fb298ecb81e9cf35cc7c68359aa04797b66 Mon Sep 17 00:00:00 2001 From: MiniRML <134226498+MiniRML@users.noreply.github.com> Date: Mon, 12 Oct 2026 09:59:52 -0700 Subject: [PATCH 3/4] test(nid): separate export-reference registration from path tests --- core/libs/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index 85e1b872b..b069cb7fb 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -163,11 +163,13 @@ if(BUILD_TESTING) endif() find_package(Python3 QUIET COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) - add_test(NAME nid_patcher_macho COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_macho_nids.py $) add_test(NAME nid_pe_references COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_pe_references.py $) endif() + if(Python3_Interpreter_FOUND) + add_test(NAME nid_patcher_macho COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_macho_nids.py $) + endif() add_test_executable(patched_libraries_tests tests/PatchedLibraries.cpp) add_dependencies(patched_libraries_tests libs) if(MINGW) From ad43a486f093527d3274bb0047366432452c251d Mon Sep 17 00:00:00 2001 From: MiniRML <134226498+MiniRML@users.noreply.github.com> Date: Mon, 12 Oct 2026 10:00:50 -0700 Subject: [PATCH 4/4] test(nid): keep reference registration independent of other topics --- core/libs/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index b069cb7fb..3dc2f302b 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -162,16 +162,16 @@ if(BUILD_TESTING) "PATH=path_list_prepend:$") endif() find_package(Python3 QUIET COMPONENTS Interpreter) - if(Python3_Interpreter_FOUND) - add_test(NAME nid_pe_references COMMAND ${Python3_EXECUTABLE} - ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_pe_references.py $) - endif() if(Python3_Interpreter_FOUND) add_test(NAME nid_patcher_macho COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_macho_nids.py $) endif() add_test_executable(patched_libraries_tests tests/PatchedLibraries.cpp) add_dependencies(patched_libraries_tests libs) + if(Python3_Interpreter_FOUND) + add_test(NAME nid_pe_references COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_pe_references.py $) + endif() if(MINGW) target_compile_options(patched_libraries_tests PRIVATE -fasynchronous-unwind-tables) target_link_options(patched_libraries_tests PRIVATE -static -static-libgcc -static-libstdc++)