-
Notifications
You must be signed in to change notification settings - Fork 6.1k
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
constant propagation of memory #3581
Comments
Any update on this? |
I took another look at this now that I'm 6 months wiser, and I was able to get something working that suits my needs. The crux of my problem was that the You can do a sort of I'll also submit a separate pull request sometime in the future with documentation improvements I made while stumbling through this. Perhaps it will help others come up with something cleaner. import java.util.HashMap;
import ghidra.app.plugin.core.analysis.ConstantPropagationContextEvaluator;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ProgramContext;
import ghidra.program.model.listing.Variable;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.util.ContextEvaluator;
import ghidra.program.util.SymbolicPropogator;
import ghidra.program.util.VarnodeContext;
public class MemoryConstantDemo extends GhidraScript {
public class MemoryEnabledSymbolicPropogator extends SymbolicPropogator {
public MemoryEnabledSymbolicPropogator(Program program) {
super(program);
this.context = new MemoryEnabledVarnodeContext(program, this.programContext, this.spaceContext);
this.context.setDebug(true);
}
public Value getMemoryValue(Address toAddr, Address memory) {
return null;
}
public MemoryEnabledVarnodeContext getContext() {
return (MemoryEnabledVarnodeContext) this.context;
}
}
public class MemoryEnabledVarnodeContext extends VarnodeContext {
public MemoryEnabledVarnodeContext(Program program, ProgramContext programContext,
ProgramContext spaceProgramContext) {
super(program, programContext, spaceProgramContext);
}
public Varnode newGetMemoryValue(Varnode varnode) {
return this.getMemoryValue(varnode);
}
@Override
protected void putMemoryValue(Varnode out, Varnode value) {
println("putMemoryValue called:");
println("out: " + out.toString() + " (" + out.getClass() + ")");
println("value: " + value.toString() + " (" + value.getClass() + ")");
println();
super.putMemoryValue(out, value);
}
/* useful if you just want to visually inspect */
public void dumpMemory() {
for (HashMap<Varnode, Varnode> mem : memoryVals) {
for (Varnode v : mem.keySet()) {
println("# memory entry");
println(v.toString() + ": " + mem.get(v).toString());
println("space id: " + v.getSpace());
println("offset: " + v.getOffset());
println();
}
}
}
public AddressSpace getAddressSpaceItself(String name) {
return addrFactory.getAddressSpace(name);
}
}
public void run() throws Exception {
Function func = currentProgram.getFunctionManager().getFunctionContaining(currentAddress);
if (func == null) {
printerr("there is no current function!");
return;
}
Address start = func.getEntryPoint();
// do the flow analysis
ContextEvaluator eval = new ConstantPropagationContextEvaluator(true);
MemoryEnabledSymbolicPropogator symEval = new MemoryEnabledSymbolicPropogator(currentProgram);
symEval.flowConstants(start, func.getBody(), eval, true, monitor);
// get the internal address space used by the propogator for ESP
AddressSpace espSpace = symEval.getContext().getAddressSpaceItself("ESP");
println("ESP address space: " + espSpace);
for (Variable v : func.getStackFrame().getLocals()) {
println("local variable: " + v.toString());
Varnode use = v.getFirstStorageVarnode();
println("first use varnode: " + use.toString());
// create the varnode the internal propogator would have used for this local
long translatedOffset = use.getOffset() + 0x100000000L;
Varnode contextVarnode = new Varnode(espSpace.getTruncatedAddress(translatedOffset, true), use.getSize());
println("equivalent varnode: " + contextVarnode);
// search for it!
Varnode result = symEval.getContext().newGetMemoryValue(contextVarnode);
if (result == null) {
println("no symbolic entry found");
} else {
println("found symbolic entry: " + result);
}
println();
}
}
} Some of the output from running this against an example function:
|
EDIT. Sorry @goatshriek I thought that the person who closed the issue was a maintainer rather than you :) |
Sure, I will leave it open in hopes that they will get to it at some point. The lack of any sort of response in over a year is not encouraging though... |
We will fix it. |
@lautalom could you please take a look? |
bump 🙂 |
One of the scripts packaged with Ghidra,
ResolveX86orX64LinuxSyscallsScript
, makes use of a constant propagater that allows constant register values to be retrieved. This turns out to be pretty handy for many things.The class that is used,
SymbolicPropogator
, has an easy way to retrieve register values at a specific point of execution. However, there doesn't seem to be an equivalent capability for memory addresses. I've tried to subclassVarnodeContext
to use its protectedgetMemoryValue
method, but haven't had any success with that, at least not when passing it stack Varnodes.Does anyone know of a way to do constant propagation with memory addresses in addition to registers? It seems like this should be possible, but I can't find a way to do it. Particularly, I'm looking for a simple way to see if stack-based variables can be resolved to constant values.
The text was updated successfully, but these errors were encountered: