mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-25 23:15:10 +08:00
Merge remote-tracking branch 'origin/GP-6887_ghidra1_ElfGnuHashBoundsCheck' into patch
This commit is contained in:
@@ -697,7 +697,7 @@ public class ElfHeader implements StructConverter {
|
||||
// p_vaddr to find it relative to a PT_LOAD segment
|
||||
long vaddr = dynamicHeaders[0].getVirtualAddress();
|
||||
if (vaddr == 0 || dynamicHeaders[0].getFileSize() == 0) {
|
||||
Msg.warn(this, "ELF Dynamic table appears to have been stripped from binary");
|
||||
logError("ELF Dynamic table appears to have been stripped from binary");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -931,7 +931,7 @@ public class ElfHeader implements StructConverter {
|
||||
!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMENT) ||
|
||||
dynamicHashType == null) {
|
||||
if (dynamicStringTable != null) {
|
||||
Msg.warn(this, "Failed to parse DT_SYMTAB, missing dynamic dependency");
|
||||
logError("Failed to parse DT_SYMTAB, missing dynamic dependency");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1017,9 +1017,21 @@ public class ElfHeader implements StructConverter {
|
||||
int bloomWordSize = is64Bit() ? 8 : 4;
|
||||
long bucketsOffset = gnuHashTableOffset + 16 + (bloomWordSize * bloomSize);
|
||||
|
||||
|
||||
// Identify restricted region which contains GNU hash table (arbitrary min-length)
|
||||
long maxOffset = getMaxOffsetForLoadedRegionContaining(gnuHashTableOffset, 12);
|
||||
if (maxOffset <= 0) {
|
||||
logError("Failed to idenitify loaded GNU Hash table");
|
||||
return 0;
|
||||
}
|
||||
|
||||
long bucketOffset = bucketsOffset;
|
||||
int maxSymbolIndex = 0;
|
||||
for (int i = 0; i < numBuckets; i++) {
|
||||
if (bucketOffset < gnuHashTableOffset || bucketOffset > maxOffset) {
|
||||
logError("Error occured while inspecting GNU Hash table");
|
||||
return 0;
|
||||
}
|
||||
int symbolIndex = reader.readInt(bucketOffset);
|
||||
if (symbolIndex > maxSymbolIndex) {
|
||||
maxSymbolIndex = symbolIndex;
|
||||
@@ -1032,6 +1044,10 @@ public class ElfHeader implements StructConverter {
|
||||
++maxSymbolIndex;
|
||||
long chainOffset = bucketOffset + (4 * chainIndex); // chains immediately follow buckets
|
||||
while (true) {
|
||||
if (chainOffset < gnuHashTableOffset || chainOffset > maxOffset) {
|
||||
logError("Error occured while inspecting GNU Hash table");
|
||||
return 0;
|
||||
}
|
||||
int chainValue = reader.readInt(chainOffset);
|
||||
if ((chainValue & 1) != 0) {
|
||||
break;
|
||||
@@ -1042,6 +1058,25 @@ public class ElfHeader implements StructConverter {
|
||||
return maxSymbolIndex;
|
||||
}
|
||||
|
||||
private long getMaxOffsetForLoadedRegionContaining(long offset, long minSize) {
|
||||
long maxOffset = -1;
|
||||
if (e_shnum != 0) {
|
||||
ElfSectionHeader sectionContaining =
|
||||
getSectionHeaderContainingFileRange(offset, minSize);
|
||||
if (sectionContaining != null) {
|
||||
maxOffset = sectionContaining.getOffset() + sectionContaining.getSize() - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ElfProgramHeader containingSegment =
|
||||
getProgramLoadHeaderContainingFileOffset(offset);
|
||||
if (containingSegment != null) {
|
||||
maxOffset = containingSegment.getOffset() + containingSegment.getFileSize() - 1;
|
||||
}
|
||||
}
|
||||
return maxOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk DT_GNU_XHASH table to determine dynamic symbol count
|
||||
* @param gnuHashTableOffset DT_GNU_XHASH table file offset
|
||||
@@ -1296,6 +1331,7 @@ public class ElfHeader implements StructConverter {
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
logError("Elf prelink read failure (see log)");
|
||||
Msg.error(this, "Elf prelink read failure", e);
|
||||
}
|
||||
return preLinkImageBase;
|
||||
|
||||
Reference in New Issue
Block a user