GP-6401: better setuptuils

GP-6401: missed one
GP-6401: more re-run tweaks
GP-6401: allow re-run
GP-6401: minor fixes
GP-6401: post-review
GP-6401: help
GP-6401: attach variants
GP-6401: opt dbgmodel
GP-6401: args fix
GP-6401: better x64dbg
GP-6401: simpler dbgeng
GP-6401: x64dbg impl
GP-6401: first pass w/ file
GP-6401: first pass w/ file
GP-6401: first successful attempt
This commit is contained in:
d-millar
2026-02-13 12:51:27 -05:00
parent a945505ee0
commit e1776460c4
21 changed files with 835 additions and 43 deletions

View File

@@ -13,7 +13,7 @@
:: See the License for the specific language governing permissions and
:: limitations under the License.
:: ##
::@title dbgeng
::@title dbgeng (.bat)
::@image-opt env:OPT_TARGET_IMG
::@desc <html><body width="300px">
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>

View File

@@ -0,0 +1,66 @@
## ###
# IP: GHIDRA
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
#@title dbgeng (.ps1)
#@image-opt env:OPT_TARGET_IMG
#@desc <html><body width="300px">
#@desc <h3>Launch with <tt>dbgeng</tt></h3>
#@desc <p>
#@desc This will launch the target on the local machine using <tt>dbgeng</tt>.
#@desc For setup instructions, press <b>F1</b>.
#@desc </p>
#@desc </body></html>
#@menu-group dbgeng
#@icon icon.debugger
#@help dbgeng#local
#@depends Debugger-rmi-trace
#@arg :file "Image" "The target binary executable image"
#@env OPT_TARGET_IMG:file="" "Image" "The target binary executable image"
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
#@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)."
. ..\support\dbgsetuputils.ps1
function Compute-Python-Args {
param($TempFile)
$arglist = @("$Env:OPT_PYTHON_EXE")
if ("$Env:OPT_PYTHON_ARGS" -ne "") {
$arglist+=($Env:OPT_PYTHON_ARGS)
}
$arglist+=($TempFile)
$arglist+=($Env:GHIDRA_TRACE_RMI_ADDR)
$arglist+=($Env:OPT_USE_DBGMODEL)
$arglist+=($Env:OPT_TARGET_IMG)
if ("$Env:OPT_TARGET_ARGS" -ne "") {
$arglist+=($Env:OPT_TARGET_ARGS)
}
return $arglist
}
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
$pypathDbg = Ghidra-Module-PyPath
$Env:PYTHONPATH = "$pypathDbg;$pypathTrace;$Env:PYTHONPATH"
$tmpfile = "..\support\local-dbgeng.py"
$arglist = Compute-Python-Args -TempFile $tmpfile
Start-Process -FilePath $arglist[0] -ArgumentList $arglist[1..$arglist.Count] `
-NoNewWindow -Wait

View File

@@ -0,0 +1,102 @@
## ###
# IP: GHIDRA
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
#@title dbgeng attach via ssh
#@desc <html><body width="300px">
#@desc <h3>Attach with <tt>dbgeng</tt> (in a Python interpreter)</h3>
#@desc <p>
#@desc This will attach to a running target on the local machine using <tt>dbgeng.dll</tt>.
#@desc For setup instructions, press <b>F1</b>.
#@desc </p>
#@desc </body></html>
#@menu-group dbgeng
#@icon icon.debugger
#@help dbgeng#ssh
#@depends Debugger-rmi-trace
#@env OPT_TARGET_PID:int=0 "Process id" "The target process id"
#@env OPT_ATTACH_FLAGS:int=0 "Attach flags" "Attach flags"
#@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"
#@env OPT_REMOTE_PORT:int=12345 "Remote Trace RMI Port" "A free port on the remote end to receive and forward the Trace RMI connection."
#@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
#@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."
. ..\support\dbgsetuputils.ps1
function Compute-Python-Args {
param($TempFile)
$arglist = @("$Env:OPT_PYTHON_EXE")
if ("$Env:OPT_PYTHON_ARGS" -ne "") {
$arglist+=($Env:OPT_PYTHON_ARGS)
}
$arglist+=($TempFile)
$arglist+=("localhost:$Env:OPT_REMOTE_PORT")
$arglist+=($Env:OPT_USE_DBGMODEL)
$arglist+=($Env:OPT_TARGET_PID)
$arglist+=($Env:OPT_ATTACH_FLAGS)
return $arglist
}
$tmpfile = "local-dbgeng-attach.py"
$arglist = Compute-Python-Args -TempFile $tmpfile
$scpargs = Compute-Scp-Args "..\support\$tmpfile"
$sshargs = Compute-Ssh-Args $arglist True
$scpproc = Start-Process -FilePath $scpargs[0] -ArgumentList $scpargs[1..$scpargs.Count] -NoNewWindow -Wait -PassThru
$sshproc = Start-Process -FilePath $sshargs[0] -ArgumentList $sshargs[1..$sshargs.Count] -NoNewWindow -Wait -PassThru
$version = Get-Ghidra-Version
$answer = Check-Result-And-Prompt-Mitigation $sshproc @"
It appears ghidradbg is missing from the remote system. This can happen if you
forgot to install the required package. This can also happen if you installed
the packages to a different Python environment than is being used by the
remote's gdb.
This script is about to offer automatic resolution. If you'd like to resolve
this manually, answer no to the next question and then see Ghidra's help by
pressing F1 in the dialog of launch parameters.
WARNING: Answering yes to the next question will invoke pip to try to install
missing or incorrectly-versioned dependencies. It may attempt to find packages
from the PyPI mirror configured on the REMOTE system. If you have not configured
one, it will connect to the official one.
WARNING: We invoke pip with the --break-system-packages flag, because some
debuggers that embed Python (gdb, lldb) may not support virtual environments,
and so the packages must be installed to your user environment.
NOTE: This will copy Python wheels into the HOME directory of the user on the
remote system. You may be prompted to authenticate a few times while packages
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'?"
if ($answer) {
Write-Host "Copying Wheels to $Env:OPT_HOST"
Mitigate-Scp-PyModules "Debugger-rmi-trace" "<SELF>"
Write-Host "Installing Wheels into python"
$arglist = Compute-Dbg-PipInstall-Args "'-f'" "os.environ['HOME']" "'ghidradbg>=$version'"
$sshargs = Compute-Ssh-Args $arglist False
Start-Process -FilePath $sshargs[0] -ArgumentList $sshargs[1..$sshargs.Count] -NoNewWindow -Wait
}

View File

@@ -0,0 +1,105 @@
## ###
# IP: GHIDRA
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
#@title dbgeng via ssh
#@image-opt env:OPT_TARGET_IMG
#@desc <html><body width="300px">
#@desc <h3>Launch with <tt>dbgeng</tt> via <tt>ssh</tt></h3>
#@desc <p>
#@desc This will start <tt>dbgeng</tt> on the remote system via a Python interpreter.
#@desc For setup instructions, press <b>F1</b>.
#@desc </p>
#@desc </body></html>
#@menu-group dbgeng
#@icon icon.debugger
#@help dbgeng#ssh
#@depends Debugger-rmi-trace
#@env OPT_TARGET_IMG:file="" "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"
#@env OPT_REMOTE_PORT:int=12345 "Remote Trace RMI Port" "A free port on the remote end to receive and forward the Trace RMI connection."
#@env OPT_EXTRA_SSH_ARGS:str="" "Extra ssh arguments" "Extra arguments to pass to ssh. Use with care."
#@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."
. ..\support\dbgsetuputils.ps1
function Compute-Python-Args {
param($TempFile)
$arglist = @("$Env:OPT_PYTHON_EXE")
if ("$Env:OPT_PYTHON_ARGS" -ne "") {
$arglist+=($Env:OPT_PYTHON_ARGS)
}
$arglist+=($TempFile)
$arglist+=("localhost:$Env:OPT_REMOTE_PORT")
$arglist+=($Env:OPT_USE_DBGMODEL)
$arglist+=($Env:OPT_TARGET_IMG)
if ("$Env:OPT_TARGET_ARGS" -ne "") {
$arglist+=($Env:OPT_TARGET_ARGS)
}
return $arglist
}
$tmpfile = "local-dbgeng.py"
$arglist = Compute-Python-Args -TempFile $tmpfile
$scpargs = Compute-Scp-Args "..\support\$tmpfile"
$sshargs = Compute-Ssh-Args $arglist True
$scpproc = Start-Process -FilePath $scpargs[0] -ArgumentList $scpargs[1..$scpargs.Count] -NoNewWindow -Wait -PassThru
$sshproc = Start-Process -FilePath $sshargs[0] -ArgumentList $sshargs[1..$sshargs.Count] -NoNewWindow -Wait -PassThru
$version = Get-Ghidra-Version
$answer = Check-Result-And-Prompt-Mitigation $sshproc @"
It appears ghidradbg is missing from the remote system. This can happen if you
forgot to install the required package. This can also happen if you installed
the packages to a different Python environment than is being used by the
remote's gdb.
This script is about to offer automatic resolution. If you'd like to resolve
this manually, answer no to the next question and then see Ghidra's help by
pressing F1 in the dialog of launch parameters.
WARNING: Answering yes to the next question will invoke pip to try to install
missing or incorrectly-versioned dependencies. It may attempt to find packages
from the PyPI mirror configured on the REMOTE system. If you have not configured
one, it will connect to the official one.
WARNING: We invoke pip with the --break-system-packages flag, because some
debuggers that embed Python (gdb, lldb) may not support virtual environments,
and so the packages must be installed to your user environment.
NOTE: This will copy Python wheels into the HOME directory of the user on the
remote system. You may be prompted to authenticate a few times while packages
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'?"
if ($answer) {
Write-Host "Copying Wheels to $Env:OPT_HOST"
Mitigate-Scp-PyModules "Debugger-rmi-trace" "<SELF>"
Write-Host "Installing Wheels into python"
$arglist = Compute-Dbg-PipInstall-Args "'-f'" "os.environ['HOME']" "'ghidradbg>=$version'"
$sshargs = Compute-Ssh-Args $arglist False
Start-Process -FilePath $sshargs[0] -ArgumentList $sshargs[1..$sshargs.Count] -NoNewWindow -Wait
}

View File

@@ -0,0 +1,27 @@
## ###
# IP: GHIDRA
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
. $Env:MODULE_Debugger_rmi_trace_HOME\data\support\setuputils.ps1
function Compute-Dbg-PipInstall-Args {
$argvpart = $args -join ", "
$arglist = @("$Env:OPT_PYTHON_EXE -c `"")
$arglist+=("import os, sys, runpy")
$arglist+=("sys.argv=['pip', 'install', '--force-reinstall', $argvpart]")
$arglist+=("os.environ['PIP_BREAK_SYSTEM_PACKAGE']='1'")
$arglist+=("runpy.run_module('pip', run_name='__main__')")
return $arglist
}

