# P-code Modeling

This module assumes you have completed the [Emulation](B2-Emulation.md) and [Scripting](B3-Scripting.md) portions of this course.
It also assumes you have fairly deep knowledge of Ghidra's low p-code.

Modeling is another one of those loaded terms.
Here we are going to focus on its use in what we will call *augmented emulation*.
This is used for things like dynamic taint analysis and concolic execution.
The idea is to leverage the emulator for concrete execution while augmenting it with some auxiliary model, e.g., taint labels or symbolic expressions.
Ghidra's abstract emulator implementations facilitate the composition of independent models so, if careful attention is given to your implementation, the auxiliary model can be re-used for other cases, perhaps even in static analysis.

This module will address the following aspects of modeling:

* Environment, i.e., p-code userops and stubbing.
* Arithmetic operations.
* Storage, addressing, and memory operations.
* Use in dynamic analysis.
* Use in static analysis.
* Integration with the GUI.

Modeling is definitely a development task.
There is generally a specific interface for each aspect, and Ghidra may provide abstract implementations of them, which you may choose to use or ignore.
If you do not already have a development environment set up, you will need to do that now.
Either use the GhidraDev plugin for Eclipse and associate it with an installation of Ghidra, or clone the `ghidra` source repository and prepare it for development in Eclipse.
When prototyping, you may find it easiest to develop a script, which is what this tutorial will do.

## Modeling the Environment

There are different pieces to the environment.
This covers the implementation of p-code userops, which generally covers everything not modeled by p-code.
For example, the x86-64 `SYSCALL` instruction just invokes the `syscall()` userop, which provides a hook for implementing them.
Modeling system calls is such a common case that Ghidra provides a special programming interface for it.
Stubbing external functions is covered, in part, by the [Emulation](B2-Emulation.md) module.
By providing common stubs in a userop library, the user can stub the external function by placing a Sleigh breakpoint that invokes the appropriate userop.

### Modeling by Java Callbacks

A userop library is created by implementing the `PcodeUseropLibrary` interface, most likely by extending `AnnotatedPcodeUseropLibrary`.
For example, to provide a stub for `strlen`:

```java {.numberLines}
public static class JavaStdLibPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
	private final AddressSpace space;
	private final Register regRSP;
	private final Register regRAX;
	private final Register regRDI;
	private final Register regRSI;

	public JavaStdLibPcodeUseropLibrary(SleighLanguage language) {
		space = language.getDefaultSpace();
		regRSP = language.getRegister("RSP");
		regRAX = language.getRegister("RAX");
		regRDI = language.getRegister("RDI");
		regRSI = language.getRegister("RSI");
	}

	@PcodeUserop
	public void __x86_64_RET(
			@OpExecutor PcodeExecutor<T> executor,
			@OpState PcodeExecutorState<T> state) {
		PcodeArithmetic<T> arithmetic = state.getArithmetic();
		T tRSP = state.getVar(regRSP, Reason.EXECUTE_READ);
		long lRSP = arithmetic.toLong(tRSP, Purpose.OTHER);
		T tReturn = state.getVar(space, lRSP, 8, true, Reason.EXECUTE_READ);
		long lReturn = arithmetic.toLong(tReturn, Purpose.BRANCH);
		state.setVar(regRSP, arithmetic.fromConst(lRSP + 8, 8));
		((PcodeThreadExecutor<T>) executor).getThread()
				.overrideCounter(space.getAddress(lReturn));
	}

	@PcodeUserop
	public void __libc_strlen(@OpState PcodeExecutorState<T> state) {
		PcodeArithmetic<T> arithmetic = state.getArithmetic();
		T tStr = state.getVar(regRDI, Reason.EXECUTE_READ);
		long lStr = arithmetic.toLong(tStr, Purpose.OTHER);
		T tMaxlen = state.getVar(regRSI, Reason.EXECUTE_READ);
		long lMaxlen = arithmetic.toLong(tMaxlen, Purpose.OTHER);

		for (int i = 0; i < lMaxlen; i++) {
			T tChar = state.getVar(space, lStr + i, 1, false, Reason.EXECUTE_READ);
			if (arithmetic.toLong(tChar, Purpose.OTHER) == 0) {
				state.setVar(regRAX, arithmetic.fromConst(Integer.toUnsignedLong(i), 8));
				break;
			}
		}
	}
}
```

Here, we implement the stub using Java callbacks.
This is more useful when modeling things outside of Ghidra's definition of machine state, e.g., to simulate kernel objects in an underlying operating system.
Nevertheless, it can be used to model simple state changes as well.
A user would place a breakpoint at either the call site or the call target, have it invoke `__libc_strlen()`, and then invoke either `emu_skip_decoded()` or `__x86_64_RET()` depending on where the breakpoint was placed.

### Modeling by Sleigh Semantics

The advantage to Java callbacks is that things are relatively intuitive to do, but the temptation, which we intentionally demonstrated above, is to make everything concrete.
You may notice the library uses a type parameter `T`, which specifies the type of all variables in the emulator's state.
Leaving it as `T` indicates the library is compatible with any type.
For a concrete emulator, `T := byte[]`, and so there is no loss in making things concrete, and then converting back to `T` using the `arithmetic` object.
However, if the emulator has been augmented, as we will discuss below, the model may become confused, because values computed by a careless userop will appear to the model a literal constant.
To avoid this, you should keep everything a T and use the `arithmetic` object to perform any arithmetic operations.
Alternatively, you can implement the userop using pre-compiled Sleigh code:

```java {.numberLines}
public static class SleighStdLibPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
	private static final String SRC_RET = """
			RIP = *:8 RSP;
			RSP = RSP + 8;
			return [RIP];
			""";
	private static final String SRC_STRLEN = """
			__result = 0;
			<loop>
			if (*:1 (str+__result) == 0 || __result >= maxlen) goto <exit>;
			__result = __result + 1;
			goto <loop>;
			<exit>
			""";
	private final Register regRAX;
	private final Register regRDI;
	private final Register regRSI;
	private final Varnode vnRAX;
	private final Varnode vnRDI;
	private final Varnode vnRSI;

	private PcodeProgram progRet;
	private PcodeProgram progStrlen;

	public SleighStdLibPcodeUseropLibrary(SleighLanguage language) {
		regRAX = language.getRegister("RAX");
		regRDI = language.getRegister("RDI");
		regRSI = language.getRegister("RSI");
		vnRAX = new Varnode(regRAX.getAddress(), regRAX.getMinimumByteSize());
		vnRDI = new Varnode(regRDI.getAddress(), regRDI.getMinimumByteSize());
		vnRSI = new Varnode(regRSI.getAddress(), regRSI.getMinimumByteSize());
	}

	@PcodeUserop
	public void __x86_64_RET(@OpExecutor PcodeExecutor<T> executor,
			@OpLibrary PcodeUseropLibrary<T> library) {
		if (progRet == null) {
			progRet = SleighProgramCompiler.co