NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
51.28k stars 5.84k forks source link

ELF unlinked object relocation with negative offsets gets invalid references #1391

Open GovanifY opened 4 years ago

GovanifY commented 4 years ago

Describe the bug When analyzing an unlinked object ELF file using negative offsets you can have invalid references which are not correctly calculated from the relocatable adresses.

To Reproduce Steps to reproduce the behavior:

  1. Import the file attached in ghidra
  2. Analyze and go to hvqm2Init2
  3. All offsets below 0x10000(if chosen as your base address) will be invalid references.

Expected behavior Stop having invalid references to unknown memory spaces in the decompiler.

Attachments weird.tar.gz

Environment:

Additional context Capstone, objdump and IDA seems to all have pretty weird takes when it comes to the decoding of the sb and lui instructions in said function. I confirmed by calculating by hand the values from the ISA that Ghidra's output is correct though, so that's pretty surprising. IDA also loads everything at address 0 and do not calculate the negative offsets: if loaded at base address 0 Ghidra will return 0xffff9f2d while at default it will return 0x9f2d. IDA apparently uses 0x9f3d for no reason(?) but the memory mapping seems correct and puts it into the .bss section relocation.

GovanifY commented 4 years ago

Actually both Ghidra and IDA seems to patch the binary when analyzing it(!!!), the original bytes of the sb instruction being a0243f5d, so the original 16bit signed value being a 3f5b, while ghidra patches it to 9f2d and IDA 9f3d. I don't think patching the binary during analysis is a wanted feature so I'm bringing that up too.

mumbel commented 4 years ago

the relocation patching is most definitely by design and not a bug

GovanifY commented 4 years ago

Gotcha, this still leaves the relocation being done differently in IDA vs Ghidra by 0x10, and the memory mapping being wholly different

mumbel commented 4 years ago

Just FYI, there is a relocation table (Window->Relocation Table) where you can see the original bytes and some info on the relocation.

this is a R_MIPS_HI16 / R_MIPS_LO16 pair at 0x15f20 and 0x15f24 https://github.com/NationalSecurityAgency/ghidra/blob/cbe5b9e9cae03ce4dea117799afc03e4ad32a488/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationConstants.java#L25

You might debug your way through: https://github.com/NationalSecurityAgency/ghidra/blob/cbe5b9e9cae03ce4dea117799afc03e4ad32a488/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationHandler.java#L351 and https://github.com/NationalSecurityAgency/ghidra/blob/cbe5b9e9cae03ce4dea117799afc03e4ad32a488/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationHandler.java#L360 to see where your issue might be in one of those 2 relocations

astrelsky commented 4 years ago

the relocation patching is most definitely by design and not a bug

This is further supported by the relocation table. When you open the relocation table it shows the original bytes that were there.