lief-project / LIEF

LIEF - Library to Instrument Executable Formats (C++, Python, Rust)
https://lief.re
Apache License 2.0
4.46k stars 622 forks source link

Wrong `e_lfanew` value from PE header when using `lief.PE.Binary`? #675

Closed neitsa closed 2 years ago

neitsa commented 2 years ago

Describe the bug

LIEF reports a wrong value for the e_lfanew PE field (from the DOS_HEADER) when instantiating lief.PE.Binary directly.

To Reproduce

From a windows 10 x64 kernel (10.0.19041.1526).

e_lfanew value is 0x118 (280):

image

Using lief.parse yields a correct result:

>>> import lief
>>> pe_lief = lief.parse(r"c:\windows\system32\ntoskrnl.exe")
PGO: UNKNOWN is not implemented yet!
>>> pe_lief.dos_header.addressof_new_exeheader
280

(as for the error message it might be the same as #560).

Using lief.Binary instead, passing the correct type (lief.PE.PE_TYPE.PE32_PLUS) for the binary, yields a wrong result:

>>> import lief
>>> from lief.PE import Binary
>>> pe_lief = Binary(r"c:\windows\system32\ntoskrnl.exe", lief.PE.PE_TYPE.PE32_PLUS)
>>> pe_lief.dos_header.addressof_new_exeheader
240

I can't really explain the 0n40 (0x28) discrepancy.

Expected behavior

Correct value for e_lfanew when instantiating directly lief.PE.Binary.

The LIEF lief.PE.Binary documentation states:

Class which represents a PE binary This is the main interface to manage and modify a PE executable

I would have expected the same behavior as using the resulting object returned from lief.parse().

As far as understand they should be the same?

Environment (please complete the following information):

romainthomas commented 2 years ago

Hi @neitsa

Actually this is not an error. lief.PE.Binary() is the constructor function for the PE.Binary object while lief.parse and lief.PE.parse effectively parse the given file and provide an instance of lief.PE.Binary.

Nevertheless, the difference comes from the fact that the lief.PE.Binary() constructor initializes the lief.PE.Header (NT Header in CFF) structure right after the DosHeader while there is actually the DOS Stub that prints "This program cannot be run in DOS mode." in the original ntoskrnl.exe.

neitsa commented 2 years ago

Hi @romainthomas! I really do hope you're doing well :)

Ahhhh OK! That's good to know. Thanks a lot for your quick answer and sorry for the bother.

I'm thinking about adding something to the documentation to that effect, but I'm not sure how to phrase it. Do you think this behavior warrants a mention in the doc though?

Let me know; I'll close the issue in a few days.

Once again thanks a lot!

romainthomas commented 2 years ago

I updated the doc :)

neitsa commented 2 years ago

Thanks a lot Romain! Closing the issue :)