View File

@@ -17,13 +17,36 @@
import os
import sys
cxn = os.getenv('GHIDRA_TRACE_RMI_ADDR')
target = os.getenv('OPT_TARGET_PID')
args = os.getenv('OPT_ATTACH_FLAGS')
def parse_parameters():
global cxn, target, args
os.environ['OPT_OS_WINDOWS'] = "true"
argc = len(sys.argv)
if argc == 1:
return True
if argc >= 4:
cxn = sys.argv[1]
os.environ['OPT_USE_DBGMODEL'] = sys.argv[2]
target = sys.argv[3]
if argc > 4:
args = sys.argv[4]
return True
print("Error: expected (cxn, use_dbgmodel, target, ...)")
return False
def append_paths():
sys.path.append(
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
from gmodutils import ghidra_module_pypath
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
sys.path.append(ghidra_module_pypath())
try:
from gmodutils import ghidra_module_pypath
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
sys.path.append(ghidra_module_pypath())
except Exception as e:
pass
def main():
@@ -38,10 +61,8 @@ def main():
global repl
repl = cmd.repl
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
flags = os.getenv('OPT_ATTACH_FLAGS')
cmd.ghidra_trace_attach(
os.getenv('OPT_TARGET_PID'), flags, start_trace=False)
cmd.ghidra_trace_connect(cxn)
cmd.ghidra_trace_attach(target, args, start_trace=False)
# TODO: HACK
try:
@@ -49,7 +70,7 @@ def main():
except KeyboardInterrupt as ki:
dbg.interrupt()
cmd.ghidra_trace_start(os.getenv('OPT_TARGET_IMG'))
cmd.ghidra_trace_start(target)
cmd.ghidra_trace_sync_enable()
on_state_changed(DbgEng.DEBUG_CES_EXECUTION_STATUS,

View File

@@ -17,17 +17,44 @@
import os
import sys
cxn = os.getenv('GHIDRA_TRACE_RMI_ADDR')
target = os.getenv('OPT_TARGET_IMG')
args = os.getenv('OPT_TARGET_ARGS')
def parse_parameters():
global cxn, target, args
os.environ['OPT_OS_WINDOWS'] = "true"
argc = len(sys.argv)
if argc == 1:
return True
if argc >= 4:
cxn = sys.argv[1]
os.environ['OPT_USE_DBGMODEL'] = sys.argv[2]
target = sys.argv[3]
if argc > 4:
args = sys.argv[4]
return True
print("Error: expected (cxn, use_dbgmodel, target, ...)")
return False
def append_paths():
sys.path.append(
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
from gmodutils import ghidra_module_pypath
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
sys.path.append(ghidra_module_pypath())
try:
from gmodutils import ghidra_module_pypath
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
sys.path.append(ghidra_module_pypath())
except Exception as e:
pass
def main():
global cxn, target, args
append_paths()
if parse_parameters() is False:
return
# Delay these imports until sys.path is patched
from ghidradbg import commands as cmd
from pybag.dbgeng import core as DbgEng
@@ -38,17 +65,15 @@ def main():
global repl
repl = cmd.repl
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
args = os.getenv('OPT_TARGET_ARGS')
if args:
args = ' ' + args
target = os.getenv('OPT_TARGET_IMG')
cmd.ghidra_trace_connect(cxn)
if target is None or target == "":
print("dbgeng requires a target image - please try again.")
cmd.ghidra_trace_disconnect()
return
cmd.ghidra_trace_create(target + args, start_trace=False)
if args:
target = target + ' ' + args
cmd.ghidra_trace_create(target, start_trace=False)
# TODO: HACK
try: