From 59c67d256189900ec1ad225c2d372c631539d931 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Tue, 23 Aug 2022 11:26:11 -0400 Subject: [PATCH] GP-2489: Fix tainted emulation of XOR EAX,EAX --- .../pcode/emu/taint/plain/TaintSpace.java | 2 +- .../java/ghidra/taint/model/TaintVec.java | 9 +-- .../trace/TaintTracePcodeEmulatorTest.java | 62 +++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/plain/TaintSpace.java b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/plain/TaintSpace.java index f05bd15494..57422e678f 100644 --- a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/plain/TaintSpace.java +++ b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/pcode/emu/taint/plain/TaintSpace.java @@ -62,7 +62,7 @@ public class TaintSpace { * Retrieve the taint sets for the variable at the given offset * *

- * This retrieve as many taint sets as there are elements in the given buffer vector. This first + * This retrieves as many taint sets as there are elements in the given buffer vector. This first * element becomes the taint set at the given offset, then each subsequent element becomes the * taint set at each subsequent offset until the vector is filled. This is analogous to the * manner in which bytes would be "read" from concrete state, starting at a given ofset, into a diff --git a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/taint/model/TaintVec.java b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/taint/model/TaintVec.java index b61d3dc8f2..6800bfdbe3 100644 --- a/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/taint/model/TaintVec.java +++ b/Ghidra/Debug/TaintAnalysis/src/main/java/ghidra/taint/model/TaintVec.java @@ -449,9 +449,9 @@ public class TaintVec { throw new IllegalArgumentException(); } TaintVec vec = new TaintVec(length); - int diff = isBigEndian ? this.length - length : 0; + int shift = isBigEndian ? this.length - length : 0; for (int i = 0; i < length; i++) { - vec.sets[i] = vec.sets[i + diff]; + vec.sets[i] = vec.sets[i + shift]; } return vec; } @@ -489,9 +489,10 @@ public class TaintVec { return truncated(length, isBigEndian); } TaintVec vec = new TaintVec(length); - int diff = isBigEndian ? length - this.length : 0; + int diff = length - this.length; + int shift = isBigEndian ? diff : 0; for (int i = 0; i < this.length; i++) { - vec.sets[i + diff] = vec.sets[i]; + vec.sets[i + shift] = this.sets[i]; } TaintSet ext = isSigned ? isBigEndian ? sets[0] : sets[this.length - 1] : TaintSet.EMPTY; int start = isBigEndian ? 0 : this.length; diff --git a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java index 24e108ac6f..ab31984b4f 100644 --- a/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java +++ b/Ghidra/Debug/TaintAnalysis/src/test/java/ghidra/pcode/emu/taint/trace/TaintTracePcodeEmulatorTest.java @@ -210,4 +210,66 @@ public class TaintTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest Range.singleton(1L), tb.range(0x00600000, 0x00600007)))); } } + + @Test + public void testZeroByXor() throws Throwable { + try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) { + TraceThread thread = initTrace(tb, + List.of( + "RIP = 0x00400000;"), + List.of( + "XOR RAX, RAX")); + + TaintTracePcodeEmulator emu = new TaintTracePcodeEmulator(tb.trace, 0); + PcodeThread> emuThread = emu.newThread(thread.getPath()); + emuThread.getState() + .setVar(tb.reg("RAX"), Pair.of( + tb.arr(1, 2, 3, 4, 5, 6, 7, 8), + TaintVec.copies(TaintSet.parse("test_0"), 8))); + + emuThread.stepInstruction(); + try (UndoableTransaction tid = tb.startTransaction()) { + emu.writeDown(tb.trace, 1, 0); + } + + TracePropertyMap taintMap = + tb.trace.getAddressPropertyManager().getPropertyMap("Taint", String.class); + TracePropertyMapRegisterSpace mapSpace = + taintMap.getPropertyMapRegisterSpace(thread, 0, false); + + assertEquals(Set.of(), + Set.copyOf(mapSpace.getEntries(Range.singleton(1L), tb.reg("RAX")))); + } + } + + @Test + public void testZeroByXorVia32() throws Throwable { + try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) { + TraceThread thread = initTrace(tb, + List.of( + "RIP = 0x00400000;"), + List.of( + "XOR EAX, EAX")); + + TaintTracePcodeEmulator emu = new TaintTracePcodeEmulator(tb.trace, 0); + PcodeThread> emuThread = emu.newThread(thread.getPath()); + emuThread.getState() + .setVar(tb.reg("RAX"), Pair.of( + tb.arr(1, 2, 3, 4, 5, 6, 7, 8), + TaintVec.copies(TaintSet.parse("test_0"), 8))); + + emuThread.stepInstruction(); + try (UndoableTransaction tid = tb.startTransaction()) { + emu.writeDown(tb.trace, 1, 0); + } + + TracePropertyMap taintMap = + tb.trace.getAddressPropertyManager().getPropertyMap("Taint", String.class); + TracePropertyMapRegisterSpace mapSpace = + taintMap.getPropertyMapRegisterSpace(thread, 0, false); + + assertEquals(Set.of(), + Set.copyOf(mapSpace.getEntries(Range.singleton(1L), tb.reg("RAX")))); + } + } }