Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disassemble .plt section and mark functions as thunks #60

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/adubbz/nx/loader/SwitchLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ protected List<Loaded<Program>> loadProgram(ByteProvider provider, String progra

@Override
protected void loadProgramInto(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
MessageLog messageLog, Program program, TaskMonitor monitor)
throws IOException
MessageLog messageLog, Program program, TaskMonitor monitor)
throws IOException, CancelledException
{
var space = program.getAddressFactory().getDefaultAddressSpace();

Expand Down
40 changes: 34 additions & 6 deletions src/main/java/adubbz/nx/loader/common/NXProgramBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import ghidra.app.util.bin.format.elf.relocation.AARCH64_ElfRelocationType;
import ghidra.app.util.bin.format.elf.relocation.ARM_ElfRelocationType;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.disassemble.Disassembler;
import ghidra.program.model.address.*;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.TerminatedStringDataType;
Expand All @@ -35,6 +36,7 @@
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.exception.NotFoundException;
Expand Down Expand Up @@ -69,7 +71,7 @@ public NXProgramBuilder(Program program, ByteProvider provider, NXOAdapter adapt
this.nxo = new NXO(program, adapter, program.getImageBase().getOffset());
}

public void load(TaskMonitor monitor)
public void load(TaskMonitor monitor) throws CancelledException
{
NXOAdapter adapter = this.nxo.getAdapter();
ByteProvider memoryProvider = adapter.getMemoryProvider();
Expand Down Expand Up @@ -117,7 +119,7 @@ public void load(TaskMonitor monitor)
this.memBlockHelper.addSection(".dynsym", adapter.getSymbolTable(this.program).getFileOffset() - this.nxo.getBaseAddress(), adapter.getSymbolTable(this.program).getFileOffset() - this.nxo.getBaseAddress(), adapter.getSymbolTable(this.program).getLength(), true, false, false);
}

this.setupRelocations();
this.setupRelocations(monitor);
this.createGlobalOffsetTable();

this.memBlockHelper.addFillerSection(".text", text.getOffset(), text.getSize(), true, false, true);
Expand Down Expand Up @@ -205,7 +207,7 @@ protected void setupSymbolTable()
}
}

protected void setupRelocations() throws AddressOutOfBoundsException, NotFoundException, IOException {
protected void setupRelocations(TaskMonitor monitor) throws AddressOutOfBoundsException, NotFoundException, IOException, CancelledException {
NXOAdapter adapter = this.nxo.getAdapter();
ByteProvider memoryProvider = adapter.getMemoryProvider();
BinaryReader memoryReader = adapter.getMemoryReader();
Expand Down Expand Up @@ -274,6 +276,7 @@ protected void setupRelocations() throws AddressOutOfBoundsException, NotFoundEx
long pltStart = this.pltEntries.get(0).off;
long pltEnd = this.pltEntries.get(this.pltEntries.size() - 1).off + 0x10;
this.memBlockHelper.addSection(".plt", pltStart, pltStart, pltEnd - pltStart, true, false, false);
disassembleRange(program.getImageBase().add(pltStart), program.getImageBase().add(pltEnd), program, monitor);
}
else {
// TODO: Find a way to locate the plt in CFI-enabled binaries.
Expand Down Expand Up @@ -382,12 +385,15 @@ else if (reloc.r_type == R_FAKE_RELR) {
{
if (gotNameLookup.containsKey(entry.target))
{
long addr = this.nxo.getBaseAddress() + entry.off;
Address addr = this.aSpace.getAddress(this.nxo.getBaseAddress() + entry.off);
String name = gotNameLookup.get(entry.target);
// TODO: Mark as func
if (name != null && !name.isEmpty())
{
this.createSymbol(this.aSpace.getAddress(addr), name, false, false, null);
Function func = createOneByteFunction(name, addr, false);
ExternalLocation extLoc = program.getExternalManager().getUniqueExternalLocation(Library.UNKNOWN, name);
if (extLoc != null) {
func.setThunkedFunction(extLoc.getFunction());
}
}
}
}
Expand Down Expand Up @@ -642,6 +648,28 @@ public Symbol createSymbol(Address addr, String name, boolean isPrimary, boolean
}
return sym;
}

// Source: https://github.com/NationalSecurityAgency/ghidra/blob/de7c3eaee2a4bc993a402e371b039c2bb2d6c545/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java#L545
private void disassembleRange(Address start, Address end, Program program, TaskMonitor monitor)
throws CancelledException {
AddressSet set = new AddressSet(start, end);
Disassembler disassembler = Disassembler.getDisassembler(program, monitor, m -> {
/* silent */});
while (!set.isEmpty()) {
monitor.checkCancelled();
AddressSet disset = disassembler.disassemble(set.getMinAddress(), null, true);
if (disset.isEmpty()) {
// Stop on first error but discard error bookmark since
// some plt sections are partly empty and must rely
// on normal flow disassembly during analysis
program.getBookmarkManager()
.removeBookmarks(set, BookmarkType.ERROR,
Disassembler.ERROR_BOOKMARK_CATEGORY, monitor);
break;//we did not disassemble anything...
}
set.delete(disset);
}
}

private Symbol checkPrimary(Symbol sym)
{
Expand Down