binarly-io / fwhunt-scan

Tools for analyzing UEFI firmware and checking UEFI modules with FwHunt rules
GNU General Public License v3.0
214 stars 30 forks source link

Calling UefiAnalyzer(blob) on non-PE data takes a LOOONG time to finish #29

Closed hughsie closed 2 years ago

hughsie commented 3 years ago

When you use UefiAnalyzer() on a small EFI binary it typically finishes in about 100ms. If you ask UefiAnalyzer() to analyse something that's not a PE file (e.g. a jpg, or a zip file, or a ROM image, or just some text) then it takes a long time to process the file. Like minutes per file.

echo "hello world" > foo2.efi
./env/bin/python ./foo.py

where foo.py is just:

from uefi_r2 import UefiAnalyzer
with open("./foo2.efi", "rb") as f:
    with UefiAnalyzer(blob=f.read()) as uefi_analyzer:
    print(uefi_analyzer.get_summary())

eventually it outputs:

{'core': {'file': 'shm://psm_07173507', 'fd': 3, 'size': 4294967295, 'humansz': '4.0G', 'iorw': False, 'mode': 'r-x', 'block': 256, 'format': 'any'}}

I assume it's just read 4G of data....

yeggor commented 3 years ago

I suppose the reason is that uefi_r2 now parses binaries not by functions (as it was before), but by instructions (since r2/rizin does not define all functions for EFI binaries due to the large number of callbacks inside). A possible solution would be to check the file type before analyzing.

hughsie commented 3 years ago

A possible solution would be to check the file type before analyzing.

If it helps, my workaround is:

if blob[0:2] != b"MZ":
    return
yeggor commented 3 years ago

Yes, I am talking about just such a check. But I was wrong, the main problem is not on the uefi_r2 side (with file instead of blob it works fine), we need to report it to the rizin.

yeggor commented 3 years ago

@hughsie what do you think, raise exception is good or will better to return empty result in get_summary()?

hughsie commented 3 years ago

Well, I can catch the exception -- that's probably the most sane thing to do.

yeggor commented 3 years ago

Uploaded in PyPI: https://pypi.org/project/uefi-r2/1.1.2/

hughsie commented 3 years ago

Don;t you need to export AnalyzerError in init.py?

hughsie commented 3 years ago

And maybe it should be called UefiAnalyzerError?

yeggor commented 3 years ago

It make sense, thank you

yeggor commented 3 years ago

@hughsie https://github.com/binarly-io/uefi_r2/commit/1de6907fddecdd284cb79bed0057d01b561a74eb https://pypi.org/project/uefi-r2/1.1.3/

XVilka commented 2 years ago

It is because sometimes the size of the shared memory is bigger than requested by the file. In our tests we solved this problem by allowing to specify the size of the object passed via shm:// right in the URI:

For example, something like shm://bla/4096

It should work not only in dev but also on stable, which is now released as 0.3.1. Let me know if that is a good enough for you.

yeggor commented 2 years ago

@XVilka, thank you