diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.ps1 b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.ps1
index c06d0bc0f5..6a58a6e93f 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.ps1
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/local-dbgeng.ps1
@@ -31,7 +31,7 @@
#@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
#@env OPT_PYTHON_ARGS:str="" "python cmd args" "Arguments passed to python (versus the target)"
#@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
-#@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
+#@env WINDBG_DIR:dir="C:\Windows\System32" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
. ..\support\dbgsetuputils.ps1
@@ -47,6 +47,7 @@ function Compute-Python-Args {
$arglist+=($Env:GHIDRA_TRACE_RMI_ADDR)
$arglist+=($Env:OPT_USE_DBGMODEL)
+ $arglist+=($Env:WINDBG_DIR)
$arglist+=($Env:OPT_TARGET_IMG)
if ("$Env:OPT_TARGET_ARGS" -ne "") {
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.ps1 b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.ps1
index 8f16c6aa0a..989005eec3 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.ps1
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.ps1
@@ -34,6 +34,7 @@
#@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
#@env OPT_PYTHON_ARGS:str="" "python cmd args" "Arguments passed to python (versus the target)"
#@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
+#@env WINDBG_DIR:dir="C:\Windows\System32" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
. ..\support\dbgsetuputils.ps1
@@ -49,6 +50,7 @@ function Compute-Python-Args {
$arglist+=("localhost:$Env:OPT_REMOTE_PORT")
$arglist+=($Env:OPT_USE_DBGMODEL)
+ $arglist+=($Env:WINDBG_DIR)
$arglist+=($Env:OPT_TARGET_PID)
$arglist+=($Env:OPT_ATTACH_FLAGS)
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.sh b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.sh
index 245bc51e58..1724e960cf 100755
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.sh
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng-attach.sh
@@ -15,7 +15,6 @@
# limitations under the License.
##
#@title dbgeng attach via ssh (shell)
-#@image-opt arg:1
#@desc
#@desc Launch with dbgeng via ssh
#@desc
@@ -36,11 +35,10 @@
#@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
#@env OPT_PYTHON_ARGS:str="" "python cmd args" "Arguments passed to python (versus the target)"
#@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
+#@env WINDBG_DIR:dir="C:\\Windows\\System32" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
. ../support/dbgsetuputils.sh
-target_image=$(echo $OPT_TARGET_IMG | sed 's/\\/\\\\/g')
-
OPT_OS_WINDOWS=true
function launch-dbg-scp() {
@@ -52,7 +50,7 @@ function launch-dbg-scp() {
function launch-dbg-ssh() {
local -a sshargs
- compute-ssh-args true "$OPT_PYTHON_EXE -i $OPT_PYTHON_ARGS .\\local-dbgeng-attach.py localhost:$OPT_REMOTE_PORT $OPT_USE_DBGMODEL $OPT_TARGET_PID $OPT_ATTACH_FLAGS"
+ compute-ssh-args true "$OPT_PYTHON_EXE -i $OPT_PYTHON_ARGS .\\local-dbgeng-attach.py localhost:$OPT_REMOTE_PORT $OPT_USE_DBGMODEL $WINDBG_DIR $OPT_TARGET_PID $OPT_ATTACH_FLAGS"
"${sshargs[@]}"
}
@@ -98,7 +96,9 @@ finished, try launching again.
" "Would you like to install 'ghidradbg>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into Python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.ps1 b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.ps1
index e1eca494ce..e49a0b0da4 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.ps1
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.ps1
@@ -26,7 +26,7 @@
#@icon icon.debugger
#@help dbgeng#ssh
#@depends Debugger-rmi-trace
-#@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image"
+#@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image"
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
#@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
#@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
@@ -35,6 +35,7 @@
#@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
#@env OPT_PYTHON_ARGS:str="" "python cmd args" "Arguments passed to python (versus the target)"
#@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
+#@env WINDBG_DIR:dir="C:\Windows\System32" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
. ..\support\dbgsetuputils.ps1
@@ -50,6 +51,7 @@ function Compute-Python-Args {
$arglist+=("localhost:$Env:OPT_REMOTE_PORT")
$arglist+=($Env:OPT_USE_DBGMODEL)
+ $arglist+=($Env:WINDBG_DIR)
$arglist+=($Env:OPT_TARGET_IMG)
if ("$Env:OPT_TARGET_ARGS" -ne "") {
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.sh b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.sh
index a5bc2814c6..cad4770fb8 100755
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.sh
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers/ssh-dbgeng.sh
@@ -15,7 +15,7 @@
# limitations under the License.
##
#@title dbgeng via ssh (shell)
-#@image-opt arg:1
+#@image-opt env:OPT_TARGET_IMG
#@desc
#@desc Launch with dbgeng via ssh
#@desc
@@ -27,7 +27,7 @@
#@icon icon.debugger
#@help dbgeng#ssh
#@depends Debugger-rmi-trace
-#@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image"
+#@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image"
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
#@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
#@env OPT_HOST:str="localhost" "[User@]Host" "The hostname or user@host"
@@ -36,6 +36,7 @@
#@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
#@env OPT_PYTHON_ARGS:str="" "python cmd args" "Arguments passed to python (versus the target)"
#@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
+#@env WINDBG_DIR:dir="C:\\Windows\\System32" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
. ../support/dbgsetuputils.sh
@@ -52,7 +53,7 @@ function launch-dbg-scp() {
function launch-dbg-ssh() {
local -a sshargs
- compute-ssh-args true "$OPT_PYTHON_EXE -i $OPT_PYTHON_ARGS .\\local-dbgeng.py localhost:$OPT_REMOTE_PORT $OPT_USE_DBGMODEL $target_image $OPT_TARGET_ARGS"
+ compute-ssh-args true "$OPT_PYTHON_EXE -i $OPT_PYTHON_ARGS .\\local-dbgeng.py localhost:$OPT_REMOTE_PORT $OPT_USE_DBGMODEL $WINDBG_DIR $target_image $OPT_TARGET_ARGS"
"${sshargs[@]}"
}
@@ -98,7 +99,9 @@ finished, try launching again.
" "Would you like to install 'ghidradbg>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into Python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/dbgsetuputils.sh b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/dbgsetuputils.sh
index 6b6a4f1aae..d26299b3a6 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/dbgsetuputils.sh
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/dbgsetuputils.sh
@@ -20,5 +20,5 @@ compute-dbg-pipinstall-args() {
printf -v argvpart ", %s" "$@"
pipargs=("$OPT_PYTHON_EXE")
pipargs+=(-c)
- pipargs+=("import os, sys, runpy; sys.argv=['pip', 'install', '--force-reinstall'$argvpart]; os.environ['PIP_BREAK_SYSTEM_PACKAGE']='1'; runpy.run_module('pip', run_name='__main__')")
+ pipargs+=("\"import os, sys, runpy; sys.argv=['pip', 'install', '--force-reinstall'$argvpart]; os.environ['PIP_BREAK_SYSTEM_PACKAGE']='1'; runpy.run_module('pip', run_name='__main__')\"")
}
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py
index 5e19000364..fe460efa9a 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/kernel-dbgeng.py
@@ -28,7 +28,13 @@ def append_paths():
def main():
append_paths()
+
# Delay these imports until sys.path is patched
+ try:
+ import ghidradbg
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from ghidradbg import util
from pybag.dbgeng import core as DbgEng
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py
index bb0aca17eb..9e8b89c1b9 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-attach.py
@@ -27,14 +27,17 @@ def parse_parameters():
global cxn, target, args
os.environ['OPT_OS_WINDOWS'] = "true"
argc = len(sys.argv)
+ # This is the .bat case:
if argc == 1:
return True
- if argc >= 4:
+ # Local and remote .ps1 cases
+ if argc >= 5:
cxn = sys.argv[1]
os.environ['OPT_USE_DBGMODEL'] = sys.argv[2]
- target = sys.argv[3]
- if argc > 4:
- args = sys.argv[4]
+ os.environ['WINDBG_DIR'] = sys.argv[3]
+ target = sys.argv[4]
+ if argc > 5:
+ args = sys.argv[5]
return True
print("Error: expected (cxn, use_dbgmodel, target, ...)")
return False
@@ -59,8 +62,9 @@ def main():
# Delay these imports until sys.path is patched
try:
import ghidradbg
- except Exception as e:
- exit(253)
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
from ghidradbg.hooks import on_state_changed
@@ -91,7 +95,5 @@ if __name__ == '__main__':
try:
main()
except SystemExit as x:
- if x.code == 253:
- exit(253)
if x.code != 0:
print(f"Exited with code {x.code}")
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py
index 61d43273cf..11ea78538c 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-ext.py
@@ -28,7 +28,13 @@ def append_paths():
def main():
append_paths()
+
# Delay these imports until sys.path is patched
+ try:
+ import ghidradbg
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
from ghidradbg.hooks import on_state_changed
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py
index 412522001d..a1c6ce787d 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng-trace.py
@@ -28,7 +28,13 @@ def append_paths():
def main():
append_paths()
+
# Delay these imports until sys.path is patched
+ try:
+ import ghidradbg
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
from ghidradbg.hooks import on_state_changed
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py
index e8e4671b56..3b75e33446 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-dbgeng.py
@@ -26,16 +26,19 @@ args = os.getenv('OPT_TARGET_ARGS')
def parse_parameters():
global cxn, target, args
argc = len(sys.argv)
+ # This is the .bat case:
if argc == 1:
return True
- if argc >= 4:
+ # Local and remote .ps1 cases
+ if argc >= 5:
cxn = sys.argv[1]
os.environ['OPT_USE_DBGMODEL'] = sys.argv[2]
- target = sys.argv[3]
- if argc > 4:
- args = sys.argv[4]
+ os.environ['WINDBG_DIR'] = sys.argv[3]
+ target = sys.argv[4]
+ if argc > 5:
+ args = sys.argv[5]
return True
- print("Error: expected (cxn, use_dbgmodel, target, ...)")
+ print("Error: expected (cxn, use_dbgmodel, windbg_dir, target, ...)")
return False
def append_paths():
@@ -52,14 +55,16 @@ def append_paths():
def main():
global cxn, target, args
append_paths()
+
if parse_parameters() is False:
return
# Delay these imports until sys.path is patched
try:
import ghidradbg
- except:
- exit(253)
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
from ghidradbg.hooks import on_state_changed
@@ -97,7 +102,5 @@ if __name__ == '__main__':
try:
main()
except SystemExit as x:
- if x.code == 253:
- exit(253)
if x.code != 0:
print(f"Exited with code {x.code}")
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py
index 657883c4de..24ad78f7e7 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/remote-dbgeng.py
@@ -28,7 +28,13 @@ def append_paths():
def main():
append_paths()
+
# Delay these imports until sys.path is patched
+ try:
+ import ghidradbg
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
from ghidradbg.hooks import on_state_changed
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py
index f99f94654b..11227a30a2 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/data/support/svrcx-dbgeng.py
@@ -28,7 +28,13 @@ def append_paths():
def main():
append_paths()
+
# Delay these imports until sys.path is patched
+ try:
+ import ghidradbg
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
from ghidradbg.hooks import on_state_changed
diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/help/help/topics/dbgeng/dbgeng.html b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/help/help/topics/dbgeng/dbgeng.html
index c13e013a87..93de4d0ef1 100644
--- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/help/help/topics/dbgeng/dbgeng.html
+++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/help/help/topics/dbgeng/dbgeng.html
@@ -35,6 +35,26 @@
might work around this by copying the affected DLLs from your WinDbg installation into your
Python installation.
+ Also worth noting, there are now two local launchers, the original .bat-based launcher and a
+ newer .ps1-based launcher. The powershell launcher is not signed. You must therefore set the
+ current user's execution policy or permissions on the script:
+
+
+
Setup
Installing WinDbg is highly recommended. If you wish to forego installing WinDbg, you can
@@ -48,7 +68,7 @@
@@ -123,7 +143,7 @@ python3 -m pip install --no-index -f Debugger-rmi-trace\pypkg\dist -f Debugger-a
Env: This is a composite string containg Environment Variable entries delineated
by '/0' separators. For example, you could redefine USERNAME and USERPROFILE with the entry
- 'USERNAME=SomeUser/0USERPROFILE=C:\Users\SomeUser'.
+ "USERNAME=SomeUser/0USERPROFILE=C:\Users\SomeUser".
CreateFlags: Flags used when creating the process, typically either
DEBUG_PROCESS(1) or DEBUG_ONLY_THIS_PROCESS(2) if you do not wish to follow spawned
@@ -163,42 +183,45 @@ python3 -m pip install --no-index -f Debugger-rmi-trace\pypkg\dist -f Debugger-a
Connection: This is the connection string specifying the transport options for
communicating with the remote debugger. A typical example might be
- 'tcp:port=12345,server=192.168.0.2' for a debugger that has issued the command
+ "tcp:port=12345,server=192.168.0.2" for a debugger that has issued the command
.server tcp:port=12345
- Remote via SSH
+ Remote via SSH
- "ssh-dbgeng" is the remote equivalent to "dbgeng";
- "ssh-dbgeng-attach" is the remote equivalent to "dbgeng-attach".
-
+ "ssh-dbgeng" is the remote equivalent to "dbgeng";
+ "ssh-dbgeng-attach" is the remote equivalent to "dbgeng-attach".
- Setup
+ Setup
- Instructions are indentical to those above but executed on the remote machine.
+ Instructions are identical to those above but executed on the remote machine. Both of these
+ commands are now implemented via powershell, so the same caveats listed above for the local
+ .ps1 launcher apply here, i.e. you will need to set the current user's execution policy or
+ permissions on the script. Separate launchers have also been added for starting the debugger on
+ a remote Windows box from a local Linux machine.
- Additional Options
+ Additional Options
-
- - ssh command: The ssh command to execute, optionaly with full path.
-
- - [User@]Host: This is the host name of the target system, optionally including a
- user name. This is passed as is to ssh, which may interpret it according to local
- configuration.
+
+ - ssh command: The ssh command to execute, optionaly with full path.
- - Remote Trace RMI Port: An available TCP port on the target system, which will
- listen for dbgeng's Trace RMI connection and forward it back to Ghidra.
+ - [User@]Host: This is the host name of the target system, optionally including a
+ user name. This is passed as is to ssh, which may interpret it according to local
+ configuration.
- - Extra ssh arguments: These are extra arguments to pass to ssh.
- They are inserted immediately after the ssh command but before the host name. Beware
- that syntax errors may cause strange behavior, and that not all features may be compatible
- with this launcher.
-
+ - Remote Trace RMI Port: An available TCP port on the target system, which will
+ listen for dbgeng's Trace RMI connection and forward it back to Ghidra.
- Process Server
+ - Extra ssh arguments: These are extra arguments to pass to ssh.
+ They are inserted immediately after the ssh command but before the host name. Beware
+ that syntax errors may cause strange behavior, and that not all features may be compatible
+ with this launcher.
+
+
+ Process Server
The "dbgeng-svrcx" launcher extends the base dbgeng launcher adding an option for
connecting through a remote process server.
@@ -209,11 +232,10 @@ python3 -m pip install --no-index -f Debugger-rmi-trace\pypkg\dist -f Debugger-a
Connection: This is the connection string specifying the transport options for
communicating with the remote server. A typical example might be
- 'tcp:port=12345,server=192.168.0.2' for a process server launched on the machine at
- 192.168.0.2 using:
+ "tcp:port=12345,server=192.168.0.2" for a process server launched on the machine
+ at 192.168.0.2 using:
- dbgsrv -t tcp:port=12345
-
+dbgsrv -t tcp:port=12345
diff --git a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh
index ae9ca68063..ddbb042b10 100755
--- a/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh
+++ b/Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers/core-drgn.sh
@@ -15,6 +15,7 @@
# limitations under the License.
##
#@title drgn core
+#@image-opt env:OPT_TARGET_IMG
#@desc
#@desc Launch with drgn-core
#@desc
diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb-win.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb-win.sh
index f0b0cab724..fa5f10d55b 100755
--- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb-win.sh
+++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb-win.sh
@@ -118,7 +118,9 @@ finished, try launching again.
" "Would you like to install 'ghidragdb>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into GDB's embedded Python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh
index fc24b26ffe..17699e4247 100755
--- a/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh
+++ b/Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers/ssh-gdb.sh
@@ -94,7 +94,9 @@ finished, try launching again.
" "Would you like to install 'ghidragdb>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into GDB's embedded Python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb-win.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb-win.sh
index 4512ec16bb..ebe3cd1247 100755
--- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb-win.sh
+++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb-win.sh
@@ -116,7 +116,9 @@ finished, try launching again.
" "Would you like to install 'ghidralldb>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into LLDB's embedded Python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh
index d70580f336..12148796ac 100755
--- a/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh
+++ b/Ghidra/Debug/Debugger-agent-lldb/data/debugger-launchers/ssh-lldb.sh
@@ -93,7 +93,9 @@ finished, try launching again.
" "Would you like to install 'ghidralldb>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into LLDB's embedded Python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg-attach.sh b/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg-attach.sh
index 440f1a4cb7..f0bc543db4 100755
--- a/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg-attach.sh
+++ b/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg-attach.sh
@@ -15,7 +15,6 @@
# limitations under the License.
##
#@title x64dbg attach via ssh (shell)
-#@image-opt arg:1
#@desc
#@desc Launch with x64dbg via ssh
#@desc
@@ -39,7 +38,6 @@
. ../support/x64dbgsetuputils.sh
-target_image=$(echo $OPT_TARGET_IMG | sed 's/\\/\\\\/g')
x64dbg_exe=$(echo $OPT_X64DBG_EXE | sed 's/\\/\\\\/g')
OPT_OS_WINDOWS=true
@@ -62,7 +60,7 @@ version=$(get-ghidra-version)
function do-installation() {
local -a pipargs
- compute-dbg-pipinstall-args "'-f'" "os.environ['HOME']" "'ghidraxdbg>=$version'"
+ compute-x64dbg-pipinstall-args "'-f'" "os.environ['HOME']" "'ghidraxdbg>=$version'"
local -a sshargs
compute-ssh-args false "${pipargs[@]}"
@@ -96,10 +94,12 @@ are copied and installed.
NOTE: Automatic resolution will cause this session to terminate. When it has
finished, try launching again.
-" "Would you like to install 'ghidradbg>=$version'?"; then
+" "Would you like to install 'ghidraxdbg>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.ps1 b/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.ps1
index 075668c2d5..f5e15b82f3 100644
--- a/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.ps1
+++ b/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.ps1
@@ -26,7 +26,7 @@
#@icon icon.debugger
#@help x64dbg#ssh
#@depends Debugger-rmi-trace
-#@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image"
+#@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image"
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
#@env OPT_TARGET_DIR:str="" "Dir" "Initial directory"
#@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
diff --git a/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.sh b/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.sh
index 045bdc06fd..aab164e86a 100755
--- a/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.sh
+++ b/Ghidra/Debug/Debugger-agent-x64dbg/data/debugger-launchers/ssh-x64dbg.sh
@@ -15,7 +15,7 @@
# limitations under the License.
##
#@title x64dbg via ssh (shell)
-#@image-opt arg:1
+#@image-opt env:OPT_TARGET_IMG
#@desc
#@desc Launch with x64dbg via ssh
#@desc
@@ -27,7 +27,7 @@
#@icon icon.debugger
#@help x64dbg#ssh
#@depends Debugger-rmi-trace
-#@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image"
+#@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image"
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
#@env OPT_TARGET_DIR:str="" "Dir" "Initial directory"
#@env OPT_SSH_PATH:file="ssh" "ssh command" "The path to ssh on the local system. Omit the full path to resolve using the system PATH."
@@ -97,10 +97,12 @@ are copied and installed.
NOTE: Automatic resolution will cause this session to terminate. When it has
finished, try launching again.
-" "Would you like to install 'ghidradbg>=$version'?"; then
+" "Would you like to install 'ghidraxdbg>=$version'?"; then
echo "Copying Wheels to $OPT_HOST"
- mitigate-scp-pymodules "Debugger-rmi-trace" ""
+ if ! mitigate-scp-pymodules "Debugger-rmi-trace" ""; then
+ exit 1
+ fi
echo "Installing Wheels into python"
do-installation
diff --git a/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg-attach.py b/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg-attach.py
index 69a1570bee..2f35f98d80 100644
--- a/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg-attach.py
+++ b/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg-attach.py
@@ -55,8 +55,9 @@ def main():
# Delay these imports until sys.path is patched
try:
import ghidraxdbg
- except:
- exit(253)
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidraxdbg import commands as cmd
from ghidraxdbg.hooks import on_state_changed
from ghidraxdbg.util import dbg
@@ -86,7 +87,5 @@ if __name__ == '__main__':
try:
main()
except SystemExit as x:
- if x.code == 253:
- exit(253)
if x.code != 0:
print(f"Exited with code {x.code}")
diff --git a/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg.py b/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg.py
index d5aacc64e0..d763be24ae 100644
--- a/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg.py
+++ b/Ghidra/Debug/Debugger-agent-x64dbg/data/support/local-x64dbg.py
@@ -65,8 +65,9 @@ def main():
# Delay these imports until sys.path is patched
try:
import ghidraxdbg
- except Exception as e:
- exit(253)
+ except ModuleNotFoundError:
+ os._exit(253)
+
from ghidraxdbg import commands as cmd
from ghidraxdbg.hooks import on_state_changed
from ghidraxdbg.util import dbg
@@ -100,7 +101,5 @@ if __name__ == '__main__':
try:
main()
except SystemExit as x:
- if x.code == 253:
- exit(253)
if x.code != 0:
print(f"Exited with code {x.code}")
diff --git a/Ghidra/Debug/Debugger-agent-x64dbg/data/support/x64dbgsetuputils.sh b/Ghidra/Debug/Debugger-agent-x64dbg/data/support/x64dbgsetuputils.sh
index a25de6975e..d7520001f5 100644
--- a/Ghidra/Debug/Debugger-agent-x64dbg/data/support/x64dbgsetuputils.sh
+++ b/Ghidra/Debug/Debugger-agent-x64dbg/data/support/x64dbgsetuputils.sh
@@ -20,5 +20,5 @@ compute-x64dbg-pipinstall-args() {
printf -v argvpart ", %s" "$@"
pipargs=("$OPT_PYTHON_EXE")
pipargs+=(-c)
- pipargs+=("import os, sys, runpy; sys.argv=['pip', 'install', '--force-reinstall'$argvpart]; os.environ['PIP_BREAK_SYSTEM_PACKAGE']='1'; runpy.run_module('pip', run_name='__main__')")
+ pipargs+=("\"import os, sys, runpy; sys.argv=['pip', 'install', '--force-reinstall'$argvpart]; os.environ['PIP_BREAK_SYSTEM_PACKAGE']='1'; runpy.run_module('pip', run_name='__main__')\"")
}
diff --git a/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh b/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh
index ed927a2223..5094f14f5f 100644
--- a/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh
+++ b/Ghidra/Debug/Debugger-rmi-trace/data/support/setuputils.sh
@@ -90,9 +90,6 @@ compute-ssh-args() {
printf -v qargs '%q ' "$@"
sshargs+=("$OPT_SSH_PATH")
- if [ -n "$OPT_OS_WINDOWS" ]; then
- sshargs+=(-t)
- fi
if [ "$forward" == "true" ]; then
sshargs+=("-R$OPT_REMOTE_PORT:$GHIDRA_TRACE_RMI_ADDR")
fi
@@ -142,6 +139,9 @@ mitigate-scp-pymodules() {
local -a scpargs
for mod in "$@"; do
dist=$(ghidra-module-pydist "$mod")
+ if [ "$?" -ne "0" ]; then
+ return 1
+ fi
scpargs+=("$dist"/*)
done
scp "${scpargs[@]}" "$OPT_HOST:~/"
diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java
index ab5b0d04b7..b645dc303c 100644
--- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java
+++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/AbstractRmiConnectorsTest.java
@@ -15,11 +15,14 @@
*/
package agent;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.Method;
+import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
@@ -33,14 +36,14 @@ import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesPlugin;
import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.NoStaticMappingException;
import ghidra.app.plugin.core.debug.gui.tracermi.launcher.TraceRmiLauncherServicePlugin;
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
-import ghidra.app.services.DebuggerAutoMappingService;
-import ghidra.app.services.TraceRmiLauncherService;
+import ghidra.app.services.*;
import ghidra.debug.api.ValStr;
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer;
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.*;
import ghidra.framework.Application;
import ghidra.framework.OperatingSystem;
import ghidra.framework.plugintool.AutoConfigState.PathIsFile;
+import ghidra.pty.*;
import ghidra.util.SystemUtilities;
public abstract class AbstractRmiConnectorsTest
@@ -52,9 +55,29 @@ public abstract class AbstractRmiConnectorsTest
return "python";
}
+ @Target(ElementType.METHOD)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface NoLocalSetup {
+ }
+
+ boolean localSetup() throws Exception {
+ Method method = null;
+ try {
+ method = getClass().getMethod(name.getMethodName());
+ }
+ catch (NoSuchMethodException e) {
+ return true;
+ }
+ NoLocalSetup annotation = method.getAnnotation(NoLocalSetup.class);
+ return annotation == null;
+ }
+
protected abstract List getPipLinkModules();
protected void unpip(String... specs) throws Exception {
+ if (!localSetup()) {
+ return;
+ }
List args = new ArrayList<>();
args.addAll(List.of(getPythonCmd(), "-m", "pip", "uninstall", "-y"));
args.addAll(List.of(specs));
@@ -63,6 +86,9 @@ public abstract class AbstractRmiConnectorsTest
}
protected void pipOob(String... specs) throws Exception {
+ if (!localSetup()) {
+ return;
+ }
List args = new ArrayList<>();
args.addAll(List.of(getPythonCmd(), "-m", "pip", "install"));
args.addAll(List.of(specs));
@@ -71,6 +97,9 @@ public abstract class AbstractRmiConnectorsTest
}
protected void pip(String... specs) throws Exception {
+ if (!localSetup()) {
+ return;
+ }
List args = new ArrayList<>();
args.addAll(List.of(getPythonCmd(), "-m", "pip", "install", "--no-index"));
for (ResourceFile root : Application.getApplicationRootDirectories()) {
@@ -90,6 +119,20 @@ public abstract class AbstractRmiConnectorsTest
assertEquals("pip failed", 0, result);
}
+ protected int runInTerminal(List command, Map env)
+ throws IOException, InterruptedException {
+ TerminalService terminalService = tool.getService(TerminalService.class);
+ if (terminalService == null) {
+ throw new NullPointerException("Terminal Service is not installed in test tool");
+ }
+ try (Pty pty = PtyFactory.local().openpty();
+ Terminal term = terminalService.createWithStreams(Charset.forName("utf8"),
+ pty.getParent().getInputStream(), pty.getParent().getOutputStream())) {
+ PtySession session = pty.getChild().session(command.toArray(String[]::new), env);
+ return session.waitExited();
+ }
+ }
+
protected boolean isWindows() {
return OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS;
}
diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java
index c7229cc2a2..86c4ba09f2 100644
--- a/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java
+++ b/Ghidra/Test/DebuggerIntegrationTest/src/test.slow/java/agent/dbgeng/rmi/DbgEngConnectorsTest.java
@@ -18,11 +18,14 @@ package agent.dbgeng.rmi;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
+import static org.junit.Assume.*;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
+import javax.swing.JOptionPane;
+
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
@@ -30,9 +33,11 @@ import org.junit.Test;
import agent.AbstractRmiConnectorsTest;
import generic.jar.ResourceFile;
import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.EarlyTerminationException;
+import ghidra.app.plugin.core.debug.gui.tracermi.launcher.AbstractTraceRmiLaunchOffer.NoStaticMappingException;
import ghidra.debug.api.tracermi.TraceRmiLaunchOffer.LaunchResult;
import ghidra.framework.Application;
import ghidra.framework.plugintool.AutoConfigState.PathIsFile;
+import ghidra.pty.testutil.DummyProc;
public class DbgEngConnectorsTest extends AbstractRmiConnectorsTest {
@@ -122,8 +127,8 @@ public class DbgEngConnectorsTest extends AbstractRmiConnectorsTest {
public void testDbgViaSsh() throws Exception {
pip("ghidradbg==%s".formatted(Application.getApplicationVersion()));
try (LaunchResult result = doLaunch("dbgeng via ssh", Map.ofEntries(
- Map.entry("env:OPT_TARGET_IMG", chooseImage()),
- Map.entry("OPT_HOST", "localhost")))) {
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", "localhost")))) {
checkResult(result);
}
}
@@ -136,15 +141,16 @@ public class DbgEngConnectorsTest extends AbstractRmiConnectorsTest {
// Overwrite with an incompatible version we don't include
pipOob("protobuf==3.19.0");
try (LaunchResult result = doLaunch("dbgeng via ssh", Map.ofEntries(
- Map.entry("env:OPT_TARGET_IMG", chooseImage()),
- Map.entry("OPT_HOST", "localhost")))) {
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", "localhost")))) {
+ // If the next line fails, make sure "python" on your box is 3.13
assertTrue(result.exception() instanceof EarlyTerminationException);
assertThat(result.sessions().get("Shell").content(),
Matchers.containsString("Would you like to install"));
}
try (LaunchResult result = doLaunch("dbgeng via ssh", Map.ofEntries(
- Map.entry("env:OPT_TARGET_IMG", chooseImage()),
- Map.entry("OPT_HOST", "localhost")))) {
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", "localhost")))) {
checkResult(result);
}
}
@@ -152,19 +158,53 @@ public class DbgEngConnectorsTest extends AbstractRmiConnectorsTest {
@Test
public void testDbgViaSshSetupGhidraDbg() throws Exception {
try (LaunchResult result = doLaunch("dbgeng via ssh", Map.ofEntries(
- Map.entry("env:OPT_TARGET_IMG", chooseImage()),
- Map.entry("OPT_HOST", "localhost")))) {
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", "localhost")))) {
+ // If the next line fails, make sure "python" on your box is 3.13
assertTrue(result.exception() instanceof EarlyTerminationException);
assertThat(result.sessions().get("Shell").content(),
Matchers.containsString("Would you like to install"));
}
try (LaunchResult result = doLaunch("dbgeng via ssh", Map.ofEntries(
- Map.entry("env:OPT_TARGET_IMG", chooseImage()),
- Map.entry("OPT_HOST", "localhost")))) {
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", "localhost")))) {
checkResult(result);
}
}
+ @Test
+ @NoLocalSetup
+ public void testLinuxToDbgViaSshSetupGhidraDbg() throws Exception {
+ assumeFalse(isWindows());
+
+ String hostname = JOptionPane.showInputDialog("Windows Hostname");
+
+ assertEquals(0, runInTerminal(
+ List.of(DummyProc.which("ssh"), hostname, "pip uninstall ghidradbg"), null));
+
+ try (LaunchResult result = doLaunch("dbgeng via ssh (shell)", Map.ofEntries(
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", hostname)))) {
+ assertTrue(result.exception() instanceof EarlyTerminationException);
+ assertThat(result.sessions().get("Shell").content(),
+ Matchers.containsString("Would you like to install"));
+ }
+ try (LaunchResult result = doLaunch("dbgeng via ssh (shell)", Map.ofEntries(
+ Map.entry("env:OPT_TARGET_IMG", chooseImage().toString()),
+ Map.entry("env:OPT_HOST", hostname)))) {
+ checkResult(result);
+ }
+ }
+
+ @Override
+ protected void checkResult(LaunchResult result) {
+ // Exits to python shell, requires quit which generates early term exc.
+ if (result.exception() != null &&
+ !(result.exception() instanceof EarlyTerminationException) &&
+ !(result.exception() instanceof NoStaticMappingException)) {
+ throw new AssertionError(result);
+ }
+ }
// LATER?: kernel
// LATER?: attach (usermode by PID)
// LATER?: ext