mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-2023 This is a combination of 15 commits.
GP-2023: fix for endless region iterator GP-2023: fix for large-value register display in Objects GP-2023: script for !address GP-2023: de facto event for new process GP-2023: alt command for memory GP-2023: cosmetic stuff GP-2023: fix for NPE GP-2023: added a few methods (unnecessarily, but...), fixes to !address processing, and the bits of code being introduced in GP-2011 GP-2023: adding a parameter for QV vs !address GP-2023: fix for duplicate process creation triggered by getProcess() and/or getSession() GP-2023: fixes for null program, _state, and (possibly) invalidMemory exception GP-2023: better fix for re-entrant process/session creation GP-2023: Adding maintenance method to suppress auto-descent into containers GP-2023: missed a piece re firing add events GP-2023: fix for switching between non-program & program
This commit is contained in:
parent
672c1f11e2
commit
050391a391
40 changed files with 578 additions and 77 deletions
|
@ -0,0 +1,161 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||
import agent.dbgeng.model.AbstractDbgModel;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.services.DebuggerModelService;
|
||||
import ghidra.app.services.DebuggerTraceManagerService;
|
||||
import ghidra.dbg.DebuggerObjectModel;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.memory.*;
|
||||
import ghidra.util.LockHold;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.database.UndoableTransaction;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* This script populates a trace database with memory derived from "!address". This is particularly
|
||||
* useful for dump files and other cases where QueryVirtual fails.
|
||||
*
|
||||
* <p>
|
||||
* Your current tool had better be the "TraceBrowser"! The demonstration serves two purposes. 1) It
|
||||
* puts interesting data into the TraceBrowser and leaves some annotations as an exercise. 2) It
|
||||
* demonstrates how a decent portion the Trace API works.
|
||||
*
|
||||
* <p>
|
||||
* A Trace is basically a collection of observations of memory and registers over the lifetime of an
|
||||
* application or computer system. In Ghidra, the Trace object also supports many of the same
|
||||
* annotations as does Program. In the same way that Program brings knowledge markup to an image of
|
||||
* bytes, Trace brings knowledge markup to bytes observed over time.
|
||||
*
|
||||
*/
|
||||
public class BangAddressToMemory extends GhidraScript {
|
||||
|
||||
/**
|
||||
* The Memory APIs all use Java NIO ByteBuffer. While it has it can sometimes be annoying, it
|
||||
* provides most of the conveniences you'd need for packing arbitrary data into a memory buffer.
|
||||
* I'll allocate one here large enough to write a couple values at a time.
|
||||
*/
|
||||
private ByteBuffer buf = ByteBuffer.allocate(16).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
private Language lang;
|
||||
private Trace trace;
|
||||
private TraceMemoryManager memory;
|
||||
|
||||
private AddressSpace defaultSpace;
|
||||
|
||||
|
||||
private DebuggerModelService modelService;
|
||||
private DebuggerTraceManagerService managerService;
|
||||
|
||||
/**
|
||||
* Create an address in the processor's (x86_64) default space.
|
||||
*
|
||||
* @param offset the byte offset
|
||||
* @return the address
|
||||
*/
|
||||
protected Address addr(long offset) {
|
||||
return defaultSpace.getAddress(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an address range in the processor's default space.
|
||||
*
|
||||
* @param min the minimum byte offset
|
||||
* @param max the maximum (inclusive) byte offset
|
||||
* @return the range
|
||||
*/
|
||||
protected AddressRange rng(long min, long max) {
|
||||
return new AddressRangeImpl(addr(min), addr(max));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
|
||||
modelService = state.getTool().getService(DebuggerModelService.class);
|
||||
if (modelService == null) {
|
||||
throw new RuntimeException("Unable to find DebuggerMemviewPlugin");
|
||||
}
|
||||
|
||||
DebuggerObjectModel model = modelService.getCurrentModel();
|
||||
if (!(model instanceof AbstractDbgModel)) {
|
||||
throw new RuntimeException("Current model must be an AbstractDbgModel");
|
||||
}
|
||||
AbstractDbgModel dbgmodel = (AbstractDbgModel) model;
|
||||
DbgManagerImpl manager = (DbgManagerImpl) dbgmodel.getManager();
|
||||
//client = manager.getClient();
|
||||
|
||||
managerService = state.getTool().getService(DebuggerTraceManagerService.class);
|
||||
trace = managerService.getCurrentTrace();
|
||||
if (trace == null) {
|
||||
throw new RuntimeException("Script requires an active trace");
|
||||
}
|
||||
memory = trace.getMemoryManager();
|
||||
|
||||
lang = currentProgram.getLanguage();
|
||||
defaultSpace = lang.getAddressFactory().getDefaultAddressSpace();
|
||||
|
||||
manager.consoleCapture("!address").thenAccept(result -> {
|
||||
parse(result);
|
||||
});
|
||||
}
|
||||
|
||||
private void parse(String result) {
|
||||
try (UndoableTransaction tid = UndoableTransaction.start(trace, "Populate memory", true);
|
||||
LockHold hold = trace.lockWrite();) {
|
||||
//Pattern pattern = Pattern.compile("\\s+(*)\\s+(*)\\s+");
|
||||
//Matcher matcher = pattern.matcher(fullclassname);
|
||||
String[] lines = result.split("\n");
|
||||
for (String line : lines) {
|
||||
if (line.startsWith("Mapping")) {
|
||||
continue;
|
||||
}
|
||||
String[] fields = line.trim().split("\\s+");
|
||||
if (fields.length < 4) {
|
||||
continue;
|
||||
}
|
||||
String startStr = fields[0].replaceAll("`", "");
|
||||
String endStr = fields[1].replaceAll("`", "");
|
||||
long start, end;
|
||||
try {
|
||||
start = Long.parseUnsignedLong(startStr, 16);
|
||||
end = Long.parseUnsignedLong(endStr, 16);
|
||||
}
|
||||
catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
String name = fields[3];
|
||||
AddressRange rng = rng(start, end - 1);
|
||||
try {
|
||||
TraceMemoryRegion region =
|
||||
memory.addRegion(startStr, Range.atLeast(0L), rng, TraceMemoryFlag.READ,
|
||||
TraceMemoryFlag.WRITE, TraceMemoryFlag.EXECUTE);
|
||||
region.setName(name);
|
||||
}
|
||||
catch (TraceOverlappedRegionException | DuplicateNameException e) {
|
||||
Msg.info(this, "Duplicate range at " + start);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue