GP-2577 fix problem handling Elf32 missing sections / headers

The special flag for offset values (-1) wasn't being recognized in 32bit binaries, causing the ELF loader to try to read from index 4294967295, causing an exception:

java.io.IOException: Invalid index: 4294967295
This commit is contained in:
dev747368 2022-09-22 14:09:33 -04:00
parent 2113bdc8b1
commit 6be23f64a2
7 changed files with 57 additions and 38 deletions

View file

@ -188,10 +188,8 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
cu.setComment(CodeUnit.PLATE_COMMENT,
"#" + i + ") " + name + " at 0x" + Long.toHexString(sections[i].getAddress()));
if (sections[i].getSize() == 0) {
continue;
}
if (sections[i].getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
if (sections[i].getType() == ElfSectionHeaderConstants.SHT_NOBITS ||
sections[i].getSize() == 0 || sections[i].isInvalidOffset()) {
continue;
}

View file

@ -518,4 +518,9 @@ public interface ElfConstants {
*/
public static final short PN_XNUM = (short) 0xffff;
/**
* 32bit "-1", used in 32bit files to signal an invalid offset
*/
public static final long ELF32_INVALID_OFFSET = 0xFFFFFFFFL;
}

View file

@ -143,7 +143,7 @@ public class ElfDefaultGotPltMarkup {
ElfProgramHeader relocTableLoadHeader =
elf.getProgramLoadHeaderContaining(relocTableAddr);
if (relocTableLoadHeader == null || relocTableLoadHeader.getOffset() < 0) {
if (relocTableLoadHeader == null || relocTableLoadHeader.isInvalidOffset()) {
return;
}
long relocTableOffset = relocTableLoadHeader.getOffset(relocTableAddr);

View file

@ -532,7 +532,7 @@ public class ElfHeader implements StructConverter, Writeable {
" linked to symbol table section " + symbolTableSection.getNameAsString() +
" affecting " + relocaBaseName);
if (section.getOffset() < 0) {
if (section.isInvalidOffset()) {
return;
}
@ -614,7 +614,7 @@ public class ElfHeader implements StructConverter, Writeable {
Long.toHexString(relocTableAddr));
return;
}
if (relocTableLoadHeader.getOffset() < 0) {
if (relocTableLoadHeader.isInvalidOffset()) {
return;
}
@ -881,7 +881,7 @@ public class ElfHeader implements StructConverter, Writeable {
for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) {
if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
if (symbolTableSectionHeader.getOffset() < 0) {
if (symbolTableSectionHeader.isInvalidOffset()) {
continue;
}
@ -1621,7 +1621,8 @@ public class ElfHeader implements StructConverter, Writeable {
long fileRangeLength) {
long maxOffset = fileOffset + fileRangeLength - 1;
for (ElfSectionHeader section : sectionHeaders) {
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL) {
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL ||
section.isInvalidOffset()) {
continue;
}
long size = section.getSize();
@ -1748,7 +1749,8 @@ public class ElfHeader implements StructConverter, Writeable {
public ElfProgramHeader getProgramLoadHeaderContainingFileOffset(long offset) {
for (ElfProgramHeader programHeader : programHeaders) {
if (programHeader == null ||
programHeader.getType() != ElfProgramHeaderConstants.PT_LOAD) {
programHeader.getType() != ElfProgramHeaderConstants.PT_LOAD ||
programHeader.isInvalidOffset()) {
continue;
}
long start = programHeader.getOffset();

View file

@ -15,9 +15,10 @@
*/
package ghidra.app.util.bin.format.elf;
import java.util.HashMap;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
@ -315,6 +316,15 @@ public class ElfProgramHeader
return p_offset;
}
/**
* Return true if this program header's offset is invalid.
*
* @return true if this program header's offset is invalid
*/
public boolean isInvalidOffset() {
return p_offset < 0 || (header.is32Bit() && p_offset == ElfConstants.ELF32_INVALID_OFFSET);
}
/**
* Compute the file offset associated with the specified loaded virtual address
* defined by this PT_LOAD program header. This can be useful when attempting to locate

View file

@ -15,9 +15,10 @@
*/
package ghidra.app.util.bin.format.elf;
import java.io.*;
import java.util.HashMap;
import java.io.*;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.StructConverter;
import ghidra.app.util.bin.format.MemoryLoadable;
@ -338,8 +339,8 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
try {
if (sh_name >= 0 && e_shstrndx > 0 && e_shstrndx < sections.length) {
// read section name from string table
long stringTableOffset = sections[e_shstrndx].getOffset();
if (stringTableOffset >= 0) {
if (!sections[e_shstrndx].isInvalidOffset()) {
long stringTableOffset = sections[e_shstrndx].getOffset();
long offset = stringTableOffset + sh_name;
if (offset < reader.length()) {
name = reader.readAsciiString(stringTableOffset + sh_name);
@ -396,6 +397,16 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
return sh_offset;
}
/**
* Returns true if this section header's offset is invalid.
*
* @return true if this section header's offset is invalid
*/
public boolean isInvalidOffset() {
return sh_offset < 0 ||
(header.is32Bit() && sh_offset == ElfConstants.ELF32_INVALID_OFFSET);
}
/**
* Sets the section's size.
* @param size the new size of the section

View file

@ -15,11 +15,12 @@
*/
package ghidra.app.util.opinion;
import java.util.*;
import java.io.*;
import java.math.BigInteger;
import java.nio.file.AccessMode;
import java.text.NumberFormat;
import java.util.*;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.apache.commons.lang3.StringUtils;
@ -224,30 +225,26 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
for (ElfProgramHeader segment : segments) {
monitor.checkCanceled();
monitor.incrementProgress(1);
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) {
long size = segment.getFileSize();
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL ||
segment.isInvalidOffset() || size <= 0) {
continue;
}
long size = segment.getFileSize();
long offset = segment.getOffset();
if (size > 0) {
fileMap.paintRange(offset, offset + size - 1, -2); // -2: used by segment
}
fileMap.paintRange(offset, offset + size - 1, -2); // -2: used by segment
}
for (ElfSectionHeader section : sections) {
monitor.checkCanceled();
monitor.incrementProgress(1);
long size = section.getSize();
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL ||
section.getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
section.getType() == ElfSectionHeaderConstants.SHT_NOBITS ||
section.isInvalidOffset() || size <= 0) {
continue;
}
section.getSize();
section.getOffset();
long size = section.getSize();
long offset = section.getOffset();
if (size > 0) {
fileMap.paintRange(offset, offset + size - 1, -3); // -3: used by section
}
fileMap.paintRange(offset, offset + size - 1, -3); // -3: used by section
}
// Ignore header regions which will always be allocated to blocks
@ -2769,13 +2766,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// Locate possible load of Elf header within section (i.e., start of file)
Address headerAddr = null;
for (ElfSectionHeader section : elf.getSections()) {
if (section.getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
if (section.getType() == ElfSectionHeaderConstants.SHT_NOBITS ||
section.isInvalidOffset()) {
continue;
}
long startOffset = section.getOffset();
if (startOffset < 0) {
continue;
}
long endOffset = startOffset + section.getSize() - 1;
if (fileOffset >= startOffset && headerEndOffset <= endOffset) {
headerAddr = findLoadAddress(section, fileOffset - section.getOffset());
@ -2787,13 +2782,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// Locate possible load of Elf header within segment
for (ElfProgramHeader segment : elf.getProgramHeaders()) {
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) {
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL ||
segment.isInvalidOffset()) {
continue;
}
long startOffset = segment.getOffset();
if (startOffset < 0) {
continue;
}
long endOffset = startOffset + segment.getFileSize() - 1;
if (fileOffset >= startOffset && headerEndOffset <= endOffset) {
headerAddr = findLoadAddress(segment, fileOffset - segment.getOffset());
@ -2948,7 +2941,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
if (!includeOtherBlocks) {
continue;
}
if (fileOffset < 0 || fileOffset >= fileBytes.getSize()) {
if (elfProgramHeader.isInvalidOffset() || fileOffset >= fileBytes.getSize()) {
log("Skipping segment[" + i + ", " + elfProgramHeader.getDescription() +
"] with invalid file offset");
continue;
@ -2964,7 +2957,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
continue;
}
}
if (fileOffset < 0 || fileOffset >= fileBytes.getSize()) {
if (elfProgramHeader.isInvalidOffset() || fileOffset >= fileBytes.getSize()) {
log("Skipping PT_LOAD segment[" + i + ", " + elfProgramHeader.getDescription() +
"] with invalid file offset");
continue;
@ -3168,7 +3161,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
(includeOtherBlocks || elfSectionToLoad.isAlloc())) {
long fileOffset = elfSectionToLoad.getOffset();
if (type != ElfSectionHeaderConstants.SHT_NOBITS &&
(fileOffset < 0 || fileOffset >= fileBytes.getSize())) {
(elfSectionToLoad.isInvalidOffset() || fileOffset >= fileBytes.getSize())) {
log("Skipping section [" + elfSectionToLoad.getNameAsString() +
"] with invalid file offset 0x" + Long.toHexString(fileOffset));
continue;