Description
Is your feature request related to a problem? Please describe.
Unless I'm mistaken, as of LIEF 0.10.0-9dd9ded
when parsing exported functions from a PE shared library, there's no (easy) way to know - when an export is forwarded - to which DLL the export function is forwarded to and what its name in the forwarded DLL.
[edit] This export forwarding mechanism is explained in the PE specification here and is called "Forwarder RVA".
As of now the address
member is just 0.
Example with kernel32
from windows 10.
>>> binary = lief.parse(r"c:\windows\system32\kernel32.dll")
>>> exports = binary.get_export()
>>> entry = next(exports.entries)
>>> entry.name
'AcquireSRWLockExclusive'
>>> entry.address
0
The same goes for the exported_functions
member.
>>> entry = binary.exported_functions[0]
>>> entry.name
'AcquireSRWLockExclusive'
>>> entry.address
0
Let's take the same example with AcquireSRWLockExclusive
.
The function RVA is 0x92c6f:
Given the export table start and size:
>>> exp_table = binary.data_directory(lief.PE.DATA_DIRECTORY.EXPORT_TABLE)
>>> f"table: {exp_table.rva:#x} ; size: {exp_table.size:#x} (end: {exp_table.rva + exp_table.size:#x})"
'table: 0x8ec80 ; size: 0xdd40 (end: 0x9c9c0)'
We can see that the exported function RVA (0x92c6f) is within the bounds of the export table.
The RVA translated to an offset gives 0x9186f, at which we find the forwarder string (namely NTDLL.RtlAcquireSRWLockExclusive
:
Describe the solution you'd like
- Simple solution: Give the function RVA, even if it's an external function (at least this gives the user a way to parse the forwarder string by themselves).
- Complete Solution A boolean in
lief.Function
indicating if the export is actually forwarded (external) or not (this flag exist inlief.PE.ExportEntry
but it's tricky becauseexported_functions
is a list oflief.Function
and not ofPE.ExportEntry
). If the export is forwarded, the name of the DLL and the forwaded function name.
Describe alternatives you've considered
Parsing everything manually as demonstrated above. It's a bit tedious.
Additional context
I can give you a hand on implementing this if you want to talk about it 👍