mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-09-13 21:56:19 +00:00
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:
parent
2113bdc8b1
commit
6be23f64a2
|
@ -188,10 +188,8 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
|
||||||
cu.setComment(CodeUnit.PLATE_COMMENT,
|
cu.setComment(CodeUnit.PLATE_COMMENT,
|
||||||
"#" + i + ") " + name + " at 0x" + Long.toHexString(sections[i].getAddress()));
|
"#" + i + ") " + name + " at 0x" + Long.toHexString(sections[i].getAddress()));
|
||||||
|
|
||||||
if (sections[i].getSize() == 0) {
|
if (sections[i].getType() == ElfSectionHeaderConstants.SHT_NOBITS ||
|
||||||
continue;
|
sections[i].getSize() == 0 || sections[i].isInvalidOffset()) {
|
||||||
}
|
|
||||||
if (sections[i].getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -518,4 +518,9 @@ public interface ElfConstants {
|
||||||
*/
|
*/
|
||||||
public static final short PN_XNUM = (short) 0xffff;
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ public class ElfDefaultGotPltMarkup {
|
||||||
|
|
||||||
ElfProgramHeader relocTableLoadHeader =
|
ElfProgramHeader relocTableLoadHeader =
|
||||||
elf.getProgramLoadHeaderContaining(relocTableAddr);
|
elf.getProgramLoadHeaderContaining(relocTableAddr);
|
||||||
if (relocTableLoadHeader == null || relocTableLoadHeader.getOffset() < 0) {
|
if (relocTableLoadHeader == null || relocTableLoadHeader.isInvalidOffset()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long relocTableOffset = relocTableLoadHeader.getOffset(relocTableAddr);
|
long relocTableOffset = relocTableLoadHeader.getOffset(relocTableAddr);
|
||||||
|
|
|
@ -532,7 +532,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
" linked to symbol table section " + symbolTableSection.getNameAsString() +
|
" linked to symbol table section " + symbolTableSection.getNameAsString() +
|
||||||
" affecting " + relocaBaseName);
|
" affecting " + relocaBaseName);
|
||||||
|
|
||||||
if (section.getOffset() < 0) {
|
if (section.isInvalidOffset()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +614,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
Long.toHexString(relocTableAddr));
|
Long.toHexString(relocTableAddr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (relocTableLoadHeader.getOffset() < 0) {
|
if (relocTableLoadHeader.isInvalidOffset()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,7 +881,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) {
|
for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) {
|
||||||
if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
|
if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
|
||||||
symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
|
symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
|
||||||
if (symbolTableSectionHeader.getOffset() < 0) {
|
if (symbolTableSectionHeader.isInvalidOffset()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1621,7 +1621,8 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
long fileRangeLength) {
|
long fileRangeLength) {
|
||||||
long maxOffset = fileOffset + fileRangeLength - 1;
|
long maxOffset = fileOffset + fileRangeLength - 1;
|
||||||
for (ElfSectionHeader section : sectionHeaders) {
|
for (ElfSectionHeader section : sectionHeaders) {
|
||||||
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL) {
|
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL ||
|
||||||
|
section.isInvalidOffset()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long size = section.getSize();
|
long size = section.getSize();
|
||||||
|
@ -1748,7 +1749,8 @@ public class ElfHeader implements StructConverter, Writeable {
|
||||||
public ElfProgramHeader getProgramLoadHeaderContainingFileOffset(long offset) {
|
public ElfProgramHeader getProgramLoadHeaderContainingFileOffset(long offset) {
|
||||||
for (ElfProgramHeader programHeader : programHeaders) {
|
for (ElfProgramHeader programHeader : programHeaders) {
|
||||||
if (programHeader == null ||
|
if (programHeader == null ||
|
||||||
programHeader.getType() != ElfProgramHeaderConstants.PT_LOAD) {
|
programHeader.getType() != ElfProgramHeaderConstants.PT_LOAD ||
|
||||||
|
programHeader.isInvalidOffset()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long start = programHeader.getOffset();
|
long start = programHeader.getOffset();
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.elf;
|
package ghidra.app.util.bin.format.elf;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
|
@ -315,6 +316,15 @@ public class ElfProgramHeader
|
||||||
return p_offset;
|
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
|
* 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
|
* defined by this PT_LOAD program header. This can be useful when attempting to locate
|
||||||
|
|
|
@ -15,9 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.elf;
|
package ghidra.app.util.bin.format.elf;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.app.util.bin.format.MemoryLoadable;
|
import ghidra.app.util.bin.format.MemoryLoadable;
|
||||||
|
@ -338,8 +339,8 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
|
||||||
try {
|
try {
|
||||||
if (sh_name >= 0 && e_shstrndx > 0 && e_shstrndx < sections.length) {
|
if (sh_name >= 0 && e_shstrndx > 0 && e_shstrndx < sections.length) {
|
||||||
// read section name from string table
|
// read section name from string table
|
||||||
long stringTableOffset = sections[e_shstrndx].getOffset();
|
if (!sections[e_shstrndx].isInvalidOffset()) {
|
||||||
if (stringTableOffset >= 0) {
|
long stringTableOffset = sections[e_shstrndx].getOffset();
|
||||||
long offset = stringTableOffset + sh_name;
|
long offset = stringTableOffset + sh_name;
|
||||||
if (offset < reader.length()) {
|
if (offset < reader.length()) {
|
||||||
name = reader.readAsciiString(stringTableOffset + sh_name);
|
name = reader.readAsciiString(stringTableOffset + sh_name);
|
||||||
|
@ -396,6 +397,16 @@ public class ElfSectionHeader implements StructConverter, Writeable, MemoryLoada
|
||||||
return sh_offset;
|
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.
|
* Sets the section's size.
|
||||||
* @param size the new size of the section
|
* @param size the new size of the section
|
||||||
|
|
|
@ -15,11 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.opinion;
|
package ghidra.app.util.opinion;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.file.AccessMode;
|
import java.nio.file.AccessMode;
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
|
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -224,30 +225,26 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
for (ElfProgramHeader segment : segments) {
|
for (ElfProgramHeader segment : segments) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) {
|
long size = segment.getFileSize();
|
||||||
|
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL ||
|
||||||
|
segment.isInvalidOffset() || size <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long size = segment.getFileSize();
|
|
||||||
long offset = segment.getOffset();
|
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) {
|
for (ElfSectionHeader section : sections) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
monitor.incrementProgress(1);
|
monitor.incrementProgress(1);
|
||||||
|
long size = section.getSize();
|
||||||
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL ||
|
if (section.getType() == ElfSectionHeaderConstants.SHT_NULL ||
|
||||||
section.getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
|
section.getType() == ElfSectionHeaderConstants.SHT_NOBITS ||
|
||||||
|
section.isInvalidOffset() || size <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
section.getSize();
|
|
||||||
section.getOffset();
|
|
||||||
long size = section.getSize();
|
|
||||||
long offset = section.getOffset();
|
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
|
// 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)
|
// Locate possible load of Elf header within section (i.e., start of file)
|
||||||
Address headerAddr = null;
|
Address headerAddr = null;
|
||||||
for (ElfSectionHeader section : elf.getSections()) {
|
for (ElfSectionHeader section : elf.getSections()) {
|
||||||
if (section.getType() == ElfSectionHeaderConstants.SHT_NOBITS) {
|
if (section.getType() == ElfSectionHeaderConstants.SHT_NOBITS ||
|
||||||
|
section.isInvalidOffset()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long startOffset = section.getOffset();
|
long startOffset = section.getOffset();
|
||||||
if (startOffset < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
long endOffset = startOffset + section.getSize() - 1;
|
long endOffset = startOffset + section.getSize() - 1;
|
||||||
if (fileOffset >= startOffset && headerEndOffset <= endOffset) {
|
if (fileOffset >= startOffset && headerEndOffset <= endOffset) {
|
||||||
headerAddr = findLoadAddress(section, fileOffset - section.getOffset());
|
headerAddr = findLoadAddress(section, fileOffset - section.getOffset());
|
||||||
|
@ -2787,13 +2782,11 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
|
|
||||||
// Locate possible load of Elf header within segment
|
// Locate possible load of Elf header within segment
|
||||||
for (ElfProgramHeader segment : elf.getProgramHeaders()) {
|
for (ElfProgramHeader segment : elf.getProgramHeaders()) {
|
||||||
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL) {
|
if (segment.getType() == ElfProgramHeaderConstants.PT_NULL ||
|
||||||
|
segment.isInvalidOffset()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long startOffset = segment.getOffset();
|
long startOffset = segment.getOffset();
|
||||||
if (startOffset < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
long endOffset = startOffset + segment.getFileSize() - 1;
|
long endOffset = startOffset + segment.getFileSize() - 1;
|
||||||
if (fileOffset >= startOffset && headerEndOffset <= endOffset) {
|
if (fileOffset >= startOffset && headerEndOffset <= endOffset) {
|
||||||
headerAddr = findLoadAddress(segment, fileOffset - segment.getOffset());
|
headerAddr = findLoadAddress(segment, fileOffset - segment.getOffset());
|
||||||
|
@ -2948,7 +2941,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
if (!includeOtherBlocks) {
|
if (!includeOtherBlocks) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fileOffset < 0 || fileOffset >= fileBytes.getSize()) {
|
if (elfProgramHeader.isInvalidOffset() || fileOffset >= fileBytes.getSize()) {
|
||||||
log("Skipping segment[" + i + ", " + elfProgramHeader.getDescription() +
|
log("Skipping segment[" + i + ", " + elfProgramHeader.getDescription() +
|
||||||
"] with invalid file offset");
|
"] with invalid file offset");
|
||||||
continue;
|
continue;
|
||||||
|
@ -2964,7 +2957,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileOffset < 0 || fileOffset >= fileBytes.getSize()) {
|
if (elfProgramHeader.isInvalidOffset() || fileOffset >= fileBytes.getSize()) {
|
||||||
log("Skipping PT_LOAD segment[" + i + ", " + elfProgramHeader.getDescription() +
|
log("Skipping PT_LOAD segment[" + i + ", " + elfProgramHeader.getDescription() +
|
||||||
"] with invalid file offset");
|
"] with invalid file offset");
|
||||||
continue;
|
continue;
|
||||||
|
@ -3168,7 +3161,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||||
(includeOtherBlocks || elfSectionToLoad.isAlloc())) {
|
(includeOtherBlocks || elfSectionToLoad.isAlloc())) {
|
||||||
long fileOffset = elfSectionToLoad.getOffset();
|
long fileOffset = elfSectionToLoad.getOffset();
|
||||||
if (type != ElfSectionHeaderConstants.SHT_NOBITS &&
|
if (type != ElfSectionHeaderConstants.SHT_NOBITS &&
|
||||||
(fileOffset < 0 || fileOffset >= fileBytes.getSize())) {
|
(elfSectionToLoad.isInvalidOffset() || fileOffset >= fileBytes.getSize())) {
|
||||||
log("Skipping section [" + elfSectionToLoad.getNameAsString() +
|
log("Skipping section [" + elfSectionToLoad.getNameAsString() +
|
||||||
"] with invalid file offset 0x" + Long.toHexString(fileOffset));
|
"] with invalid file offset 0x" + Long.toHexString(fileOffset));
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue