Skip to content

PE: fix base relocation parser panic #465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 7, 2025
Merged

Conversation

kkent030315
Copy link
Contributor

@kkent030315 kkent030315 commented Apr 14, 2025

  • Fixes base relocation parser panicking on malformed binaries.

Found the issue on the same binary in PR below.

Malformed entity: tls raw data offset (0xae400) and size (0x10) greater than byte slice len (0x415eb)

The base relocation directory 0xB1000..size(0xADAC) does not exists in the binary.

1, .nsp0, 0x400, 0x400, 0, 0x1000, 0xc7000, 792 kB, Code, Initialized data, Executable, Readable, Writeable (0xe0000060), , , , 
2, .nsp1, 0x400, 0x4155a, 260.34 kB, 0xc7000, 0x109000, 264 kB, Code, Initialized data, Executable, Readable, Writeable (0xe0000060), 6e162fbb8f934b424d0f8c91d9a7d78b, 7.98, 6144:3J4KYvxupv2mlkmJhJP7JC9AnruTag4lsFItEnYFupq4gI0:54K+xusn9ArCag9FItEnmupq4gI0, T1E84423B7321D5F00E44C74FBFADD2733B6E7C9F3158AA34A1A612488BE759801DA1167
3, .nsp2, 0x400, 0x400, 0, 0x109000, 0x109562, 1.35 kB, Code, Initialized data, Executable, Readable, Writeable (0xe0000060), , , , 

N.B.
This is the super "special" case where only supposed to happen in this sort of badly "packed" binaries. Proprietary linkers would usually not produce such a completely broken binaries.

Copy link
Owner

@m4b m4b left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One worry j have is proliferation of these flags so that it overwhelms the user or has weird hard to debug affects if multiple settings are changed and they affect parsing in various hard to understand ways, but I don’t think we’re there yet (or ever will be?)

I would like to understand why the te has this set to false otherwise seems reasonable !

src/pe/mod.rs Outdated
opts,
)?);
if opts.parse_basereloc {
if let Some(&baserelocs_dir) =
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be maybe more idiomatic to write something like:

relocation_data = get_base_relocation_data().map(|dir|
RelocationData::parse(bytes, dir, etc))

Sorry for not complete example, on phone. But I think you get the gist of using map here and assigning to relocation data so the Some wraps disappear.

@kkent030315
Copy link
Contributor Author

One worry j have is proliferation of these flags so that it overwhelms the user or has weird hard to debug affects if multiple settings are changed and they affect parsing in various hard to understand ways, but I don’t think we’re there yet (or ever will be?)

I would like to understand why the te has this set to false otherwise seems reasonable !

IMO returning an empty basereloc table in the case of the malformation would be an alternate option, but frankly, I don't like such a fail-silence design that makes debugging harder. However while I don't think basereloc malformation error is ever "useful."

Should we stand by parse_basereloc flag?

@kkent030315
Copy link
Contributor Author

i.e., most PE parsers ignore basereloc malformation and are returning empty info

@chf0x
Copy link
Contributor

chf0x commented Apr 24, 2025

How about we just get .reloc size from the SectionTable when reported size in DIRECTORY is invalid?
Something like this, works well for me: chf0x@3b46c38

@kkent030315
Copy link
Contributor Author

How about we just get .reloc size from the SectionTable when reported size in DIRECTORY is invalid? Something like this, works well for me: chf0x@3b46c38

Hi there. Thank you for your proposal. If I get your solution correct, you're ignoring the invalid range of bytes while parsing the other. That would be an option too but my concern still stands by. The concern is that whether ignoring malformations in such a way isn't a traditional way in goblin. As I mentioned previously, yet it is totally doable particularly this case however.

And specifically for the binary in question, the base relocation directory is completely wrong even if some partial bytes point to the correct range of bytes. This is also my concern if this is confusing to consumers.

@kkent030315
Copy link
Contributor Author

kkent030315 commented Jun 14, 2025

@m4b I reverted the change that introduces parse_basereloc: bool option in ParseOptions. Instead, it should store an empty bytes that implies no-op (so that consumers can parse the rest of binary). Is this acceptable solution?

@kkent030315
Copy link
Contributor Author

The CI failure is not relevant to this change it seems (it is in ELF parser)

@m4b
Copy link
Owner

m4b commented Jun 16, 2025

can this be rebased, the CI failure was fixed

@kkent030315
Copy link
Contributor Author

@m4b Done!

Copy link
Owner

@m4b m4b left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@m4b m4b merged commit 9a87a99 into m4b:master Jul 7, 2025
5 checks passed
@m4b
Copy link
Owner

m4b commented Jul 7, 2025

NB: non-breaking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants