Skip to content

PE file: Forwarded exports #307

Closed
sthagen/lief-project-LIEF
#16
@neitsa

Description

@neitsa

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:

image

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:

image

Describe the solution you'd like

  1. 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).
  2. Complete Solution A boolean in lief.Function indicating if the export is actually forwarded (external) or not (this flag exist in lief.PE.ExportEntry but it's tricky because exported_functions is a list of lief.Function and not of PE.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 👍

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions