Environment information
- Operating System: Windows 11
- Cutter version: 2.4.1-HEAD-a5f88d1
- Rizin version: rizin 0.8.1 @ windows-x86-64 commit: c009cb739ca4fd289e634c2bea432d1e7bcd3676
- Obtained from:
- File format: Windows PE
Bug Description
When resolving ordinals in the Import Table, Cutter seems to assume a hardcoded OrdinalBase of 1, even though the actual OrdinalBase is 2 in the specific DLL (OLEAUT32.dll) I am analyzing.
To Reproduce
Inspect the Import Table of a program that imports functions from OLEAUT32.dll by ordinal (where functions are stored by their ordinal numbers instead of names).
Example Analysis:
In the .idata section at address 0x006986d4, the value is .dword 0x8000008d.
The raw ordinal value is 0x8d (141).
In this specific version of OLEAUT32.dll, the OrdinalBase is 0x2.
Therefore, the actual OrdinalIndex should be: 0x8d - 0x2 = 0x8b (139).
If we look up the key corresponding to OrdinalIndex 0x8b in the OrdinalNameTable of OLEAUT32.dll, we find it points to the 116th entry. Checking the ExportNameTable[116] reveals the function name: "VarAdd".
Verification with Binary Ninja:
To verify my manual calculation, I checked the same address in Binary Ninja, which correctly identifies the function:
006986d4 HRESULT (__stdcall* const OLEAUT32:VarAdd)(...) = VarAdd
Cutter's Incorrect Result:
However, Cutter interprets this address as:
;-- VarAnd:
Root Cause Analysis:
Cutter appears to be incorrectly assuming an OrdinalBase of 1. Let's test this hypothesis:
If OrdinalBase is assumed to be 1: 0x8d - 0x1 = 0x8c (140).
The key for 0x8c in the OrdinalNameTable points to index 117.
ExportNameTable[117] in this DLL is "VarAnd".
This confirms that Cutter is incorrectly resolving the import because it fails to respect the actual OrdinalBase defined in the DLL's Export Directory.
Screenshots
BinaryNinja ss:

Cutter ss:

Another example comparing Binary Ninja and Cutter within the disassembler view:
Cutter:

BinaryNinja:

Environment information
Bug Description
When resolving ordinals in the Import Table, Cutter seems to assume a hardcoded OrdinalBase of 1, even though the actual OrdinalBase is 2 in the specific DLL (OLEAUT32.dll) I am analyzing.
To Reproduce
Inspect the Import Table of a program that imports functions from OLEAUT32.dll by ordinal (where functions are stored by their ordinal numbers instead of names).
Example Analysis:
In the .idata section at address 0x006986d4, the value is .dword 0x8000008d.
The raw ordinal value is 0x8d (141).
In this specific version of OLEAUT32.dll, the OrdinalBase is 0x2.
Therefore, the actual OrdinalIndex should be: 0x8d - 0x2 = 0x8b (139).
If we look up the key corresponding to OrdinalIndex 0x8b in the OrdinalNameTable of OLEAUT32.dll, we find it points to the 116th entry. Checking the ExportNameTable[116] reveals the function name: "VarAdd".
Verification with Binary Ninja:
To verify my manual calculation, I checked the same address in Binary Ninja, which correctly identifies the function:
006986d4 HRESULT (__stdcall* const OLEAUT32:VarAdd)(...) = VarAdd
Cutter's Incorrect Result:
However, Cutter interprets this address as:
;-- VarAnd:
Root Cause Analysis:
Cutter appears to be incorrectly assuming an OrdinalBase of 1. Let's test this hypothesis:
If OrdinalBase is assumed to be 1: 0x8d - 0x1 = 0x8c (140).
The key for 0x8c in the OrdinalNameTable points to index 117.
ExportNameTable[117] in this DLL is "VarAnd".
This confirms that Cutter is incorrectly resolving the import because it fails to respect the actual OrdinalBase defined in the DLL's Export Directory.
Screenshots

BinaryNinja ss:
Cutter ss:

Another example comparing Binary Ninja and Cutter within the disassembler view:

Cutter:
BinaryNinja: