From e332f3e17cd9b8a6494968e478805287d644ab57 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Wed, 15 Dec 2021 13:16:42 -0500 Subject: [PATCH 1/8] GP-1590: Adjusting MemoryBytes to use viewport state --- .../DebuggerMemoryByteViewerComponent.java | 70 +++++++++---------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryByteViewerComponent.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryByteViewerComponent.java index 26fa5fb9d0..71332b53ba 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryByteViewerComponent.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/DebuggerMemoryByteViewerComponent.java @@ -20,7 +20,6 @@ import java.awt.FontMetrics; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import java.util.Map.Entry; import docking.widgets.fieldpanel.internal.LayoutBackgroundColorManager; import docking.widgets.fieldpanel.support.FieldSelection; @@ -34,7 +33,6 @@ import ghidra.framework.options.AutoOptions; import ghidra.framework.options.annotation.AutoOptionConsumed; import ghidra.program.model.address.*; import ghidra.trace.model.Trace; -import ghidra.trace.model.TraceAddressSnapRange; import ghidra.trace.model.memory.TraceMemoryState; public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent @@ -71,37 +69,45 @@ public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent } Trace trace = coordinates.getTrace(); // TODO: Mimic the listing's background, or factor into common - long snap = coordinates.getSnap(); + long viewSnap = coordinates.getViewSnap(); // TODO: Span out and cache? AddressSetView lineAddresses = translator.convertFieldToAddress(lineFieldSel); - // Because UNKNOWN need not be explicitly recorded, compute it by subtracting others - AddressSet unknown = new AddressSet(lineAddresses); - for (AddressRange range : lineAddresses) { - for (Entry entry : trace.getMemoryManager() - .getStates(snap, range)) { - if (entry.getValue() != TraceMemoryState.UNKNOWN) { - unknown.delete(entry.getKey().getRange()); - } - Color color = colorForState(entry.getValue()); - if (color == null) { - continue; - } - // NOTE: Only TraceMemoryState.ERROR should reach here - FieldSelection resultFieldSel = - translator.convertAddressToField(entry.getKey().getRange()); - if (!resultFieldSel.isEmpty()) { - selections.add(new ColoredFieldSelection(resultFieldSel, color)); - } + AddressSet known = new AddressSet(); + AddressSet error = new AddressSet(); + + for (Address addr : lineAddresses.getAddresses(true)) { + TraceMemoryState state = + trace.getMemoryManager().getViewState(viewSnap, addr).getValue(); + switch (state) { + case KNOWN: + known.add(addr); + break; + case ERROR: + error.add(addr); + break; + default: + // Don't care } } - if (unknownColor == null) { + AddressSet unknown = new AddressSet(lineAddresses); + unknown.delete(known); + unknown.delete(error); + + doAddSelections(unknownColor, unknown, translator, selections); + doAddSelections(errorColor, error, translator, selections); + } + + protected void doAddSelections(Color color, AddressSetView set, + SelectionTranslator translator, List selections) { + if (color == null) { return; } - for (AddressRange unk : unknown) { - FieldSelection resultFieldSel = translator.convertAddressToField(unk); - if (!resultFieldSel.isEmpty()) { - selections.add(new ColoredFieldSelection(resultFieldSel, unknownColor)); + for (AddressRange rng : set) { + FieldSelection resultFieldSel = translator.convertAddressToField(rng); + if (resultFieldSel.isEmpty()) { + continue; } + selections.add(new ColoredFieldSelection(resultFieldSel, color)); } } } @@ -133,18 +139,6 @@ public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent // NOTE: Cursor, being line-by-line, is done via background color model in super } - protected Color colorForState(TraceMemoryState state) { - switch (state) { - case ERROR: - return errorColor; - case KNOWN: - return null; - case UNKNOWN: - return unknownColor; - } - throw new AssertionError(); - } - @Override protected LayoutBackgroundColorManager getLayoutSelectionMap(BigInteger layoutIndex) { Color backgroundColor = backgroundColorModel.getBackgroundColor(layoutIndex); From b1c17db4e11958d832b02d8198c8bb68e22fd2d0 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Wed, 15 Dec 2021 16:51:18 -0500 Subject: [PATCH 2/8] GP-1469: Double-clicking Watch Repr cell may go to value. --- .../DebuggerWatchesPlugin.html | 6 +- .../gui/watch/DebuggerWatchesProvider.java | 57 +++++++++++++------ .../plugin/core/debug/gui/watch/WatchRow.java | 22 ++++++- 3 files changed, 62 insertions(+), 23 deletions(-) diff --git a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerWatchesPlugin/DebuggerWatchesPlugin.html b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerWatchesPlugin/DebuggerWatchesPlugin.html index f863cf99e1..4b958a373e 100644 --- a/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerWatchesPlugin/DebuggerWatchesPlugin.html +++ b/Ghidra/Debug/Debugger/src/main/help/help/topics/DebuggerWatchesPlugin/DebuggerWatchesPlugin.html @@ -57,7 +57,7 @@
  • Address - when evaluation succeeds, the address of the watch's value. This field is really only meaningful when the outermost operator of the expression is a memory dereference. - Double-clicking a row will navigate the primary dynamic listing to this address, if + Double-clicking this cell will navigate the primary dynamic listing to this address, if possible.
  • Value - the raw bytes of the watched buffer. If the expression is a register, then this @@ -71,7 +71,9 @@ possible.
  • Representation - the value of the watch as interpreted by the selected data type. This - field is not yet user modifiable, even if the Enable Edits toggle is on.
  • + field is not yet user modifiable, even if the Enable Edits toggle is on. If the value + is an address, i.e., Type is a pointer, then double-clicking this cell will navigate the + primary dynamic listing, if possible.
  • Error - if an error occurs during compilation or evaluation of the expression, that error is rendered here. Double-clicking the row will display the stack trace. Note that errors diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java index 931b31ea7f..1afed55abc 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/DebuggerWatchesProvider.java @@ -334,24 +334,7 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter { if (e.getClickCount() != 2 || e.getButton() != MouseEvent.BUTTON1) { return; } - if (myActionContext == null) { - return; - } - WatchRow row = myActionContext.getWatchRow(); - if (row == null) { - return; - } - Throwable error = row.getError(); - if (error != null) { - Msg.showError(this, getComponent(), "Evaluation error", - "Could not evaluate watch", error); - return; - } - Address address = myActionContext.getWatchRow().getAddress(); - if (listingService == null || address == null || !address.isMemoryAddress()) { - return; - } - listingService.goTo(address, true); + navigateToSelectedWatch(); } }); @@ -371,6 +354,44 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter { super.contextChanged(); } + protected void navigateToSelectedWatch() { + if (myActionContext == null) { + return; + } + WatchRow row = myActionContext.getWatchRow(); + if (row == null) { + return; + } + int modelCol = watchTable.convertColumnIndexToModel(watchTable.getSelectedColumn()); + Throwable error = row.getError(); // I don't care the selected column for errors + if (error != null) { + Msg.showError(this, getComponent(), "Evaluation error", + "Could not evaluate watch", error); + } + else if (modelCol == WatchTableColumns.ADDRESS.ordinal()) { + Address address = row.getAddress(); + if (address != null) { + navigateToAddress(address); + } + } + else if (modelCol == WatchTableColumns.REPR.ordinal()) { + Object val = row.getValueObj(); + if (val instanceof Address) { + navigateToAddress((Address) val); + } + } + } + + protected void navigateToAddress(Address address) { + if (listingService == null) { + return; + } + if (address.isMemoryAddress()) { + listingService.goTo(address, true); + return; + } + } + protected void createActions() { actionEnableEdits = DebuggerResources.EnableEditsAction.builder(plugin) .enabledWhen(c -> current.getTrace() != null) diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java index 6db7665f7c..ca346ac0d3 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/watch/WatchRow.java @@ -64,6 +64,7 @@ public class WatchRow { private byte[] value; private byte[] prevValue; // Value at previous coordinates private String valueString; + private Object valueObj; private Throwable error = null; public WatchRow(DebuggerWatchesProvider provider, String expression) { @@ -77,6 +78,7 @@ public class WatchRow { reads = null; value = null; valueString = null; + valueObj = null; } protected void recompile() { @@ -125,20 +127,29 @@ public class WatchRow { address = valueWithAddress.getRight(); reads = executorWithAddress.getReads(); - valueString = parseAsDataType(); + valueObj = parseAsDataTypeObj(); + valueString = parseAsDataTypeStr(); } catch (Exception e) { error = e; } } - protected String parseAsDataType() { + protected String parseAsDataTypeStr() { if (dataType == null || value == null) { return ""; } MemBuffer buffer = new ByteMemBufferImpl(address, value, language.isBigEndian()); return dataType.getRepresentation(buffer, SettingsImpl.NO_SETTINGS, value.length); } + + protected Object parseAsDataTypeObj() { + if (dataType == null || value == null) { + return null; + } + MemBuffer buffer = new ByteMemBufferImpl(address, value, language.isBigEndian()); + return dataType.getValue(buffer, SettingsImpl.NO_SETTINGS, value.length); + } public static class ReadDepsTraceBytesPcodeExecutorState extends TraceBytesPcodeExecutorState { @@ -299,7 +310,8 @@ public class WatchRow { public void setDataType(DataType dataType) { this.typePath = dataType == null ? null : dataType.getPathName(); this.dataType = dataType; - valueString = parseAsDataType(); + valueString = parseAsDataTypeStr(); + valueObj = parseAsDataTypeObj(); provider.contextChanged(); } @@ -357,6 +369,10 @@ public class WatchRow { return valueString; } + public Object getValueObj() { + return valueObj; + } + public boolean isValueEditable() { return address != null && provider.isEditsEnabled(); } From 8e98b28cc4387ab12cb7dc7aa87fe34b08b04246 Mon Sep 17 00:00:00 2001 From: Bhaskara Ram <39507881+bhaskarvilles@users.noreply.github.com> Date: Thu, 23 Dec 2021 22:08:40 +0530 Subject: [PATCH 3/8] Deserialization of Untrusted Data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit introduced through: unknown:unknown@0.0.0 › com.google.code.gson:gson@2.8.6 Fix: Upgrade to com.google.code.gson:gson@2.8.9 Affected versions of this package are vulnerable to Deserialization of Untrusted Data via the writeReplace() method in internal classes, which may lead to DoS attacks. --- GhidraBuild/BuildFiles/JsonDoclet/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GhidraBuild/BuildFiles/JsonDoclet/build.gradle b/GhidraBuild/BuildFiles/JsonDoclet/build.gradle index 22f9dfd764..338f9868b9 100644 --- a/GhidraBuild/BuildFiles/JsonDoclet/build.gradle +++ b/GhidraBuild/BuildFiles/JsonDoclet/build.gradle @@ -19,7 +19,7 @@ eclipse.project.name = '_JsonDoclet' apply plugin: 'java-library' dependencies { - api "com.google.code.gson:gson:2.8.6" + api "com.google.code.gson:gson@2.8.9" } rootProject.createJsondocs.dependsOn jar From e077f51b9965ffcd71a4add8ee0063d9ad146854 Mon Sep 17 00:00:00 2001 From: Bhaskara Ram <39507881+bhaskarvilles@users.noreply.github.com> Date: Wed, 29 Dec 2021 19:50:57 +0530 Subject: [PATCH 4/8] Update build.gradle --- GhidraBuild/BuildFiles/JsonDoclet/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GhidraBuild/BuildFiles/JsonDoclet/build.gradle b/GhidraBuild/BuildFiles/JsonDoclet/build.gradle index 338f9868b9..b7b782545d 100644 --- a/GhidraBuild/BuildFiles/JsonDoclet/build.gradle +++ b/GhidraBuild/BuildFiles/JsonDoclet/build.gradle @@ -19,7 +19,7 @@ eclipse.project.name = '_JsonDoclet' apply plugin: 'java-library' dependencies { - api "com.google.code.gson:gson@2.8.9" + api "com.google.code.gson:gson:2.8.9" } rootProject.createJsondocs.dependsOn jar From 522d896215511f1c3eaf1fcf94519605a5a1a01d Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 29 Dec 2021 13:35:55 -0500 Subject: [PATCH 5/8] GP-1632: Upgrading Gson to 2.8.9 --- Ghidra/Framework/Generic/Module.manifest | 2 +- Ghidra/Framework/Generic/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Framework/Generic/Module.manifest b/Ghidra/Framework/Generic/Module.manifest index 2f96a05370..920378145b 100644 --- a/Ghidra/Framework/Generic/Module.manifest +++ b/Ghidra/Framework/Generic/Module.manifest @@ -7,7 +7,7 @@ MODULE FILE LICENSE: lib/commons-collections4-4.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-lang3-3.9.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-io-2.6.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-text-1.6.jar Apache License 2.0 -MODULE FILE LICENSE: lib/gson-2.8.6.jar Apache License 2.0 +MODULE FILE LICENSE: lib/gson-2.8.9.jar Apache License 2.0 MODULE FILE LICENSE: lib/bcpkix-jdk15on-1.69.jar Bouncy Castle License MODULE FILE LICENSE: lib/bcprov-jdk15on-1.69.jar Bouncy Castle License MODULE FILE LICENSE: lib/bcutil-jdk15on-1.69.jar Bouncy Castle License diff --git a/Ghidra/Framework/Generic/build.gradle b/Ghidra/Framework/Generic/build.gradle index ee89c14527..8ef6f8d064 100644 --- a/Ghidra/Framework/Generic/build.gradle +++ b/Ghidra/Framework/Generic/build.gradle @@ -35,7 +35,7 @@ dependencies { api "org.apache.commons:commons-lang3:3.9" api "org.apache.commons:commons-text:1.6" api "commons-io:commons-io:2.6" - api "com.google.code.gson:gson:2.8.6" + api "com.google.code.gson:gson:2.8.9" api 'org.bouncycastle:bcpkix-jdk15on:1.69' // requires bcutil and bcprov api 'org.bouncycastle:bcprov-jdk15on:1.69' api 'org.bouncycastle:bcutil-jdk15on:1.69' From 2965c49d19f0ab821b400ae1110c3b898cf1a502 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Wed, 29 Dec 2021 16:05:52 -0500 Subject: [PATCH 6/8] GP-1641: Upgrading log4j to 2.17.1 --- Ghidra/Features/Base/build.gradle | 2 +- Ghidra/Framework/Generic/Module.manifest | 4 ++-- Ghidra/Framework/Generic/build.gradle | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Ghidra/Features/Base/build.gradle b/Ghidra/Features/Base/build.gradle index 3779d62813..f31f75a58a 100644 --- a/Ghidra/Features/Base/build.gradle +++ b/Ghidra/Features/Base/build.gradle @@ -54,7 +54,7 @@ dependencies { runtimeOnly "org.slf4j:slf4j-nop:1.7.25" // use this if you want slf4j log messages sent to log4j - // runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:2.17.0" + // runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:2.17.1" compileOnly "junit:junit:4.12" diff --git a/Ghidra/Framework/Generic/Module.manifest b/Ghidra/Framework/Generic/Module.manifest index 2f96a05370..42ac479ef5 100644 --- a/Ghidra/Framework/Generic/Module.manifest +++ b/Ghidra/Framework/Generic/Module.manifest @@ -1,8 +1,8 @@ MODULE FILE LICENSE: lib/cglib-nodep-2.2.jar Apache License 2.0 MODULE FILE LICENSE: lib/guava-19.0.jar Apache License 2.0 MODULE FILE LICENSE: lib/jdom-legacy-1.1.3.jar JDOM License -MODULE FILE LICENSE: lib/log4j-api-2.17.0.jar Apache License 2.0 -MODULE FILE LICENSE: lib/log4j-core-2.17.0.jar Apache License 2.0 +MODULE FILE LICENSE: lib/log4j-api-2.17.1.jar Apache License 2.0 +MODULE FILE LICENSE: lib/log4j-core-2.17.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-collections4-4.1.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-lang3-3.9.jar Apache License 2.0 MODULE FILE LICENSE: lib/commons-io-2.6.jar Apache License 2.0 diff --git a/Ghidra/Framework/Generic/build.gradle b/Ghidra/Framework/Generic/build.gradle index ee89c14527..ca0a87a061 100644 --- a/Ghidra/Framework/Generic/build.gradle +++ b/Ghidra/Framework/Generic/build.gradle @@ -29,8 +29,8 @@ dependencies { api "cglib:cglib-nodep:2.2" api "com.google.guava:guava:19.0" api "org.jdom:jdom-legacy:1.1.3" - api "org.apache.logging.log4j:log4j-api:2.17.0" - api "org.apache.logging.log4j:log4j-core:2.17.0" + api "org.apache.logging.log4j:log4j-api:2.17.1" + api "org.apache.logging.log4j:log4j-core:2.17.1" api "org.apache.commons:commons-collections4:4.1" api "org.apache.commons:commons-lang3:3.9" api "org.apache.commons:commons-text:1.6" From 116b12badb9acfa5833e39d6dbb923f25bee8fef Mon Sep 17 00:00:00 2001 From: ArandomDev Date: Wed, 29 Dec 2021 13:26:01 -0500 Subject: [PATCH 7/8] Refixed relative objc methods issue in #3611. Added null check for ObjectiveC2_class. --- .../app/util/bin/format/objc2/ObjectiveC2_Class.java | 2 +- .../app/util/bin/format/objc2/ObjectiveC2_Method.java | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Class.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Class.java index 8890b16d1d..f51ef59801 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Class.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Class.java @@ -52,7 +52,7 @@ public class ObjectiveC2_Class implements StructConverter { AddressSpace space = _state.program.getAddressFactory().getDefaultAddressSpace(); Address addr = space.getAddress(_index); Symbol symbol = _state.program.getSymbolTable().getPrimarySymbol(addr); - if (symbol.getParentNamespace().getName().equals(SectionNames.SECT_GOT)) { + if (symbol != null && symbol.getParentNamespace().getName().equals(SectionNames.SECT_GOT)) { return; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java index 11ec241f45..38ed8f3b66 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java @@ -37,9 +37,13 @@ public class ObjectiveC2_Method extends ObjectiveC_Method { if (isSmallList) { int nameOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true); - int namePtr = reader.readInt(_index + nameOffset); - long imagebase = state.program.getImageBase().getOffset(); // When we support dyld_shared_cache, this base will likely have to change - name = reader.readAsciiString(imagebase + namePtr); + long namePtr; + if (state.is32bit) + namePtr = reader.readInt(_index + nameOffset); + else + namePtr = reader.readLong(_index + nameOffset); + + name = reader.readAsciiString(namePtr); int typesOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true); types = reader.readAsciiString(_index + 4 + typesOffset); From aecec8988ee99aafd6ff3f812694956320d140e2 Mon Sep 17 00:00:00 2001 From: ArandomDev Date: Wed, 29 Dec 2021 15:17:22 -0500 Subject: [PATCH 8/8] Fix formatting issues --- .../app/util/bin/format/objc2/ObjectiveC2_Method.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java index 38ed8f3b66..30519dc79d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java @@ -38,10 +38,12 @@ public class ObjectiveC2_Method extends ObjectiveC_Method { if (isSmallList) { int nameOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true); long namePtr; - if (state.is32bit) + if (state.is32bit) { namePtr = reader.readInt(_index + nameOffset); - else + } + else { namePtr = reader.readLong(_index + nameOffset); + } name = reader.readAsciiString(namePtr);