Merge remote-tracking branch

'origin/GP-3926_ryanmkurtz_macho-obfuscated' (Closes #3876)
This commit is contained in:
Ryan Kurtz 2023-10-13 07:13:11 -04:00
commit 585a94399a
4 changed files with 50 additions and 23 deletions

View File

@ -18,11 +18,13 @@ package ghidra.app.util.bin.format.macho;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import ghidra.app.util.bin.*;
import ghidra.app.util.bin.format.macho.commands.*;
import ghidra.app.util.opinion.DyldCacheUtils.SplitDyldCache;
import ghidra.program.model.data.*;
import ghidra.program.model.mem.Memory;
import ghidra.util.DataConverter;
import ghidra.util.exception.DuplicateNameException;
@ -186,6 +188,7 @@ public class MachHeader implements StructConverter {
LoadCommand lc = LoadCommandFactory.getLoadCommand(_reader, this, splitDyldCache);
_commands.add(lc);
}
sanitizeSegmentSectionNames(getAllSegments());
_parsed = true;
return this;
}
@ -211,6 +214,7 @@ public class MachHeader implements StructConverter {
_reader.setPointerIndex(_reader.getPointerIndex() + size - 8);
}
}
sanitizeSegmentSectionNames(segments);
return segments;
}
@ -383,6 +387,30 @@ public class MachHeader implements StructConverter {
return getDescription();
}
/**
* Sanitizes invalid segment/section names so they can be used as memory blocks and program tree
* modules
*
* @param segments A {@link List} of {@link SegmentCommand segments} to sanitize
*/
private void sanitizeSegmentSectionNames(List<SegmentCommand> segments) {
Function<String, Boolean> invalid = s -> s.isBlank() || !Memory.isValidMemoryBlockName(s);
for (int i = 0; i < segments.size(); i++) {
SegmentCommand segment = segments.get(i);
if (invalid.apply(segment.getSegmentName())) {
segment.setSegmentName("__INVALID.%d".formatted(i));
}
List<Section> sections = segment.getSections();
for (int j = 0; j < sections.size(); j++) {
Section section = sections.get(j);
section.setSegmentName(segment.getSegmentName());
if (invalid.apply(section.getSectionName())) {
section.setSectionName("__invalid.%d".formatted(j));
}
}
}
}
/**
* Creates a new Mach Header byte array
*

View File

@ -166,10 +166,18 @@ public class Section implements StructConverter {
return sectname;
}
public void setSectionName(String name) {
this.sectname = name;
}
public String getSegmentName() {
return segname;
}
public void setSegmentName(String name) {
this.segname = name;
}
public long getAddress() {
// Mask off possible chained fixup found in kernelcache section addresses
if ((addr & 0xfff000000000L) == 0xfff000000000L) {

View File

@ -106,6 +106,10 @@ public class SegmentCommand extends LoadCommand {
return segname;
}
public void setSegmentName(String name) {
this.segname = name;
}
public long getVMaddress() {
// Mask off possible chained fixup found in kernelcache segment addresses
if ((vmaddr & 0xfff000000000L) == 0xfff000000000L) {

View File

@ -196,32 +196,26 @@ public class MachoProgramBuilder {
}
// Create memory blocks for segments.
ListIterator<SegmentCommand> it = header.getAllSegments().listIterator();
while (it.hasNext()) {
int i = it.nextIndex();
final SegmentCommand segment = it.next();
for (SegmentCommand segment : header.getAllSegments()) {
if (monitor.isCancelled()) {
break;
}
if (segment.getFileSize() > 0 && (allowZeroAddr || segment.getVMaddress() != 0)) {
String segmentName = segment.getSegmentName();
if (segmentName.isBlank()) {
segmentName = "SEGMENT." + i;
}
if (createMemoryBlock(segmentName, space.getAddress(segment.getVMaddress()),
segment.getFileOffset(), segment.getFileSize(), segmentName, source,
segment.isRead(), segment.isWrite(), segment.isExecute(), false) == null) {
if (createMemoryBlock(segment.getSegmentName(),
space.getAddress(segment.getVMaddress()), segment.getFileOffset(),
segment.getFileSize(), segment.getSegmentName(), source, segment.isRead(),
segment.isWrite(), segment.isExecute(), false) == null) {
log.appendMsg(String.format("Failed to create block: %s 0x%x 0x%x",
segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize()));
}
if (segment.getVMsize() > segment.getFileSize()) {
// Pad the remaining address range with uninitialized data
if (createMemoryBlock(segmentName,
if (createMemoryBlock(segment.getSegmentName(),
space.getAddress(segment.getVMaddress()).add(segment.getFileSize()), 0,
segment.getVMsize() - segment.getFileSize(), segmentName, source,
segment.isRead(), segment.isWrite(), segment.isExecute(), true) == null) {
segment.getVMsize() - segment.getFileSize(), segment.getSegmentName(),
source, segment.isRead(), segment.isWrite(), segment.isExecute(),
true) == null) {
log.appendMsg(String.format("Failed to create block: %s 0x%x 0x%x",
segment.getSegmentName(), segment.getVMaddress(), segment.getVMsize()));
}
@ -341,11 +335,7 @@ public class MachoProgramBuilder {
*/
protected void fixupProgramTree() throws Exception {
ProgramModule rootModule = listing.getDefaultRootModule();
ListIterator<SegmentCommand> it = machoHeader.getAllSegments().listIterator();
while (it.hasNext()) {
int i = it.nextIndex();
SegmentCommand segment = it.next();
for (SegmentCommand segment : machoHeader.getAllSegments()) {
if (segment.getVMsize() == 0) {
continue;
}
@ -361,9 +351,6 @@ public class MachoProgramBuilder {
// section fragments, it will represent the parts of the segment that weren't in any
// section.
String segmentName = segment.getSegmentName();
if (segmentName.isBlank()) {
segmentName = "SEGMENT." + i;
}
String noSectionsName = segmentName + " <no section>";
ProgramFragment segmentFragment = null;
for (Group group : rootModule.getChildren()) {