al3xtjames / ghidra-firmware-utils

Ghidra utilities for analyzing PC firmware
Other
386 stars 43 forks source link

UEFIHelper.java exception with position-independent PE32's #13

Open zznop opened 3 years ago

zznop commented 3 years ago

If a UEFI PE32 module is built position-independent, Ghidra loads it at 0x10000. When it searches for global assignments, it finds the SystemTable->BootServices, which in almost every case is somewhere before 0x10000 because it's based on the PE being loaded at 0. It then tries to apply a type before the base of the PE raising an exception that resembles the following:

> Error running script: UEFIHelper.java
ghidra.program.model.util.CodeUnitInsertionException: Insufficent memory at address 0000146c (length: 4 bytes)
        at ghidra.program.database.code.CodeManager.checkValidAddressRange(CodeManager.java:1916)
        ...
        UEFIHelper.defineData(UEFIHelper.java:138)
        ...

There is a simple workaround: upon loading the PE32 click the Memory Map and rebase the binary to 0x0. However, I think you can also address this in code by detecting if the PE32 is position-independent in UEFIHelper.java and rebase to 0x0 automatically, or add Ghidra's 0x10000 default base address to resolve the correct location of global variables.

al3xtjames commented 3 years ago

Thanks for reporting this. Do you have an example binary which reproduces this issue?

zznop commented 3 years ago

Unfortunately, I don't have a binary that I can share at the moment. When I have the time, I'll look through online firmware samples or try to build a module from edk2 and report back.

zznop commented 3 years ago

I think the issue only effects x86 PE32's, not x86-64. A position-independent x86-64 PE32 loads fine in my testing. Unfortunately, the only firmware samples I can find online only contain 32-bit UEFI modules.