mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-10 06:02:09 +00:00
Renaming Pyhidra to PyGhidra
This commit is contained in:
parent
92d0f1dacf
commit
5b81139197
@ -65,7 +65,7 @@ public class VSCodeProjectScript extends GhidraScript {
|
|||||||
writeSettings(installDir, projectDir, classpathSourceMap);
|
writeSettings(installDir, projectDir, classpathSourceMap);
|
||||||
writeLaunch(installDir, projectDir, classpathSourceMap);
|
writeLaunch(installDir, projectDir, classpathSourceMap);
|
||||||
writeSampleScriptJava(projectDir);
|
writeSampleScriptJava(projectDir);
|
||||||
writeSampleScriptPyhidra(projectDir);
|
writeSampleScriptPyGhidra(projectDir);
|
||||||
writeSampleModule(installDir, projectDir);
|
writeSampleModule(installDir, projectDir);
|
||||||
|
|
||||||
println("Successfully created VSCode project directory at: " + projectDir);
|
println("Successfully created VSCode project directory at: " + projectDir);
|
||||||
@ -228,13 +228,13 @@ public class VSCodeProjectScript extends GhidraScript {
|
|||||||
FileUtils.writeStringToFile(scriptFile, sampleScript, StandardCharsets.UTF_8);
|
FileUtils.writeStringToFile(scriptFile, sampleScript, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeSampleScriptPyhidra(File projectDir) throws IOException {
|
private void writeSampleScriptPyGhidra(File projectDir) throws IOException {
|
||||||
File scriptsDir = new File(projectDir, "ghidra_scripts");
|
File scriptsDir = new File(projectDir, "ghidra_scripts");
|
||||||
File scriptFile = new File(scriptsDir, "sample_script.py");
|
File scriptFile = new File(scriptsDir, "sample_script.py");
|
||||||
String sampleScript = """
|
String sampleScript = """
|
||||||
# Sample Pyhidra GhidraScript
|
# Sample PyGhidra GhidraScript
|
||||||
# @category Examples
|
# @category Examples
|
||||||
# @runtime Pyhidra
|
# @runtime PyGhidra
|
||||||
|
|
||||||
from java.util import LinkedList
|
from java.util import LinkedList
|
||||||
java_list = LinkedList([1,2,3])
|
java_list = LinkedList([1,2,3])
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<launchConfiguration type="org.eclipse.jdt.launching.remoteJavaApplication">
|
<launchConfiguration type="org.eclipse.jdt.launching.remoteJavaApplication">
|
||||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||||
<listEntry value="/Features Pyhidra"/>
|
<listEntry value="/Features PyGhidra"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||||
<listEntry value="4"/>
|
<listEntry value="4"/>
|
||||||
@ -12,6 +12,6 @@
|
|||||||
<mapEntry key="hostname" value="localhost"/>
|
<mapEntry key="hostname" value="localhost"/>
|
||||||
<mapEntry key="port" value="18001"/>
|
<mapEntry key="port" value="18001"/>
|
||||||
</mapAttribute>
|
</mapAttribute>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Features Pyhidra"/>
|
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Features PyGhidra"/>
|
||||||
<stringAttribute key="org.eclipse.jdt.launching.VM_CONNECTOR_ID" value="org.eclipse.jdt.launching.socketAttachConnector"/>
|
<stringAttribute key="org.eclipse.jdt.launching.VM_CONNECTOR_ID" value="org.eclipse.jdt.launching.socketAttachConnector"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
@ -5,7 +5,7 @@
|
|||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/>
|
||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/>
|
||||||
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/>
|
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/>
|
||||||
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_Pyhidra GUI Debug"/>
|
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_PyGhidra GUI Debug"/>
|
||||||
<stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/>
|
<stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/>
|
||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/>
|
||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/>
|
@ -2,7 +2,7 @@
|
|||||||
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
||||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||||
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/>
|
<listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||||
<listEntry value="2"/>
|
<listEntry value="2"/>
|
||||||
@ -14,11 +14,11 @@
|
|||||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v -g"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v -g"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
|
||||||
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
@ -5,7 +5,7 @@
|
|||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.adoptIfRunning" value="false"/>
|
||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.0.enabled" value="true"/>
|
||||||
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/>
|
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.mode" value="debug"/>
|
||||||
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_Pyhidra Interpreter Debug"/>
|
<stringAttribute key="org.eclipse.debug.core.launchGroup.0.name" value="_PyGhidra Interpreter Debug"/>
|
||||||
<stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/>
|
<stringAttribute key="org.eclipse.debug.core.launchGroup.1.action" value="NONE"/>
|
||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.adoptIfRunning" value="true"/>
|
||||||
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/>
|
<booleanAttribute key="org.eclipse.debug.core.launchGroup.1.enabled" value="true"/>
|
@ -2,7 +2,7 @@
|
|||||||
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
||||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||||
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/>
|
<listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||||
<listEntry value="2"/>
|
<listEntry value="2"/>
|
||||||
@ -14,11 +14,11 @@
|
|||||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
|
||||||
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
@ -2,7 +2,7 @@
|
|||||||
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
||||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||||
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/>
|
<listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||||
<listEntry value="2"/>
|
<listEntry value="2"/>
|
||||||
@ -10,13 +10,13 @@
|
|||||||
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
|
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
|
||||||
<mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/>
|
<mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/>
|
||||||
<mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/>
|
<mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/>
|
||||||
<mapEntry key="PYHIDRA_DEBUG" value="1"/>
|
<mapEntry key="PYGHIDRA_DEBUG" value="1"/>
|
||||||
</mapAttribute>
|
</mapAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v -g"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v -g"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
|
||||||
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
@ -2,7 +2,7 @@
|
|||||||
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
|
||||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||||
<listEntry value="/Features Pyhidra/src/main/py/src/pyhidra"/>
|
<listEntry value="/Features PyGhidra/src/main/py/src/pyghidra"/>
|
||||||
</listAttribute>
|
</listAttribute>
|
||||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||||
<listEntry value="2"/>
|
<listEntry value="2"/>
|
||||||
@ -10,13 +10,13 @@
|
|||||||
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
|
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
|
||||||
<mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/>
|
<mapEntry key="GHIDRA_INSTALL_DIR" value="${project_loc:/___root}"/>
|
||||||
<mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/>
|
<mapEntry key="JAVA_HOME_OVERRIDE" value="${ee_home:JavaSE-21}"/>
|
||||||
<mapEntry key="PYHIDRA_DEBUG" value="1"/>
|
<mapEntry key="PYGHIDRA_DEBUG" value="1"/>
|
||||||
</mapAttribute>
|
</mapAttribute>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-v"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features Pyhidra/src/main/py/src/pyhidra}"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:Features PyGhidra/src/main/py/src/pyghidra}"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
|
||||||
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features Pyhidra"/>
|
<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Features PyGhidra"/>
|
||||||
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
<stringAttribute key="process_factory_id" value="org.python.pydev.debug.processfactory.PyProcessFactory"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
@ -22,7 +22,7 @@ apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
|
|||||||
apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle"
|
apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle"
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
|
|
||||||
eclipse.project.name = 'Features Pyhidra'
|
eclipse.project.name = 'Features PyGhidra'
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -53,28 +53,28 @@ distributePyDep("setuptools-68.0.0-py3-none-any.whl")
|
|||||||
task installJPype(type: Exec) {
|
task installJPype(type: Exec) {
|
||||||
dependsOn(":createPythonVirtualEnvironment")
|
dependsOn(":createPythonVirtualEnvironment")
|
||||||
|
|
||||||
File depsDir = file("${DEPS_DIR}/Pyhidra")
|
File depsDir = file("${DEPS_DIR}/PyGhidra")
|
||||||
File binRepoDir = file("${BIN_REPO}/Ghidra/Features/Pyhidra")
|
File binRepoDir = file("${BIN_REPO}/Ghidra/Features/PyGhidra")
|
||||||
def dir = depsDir.exists() ? depsDir : binRepoDir
|
def dir = depsDir.exists() ? depsDir : binRepoDir
|
||||||
|
|
||||||
commandLine "$PYTHON3_VENV", "-m", "pip", "install", "--no-index", "-f", "$dir", "JPype1"
|
commandLine "$PYTHON3_VENV", "-m", "pip", "install", "--no-index", "-f", "$dir", "JPype1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install Pyhidra in editable mode to the development virtual environment
|
// Install PyGhidra in editable mode to the development virtual environment
|
||||||
task installEditablePyhidra(type: Exec) {
|
task installEditablePyGhidra(type: Exec) {
|
||||||
dependsOn("installJPype")
|
dependsOn("installJPype")
|
||||||
|
|
||||||
commandLine "$PYTHON3_VENV", "-m", "pip", "install", "-e", "src/main/py"
|
commandLine "$PYTHON3_VENV", "-m", "pip", "install", "-e", "src/main/py"
|
||||||
}
|
}
|
||||||
rootProject.prepDev.dependsOn installEditablePyhidra
|
rootProject.prepDev.dependsOn installEditablePyGhidra
|
||||||
|
|
||||||
// Add pyhidraLauncher.py to the release
|
// Add pyghidra_launcher.py to the release
|
||||||
rootProject.assembleDistribution {
|
rootProject.assembleDistribution {
|
||||||
dependsOn(buildPyPackage)
|
dependsOn(buildPyPackage)
|
||||||
def p = this.project
|
def p = this.project
|
||||||
def zipPath = getZipPath(p)
|
def zipPath = getZipPath(p)
|
||||||
from (this.project.projectDir.toString()) {
|
from (this.project.projectDir.toString()) {
|
||||||
include "pyhidraLauncher.py"
|
include "pyghidra_launcher.py"
|
||||||
into { zipPath }
|
into { zipPath }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,5 +3,5 @@
|
|||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
data/python.theme.properties||GHIDRA||||END|
|
data/python.theme.properties||GHIDRA||||END|
|
||||||
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
|
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
|
||||||
src/main/help/help/topics/Pyhidra/interpreter.html||GHIDRA||||END|
|
src/main/help/help/topics/PyGhidra/interpreter.html||GHIDRA||||END|
|
||||||
src/main/resources/images/python.png||GHIDRA||||END|
|
src/main/resources/images/python.png||GHIDRA||||END|
|
@ -1,6 +1,6 @@
|
|||||||
# Examples of Pyhidra-specific functionality
|
# Examples of PyGhidra-specific functionality
|
||||||
# @category: Examples.Python
|
# @category: Examples.Python
|
||||||
# @runtime Pyhidra
|
# @runtime PyGhidra
|
||||||
|
|
||||||
|
|
||||||
# we can import java libraries just as if they were python libraries
|
# we can import java libraries just as if they were python libraries
|
@ -6,16 +6,16 @@ from pathlib import Path
|
|||||||
from typing import List
|
from typing import List
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
|
|
||||||
def upgrade(pip_args: List[str], dist_dir: Path, current_pyhidra_version: str) -> bool:
|
def upgrade(pip_args: List[str], dist_dir: Path, current_pyghidra_version: str) -> bool:
|
||||||
from packaging.version import Version # if pyhidra imported, we know we have packaging
|
from packaging.version import Version # if pyghidra imported, we know we have packaging
|
||||||
included_pyhidra: Path = next(dist_dir.glob('pyhidra-*.whl'), None)
|
included_pyghidra: Path = next(dist_dir.glob('pyghidra-*.whl'), None)
|
||||||
if included_pyhidra is None:
|
if included_pyghidra is None:
|
||||||
print('Warning: included pyhidra wheel was not found', file=sys.stderr)
|
print('Warning: included pyghidra wheel was not found', file=sys.stderr)
|
||||||
return
|
return
|
||||||
included_version: Version = Version(included_pyhidra.name.split('-')[1])
|
included_version: Version = Version(included_pyghidra.name.split('-')[1])
|
||||||
current_version: Version = Version(current_pyhidra_version)
|
current_version: Version = Version(current_pyghidra_version)
|
||||||
if included_version > current_version:
|
if included_version > current_version:
|
||||||
choice: str = input(f'Do you wish to upgrade Pyhidra {current_version} to {included_version} (y/n)? ')
|
choice: str = input(f'Do you wish to upgrade PyGhidra {current_version} to {included_version} (y/n)? ')
|
||||||
if choice.lower() in ('y', 'yes'):
|
if choice.lower() in ('y', 'yes'):
|
||||||
pip_args.append('-U')
|
pip_args.append('-U')
|
||||||
subprocess.check_call(pip_args)
|
subprocess.check_call(pip_args)
|
||||||
@ -25,7 +25,7 @@ def upgrade(pip_args: List[str], dist_dir: Path, current_pyhidra_version: str) -
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def install(pip_args: List[str], dist_dir: Path) -> bool:
|
def install(pip_args: List[str], dist_dir: Path) -> bool:
|
||||||
choice: str = input('Do you wish to install Pyhidra (y/n)? ')
|
choice: str = input('Do you wish to install PyGhidra (y/n)? ')
|
||||||
if choice.lower() in ('y', 'yes'):
|
if choice.lower() in ('y', 'yes'):
|
||||||
subprocess.check_call(pip_args)
|
subprocess.check_call(pip_args)
|
||||||
return True
|
return True
|
||||||
@ -48,16 +48,16 @@ def main() -> None:
|
|||||||
python_cmd: str = sys.executable
|
python_cmd: str = sys.executable
|
||||||
install_dir: Path = Path(args.install_dir)
|
install_dir: Path = Path(args.install_dir)
|
||||||
venv_dir: Path = install_dir / 'build' / 'venv'
|
venv_dir: Path = install_dir / 'build' / 'venv'
|
||||||
pyhidra_dir: Path = install_dir / 'Ghidra' / 'Features' / 'Pyhidra'
|
pyghidra_dir: Path = install_dir / 'Ghidra' / 'Features' / 'PyGhidra'
|
||||||
src_dir: Path = pyhidra_dir / 'src' / 'main' / 'py'
|
src_dir: Path = pyghidra_dir / 'src' / 'main' / 'py'
|
||||||
dist_dir: Path = pyhidra_dir / 'pypkg' / 'dist'
|
dist_dir: Path = pyghidra_dir / 'pypkg' / 'dist'
|
||||||
|
|
||||||
# If headless, force console mode
|
# If headless, force console mode
|
||||||
if args.headless:
|
if args.headless:
|
||||||
args.console = True
|
args.console = True
|
||||||
|
|
||||||
if args.dev:
|
if args.dev:
|
||||||
# If in dev mode, launch pyhidra from the source tree using the development virtual environment
|
# If in dev mode, launch PyGhidra from the source tree using the development virtual environment
|
||||||
if not venv_dir.is_dir():
|
if not venv_dir.is_dir():
|
||||||
print('Virtual environment not found!')
|
print('Virtual environment not found!')
|
||||||
print('Run "gradle prepdev" and try again.')
|
print('Run "gradle prepdev" and try again.')
|
||||||
@ -66,17 +66,17 @@ def main() -> None:
|
|||||||
linux_python_cmd = str(venv_dir / 'bin' / 'python3')
|
linux_python_cmd = str(venv_dir / 'bin' / 'python3')
|
||||||
python_cmd = win_python_cmd if os.name == 'nt' else linux_python_cmd
|
python_cmd = win_python_cmd if os.name == 'nt' else linux_python_cmd
|
||||||
else:
|
else:
|
||||||
# If in release mode, offer to install or upgrade pyhidra before launching from user-controlled environment
|
# If in release mode, offer to install or upgrade PyGhidra before launching from user-controlled environment
|
||||||
pip_args: List[str] = [python_cmd, '-m', 'pip', 'install', '--no-index', '-f', str(dist_dir), 'pyhidra']
|
pip_args: List[str] = [python_cmd, '-m', 'pip', 'install', '--no-index', '-f', str(dist_dir), 'pyghidra']
|
||||||
try:
|
try:
|
||||||
import pyhidra
|
import pyghidra
|
||||||
upgrade(pip_args, dist_dir, pyhidra.__version__)
|
upgrade(pip_args, dist_dir, pyghidra.__version__)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
if not install(pip_args, dist_dir):
|
if not install(pip_args, dist_dir):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Launch Pyhidra
|
# Launch PyGhidra
|
||||||
py_args: List[str] = [python_cmd, '-m', 'pyhidra.ghidra_launch', '--install-dir', str(install_dir)]
|
py_args: List[str] = [python_cmd, '-m', 'pyghidra.ghidra_launch', '--install-dir', str(install_dir)]
|
||||||
if args.headless:
|
if args.headless:
|
||||||
py_args += ['ghidra.app.util.headless.AnalyzeHeadless']
|
py_args += ['ghidra.app.util.headless.AnalyzeHeadless']
|
||||||
else:
|
else:
|
||||||
@ -86,6 +86,6 @@ def main() -> None:
|
|||||||
else:
|
else:
|
||||||
creation_flags = getattr(subprocess, 'CREATE_NO_WINDOW', 0)
|
creation_flags = getattr(subprocess, 'CREATE_NO_WINDOW', 0)
|
||||||
subprocess.Popen(py_args + remaining, creationflags=creation_flags, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
subprocess.Popen(py_args + remaining, creationflags=creation_flags, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@ -3,7 +3,7 @@
|
|||||||
<tocroot>
|
<tocroot>
|
||||||
<tocref id="Ghidra Functionality">
|
<tocref id="Ghidra Functionality">
|
||||||
<tocref id="Scripting">
|
<tocref id="Scripting">
|
||||||
<tocdef id="Pyhidra Interpreter" sortgroup="z" text="Pyhidra Interpreter" target="help/topics/Pyhidra/interpreter.html" />
|
<tocdef id="PyGhidra Interpreter" sortgroup="z" text="PyGhidra Interpreter" target="help/topics/PyGhidra/interpreter.html" />
|
||||||
</tocref>
|
</tocref>
|
||||||
</tocref>
|
</tocref>
|
||||||
</tocroot>
|
</tocroot>
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
<HTML>
|
<HTML>
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<TITLE>Pyhidra Interpreter</TITLE>
|
<TITLE>PyGhidra Interpreter</TITLE>
|
||||||
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||||
</HEAD>
|
</HEAD>
|
||||||
|
|
||||||
<BODY lang="EN-US">
|
<BODY lang="EN-US">
|
||||||
<H1><A name="Pyhidra"></A>Pyhidra Interpreter</H1>
|
<H1><A name="PyGhidra"></A>PyGhidra Interpreter</H1>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
The Ghidra <I>Pyhidra Interpreter</I> provides a full general-purpose Python interactive shell
|
The Ghidra <I>PyGhidra Interpreter</I> provides a full general-purpose Python interactive shell
|
||||||
and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java
|
and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java
|
||||||
API through the magic of Jpype.
|
API through the magic of Jpype.
|
||||||
</P>
|
</P>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<H2>Environment</H2>
|
<H2>Environment</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
The Ghidra <I>Pyhidra Interpreter</I> is configured to run in a similar context as a Ghidra
|
The Ghidra <I>PyGhidra Interpreter</I> is configured to run in a similar context as a Ghidra
|
||||||
script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>,
|
script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>,
|
||||||
<TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them.
|
<TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them.
|
||||||
These variables exist as Java objects behind the scenes, but Jpype allows you to interact with
|
These variables exist as Java objects behind the scenes, but Jpype allows you to interact with
|
||||||
@ -78,7 +78,7 @@
|
|||||||
<H2>Keybindings</H2>
|
<H2>Keybindings</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
The Ghidra <I>Pyhidra Interpreter</I> supports the following hard-coded keybindings:
|
The Ghidra <I>PyGhidra Interpreter</I> supports the following hard-coded keybindings:
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>(up):</B> Move backward in command stack</LI>
|
<LI><B>(up):</B> Move backward in command stack</LI>
|
||||||
<LI><B>(down):</B> Move forward in command stack</LI>
|
<LI><B>(down):</B> Move forward in command stack</LI>
|
||||||
@ -100,7 +100,7 @@
|
|||||||
<H2>Copy/Paste</H2>
|
<H2>Copy/Paste</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
Copy and paste from within the Ghidra <I>Pyhidra Interpreter</I> should work as expected for
|
Copy and paste from within the Ghidra <I>PyGhidra Interpreter</I> should work as expected for
|
||||||
your given environment:
|
your given environment:
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>Windows:</B> CTRL+C / CTRL+V</LI>
|
<LI><B>Windows:</B> CTRL+C / CTRL+V</LI>
|
||||||
@ -113,7 +113,7 @@
|
|||||||
<H2>API Documentation</H2>
|
<H2>API Documentation</H2>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<P>
|
<P>
|
||||||
The built-in <TT>help()</TT> Python function has been altered by the Ghidra <I>Pyhidra Interpreter</I>
|
The built-in <TT>help()</TT> Python function has been altered by the Ghidra <I>PyGhidra Interpreter</I>
|
||||||
to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method,
|
to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method,
|
||||||
or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do:
|
or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do:
|
||||||
<PRE>
|
<PRE>
|
||||||
@ -156,7 +156,7 @@
|
|||||||
</P>
|
</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P align="left" class="providedbyplugin">Provided by: <I>PyhidraPlugin</I></P>
|
<P align="left" class="providedbyplugin">Provided by: <I>PyGhidraPlugin</I></P>
|
||||||
|
|
||||||
<P> </P>
|
<P> </P>
|
||||||
<BR>
|
<BR>
|
@ -1,11 +1,11 @@
|
|||||||
package ghidra.pyhidra;
|
package ghidra.pyghidra;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import ghidra.app.CorePluginPackage;
|
import ghidra.app.CorePluginPackage;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.plugin.ProgramPlugin;
|
import ghidra.app.plugin.ProgramPlugin;
|
||||||
import ghidra.app.plugin.core.interpreter.*;
|
import ghidra.app.plugin.core.interpreter.InterpreterPanelService;
|
||||||
import ghidra.app.script.GhidraState;
|
import ghidra.app.script.GhidraState;
|
||||||
import ghidra.framework.plugintool.PluginInfo;
|
import ghidra.framework.plugintool.PluginInfo;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@ -13,8 +13,8 @@ import ghidra.framework.plugintool.util.PluginStatus;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.pyhidra.interpreter.InterpreterGhidraScript;
|
import ghidra.pyghidra.interpreter.InterpreterGhidraScript;
|
||||||
import ghidra.pyhidra.interpreter.PyhidraInterpreter;
|
import ghidra.pyghidra.interpreter.PyGhidraInterpreter;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,20 +25,20 @@ import ghidra.util.exception.AssertException;
|
|||||||
status = PluginStatus.RELEASED,
|
status = PluginStatus.RELEASED,
|
||||||
packageName = CorePluginPackage.NAME,
|
packageName = CorePluginPackage.NAME,
|
||||||
category = PluginCategoryNames.COMMON,
|
category = PluginCategoryNames.COMMON,
|
||||||
shortDescription = "Pyhidra Interpreter",
|
shortDescription = "PyGhidra Interpreter",
|
||||||
description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.",
|
description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.",
|
||||||
servicesRequired = { InterpreterPanelService.class }
|
servicesRequired = { InterpreterPanelService.class }
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class PyhidraPlugin extends ProgramPlugin {
|
public class PyGhidraPlugin extends ProgramPlugin {
|
||||||
|
|
||||||
public static final String TITLE = "Pyhidra";
|
public static final String TITLE = "PyGhidra";
|
||||||
private static Consumer<PyhidraPlugin> initializer = null;
|
private static Consumer<PyGhidraPlugin> initializer = null;
|
||||||
|
|
||||||
public final InterpreterGhidraScript script = new InterpreterGhidraScript();
|
public final InterpreterGhidraScript script = new InterpreterGhidraScript();
|
||||||
public PyhidraInterpreter interpreter;
|
public PyGhidraInterpreter interpreter;
|
||||||
|
|
||||||
public PyhidraPlugin(PluginTool tool) {
|
public PyGhidraPlugin(PluginTool tool) {
|
||||||
super(tool);
|
super(tool);
|
||||||
GhidraState state = new GhidraState(tool, tool.getProject(), null, null, null, null);
|
GhidraState state = new GhidraState(tool, tool.getProject(), null, null, null, null);
|
||||||
// use the copy constructor so this state doesn't fire plugin events
|
// use the copy constructor so this state doesn't fire plugin events
|
||||||
@ -54,16 +54,16 @@ public class PyhidraPlugin extends ProgramPlugin {
|
|||||||
* @param initializer the Python side initializer
|
* @param initializer the Python side initializer
|
||||||
* @throws AssertException if the code completer has already been set
|
* @throws AssertException if the code completer has already been set
|
||||||
*/
|
*/
|
||||||
public static void setInitializer(Consumer<PyhidraPlugin> initializer) {
|
public static void setInitializer(Consumer<PyGhidraPlugin> initializer) {
|
||||||
if (PyhidraPlugin.initializer != null) {
|
if (PyGhidraPlugin.initializer != null) {
|
||||||
throw new AssertException("PyhidraPlugin initializer has already been set");
|
throw new AssertException("PyGhidraPlugin initializer has already been set");
|
||||||
}
|
}
|
||||||
PyhidraPlugin.initializer = initializer;
|
PyGhidraPlugin.initializer = initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
interpreter = new PyhidraInterpreter(this, PyhidraPlugin.initializer != null);
|
interpreter = new PyGhidraInterpreter(this, PyGhidraPlugin.initializer != null);
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
initializer.accept(this);
|
initializer.accept(this);
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package ghidra.pyhidra;
|
package ghidra.pyghidra;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.PrintWriter;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -12,15 +12,15 @@ import ghidra.program.model.address.Address;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.pyhidra.PythonFieldExposer.ExposedFields;
|
import ghidra.pyghidra.PythonFieldExposer.ExposedFields;
|
||||||
import ghidra.util.exception.AssertException;
|
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link GhidraScript} provider for native python3 scripts
|
* {@link GhidraScript} provider for native python3 scripts
|
||||||
*/
|
*/
|
||||||
public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
|
public final class PyGhidraScriptProvider extends AbstractPythonScriptProvider {
|
||||||
|
|
||||||
private static Consumer<GhidraScript> scriptRunner = null;
|
private static Consumer<GhidraScript> scriptRunner = null;
|
||||||
|
|
||||||
@ -34,37 +34,37 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||||||
* @throws AssertException if the script runner has already been set
|
* @throws AssertException if the script runner has already been set
|
||||||
*/
|
*/
|
||||||
public static void setScriptRunner(Consumer<GhidraScript> scriptRunner) {
|
public static void setScriptRunner(Consumer<GhidraScript> scriptRunner) {
|
||||||
if (PyhidraScriptProvider.scriptRunner != null) {
|
if (PyGhidraScriptProvider.scriptRunner != null) {
|
||||||
throw new AssertException("scriptRunner has already been set");
|
throw new AssertException("scriptRunner has already been set");
|
||||||
}
|
}
|
||||||
PyhidraScriptProvider.scriptRunner = scriptRunner;
|
PyGhidraScriptProvider.scriptRunner = scriptRunner;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return PyhidraPlugin.TITLE;
|
return PyGhidraPlugin.TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRuntimeEnvironmentName() {
|
public String getRuntimeEnvironmentName() {
|
||||||
return PyhidraPlugin.TITLE;
|
return PyGhidraPlugin.TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter writer)
|
public GhidraScript getScriptInstance(ResourceFile sourceFile, PrintWriter writer)
|
||||||
throws GhidraScriptLoadException {
|
throws GhidraScriptLoadException {
|
||||||
if (scriptRunner == null) {
|
if (scriptRunner == null) {
|
||||||
String msg = "Ghidra was not started with pyhidra. Python is not available";
|
String msg = "Ghidra was not started with PyGhidra. Python is not available";
|
||||||
throw new GhidraScriptLoadException(msg);
|
throw new GhidraScriptLoadException(msg);
|
||||||
}
|
}
|
||||||
GhidraScript script = SystemUtilities.isInHeadlessMode() ? new PyhidraHeadlessScript()
|
GhidraScript script = SystemUtilities.isInHeadlessMode() ? new PyGhidraHeadlessScript()
|
||||||
: new PyhidraGhidraScript();
|
: new PyGhidraGhidraScript();
|
||||||
script.setSourceFile(sourceFile);
|
script.setSourceFile(sourceFile);
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExposedFields(
|
@ExposedFields(
|
||||||
exposer = PyhidraGhidraScript.ExposedField.class,
|
exposer = PyGhidraGhidraScript.ExposedField.class,
|
||||||
names = {
|
names = {
|
||||||
"currentAddress", "currentLocation", "currentSelection",
|
"currentAddress", "currentLocation", "currentSelection",
|
||||||
"currentHighlight", "currentProgram", "monitor",
|
"currentHighlight", "currentProgram", "monitor",
|
||||||
@ -78,7 +78,7 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||||||
ResourceFile.class, GhidraState.class, PrintWriter.class
|
ResourceFile.class, GhidraState.class, PrintWriter.class
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
final static class PyhidraGhidraScript extends GhidraScript
|
final static class PyGhidraGhidraScript extends GhidraScript
|
||||||
implements PythonFieldExposer {
|
implements PythonFieldExposer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -92,13 +92,13 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||||||
*/
|
*/
|
||||||
private static class ExposedField extends PythonFieldExposer.ExposedField {
|
private static class ExposedField extends PythonFieldExposer.ExposedField {
|
||||||
public ExposedField(String name, Class<?> type) {
|
public ExposedField(String name, Class<?> type) {
|
||||||
super(MethodHandles.lookup().in(PyhidraGhidraScript.class), name, type);
|
super(MethodHandles.lookup().in(PyGhidraGhidraScript.class), name, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExposedFields(
|
@ExposedFields(
|
||||||
exposer = PyhidraHeadlessScript.ExposedField.class,
|
exposer = PyGhidraHeadlessScript.ExposedField.class,
|
||||||
names = {
|
names = {
|
||||||
"currentAddress", "currentLocation", "currentSelection",
|
"currentAddress", "currentLocation", "currentSelection",
|
||||||
"currentHighlight", "currentProgram", "monitor",
|
"currentHighlight", "currentProgram", "monitor",
|
||||||
@ -112,7 +112,7 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||||||
ResourceFile.class, GhidraState.class, PrintWriter.class
|
ResourceFile.class, GhidraState.class, PrintWriter.class
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
final static class PyhidraHeadlessScript extends HeadlessScript
|
final static class PyGhidraHeadlessScript extends HeadlessScript
|
||||||
implements PythonFieldExposer {
|
implements PythonFieldExposer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -126,7 +126,7 @@ public final class PyhidraScriptProvider extends AbstractPythonScriptProvider {
|
|||||||
*/
|
*/
|
||||||
private static class ExposedField extends PythonFieldExposer.ExposedField {
|
private static class ExposedField extends PythonFieldExposer.ExposedField {
|
||||||
public ExposedField(String name, Class<?> type) {
|
public ExposedField(String name, Class<?> type) {
|
||||||
super(MethodHandles.lookup().in(PyhidraHeadlessScript.class), name, type);
|
super(MethodHandles.lookup().in(PyGhidraHeadlessScript.class), name, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra;
|
package ghidra.pyghidra;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -21,8 +21,8 @@ import ghidra.util.exception.AssertException;
|
|||||||
* This interface is for <b>internal use only</b> and is only public so it can be
|
* This interface is for <b>internal use only</b> and is only public so it can be
|
||||||
* visible to Python to apply the Jpype class customizations.
|
* visible to Python to apply the Jpype class customizations.
|
||||||
*/
|
*/
|
||||||
public sealed interface PythonFieldExposer permits PyhidraScriptProvider.PyhidraGhidraScript,
|
public sealed interface PythonFieldExposer permits PyGhidraScriptProvider.PyGhidraGhidraScript,
|
||||||
PyhidraScriptProvider.PyhidraHeadlessScript {
|
PyGhidraScriptProvider.PyGhidraHeadlessScript {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a mapping of all the explicitly exposed fields of a class.
|
* Gets a mapping of all the explicitly exposed fields of a class.
|
@ -1,13 +1,13 @@
|
|||||||
package ghidra.pyhidra.interpreter;
|
package ghidra.pyghidra.interpreter;
|
||||||
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import ghidra.pyhidra.PyhidraPlugin;
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.action.KeyBindingData;
|
import docking.action.KeyBindingData;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
import docking.action.ToolBarData;
|
import docking.action.ToolBarData;
|
||||||
|
import ghidra.pyghidra.PyGhidraPlugin;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
|
|
||||||
@ -15,10 +15,10 @@ import static docking.DockingUtils.CONTROL_KEY_MODIFIER_MASK;
|
|||||||
|
|
||||||
final class CancelAction extends DockingAction {
|
final class CancelAction extends DockingAction {
|
||||||
|
|
||||||
private final PyhidraConsole console;
|
private final PyGhidraConsole console;
|
||||||
|
|
||||||
CancelAction(PyhidraConsole console) {
|
CancelAction(PyGhidraConsole console) {
|
||||||
super("Cancel", PyhidraPlugin.class.getSimpleName());
|
super("Cancel", PyGhidraPlugin.class.getSimpleName());
|
||||||
this.console = console;
|
this.console = console;
|
||||||
setDescription("Interrupt the interpreter");
|
setDescription("Interrupt the interpreter");
|
||||||
ImageIcon image = ResourceManager.loadImage("images/dialog-cancel.png");
|
ImageIcon image = ResourceManager.loadImage("images/dialog-cancel.png");
|
||||||
@ -26,7 +26,7 @@ final class CancelAction extends DockingAction {
|
|||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
KeyBindingData key = new KeyBindingData(KeyEvent.VK_I, CONTROL_KEY_MODIFIER_MASK);
|
KeyBindingData key = new KeyBindingData(KeyEvent.VK_I, CONTROL_KEY_MODIFIER_MASK);
|
||||||
setKeyBindingData(key);
|
setKeyBindingData(key);
|
||||||
setHelpLocation(new HelpLocation(PyhidraPlugin.TITLE, "Interrupt_Interpreter"));
|
setHelpLocation(new HelpLocation(PyGhidraPlugin.TITLE, "Interrupt_Interpreter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.interpreter;
|
package ghidra.pyghidra.interpreter;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@ -10,11 +10,11 @@ import ghidra.program.util.ProgramLocation;
|
|||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom {@link GhidraScript} only for use with the pyhidra interpreter console
|
* Custom {@link GhidraScript} only for use with the PyGhidra interpreter console
|
||||||
*/
|
*/
|
||||||
public final class InterpreterGhidraScript extends GhidraScript {
|
public final class InterpreterGhidraScript extends GhidraScript {
|
||||||
|
|
||||||
// public default constructor for use by PyhidraPlugin
|
// public default constructor for use by PyGhidraPlugin
|
||||||
// the default constructor for FlatProgramAPI has protected visibility
|
// the default constructor for FlatProgramAPI has protected visibility
|
||||||
public InterpreterGhidraScript() {
|
public InterpreterGhidraScript() {
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.interpreter;
|
package ghidra.pyghidra.interpreter;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@ -14,6 +14,6 @@ final class InterpreterTaskMonitor extends TaskMonitorAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMessage(String message) {
|
public void setMessage(String message) {
|
||||||
output.println("<pyhidra-interactive>: " + message);
|
output.println("<pyghidra-interactive>: " + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.interpreter;
|
package ghidra.pyghidra.interpreter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -12,10 +12,10 @@ import ghidra.util.Disposable;
|
|||||||
* This interface is for <b>internal use only</b> and is only public so it can be
|
* This interface is for <b>internal use only</b> and is only public so it can be
|
||||||
* implemented in Python.
|
* implemented in Python.
|
||||||
*/
|
*/
|
||||||
public interface PyhidraConsole extends Disposable {
|
public interface PyGhidraConsole extends Disposable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates code completions for the pyhidra interpreter
|
* Generates code completions for the PyGhidra interpreter
|
||||||
*
|
*
|
||||||
* @param cmd The command to get code completions for
|
* @param cmd The command to get code completions for
|
||||||
* @param caretPos The position of the caret in the input string 'cmd'.
|
* @param caretPos The position of the caret in the input string 'cmd'.
|
||||||
@ -26,12 +26,12 @@ public interface PyhidraConsole extends Disposable {
|
|||||||
List<CodeCompletion> getCompletions(String cmd, int caretPos);
|
List<CodeCompletion> getCompletions(String cmd, int caretPos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restarts the pyhidra console
|
* Restarts the PyGhidra console
|
||||||
*/
|
*/
|
||||||
void restart();
|
void restart();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interrupts the code running in the pyhidra console
|
* Interrupts the code running in the PyGhidra console
|
||||||
*/
|
*/
|
||||||
void interrupt();
|
void interrupt();
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.interpreter;
|
package ghidra.pyghidra.interpreter;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -8,20 +8,20 @@ import ghidra.app.plugin.core.console.CodeCompletion;
|
|||||||
import ghidra.app.plugin.core.interpreter.InterpreterConnection;
|
import ghidra.app.plugin.core.interpreter.InterpreterConnection;
|
||||||
import ghidra.app.plugin.core.interpreter.InterpreterConsole;
|
import ghidra.app.plugin.core.interpreter.InterpreterConsole;
|
||||||
import ghidra.app.plugin.core.interpreter.InterpreterPanelService;
|
import ghidra.app.plugin.core.interpreter.InterpreterPanelService;
|
||||||
import ghidra.pyhidra.PyhidraPlugin;
|
import ghidra.pyghidra.PyGhidraPlugin;
|
||||||
import ghidra.util.Disposable;
|
import ghidra.util.Disposable;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The pyhidra interpreter connection
|
* The PyGhidra interpreter connection
|
||||||
*/
|
*/
|
||||||
public final class PyhidraInterpreter implements Disposable, InterpreterConnection {
|
public final class PyGhidraInterpreter implements Disposable, InterpreterConnection {
|
||||||
|
|
||||||
private PyhidraConsole pyhidraConsole = null;
|
private PyGhidraConsole pyghidraConsole = null;
|
||||||
public final InterpreterConsole console;
|
public final InterpreterConsole console;
|
||||||
|
|
||||||
public PyhidraInterpreter(PyhidraPlugin plugin, boolean isPythonAvailable) {
|
public PyGhidraInterpreter(PyGhidraPlugin plugin, boolean isPythonAvailable) {
|
||||||
InterpreterPanelService service =
|
InterpreterPanelService service =
|
||||||
plugin.getTool().getService(InterpreterPanelService.class);
|
plugin.getTool().getService(InterpreterPanelService.class);
|
||||||
console = service.createInterpreterPanel(this, false);
|
console = service.createInterpreterPanel(this, false);
|
||||||
@ -32,8 +32,8 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (pyhidraConsole != null) {
|
if (pyghidraConsole != null) {
|
||||||
pyhidraConsole.dispose();
|
pyghidraConsole.dispose();
|
||||||
}
|
}
|
||||||
console.dispose();
|
console.dispose();
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return PyhidraPlugin.TITLE;
|
return PyGhidraPlugin.TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -55,20 +55,20 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
|
public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
|
||||||
if (pyhidraConsole == null) {
|
if (pyghidraConsole == null) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
return pyhidraConsole.getCompletions(cmd, caretPos);
|
return pyghidraConsole.getCompletions(cmd, caretPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unavailableCallback() {
|
private void unavailableCallback() {
|
||||||
console.setInputPermitted(false);
|
console.setInputPermitted(false);
|
||||||
PrintWriter out = console.getOutWriter();
|
PrintWriter out = console.getOutWriter();
|
||||||
out.println("Ghidra was not started with pyhidra. Python is not available.");
|
out.println("Ghidra was not started with PyGhidra. Python is not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the interpreter with the provided PyhidraConsole.
|
* Initializes the interpreter with the provided PyGhidraConsole.
|
||||||
*
|
*
|
||||||
* This method is for <b>internal use only</b> and is only public so it can be
|
* This method is for <b>internal use only</b> and is only public so it can be
|
||||||
* called from Python.
|
* called from Python.
|
||||||
@ -76,13 +76,13 @@ public final class PyhidraInterpreter implements Disposable, InterpreterConnecti
|
|||||||
* @param pythonSideConsole the python side console
|
* @param pythonSideConsole the python side console
|
||||||
* @throws AssertException if the interpreter has already been initialized
|
* @throws AssertException if the interpreter has already been initialized
|
||||||
*/
|
*/
|
||||||
public void init(PyhidraConsole pythonSideConsole) {
|
public void init(PyGhidraConsole pythonSideConsole) {
|
||||||
if (pyhidraConsole != null) {
|
if (pyghidraConsole != null) {
|
||||||
throw new AssertException("the interpreter has already been initialized");
|
throw new AssertException("the interpreter has already been initialized");
|
||||||
}
|
}
|
||||||
pyhidraConsole = pythonSideConsole;
|
pyghidraConsole = pythonSideConsole;
|
||||||
console.addFirstActivationCallback(pyhidraConsole::restart);
|
console.addFirstActivationCallback(pyghidraConsole::restart);
|
||||||
console.addAction(new CancelAction(pyhidraConsole));
|
console.addAction(new CancelAction(pyghidraConsole));
|
||||||
console.addAction(new ResetAction(pyhidraConsole));
|
console.addAction(new ResetAction(pyghidraConsole));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
package ghidra.pyhidra.interpreter;
|
package ghidra.pyghidra.interpreter;
|
||||||
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import ghidra.pyhidra.PyhidraPlugin;
|
import ghidra.pyghidra.PyGhidraPlugin;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
@ -15,10 +15,10 @@ import static docking.DockingUtils.CONTROL_KEY_MODIFIER_MASK;
|
|||||||
|
|
||||||
final class ResetAction extends DockingAction {
|
final class ResetAction extends DockingAction {
|
||||||
|
|
||||||
private final PyhidraConsole console;
|
private final PyGhidraConsole console;
|
||||||
|
|
||||||
ResetAction(PyhidraConsole console) {
|
ResetAction(PyGhidraConsole console) {
|
||||||
super("Reset", PyhidraPlugin.class.getSimpleName());
|
super("Reset", PyGhidraPlugin.class.getSimpleName());
|
||||||
this.console = console;
|
this.console = console;
|
||||||
setDescription("Reset the interpreter");
|
setDescription("Reset the interpreter");
|
||||||
ImageIcon image = ResourceManager.loadImage("images/reload3.png");
|
ImageIcon image = ResourceManager.loadImage("images/reload3.png");
|
||||||
@ -26,7 +26,7 @@ final class ResetAction extends DockingAction {
|
|||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
KeyBindingData key = new KeyBindingData(KeyEvent.VK_D, CONTROL_KEY_MODIFIER_MASK);
|
KeyBindingData key = new KeyBindingData(KeyEvent.VK_D, CONTROL_KEY_MODIFIER_MASK);
|
||||||
setKeyBindingData(key);
|
setKeyBindingData(key);
|
||||||
setHelpLocation(new HelpLocation(PyhidraPlugin.TITLE, "Reset_Interpreter"));
|
setHelpLocation(new HelpLocation(PyGhidraPlugin.TITLE, "Reset_Interpreter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ import java.lang.invoke.MethodHandle;
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* The pyhidra internals expects every {@link JavaProperty} to be an instance of this class.
|
* The PyGhidra internals expects every {@link JavaProperty} to be an instance of this class.
|
||||||
* No checking is required or performed since the {@link JavaProperty} interface and this
|
* No checking is required or performed since the {@link JavaProperty} interface and this
|
||||||
* class are sealed.
|
* class are sealed.
|
||||||
*/
|
*/
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property interface for creating a Python property for getters and setters.
|
* Property interface for creating a Python property for getters and setters.
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.property;
|
package ghidra.pyghidra.property;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
# pyhidra
|
# PyGhidra
|
||||||
|
|
||||||
Pyhidra is a Python library that provides direct access to the Ghidra API within a native CPython interpreter using [jpype](https://jpype.readthedocs.io/en/latest). As well, Pyhidra contains some conveniences for setting up analysis on a given sample and running a Ghidra script locally. It also contains a Ghidra plugin to allow the use of CPython from the Ghidra user interface.
|
PyGhidra is a Python library that provides direct access to the Ghidra API within a native CPython interpreter using [jpype](https://jpype.readthedocs.io/en/latest). As well, PyGhidra contains some conveniences for setting up analysis on a given sample and running a Ghidra script locally. It also contains a Ghidra plugin to allow the use of CPython from the Ghidra user interface.
|
||||||
|
|
||||||
Pyhidra was initially developed for use with Dragodis and is designed to be installable without requiring Java or Ghidra. This allows other Python projects
|
PyGhidra was initially developed for use with Dragodis and is designed to be installable without requiring Java or Ghidra. This allows other Python projects
|
||||||
have pyhidra as a dependency and provide optional Ghidra functionality without requiring all users to install Java and Ghidra. It is recommended to recommend that users set the `GHIDRA_INSTALL_DIR` environment variable to simplify locating Ghidra.
|
have PyGhidra as a dependency and provide optional Ghidra functionality without requiring all users to install Java and Ghidra. It is recommended to recommend that users set the `GHIDRA_INSTALL_DIR` environment variable to simplify locating Ghidra.
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -18,8 +18,8 @@ which will allow you to directly import `ghidra` and `java`.
|
|||||||
*NOTE: No projects or programs get setup in this mode.*
|
*NOTE: No projects or programs get setup in this mode.*
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import pyhidra
|
import pyghidra
|
||||||
pyhidra.start()
|
pyghidra.start()
|
||||||
|
|
||||||
import ghidra
|
import ghidra
|
||||||
from ghidra.app.util.headless import HeadlessAnalyzer
|
from ghidra.app.util.headless import HeadlessAnalyzer
|
||||||
@ -32,12 +32,12 @@ from java.lang import String
|
|||||||
|
|
||||||
### Customizing Java and Ghidra initialization
|
### Customizing Java and Ghidra initialization
|
||||||
|
|
||||||
JVM configuration for the classpath and vmargs may be done through a `PyhidraLauncher`.
|
JVM configuration for the classpath and vmargs may be done through a `PyGhidraLauncher`.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from pyhidra.launcher import HeadlessPyhidraLauncher
|
from pyghidra.launcher import HeadlessPyGhidraLauncher
|
||||||
|
|
||||||
launcher = HeadlessPyhidraLauncher()
|
launcher = HeadlessPyGhidraLauncher()
|
||||||
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
|
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
|
||||||
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
|
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
|
||||||
launcher.start()
|
launcher.start()
|
||||||
@ -45,10 +45,10 @@ launcher.start()
|
|||||||
|
|
||||||
### Registering an Entry Point
|
### Registering an Entry Point
|
||||||
|
|
||||||
The `PyhidraLauncher` can also be configured through the use of a registered entry point on your own python project.
|
The `PyGhidraLauncher` can also be configured through the use of a registered entry point on your own python project.
|
||||||
This is useful for installing your own Ghidra plugin which uses pyhidra and self-compiles.
|
This is useful for installing your own Ghidra plugin which uses PyGhidra and self-compiles.
|
||||||
|
|
||||||
First create an [entry_point](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) for `pyhidra.setup`
|
First create an [entry_point](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) for `pyghidra.setup`
|
||||||
pointing to a single argument function which accepts the launcher instance.
|
pointing to a single argument function which accepts the launcher instance.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@ -58,7 +58,7 @@ from setuptools import setup
|
|||||||
setup(
|
setup(
|
||||||
# ...,
|
# ...,
|
||||||
entry_points={
|
entry_points={
|
||||||
'pyhidra.setup': [
|
'pyghidra.setup': [
|
||||||
'acme_plugin = acme.ghidra_plugin.install:setup',
|
'acme_plugin = acme.ghidra_plugin.install:setup',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -67,25 +67,25 @@ setup(
|
|||||||
|
|
||||||
|
|
||||||
Then we create the target function.
|
Then we create the target function.
|
||||||
This function will be called every time a user starts a pyhidra launcher.
|
This function will be called every time a user starts a PyGhidra launcher.
|
||||||
In the same fashion, another entry point `pyhidra.pre_launch` may be registered and will be called after Ghidra and all
|
In the same fashion, another entry point `pyghidra.pre_launch` may be registered and will be called after Ghidra and all
|
||||||
plugins have been loaded.
|
plugins have been loaded.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# acme/ghidra_plugin/install.py
|
# acme/ghidra_plugin/install.py
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pyhidra
|
import pyghidra
|
||||||
|
|
||||||
def setup(launcher):
|
def setup(launcher):
|
||||||
"""
|
"""
|
||||||
Run by pyhidra launcher to install our plugin.
|
Run by PyGhidra launcher to install our plugin.
|
||||||
"""
|
"""
|
||||||
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
|
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
|
||||||
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
|
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
|
||||||
|
|
||||||
# Install our plugin.
|
# Install our plugin.
|
||||||
source_path = Path(__file__).parent / "java" / "plugin" # path to uncompiled .java code
|
source_path = Path(__file__).parent / "java" / "plugin" # path to uncompiled .java code
|
||||||
details = pyhidra.ExtensionDetails(
|
details = pyghidra.ExtensionDetails(
|
||||||
name="acme_plugin",
|
name="acme_plugin",
|
||||||
description="My Cool Plugin",
|
description="My Cool Plugin",
|
||||||
author="acme",
|
author="acme",
|
||||||
@ -97,15 +97,15 @@ def setup(launcher):
|
|||||||
|
|
||||||
### Analyze a File
|
### Analyze a File
|
||||||
|
|
||||||
To have pyhidra setup a binary file for you, use the `open_program()` function.
|
To have PyGhidra setup a binary file for you, use the `open_program()` function.
|
||||||
This will setup a Ghidra project and import the given binary file as a program for you.
|
This will setup a Ghidra project and import the given binary file as a program for you.
|
||||||
|
|
||||||
Again, this will also allow you to import `ghidra` and `java` to perform more advanced processing.
|
Again, this will also allow you to import `ghidra` and `java` to perform more advanced processing.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import pyhidra
|
import pyghidra
|
||||||
|
|
||||||
with pyhidra.open_program("binary_file.exe") as flat_api:
|
with pyghidra.open_program("binary_file.exe") as flat_api:
|
||||||
program = flat_api.getCurrentProgram()
|
program = flat_api.getCurrentProgram()
|
||||||
listing = program.getListing()
|
listing = program.getListing()
|
||||||
print(listing.getCodeUnitAt(flat_api.toAddr(0x1234)))
|
print(listing.getCodeUnitAt(flat_api.toAddr(0x1234)))
|
||||||
@ -117,12 +117,12 @@ with pyhidra.open_program("binary_file.exe") as flat_api:
|
|||||||
decomp_api.dispose()
|
decomp_api.dispose()
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, pyhidra will run analysis for you. If you would like to do this yourself, set `analyze` to `False`.
|
By default, PyGhidra will run analysis for you. If you would like to do this yourself, set `analyze` to `False`.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import pyhidra
|
import pyghidra
|
||||||
|
|
||||||
with pyhidra.open_program("binary_file.exe", analyze=False) as flat_api:
|
with pyghidra.open_program("binary_file.exe", analyze=False) as flat_api:
|
||||||
from ghidra.program.util import GhidraProgramUtilities
|
from ghidra.program.util import GhidraProgramUtilities
|
||||||
|
|
||||||
program = flat_api.getCurrentProgram()
|
program = flat_api.getCurrentProgram()
|
||||||
@ -135,16 +135,16 @@ The `open_program()` function can also accept optional arguments to control the
|
|||||||
(Helpful for opening up a sample in an already existing project.)
|
(Helpful for opening up a sample in an already existing project.)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import pyhidra
|
import pyghidra
|
||||||
|
|
||||||
with pyhidra.open_program("binary_file.exe", project_name="EXAM_231", project_location=r"C:\exams\231") as flat_api:
|
with pyghidra.open_program("binary_file.exe", project_name="EXAM_231", project_location=r"C:\exams\231") as flat_api:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Run a Script
|
### Run a Script
|
||||||
|
|
||||||
Pyhidra can also be used to run an existing Ghidra Python script directly in your native python interpreter
|
PyGhidra can also be used to run an existing Ghidra Python script directly in your native python interpreter
|
||||||
using the `run_script()` command.
|
using the `run_script()` command.
|
||||||
However, while you can technically run an existing Ghidra script unmodified, you may
|
However, while you can technically run an existing Ghidra script unmodified, you may
|
||||||
run into issues due to differences between Jython 2 and CPython 3.
|
run into issues due to differences between Jython 2 and CPython 3.
|
||||||
@ -152,21 +152,21 @@ Therefore, some modification to the script may be needed.
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
||||||
import pyhidra
|
import pyghidra
|
||||||
|
|
||||||
pyhidra.run_script(r"C:\input.exe", r"C:\some_ghidra_script.py")
|
pyghidra.run_script(r"C:\input.exe", r"C:\some_ghidra_script.py")
|
||||||
```
|
```
|
||||||
|
|
||||||
This can also be done on the command line using `pyhidra`.
|
This can also be done on the command line using `pyghidra`.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
> pyhidra C:\input.exe C:\some_ghidra_script.py <CLI ARGS PASSED TO SCRIPT>
|
> pyghidra C:\input.exe C:\some_ghidra_script.py <CLI ARGS PASSED TO SCRIPT>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Handling Package Name Conflicts
|
### Handling Package Name Conflicts
|
||||||
|
|
||||||
There may be some Python modules and Java packages with the same import path. When this occurs the Python module takes precedence.
|
There may be some Python modules and Java packages with the same import path. When this occurs the Python module takes precedence.
|
||||||
While jpype has its own mechanism for handling this situation, pyhidra automatically makes the Java package accessible by allowing
|
While jpype has its own mechanism for handling this situation, PyGhidra automatically makes the Java package accessible by allowing
|
||||||
it to be imported with an underscore appended to the package name.
|
it to be imported with an underscore appended to the package name.
|
||||||
|
|
||||||
```python
|
```python
|
@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
|
|||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pyhidra"
|
name = "pyghidra"
|
||||||
dynamic = ["version", "readme"]
|
dynamic = ["version", "readme"]
|
||||||
description = "Native CPython for Ghidra"
|
description = "Native CPython for Ghidra"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
@ -39,16 +39,16 @@ testing = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
pyhidra = "pyhidra.__main__:main"
|
pyghidra = "pyghidra.__main__:main"
|
||||||
|
|
||||||
[project.gui-scripts]
|
[project.gui-scripts]
|
||||||
pyhidraw = "pyhidra.gui:_gui"
|
pyghidraw = "pyghidra.gui:_gui"
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Repository = "https://github.com/NationalSecurityAgency/ghidra"
|
Repository = "https://github.com/NationalSecurityAgency/ghidra"
|
||||||
|
|
||||||
[tool.setuptools.dynamic]
|
[tool.setuptools.dynamic]
|
||||||
version = {attr = "pyhidra.__version__"}
|
version = {attr = "pyghidra.__version__"}
|
||||||
readme = {file = ["README.md"], content-type = "text/markdown"}
|
readme = {file = ["README.md"], content-type = "text/markdown"}
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
@ -41,13 +41,13 @@ debug_callback = _debug_callback
|
|||||||
|
|
||||||
# Expose API
|
# Expose API
|
||||||
from .core import run_script, start, started, open_program
|
from .core import run_script, start, started, open_program
|
||||||
from .launcher import DeferredPyhidraLauncher, GuiPyhidraLauncher, HeadlessPyhidraLauncher
|
from .launcher import DeferredPyGhidraLauncher, GuiPyGhidraLauncher, HeadlessPyGhidraLauncher
|
||||||
from .script import get_current_interpreter
|
from .script import get_current_interpreter
|
||||||
from .version import ApplicationInfo, ExtensionDetails
|
from .version import ApplicationInfo, ExtensionDetails
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"debug_callback", "get_current_interpreter", "open_program", "run_script", "start",
|
"debug_callback", "get_current_interpreter", "open_program", "run_script", "start",
|
||||||
"started", "ApplicationInfo", "DeferredPyhidraLauncher", "ExtensionDetails",
|
"started", "ApplicationInfo", "DeferredPyGhidraLauncher", "ExtensionDetails",
|
||||||
"GuiPyhidraLauncher", "HeadlessPyhidraLauncher"
|
"GuiPyGhidraLauncher", "HeadlessPyGhidraLauncher"
|
||||||
]
|
]
|
@ -5,13 +5,13 @@ import logging
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import pyhidra
|
import pyghidra
|
||||||
import pyhidra.core
|
import pyghidra.core
|
||||||
import pyhidra.gui
|
import pyghidra.gui
|
||||||
|
|
||||||
|
|
||||||
# NOTE: this must be "pyhidra" and not __name__
|
# NOTE: this must be "pyghidra" and not __name__
|
||||||
logger = logging.getLogger("pyhidra")
|
logger = logging.getLogger("pyghidra")
|
||||||
|
|
||||||
|
|
||||||
def _interpreter(interpreter_globals: dict):
|
def _interpreter(interpreter_globals: dict):
|
||||||
@ -24,7 +24,7 @@ def _interpreter(interpreter_globals: dict):
|
|||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class PyhidraArgs(argparse.Namespace):
|
class PyGhidraArgs(argparse.Namespace):
|
||||||
"""
|
"""
|
||||||
Custom namespace for holding the command line arguments
|
Custom namespace for holding the command line arguments
|
||||||
"""
|
"""
|
||||||
@ -60,18 +60,18 @@ class PyhidraArgs(argparse.Namespace):
|
|||||||
vmargs = self.jvm_args
|
vmargs = self.jvm_args
|
||||||
|
|
||||||
if self.gui:
|
if self.gui:
|
||||||
pyhidra.gui.gui(self.install_dir, vmargs)
|
pyghidra.gui.gui(self.install_dir, vmargs)
|
||||||
return
|
return
|
||||||
|
|
||||||
# not in gui mode so it is easier to start Ghidra now
|
# not in gui mode so it is easier to start Ghidra now
|
||||||
launcher = pyhidra.HeadlessPyhidraLauncher(
|
launcher = pyghidra.HeadlessPyGhidraLauncher(
|
||||||
verbose=self.verbose, install_dir=self.install_dir)
|
verbose=self.verbose, install_dir=self.install_dir)
|
||||||
launcher.vm_args = vmargs + launcher.vm_args
|
launcher.vm_args = vmargs + launcher.vm_args
|
||||||
launcher.start()
|
launcher.start()
|
||||||
|
|
||||||
if self.script_path is not None:
|
if self.script_path is not None:
|
||||||
try:
|
try:
|
||||||
pyhidra.run_script(
|
pyghidra.run_script(
|
||||||
self.binary_path,
|
self.binary_path,
|
||||||
self.script_path,
|
self.script_path,
|
||||||
project_location=self.project_path,
|
project_location=self.project_path,
|
||||||
@ -92,7 +92,7 @@ class PyhidraArgs(argparse.Namespace):
|
|||||||
self.verbose,
|
self.verbose,
|
||||||
not self.skip_analysis
|
not self.skip_analysis
|
||||||
)
|
)
|
||||||
with pyhidra.core._flat_api(*args, install_dir=self.install_dir) as api:
|
with pyghidra.core._flat_api(*args, install_dir=self.install_dir) as api:
|
||||||
_interpreter(api)
|
_interpreter(api)
|
||||||
else:
|
else:
|
||||||
_interpreter(globals())
|
_interpreter(globals())
|
||||||
@ -129,7 +129,7 @@ class PathAction(argparse.Action):
|
|||||||
self.nargs = '*'
|
self.nargs = '*'
|
||||||
self.type = str
|
self.type = str
|
||||||
|
|
||||||
def __call__(self, parser, namespace: PyhidraArgs, values, option_string=None):
|
def __call__(self, parser, namespace: PyGhidraArgs, values, option_string=None):
|
||||||
|
|
||||||
if not values:
|
if not values:
|
||||||
return
|
return
|
||||||
@ -168,7 +168,7 @@ class PathAction(argparse.Action):
|
|||||||
|
|
||||||
|
|
||||||
def _get_parser():
|
def _get_parser():
|
||||||
parser = argparse.ArgumentParser(prog="pyhidra")
|
parser = argparse.ArgumentParser(prog="pyghidra")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-v",
|
"-v",
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -215,7 +215,7 @@ def _get_parser():
|
|||||||
action=PathAction,
|
action=PathAction,
|
||||||
help=(
|
help=(
|
||||||
"Headless script path. The script must have a .py extension. "
|
"Headless script path. The script must have a .py extension. "
|
||||||
"If a script is not provided, pyhidra will drop into a repl."
|
"If a script is not provided, pyghidra will drop into a repl."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@ -258,7 +258,7 @@ def _get_parser():
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
pyhidra module main function
|
pyghidra module main function
|
||||||
"""
|
"""
|
||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
formatter = logging.Formatter("%(filename)s:%(lineno)d %(message)s")
|
formatter = logging.Formatter("%(filename)s:%(lineno)d %(message)s")
|
||||||
@ -266,7 +266,7 @@ def main():
|
|||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
|
|
||||||
parser = _get_parser()
|
parser = _get_parser()
|
||||||
parser.parse_args(namespace=PyhidraArgs(parser)).func()
|
parser.parse_args(namespace=PyGhidraArgs(parser)).func()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
@ -2,18 +2,18 @@ import contextlib
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union, TYPE_CHECKING, Tuple, ContextManager, List, Optional
|
from typing import Union, TYPE_CHECKING, Tuple, ContextManager, List, Optional
|
||||||
|
|
||||||
from pyhidra.converters import * # pylint: disable=wildcard-import, unused-wildcard-import
|
from pyghidra.converters import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pyhidra.launcher import PyhidraLauncher
|
from pyghidra.launcher import PyGhidraLauncher
|
||||||
from ghidra.base.project import GhidraProject
|
from ghidra.base.project import GhidraProject
|
||||||
from ghidra.program.flatapi import FlatProgramAPI
|
from ghidra.program.flatapi import FlatProgramAPI
|
||||||
from ghidra.program.model.lang import CompilerSpec, Language, LanguageService
|
from ghidra.program.model.lang import CompilerSpec, Language, LanguageService
|
||||||
from ghidra.program.model.listing import Program
|
from ghidra.program.model.listing import Program
|
||||||
|
|
||||||
|
|
||||||
def start(verbose=False, *, install_dir: Path = None) -> "PyhidraLauncher":
|
def start(verbose=False, *, install_dir: Path = None) -> "PyGhidraLauncher":
|
||||||
"""
|
"""
|
||||||
Starts the JVM and fully initializes Ghidra in Headless mode.
|
Starts the JVM and fully initializes Ghidra in Headless mode.
|
||||||
|
|
||||||
@ -22,18 +22,18 @@ def start(verbose=False, *, install_dir: Path = None) -> "PyhidraLauncher":
|
|||||||
(Defaults to the GHIDRA_INSTALL_DIR environment variable)
|
(Defaults to the GHIDRA_INSTALL_DIR environment variable)
|
||||||
:return: The PhyidraLauncher used to start the JVM
|
:return: The PhyidraLauncher used to start the JVM
|
||||||
"""
|
"""
|
||||||
from pyhidra.launcher import HeadlessPyhidraLauncher
|
from pyghidra.launcher import HeadlessPyGhidraLauncher
|
||||||
launcher = HeadlessPyhidraLauncher(verbose=verbose, install_dir=install_dir)
|
launcher = HeadlessPyGhidraLauncher(verbose=verbose, install_dir=install_dir)
|
||||||
launcher.start()
|
launcher.start()
|
||||||
return launcher
|
return launcher
|
||||||
|
|
||||||
|
|
||||||
def started() -> bool:
|
def started() -> bool:
|
||||||
"""
|
"""
|
||||||
Whether the PyhidraLauncher has already started.
|
Whether the PyGhidraLauncher has already started.
|
||||||
"""
|
"""
|
||||||
from pyhidra.launcher import PyhidraLauncher
|
from pyghidra.launcher import PyGhidraLauncher
|
||||||
return PyhidraLauncher.has_launched()
|
return PyGhidraLauncher.has_launched()
|
||||||
|
|
||||||
|
|
||||||
def _get_language(id: str) -> "Language":
|
def _get_language(id: str) -> "Language":
|
||||||
@ -137,7 +137,7 @@ def _setup_project(
|
|||||||
|
|
||||||
|
|
||||||
def _setup_script(project: "GhidraProject", program: "Program"):
|
def _setup_script(project: "GhidraProject", program: "Program"):
|
||||||
from pyhidra.script import PyGhidraScript
|
from pyghidra.script import PyGhidraScript
|
||||||
from ghidra.app.script import GhidraState
|
from ghidra.app.script import GhidraState
|
||||||
from ghidra.program.util import ProgramLocation
|
from ghidra.program.util import ProgramLocation
|
||||||
from ghidra.util.task import TaskMonitor
|
from ghidra.util.task import TaskMonitor
|
||||||
@ -205,10 +205,10 @@ def open_program(
|
|||||||
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pyhidra.launcher import PyhidraLauncher, HeadlessPyhidraLauncher
|
from pyghidra.launcher import PyGhidraLauncher, HeadlessPyGhidraLauncher
|
||||||
|
|
||||||
if not PyhidraLauncher.has_launched():
|
if not PyGhidraLauncher.has_launched():
|
||||||
HeadlessPyhidraLauncher().start()
|
HeadlessPyGhidraLauncher().start()
|
||||||
|
|
||||||
from ghidra.app.script import GhidraScriptUtil
|
from ghidra.app.script import GhidraScriptUtil
|
||||||
from ghidra.program.flatapi import FlatProgramAPI
|
from ghidra.program.flatapi import FlatProgramAPI
|
||||||
@ -273,10 +273,10 @@ def _flat_api(
|
|||||||
:raises ValueError: If the provided language, compiler or loader is invalid.
|
:raises ValueError: If the provided language, compiler or loader is invalid.
|
||||||
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
:raises TypeError: If the provided loader does not implement `ghidra.app.util.opinion.Loader`.
|
||||||
"""
|
"""
|
||||||
from pyhidra.launcher import PyhidraLauncher, HeadlessPyhidraLauncher
|
from pyghidra.launcher import PyGhidraLauncher, HeadlessPyGhidraLauncher
|
||||||
|
|
||||||
if not PyhidraLauncher.has_launched():
|
if not PyGhidraLauncher.has_launched():
|
||||||
HeadlessPyhidraLauncher(verbose=verbose, install_dir=install_dir).start()
|
HeadlessPyGhidraLauncher(verbose=verbose, install_dir=install_dir).start()
|
||||||
|
|
||||||
project, program = None, None
|
project, program = None, None
|
||||||
if binary_path or project_location:
|
if binary_path or project_location:
|
@ -4,10 +4,10 @@ from pathlib import Path
|
|||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from .launcher import PyhidraLauncher, _run_mac_app
|
from .launcher import PyGhidraLauncher, _run_mac_app
|
||||||
|
|
||||||
|
|
||||||
class GhidraLauncher(PyhidraLauncher):
|
class GhidraLauncher(PyGhidraLauncher):
|
||||||
|
|
||||||
def __init__(self, verbose=False, class_name=str, gui=False, *, install_dir: Path = None):
|
def __init__(self, verbose=False, class_name=str, gui=False, *, install_dir: Path = None):
|
||||||
super().__init__(verbose=verbose, install_dir=install_dir)
|
super().__init__(verbose=verbose, install_dir=install_dir)
|
@ -50,14 +50,14 @@ class _Helper:
|
|||||||
self.msg += " # Perform headless processing\n"
|
self.msg += " # Perform headless processing\n"
|
||||||
self.msg += " headless.processLocal(...)\n\n"
|
self.msg += " headless.processLocal(...)\n\n"
|
||||||
else:
|
else:
|
||||||
# PyhidraPlugin scenario
|
# PyGhidraPlugin scenario
|
||||||
self.msg = "Press 'F1' for usage instructions"
|
self.msg = "Press 'F1' for usage instructions"
|
||||||
|
|
||||||
def __call__(self, param=None):
|
def __call__(self, param=None):
|
||||||
|
|
||||||
def get_class_and_method(param):
|
def get_class_and_method(param):
|
||||||
if param is None and not SystemUtilities.isInHeadlessMode():
|
if param is None and not SystemUtilities.isInHeadlessMode():
|
||||||
# Enable help() in PyhidraPlugin scenario to show help for GhidraScript
|
# Enable help() in PyGhidraPlugin scenario to show help for GhidraScript
|
||||||
return "ghidra.app.script.GhidraScript", None
|
return "ghidra.app.script.GhidraScript", None
|
||||||
class_name = None
|
class_name = None
|
||||||
method_name = None
|
method_name = None
|
@ -8,7 +8,7 @@ import traceback
|
|||||||
from typing import List, NoReturn
|
from typing import List, NoReturn
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
import pyhidra
|
import pyghidra
|
||||||
|
|
||||||
|
|
||||||
class _GuiOutput(io.StringIO):
|
class _GuiOutput(io.StringIO):
|
||||||
@ -44,7 +44,7 @@ def _gui_mac() -> NoReturn:
|
|||||||
path = Path(sys.base_exec_prefix) / "Resources/Python.app/Contents/MacOS/Python"
|
path = Path(sys.base_exec_prefix) / "Resources/Python.app/Contents/MacOS/Python"
|
||||||
if path.exists():
|
if path.exists():
|
||||||
# the python launcher app will correctly start the venv if sys.executable is in a venv
|
# the python launcher app will correctly start the venv if sys.executable is in a venv
|
||||||
argv = [sys.executable, "-m", "pyhidra", "-g"]
|
argv = [sys.executable, "-m", "pyghidra", "-g"]
|
||||||
if install_dir is not None:
|
if install_dir is not None:
|
||||||
argv += ["--install-dir", str(install_dir)]
|
argv += ["--install-dir", str(install_dir)]
|
||||||
actions = ((os.POSIX_SPAWN_CLOSE, 0), (os.POSIX_SPAWN_CLOSE, 1), (os.POSIX_SPAWN_CLOSE, 2))
|
actions = ((os.POSIX_SPAWN_CLOSE, 0), (os.POSIX_SPAWN_CLOSE, 1), (os.POSIX_SPAWN_CLOSE, 2))
|
||||||
@ -55,7 +55,7 @@ def _gui_mac() -> NoReturn:
|
|||||||
|
|
||||||
|
|
||||||
def _parse_args():
|
def _parse_args():
|
||||||
parser = _GuiArgumentParser(prog="pyhidraw")
|
parser = _GuiArgumentParser(prog="pyghidraw")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--install-dir",
|
"--install-dir",
|
||||||
type=Path,
|
type=Path,
|
||||||
@ -133,7 +133,7 @@ def gui(install_dir: Path = None, vm_args: List[str] = None):
|
|||||||
(Defaults to the GHIDRA_INSTALL_DIR environment variable)
|
(Defaults to the GHIDRA_INSTALL_DIR environment variable)
|
||||||
:param vm_args: Additional vm arguments to be passed ot the JVM.
|
:param vm_args: Additional vm arguments to be passed ot the JVM.
|
||||||
"""
|
"""
|
||||||
launcher = pyhidra.GuiPyhidraLauncher(install_dir=install_dir)
|
launcher = pyghidra.GuiPyGhidraLauncher(install_dir=install_dir)
|
||||||
if vm_args:
|
if vm_args:
|
||||||
launcher.vm_args += vm_args
|
launcher.vm_args += vm_args
|
||||||
launcher.start()
|
launcher.start()
|
||||||
@ -141,8 +141,8 @@ def gui(install_dir: Path = None, vm_args: List[str] = None):
|
|||||||
|
|
||||||
def get_current_interpreter():
|
def get_current_interpreter():
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"get_current_interpreter has been moved. Please use pyhidra.get_current_interpreter",
|
"get_current_interpreter has been moved. Please use pyghidra.get_current_interpreter",
|
||||||
DeprecationWarning
|
DeprecationWarning
|
||||||
)
|
)
|
||||||
return pyhidra.get_current_interpreter()
|
return pyghidra.get_current_interpreter()
|
||||||
|
|
@ -9,8 +9,8 @@ import types
|
|||||||
from code import InteractiveConsole
|
from code import InteractiveConsole
|
||||||
|
|
||||||
from ghidra.framework import Application
|
from ghidra.framework import Application
|
||||||
from ghidra.pyhidra import PyhidraScriptProvider, PyhidraPlugin
|
from ghidra.pyghidra import PyGhidraScriptProvider, PyGhidraPlugin
|
||||||
from ghidra.pyhidra.interpreter import PyhidraConsole
|
from ghidra.pyghidra.interpreter import PyGhidraConsole
|
||||||
from java.io import BufferedReader, InputStreamReader
|
from java.io import BufferedReader, InputStreamReader
|
||||||
from java.lang import String
|
from java.lang import String
|
||||||
from java.lang import Thread as JThread
|
from java.lang import Thread as JThread
|
||||||
@ -18,8 +18,8 @@ from java.util import Collections
|
|||||||
from java.util.function import Consumer
|
from java.util.function import Consumer
|
||||||
from jpype import JClass, JImplements, JOverride
|
from jpype import JClass, JImplements, JOverride
|
||||||
|
|
||||||
from pyhidra.internal.plugin.completions import PythonCodeCompleter
|
from pyghidra.internal.plugin.completions import PythonCodeCompleter
|
||||||
from pyhidra.script import PyGhidraScript
|
from pyghidra.script import PyGhidraScript
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -125,15 +125,15 @@ class ConsoleState(enum.Enum):
|
|||||||
RESET = enum.auto()
|
RESET = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
@JImplements(PyhidraConsole)
|
@JImplements(PyGhidraConsole)
|
||||||
class PyConsole(InteractiveConsole):
|
class PyConsole(InteractiveConsole):
|
||||||
"""
|
"""
|
||||||
Pyhidra Interactive Console
|
PyGhidra Interactive Console
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_WORD_PATTERN = re.compile(r".*?([\w\.]+)\Z") # get the last word, including '.', from the right
|
_WORD_PATTERN = re.compile(r".*?([\w\.]+)\Z") # get the last word, including '.', from the right
|
||||||
|
|
||||||
def __init__(self, py_plugin: PyhidraPlugin):
|
def __init__(self, py_plugin: PyGhidraPlugin):
|
||||||
super().__init__(locals=PyGhidraScript(py_plugin.script))
|
super().__init__(locals=PyGhidraScript(py_plugin.script))
|
||||||
appVersion = Application.getApplicationVersion()
|
appVersion = Application.getApplicationVersion()
|
||||||
appName = Application.getApplicationReleaseName()
|
appName = Application.getApplicationReleaseName()
|
||||||
@ -314,11 +314,11 @@ class PyConsole(InteractiveConsole):
|
|||||||
return Collections.emptyList()
|
return Collections.emptyList()
|
||||||
|
|
||||||
|
|
||||||
def _init_plugin(plugin: PyhidraPlugin):
|
def _init_plugin(plugin: PyGhidraPlugin):
|
||||||
console = PyConsole(plugin)
|
console = PyConsole(plugin)
|
||||||
plugin.interpreter.init(console)
|
plugin.interpreter.init(console)
|
||||||
|
|
||||||
|
|
||||||
def setup_plugin():
|
def setup_plugin():
|
||||||
PyhidraPlugin.setInitializer(Consumer @ _init_plugin)
|
PyGhidraPlugin.setInitializer(Consumer @ _init_plugin)
|
||||||
PyhidraScriptProvider.setScriptRunner(Consumer @ _run_script)
|
PyGhidraScriptProvider.setScriptRunner(Consumer @ _run_script)
|
@ -76,7 +76,7 @@ def _load_entry_points(group: str, *args):
|
|||||||
logger.error(f"Failed to run {group} entry point {name} with error: {e}")
|
logger.error(f"Failed to run {group} entry point {name} with error: {e}")
|
||||||
|
|
||||||
|
|
||||||
class _PyhidraImportLoader:
|
class _PyGhidraImportLoader:
|
||||||
""" (internal) Finder hook for importlib to handle Python mod conflicts. """
|
""" (internal) Finder hook for importlib to handle Python mod conflicts. """
|
||||||
|
|
||||||
def find_spec(self, name, path, target=None):
|
def find_spec(self, name, path, target=None):
|
||||||
@ -101,7 +101,7 @@ def _plugin_lock():
|
|||||||
File lock for processing plugins
|
File lock for processing plugins
|
||||||
"""
|
"""
|
||||||
from java.io import RandomAccessFile
|
from java.io import RandomAccessFile
|
||||||
path = Path(tempfile.gettempdir()) / "pyhidra_plugin_lock"
|
path = Path(tempfile.gettempdir()) / "pyghidra_plugin_lock"
|
||||||
try:
|
try:
|
||||||
# Python doesn't have a file lock except for unix systems
|
# Python doesn't have a file lock except for unix systems
|
||||||
# so use the one available in Java instead of adding on
|
# so use the one available in Java instead of adding on
|
||||||
@ -117,19 +117,19 @@ def _plugin_lock():
|
|||||||
path.unlink()
|
path.unlink()
|
||||||
except:
|
except:
|
||||||
# if it fails it's ok
|
# if it fails it's ok
|
||||||
# another pyhidra process has the lock
|
# another pyghidra process has the lock
|
||||||
# it will be removed by said process when done
|
# it will be removed by said process when done
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PyhidraLauncher:
|
class PyGhidraLauncher:
|
||||||
"""
|
"""
|
||||||
Base pyhidra launcher
|
Base pyghidra launcher
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, verbose=False, *, install_dir: Path = None):
|
def __init__(self, verbose=False, *, install_dir: Path = None):
|
||||||
"""
|
"""
|
||||||
Initializes a new `PyhidraLauncher`.
|
Initializes a new `PyGhidraLauncher`.
|
||||||
|
|
||||||
:param verbose: True to enable verbose output when starting Ghidra.
|
:param verbose: True to enable verbose output when starting Ghidra.
|
||||||
:param install_dir: Ghidra installation directory.
|
:param install_dir: Ghidra installation directory.
|
||||||
@ -296,10 +296,10 @@ class PyhidraLauncher:
|
|||||||
# dev mode
|
# dev mode
|
||||||
return install_dir
|
return install_dir
|
||||||
|
|
||||||
path = install_dir / "Ghidra" / "Features" / "Pyhidra" / "lib" / "Pyhidra.jar"
|
path = install_dir / "Ghidra" / "Features" / "PyGhidra" / "lib" / "PyGhidra.jar"
|
||||||
|
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
msg = "The Ghidra installation does not contain the Pyhidra module\n" + \
|
msg = "The Ghidra installation does not contain the PyGhidra module\n" + \
|
||||||
f"{path} does not exist"
|
f"{path} does not exist"
|
||||||
cls._report_fatal_error("Incorrect Ghidra installation directory", msg, ValueError(msg))
|
cls._report_fatal_error("Incorrect Ghidra installation directory", msg, ValueError(msg))
|
||||||
|
|
||||||
@ -344,12 +344,12 @@ class PyhidraLauncher:
|
|||||||
Run setup entry points, start the JVM and prepare ghidra imports
|
Run setup entry points, start the JVM and prepare ghidra imports
|
||||||
"""
|
"""
|
||||||
# Before starting up, give launcher to installed entry points so they can do their thing.
|
# Before starting up, give launcher to installed entry points so they can do their thing.
|
||||||
_load_entry_points("pyhidra.setup", self)
|
_load_entry_points("pyghidra.setup", self)
|
||||||
|
|
||||||
# Merge classpath
|
# Merge classpath
|
||||||
jpype_kwargs['classpath'] = self.class_path + jpype_kwargs.get('classpath', [])
|
jpype_kwargs['classpath'] = self.class_path + jpype_kwargs.get('classpath', [])
|
||||||
|
|
||||||
# force convert strings (required by pyhidra)
|
# force convert strings (required by pyghidra)
|
||||||
jpype_kwargs['convertStrings'] = True
|
jpype_kwargs['convertStrings'] = True
|
||||||
|
|
||||||
# set the JAVA_HOME environment variable to the correct one so jpype uses it
|
# set the JAVA_HOME environment variable to the correct one so jpype uses it
|
||||||
@ -357,7 +357,7 @@ class PyhidraLauncher:
|
|||||||
|
|
||||||
jpype_kwargs['ignoreUnrecognized'] = True
|
jpype_kwargs['ignoreUnrecognized'] = True
|
||||||
|
|
||||||
if os.getenv("PYHIDRA_DEBUG"):
|
if os.getenv("PYGHIDRA_DEBUG"):
|
||||||
debug = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:18001"
|
debug = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:18001"
|
||||||
self.vm_args.insert(0, debug)
|
self.vm_args.insert(0, debug)
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ class PyhidraLauncher:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Install hook into python importlib
|
# Install hook into python importlib
|
||||||
sys.meta_path.append(_PyhidraImportLoader())
|
sys.meta_path.append(_PyGhidraImportLoader())
|
||||||
|
|
||||||
imports.registerDomain("ghidra")
|
imports.registerDomain("ghidra")
|
||||||
|
|
||||||
@ -384,11 +384,11 @@ class PyhidraLauncher:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# remove any installed pyhidra extension
|
# remove any old installed pyhidra extension
|
||||||
# if left in place Ghidra will fail to start with a confusing
|
# if left in place Ghidra will fail to start with a confusing
|
||||||
# and unrelated error about the InterpreterConsole class not being found
|
# and unrelated error about the InterpreterConsole class not being found
|
||||||
# this is only needed for those using a DEV build of Ghidra
|
# this is only needed for those using a DEV build of Ghidra
|
||||||
# who also have pyhidra installed.
|
# who also have and old version of pyhidra installed.
|
||||||
# however, this took an unnecessary amount of time to debug
|
# however, this took an unnecessary amount of time to debug
|
||||||
self.uninstall_plugin("pyhidra")
|
self.uninstall_plugin("pyhidra")
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ class PyhidraLauncher:
|
|||||||
self._layout = GhidraLauncher.initializeGhidraEnvironment()
|
self._layout = GhidraLauncher.initializeGhidraEnvironment()
|
||||||
|
|
||||||
# import it at the end so interfaces in our java code may be implemented
|
# import it at the end so interfaces in our java code may be implemented
|
||||||
from pyhidra.internal.plugin.plugin import setup_plugin
|
from pyghidra.internal.plugin.plugin import setup_plugin
|
||||||
setup_plugin()
|
setup_plugin()
|
||||||
|
|
||||||
# Add extra class paths
|
# Add extra class paths
|
||||||
@ -432,7 +432,7 @@ class PyhidraLauncher:
|
|||||||
# import properties to register the property customizer
|
# import properties to register the property customizer
|
||||||
from . import properties as _
|
from . import properties as _
|
||||||
|
|
||||||
_load_entry_points("pyhidra.pre_launch")
|
_load_entry_points("pyghidra.pre_launch")
|
||||||
|
|
||||||
def start(self, **jpype_kwargs):
|
def start(self, **jpype_kwargs):
|
||||||
"""
|
"""
|
||||||
@ -548,9 +548,9 @@ class PyhidraLauncher:
|
|||||||
return Application.isInitialized()
|
return Application.isInitialized()
|
||||||
|
|
||||||
|
|
||||||
class DeferredPyhidraLauncher(PyhidraLauncher):
|
class DeferredPyGhidraLauncher(PyGhidraLauncher):
|
||||||
"""
|
"""
|
||||||
PyhidraLauncher which allows full Ghidra initialization to be deferred.
|
PyGhidraLauncher which allows full Ghidra initialization to be deferred.
|
||||||
initialize_ghidra must be called before all Ghidra classes are fully available.
|
initialize_ghidra must be called before all Ghidra classes are fully available.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -571,9 +571,9 @@ class DeferredPyhidraLauncher(PyhidraLauncher):
|
|||||||
GhidraRun().launch(self._layout, self.args)
|
GhidraRun().launch(self._layout, self.args)
|
||||||
|
|
||||||
|
|
||||||
class HeadlessPyhidraLauncher(PyhidraLauncher):
|
class HeadlessPyGhidraLauncher(PyGhidraLauncher):
|
||||||
"""
|
"""
|
||||||
Headless pyhidra launcher
|
Headless pyghidra launcher
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _launch(self):
|
def _launch(self):
|
||||||
@ -583,7 +583,7 @@ class HeadlessPyhidraLauncher(PyhidraLauncher):
|
|||||||
Application.initializeApplication(self._layout, config)
|
Application.initializeApplication(self._layout, config)
|
||||||
|
|
||||||
|
|
||||||
class _PyhidraStdOut:
|
class _PyGhidraStdOut:
|
||||||
|
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
self._stream = stream
|
self._stream = stream
|
||||||
@ -615,9 +615,9 @@ class _PyhidraStdOut:
|
|||||||
return self._stream.write(s)
|
return self._stream.write(s)
|
||||||
|
|
||||||
|
|
||||||
class GuiPyhidraLauncher(PyhidraLauncher):
|
class GuiPyGhidraLauncher(PyGhidraLauncher):
|
||||||
"""
|
"""
|
||||||
GUI pyhidra launcher
|
GUI pyghidra launcher
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -647,8 +647,8 @@ class GuiPyhidraLauncher(PyhidraLauncher):
|
|||||||
appid = ctypes.c_wchar_p(self.app_info.name)
|
appid = ctypes.c_wchar_p(self.app_info.name)
|
||||||
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid)
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid)
|
||||||
|
|
||||||
stdout = _PyhidraStdOut(sys.stdout)
|
stdout = _PyGhidraStdOut(sys.stdout)
|
||||||
stderr = _PyhidraStdOut(sys.stderr)
|
stderr = _PyGhidraStdOut(sys.stderr)
|
||||||
with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(stderr):
|
with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(stderr):
|
||||||
Thread(lambda: Ghidra.main(["ghidra.GhidraRun", *self.args])).start()
|
Thread(lambda: Ghidra.main(["ghidra.GhidraRun", *self.args])).start()
|
||||||
is_exiting = threading.Event()
|
is_exiting = threading.Event()
|
@ -14,10 +14,10 @@ class _JavaObject:
|
|||||||
if isinstance(self, jpype.JException):
|
if isinstance(self, jpype.JException):
|
||||||
# don't process any exceptions
|
# don't process any exceptions
|
||||||
return
|
return
|
||||||
exposer = jpype.JClass("ghidra.pyhidra.PythonFieldExposer")
|
exposer = jpype.JClass("ghidra.pyghidra.PythonFieldExposer")
|
||||||
if exposer.class_.isAssignableFrom(self.class_):
|
if exposer.class_.isAssignableFrom(self.class_):
|
||||||
return
|
return
|
||||||
utils = jpype.JClass("ghidra.pyhidra.property.PropertyUtils")
|
utils = jpype.JClass("ghidra.pyghidra.property.PropertyUtils")
|
||||||
for prop in utils.getProperties(self.class_):
|
for prop in utils.getProperties(self.class_):
|
||||||
field = prop.field
|
field = prop.field
|
||||||
if keyword.iskeyword(field):
|
if keyword.iskeyword(field):
|
@ -12,7 +12,7 @@ from jpype import JClass, JImplementationFor
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
from pyhidra import debug_callback
|
from pyghidra import debug_callback
|
||||||
|
|
||||||
_NO_ATTRIBUTE = object()
|
_NO_ATTRIBUTE = object()
|
||||||
|
|
||||||
@ -70,12 +70,12 @@ class _JavaProperty(property):
|
|||||||
|
|
||||||
|
|
||||||
#pylint: disable=too-few-public-methods
|
#pylint: disable=too-few-public-methods
|
||||||
@JImplementationFor("ghidra.pyhidra.PythonFieldExposer")
|
@JImplementationFor("ghidra.pyghidra.PythonFieldExposer")
|
||||||
class _PythonFieldExposer:
|
class _PythonFieldExposer:
|
||||||
|
|
||||||
#pylint: disable=no-member
|
#pylint: disable=no-member
|
||||||
def __jclass_init__(self):
|
def __jclass_init__(self):
|
||||||
exposer = JClass("ghidra.pyhidra.PythonFieldExposer")
|
exposer = JClass("ghidra.pyghidra.PythonFieldExposer")
|
||||||
if self.class_ == exposer:
|
if self.class_ == exposer:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -135,8 +135,8 @@ class PyGhidraScript(dict):
|
|||||||
def __init__(self, jobj=None):
|
def __init__(self, jobj=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
if jobj is None:
|
if jobj is None:
|
||||||
from ghidra.pyhidra import PyhidraScriptProvider
|
from ghidra.pyghidra import PyGhidraScriptProvider
|
||||||
jobj = PyhidraScriptProvider().getScriptInstance(None, None)
|
jobj = PyGhidraScriptProvider().getScriptInstance(None, None)
|
||||||
self._script = jobj
|
self._script = jobj
|
||||||
|
|
||||||
global _headless_interpreter
|
global _headless_interpreter
|
||||||
@ -258,7 +258,7 @@ class PyGhidraScript(dict):
|
|||||||
|
|
||||||
def get_current_interpreter():
|
def get_current_interpreter():
|
||||||
"""
|
"""
|
||||||
Gets the underlying GhidraScript for the focused Pyhidra InteractiveConsole.
|
Gets the underlying GhidraScript for the focused PyGhidra InteractiveConsole.
|
||||||
This will always return None unless it is being access from a function
|
This will always return None unless it is being access from a function
|
||||||
called from within the interactive console.
|
called from within the interactive console.
|
||||||
|
|
||||||
@ -274,8 +274,8 @@ def get_current_interpreter():
|
|||||||
if SystemUtilities.isInHeadlessMode():
|
if SystemUtilities.isInHeadlessMode():
|
||||||
if _headless_interpreter is None:
|
if _headless_interpreter is None:
|
||||||
# one hasn't been created yet so make one now
|
# one hasn't been created yet so make one now
|
||||||
PyhidraScriptProvider = JClass("ghidra.pyhidra.PyhidraScriptProvider")
|
PyGhidraScriptProvider = JClass("ghidra.pyghidra.PyGhidraScriptProvider")
|
||||||
_headless_interpreter = PyhidraScriptProvider.PyhidraHeadlessScript()
|
_headless_interpreter = PyGhidraScriptProvider.PyGhidraHeadlessScript()
|
||||||
return _headless_interpreter
|
return _headless_interpreter
|
||||||
|
|
||||||
project = AppInfo.getActiveProject()
|
project = AppInfo.getActiveProject()
|
||||||
@ -293,7 +293,7 @@ def get_current_interpreter():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
for plugin in tool.getManagedPlugins():
|
for plugin in tool.getManagedPlugins():
|
||||||
if plugin.name == 'PyhidraPlugin':
|
if plugin.name == 'PyGhidraPlugin':
|
||||||
return plugin.script
|
return plugin.script
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
@ -1,4 +1,4 @@
|
|||||||
package ghidra.pyhidra.test;
|
package ghidra.pyghidra.test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a bad class that will fail to compile.
|
* This is a bad class that will fail to compile.
|
@ -1,9 +1,9 @@
|
|||||||
package ghidra.pyhidra.test;
|
package ghidra.pyghidra.test;
|
||||||
|
|
||||||
import ghidra.app.util.recognizer.Recognizer;
|
import ghidra.app.util.recognizer.Recognizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple ExtensionPoint class for pyhidra plugin test.
|
* Simple ExtensionPoint class for PyGhidra plugin test.
|
||||||
*
|
*
|
||||||
* This can be any ExtensionPoint. Recognizer was chosen here
|
* This can be any ExtensionPoint. Recognizer was chosen here
|
||||||
* because it has a small number of methods and hasn't changed in a long time.
|
* because it has a small number of methods and hasn't changed in a long time.
|
@ -2,9 +2,9 @@ from pathlib import Path
|
|||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pyhidra.__main__ import _get_parser, PyhidraArgs
|
from pyghidra.__main__ import _get_parser, PyGhidraArgs
|
||||||
from pyhidra.ghidra_launch import ParsedArgs
|
from pyghidra.ghidra_launch import ParsedArgs
|
||||||
from pyhidra.ghidra_launch import get_parser as get_ghidra_launcher_parser
|
from pyghidra.ghidra_launch import get_parser as get_ghidra_launcher_parser
|
||||||
|
|
||||||
|
|
||||||
PROJECT_NAME = "stub_name"
|
PROJECT_NAME = "stub_name"
|
||||||
@ -20,9 +20,9 @@ def exe_file(shared_datadir: Path):
|
|||||||
|
|
||||||
class TestArgParser:
|
class TestArgParser:
|
||||||
|
|
||||||
def parse(self, *args) -> PyhidraArgs:
|
def parse(self, *args) -> PyGhidraArgs:
|
||||||
parser = _get_parser()
|
parser = _get_parser()
|
||||||
parser_args = PyhidraArgs(parser)
|
parser_args = PyGhidraArgs(parser)
|
||||||
args = [str(arg) for arg in args]
|
args = [str(arg) for arg in args]
|
||||||
parser.parse_args(args, namespace=parser_args)
|
parser.parse_args(args, namespace=parser_args)
|
||||||
return parser_args
|
return parser_args
|
@ -4,7 +4,7 @@ import textwrap
|
|||||||
import importlib
|
import importlib
|
||||||
import sys
|
import sys
|
||||||
import jpype
|
import jpype
|
||||||
import pyhidra
|
import pyghidra
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
EXE_NAME = "strings.exe"
|
EXE_NAME = "strings.exe"
|
||||||
@ -23,7 +23,7 @@ def class_file(shared_datadir: Path):
|
|||||||
def test_invalid_jpype_keyword_arg():
|
def test_invalid_jpype_keyword_arg():
|
||||||
assert not jpype.isJVMStarted()
|
assert not jpype.isJVMStarted()
|
||||||
|
|
||||||
launcher = pyhidra.launcher.HeadlessPyhidraLauncher()
|
launcher = pyghidra.launcher.HeadlessPyGhidraLauncher()
|
||||||
with pytest.raises(TypeError) as ex:
|
with pytest.raises(TypeError) as ex:
|
||||||
launcher.start(someBogusKeywordArg=True)
|
launcher.start(someBogusKeywordArg=True)
|
||||||
assert "startJVM() got an unexpected keyword argument 'someBogusKeywordArg'" in str(ex.value)
|
assert "startJVM() got an unexpected keyword argument 'someBogusKeywordArg'" in str(ex.value)
|
||||||
@ -32,7 +32,7 @@ def test_invalid_jpype_keyword_arg():
|
|||||||
def test_invalid_vm_arg_succeed():
|
def test_invalid_vm_arg_succeed():
|
||||||
assert not jpype.isJVMStarted()
|
assert not jpype.isJVMStarted()
|
||||||
|
|
||||||
launcher = pyhidra.launcher.HeadlessPyhidraLauncher()
|
launcher = pyghidra.launcher.HeadlessPyGhidraLauncher()
|
||||||
launcher.add_vmargs('-XX:SomeBogusJvmArg')
|
launcher.add_vmargs('-XX:SomeBogusJvmArg')
|
||||||
launcher.start(ignoreUnrecognized=True)
|
launcher.start(ignoreUnrecognized=True)
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ def test_invalid_vm_arg_succeed():
|
|||||||
def test_run_script(capsys, shared_datadir: Path):
|
def test_run_script(capsys, shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
script_path = shared_datadir / "example_script.py"
|
script_path = shared_datadir / "example_script.py"
|
||||||
pyhidra.run_script(strings_exe, script_path, script_args=["my", "--commands"], analyze=False)
|
pyghidra.run_script(strings_exe, script_path, script_args=["my", "--commands"], analyze=False)
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
|
|
||||||
assert captured.err == ""
|
assert captured.err == ""
|
||||||
@ -56,7 +56,7 @@ def test_run_script(capsys, shared_datadir: Path):
|
|||||||
|
|
||||||
def test_open_program(shared_datadir: Path):
|
def test_open_program(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pyhidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE, compiler=TEST_COMPILER) as flat_api:
|
with pyghidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE, compiler=TEST_COMPILER) as flat_api:
|
||||||
assert flat_api.currentProgram.name == strings_exe.name
|
assert flat_api.currentProgram.name == strings_exe.name
|
||||||
assert flat_api.getCurrentProgram().listing
|
assert flat_api.getCurrentProgram().listing
|
||||||
assert flat_api.getCurrentProgram().changeable
|
assert flat_api.getCurrentProgram().changeable
|
||||||
@ -65,7 +65,7 @@ def test_open_program(shared_datadir: Path):
|
|||||||
def test_bad_language(shared_datadir: Path):
|
def test_bad_language(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
with pyhidra.open_program(
|
with pyghidra.open_program(
|
||||||
strings_exe,
|
strings_exe,
|
||||||
analyze=False,
|
analyze=False,
|
||||||
language="invalid"
|
language="invalid"
|
||||||
@ -76,7 +76,7 @@ def test_bad_language(shared_datadir: Path):
|
|||||||
def test_bad_compiler(shared_datadir: Path):
|
def test_bad_compiler(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
with pyhidra.open_program(
|
with pyghidra.open_program(
|
||||||
strings_exe,
|
strings_exe,
|
||||||
analyze=False,
|
analyze=False,
|
||||||
language=TEST_LANGUAGE,
|
language=TEST_LANGUAGE,
|
||||||
@ -87,19 +87,19 @@ def test_bad_compiler(shared_datadir: Path):
|
|||||||
|
|
||||||
def test_no_compiler(shared_datadir: Path):
|
def test_no_compiler(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pyhidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE) as flat_api:
|
with pyghidra.open_program(strings_exe, analyze=False, language=TEST_LANGUAGE) as flat_api:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_no_language_with_compiler(shared_datadir: Path):
|
def test_no_language_with_compiler(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pyhidra.open_program(strings_exe, analyze=False, compiler=TEST_COMPILER) as flat_api:
|
with pyghidra.open_program(strings_exe, analyze=False, compiler=TEST_COMPILER) as flat_api:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_loader(shared_datadir: Path):
|
def test_loader(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pyhidra.open_program(
|
with pyghidra.open_program(
|
||||||
strings_exe,
|
strings_exe,
|
||||||
analyze=False,
|
analyze=False,
|
||||||
language="DATA:LE:64:default",
|
language="DATA:LE:64:default",
|
||||||
@ -112,7 +112,7 @@ def test_loader(shared_datadir: Path):
|
|||||||
def test_invalid_loader(shared_datadir: Path):
|
def test_invalid_loader(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
with pyhidra.open_program(
|
with pyghidra.open_program(
|
||||||
strings_exe,
|
strings_exe,
|
||||||
analyze=False,
|
analyze=False,
|
||||||
language="DATA:LE:64:default",
|
language="DATA:LE:64:default",
|
||||||
@ -125,7 +125,7 @@ def test_invalid_loader(shared_datadir: Path):
|
|||||||
def test_invalid_loader_type(shared_datadir: Path):
|
def test_invalid_loader_type(shared_datadir: Path):
|
||||||
strings_exe = shared_datadir / EXE_NAME
|
strings_exe = shared_datadir / EXE_NAME
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
with pyhidra.open_program(
|
with pyghidra.open_program(
|
||||||
strings_exe,
|
strings_exe,
|
||||||
analyze=False,
|
analyze=False,
|
||||||
language="DATA:LE:64:default",
|
language="DATA:LE:64:default",
|
||||||
@ -136,7 +136,7 @@ def test_invalid_loader_type(shared_datadir: Path):
|
|||||||
|
|
||||||
|
|
||||||
def test_no_project(capsys, shared_datadir: Path):
|
def test_no_project(capsys, shared_datadir: Path):
|
||||||
pyhidra.run_script(None, shared_datadir / "projectless_script.py")
|
pyghidra.run_script(None, shared_datadir / "projectless_script.py")
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
assert captured.out.rstrip() == "projectless_script executed successfully"
|
assert captured.out.rstrip() == "projectless_script executed successfully"
|
||||||
|
|
||||||
@ -145,14 +145,14 @@ def test_no_program(capsys, shared_datadir: Path):
|
|||||||
script_path = shared_datadir / "programless_script.py"
|
script_path = shared_datadir / "programless_script.py"
|
||||||
project_path = shared_datadir / "programless_ghidra"
|
project_path = shared_datadir / "programless_ghidra"
|
||||||
|
|
||||||
pyhidra.run_script(None, script_path, project_path, "programless")
|
pyghidra.run_script(None, script_path, project_path, "programless")
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
assert captured.out.rstrip() == "programless_script executed successfully"
|
assert captured.out.rstrip() == "programless_script executed successfully"
|
||||||
|
|
||||||
|
|
||||||
def test_import_script(capsys, shared_datadir: Path):
|
def test_import_script(capsys, shared_datadir: Path):
|
||||||
script_path = shared_datadir / "import_test_script.py"
|
script_path = shared_datadir / "import_test_script.py"
|
||||||
pyhidra.run_script(None, script_path)
|
pyghidra.run_script(None, script_path)
|
||||||
captured = capsys.readouterr()
|
captured = capsys.readouterr()
|
||||||
assert captured.out.rstrip() == "imported successfully"
|
assert captured.out.rstrip() == "imported successfully"
|
||||||
|
|
||||||
@ -176,16 +176,16 @@ def test_import_ghidra_base_java_packages():
|
|||||||
def wrap_mod(mod):
|
def wrap_mod(mod):
|
||||||
return mod + '_'
|
return mod + '_'
|
||||||
|
|
||||||
launcher = pyhidra.start()
|
launcher = pyghidra.start()
|
||||||
|
|
||||||
# Test to ensure _PyhidraImportLoader is last loader
|
# Test to ensure _PyGhidraImportLoader is last loader
|
||||||
assert isinstance(sys.meta_path[-1], pyhidra.launcher._PyhidraImportLoader)
|
assert isinstance(sys.meta_path[-1], pyghidra.launcher._PyGhidraImportLoader)
|
||||||
|
|
||||||
packages = get_runtime_top_level_java_packages(launcher)
|
packages = get_runtime_top_level_java_packages(launcher)
|
||||||
|
|
||||||
assert len(packages) > 0
|
assert len(packages) > 0
|
||||||
|
|
||||||
# Test full coverage for Java base packages (_JImportLoader or _PyhidraImportLoader)
|
# Test full coverage for Java base packages (_JImportLoader or _PyGhidraImportLoader)
|
||||||
for mod in packages:
|
for mod in packages:
|
||||||
# check spec using standard import machinery "import mod"
|
# check spec using standard import machinery "import mod"
|
||||||
spec = importlib.util.find_spec(mod)
|
spec = importlib.util.find_spec(mod)
|
||||||
@ -195,13 +195,13 @@ def test_import_ghidra_base_java_packages():
|
|||||||
|
|
||||||
assert spec is not None
|
assert spec is not None
|
||||||
assert isinstance(spec.loader, jpype.imports._JImportLoader) or isinstance(
|
assert isinstance(spec.loader, jpype.imports._JImportLoader) or isinstance(
|
||||||
spec.loader, pyhidra.launcher._PyhidraImportLoader)
|
spec.loader, pyghidra.launcher._PyGhidraImportLoader)
|
||||||
|
|
||||||
# Test all Java base packages are available with '_'
|
# Test all Java base packages are available with '_'
|
||||||
for mod in packages:
|
for mod in packages:
|
||||||
spec_ = importlib.util.find_spec(wrap_mod(mod))
|
spec_ = importlib.util.find_spec(wrap_mod(mod))
|
||||||
assert spec_ is not None
|
assert spec_ is not None
|
||||||
assert isinstance(spec_.loader, pyhidra.launcher._PyhidraImportLoader)
|
assert isinstance(spec_.loader, pyghidra.launcher._PyGhidraImportLoader)
|
||||||
|
|
||||||
# Test standard import
|
# Test standard import
|
||||||
import ghidra
|
import ghidra
|
||||||
@ -209,7 +209,7 @@ def test_import_ghidra_base_java_packages():
|
|||||||
|
|
||||||
# Test import with conflict
|
# Test import with conflict
|
||||||
import pdb_
|
import pdb_
|
||||||
assert isinstance(pdb_.__loader__, pyhidra.launcher._PyhidraImportLoader)
|
assert isinstance(pdb_.__loader__, pyghidra.launcher._PyGhidraImportLoader)
|
||||||
|
|
||||||
# Test "from" import with conflict
|
# Test "from" import with conflict
|
||||||
from pdb_ import PdbPlugin
|
from pdb_ import PdbPlugin
|
@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
import typing
|
import typing
|
||||||
|
|
||||||
import jpype
|
import jpype
|
||||||
import pyhidra
|
import pyghidra
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
@ -13,8 +13,8 @@ import pytest
|
|||||||
pytestmark = pytest.mark.plugin
|
pytestmark = pytest.mark.plugin
|
||||||
|
|
||||||
|
|
||||||
SETUP_KEY = "pyhidra.setup"
|
SETUP_KEY = "pyghidra.setup"
|
||||||
PRE_LAUNCH_KEY = "pyhidra.pre_launch"
|
PRE_LAUNCH_KEY = "pyghidra.pre_launch"
|
||||||
NAME_KEY = "names"
|
NAME_KEY = "names"
|
||||||
|
|
||||||
|
|
||||||
@ -30,10 +30,10 @@ class PluginTest:
|
|||||||
ran_setup = False
|
ran_setup = False
|
||||||
ran_prelaunch = False
|
ran_prelaunch = False
|
||||||
|
|
||||||
details: pyhidra.ExtensionDetails = None
|
details: pyghidra.ExtensionDetails = None
|
||||||
|
|
||||||
def __init_subclass__(cls) -> None:
|
def __init_subclass__(cls) -> None:
|
||||||
cls.details = pyhidra.ExtensionDetails(
|
cls.details = pyghidra.ExtensionDetails(
|
||||||
name=cls.__name__,
|
name=cls.__name__,
|
||||||
description="Test Plugin",
|
description="Test Plugin",
|
||||||
author=""
|
author=""
|
||||||
@ -43,7 +43,7 @@ class PluginTest:
|
|||||||
_prelaunch = cls.prelaunch
|
_prelaunch = cls.prelaunch
|
||||||
|
|
||||||
@functools.wraps(_setup)
|
@functools.wraps(_setup)
|
||||||
def setup(launcher: pyhidra.HeadlessPyhidraLauncher):
|
def setup(launcher: pyghidra.HeadlessPyGhidraLauncher):
|
||||||
_setup(launcher)
|
_setup(launcher)
|
||||||
cls.ran_setup = True
|
cls.ran_setup = True
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ class PluginTest:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def setup(cls, launcher: pyhidra.HeadlessPyhidraLauncher):
|
def setup(cls, launcher: pyghidra.HeadlessPyGhidraLauncher):
|
||||||
...
|
...
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -110,7 +110,7 @@ def with_ghidra():
|
|||||||
"""
|
"""
|
||||||
_monkey_patch_entry_points()
|
_monkey_patch_entry_points()
|
||||||
try:
|
try:
|
||||||
launcher = pyhidra.HeadlessPyhidraLauncher()
|
launcher = pyghidra.HeadlessPyGhidraLauncher()
|
||||||
launcher.start()
|
launcher.start()
|
||||||
yield # can't yield None
|
yield # can't yield None
|
||||||
finally:
|
finally:
|
||||||
@ -128,29 +128,29 @@ def with_ghidra():
|
|||||||
class TestValidPlugin(PluginTest):
|
class TestValidPlugin(PluginTest):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup(cls, launcher: pyhidra.HeadlessPyhidraLauncher):
|
def setup(cls, launcher: pyghidra.HeadlessPyGhidraLauncher):
|
||||||
source_path = Path(__file__).parent / "data" / "good_plugin"
|
source_path = Path(__file__).parent / "data" / "good_plugin"
|
||||||
launcher.install_plugin(source_path, cls.details)
|
launcher.install_plugin(source_path, cls.details)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def prelaunch(cls):
|
def prelaunch(cls):
|
||||||
DummyTestRecognizer = jpype.JClass("ghidra.pyhidra.test.DummyTestRecognizer")
|
DummyTestRecognizer = jpype.JClass("ghidra.pyghidra.test.DummyTestRecognizer")
|
||||||
DummyTestRecognizer.preLaunchInitialized = True
|
DummyTestRecognizer.preLaunchInitialized = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def test_extension_point(cls):
|
def test_extension_point(cls):
|
||||||
from ghidra.app.util.recognizer import Recognizer
|
from ghidra.app.util.recognizer import Recognizer
|
||||||
from ghidra.util.classfinder import ClassSearcher
|
from ghidra.util.classfinder import ClassSearcher
|
||||||
DummyTestRecognizer = jpype.JClass("ghidra.pyhidra.test.DummyTestRecognizer")
|
DummyTestRecognizer = jpype.JClass("ghidra.pyghidra.test.DummyTestRecognizer")
|
||||||
assert DummyTestRecognizer in ClassSearcher.getClasses(Recognizer)
|
assert DummyTestRecognizer in ClassSearcher.getClasses(Recognizer)
|
||||||
|
|
||||||
|
|
||||||
class TestBadPlugin(PluginTest):
|
class TestBadPlugin(PluginTest):
|
||||||
|
|
||||||
launcher: pyhidra.HeadlessPyhidraLauncher = None
|
launcher: pyghidra.HeadlessPyGhidraLauncher = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup(cls, launcher: pyhidra.HeadlessPyhidraLauncher):
|
def setup(cls, launcher: pyghidra.HeadlessPyGhidraLauncher):
|
||||||
source_path = Path(__file__).parent / "data" / "bad_plugin"
|
source_path = Path(__file__).parent / "data" / "bad_plugin"
|
||||||
launcher.install_plugin(source_path, cls.details)
|
launcher.install_plugin(source_path, cls.details)
|
||||||
cls.launcher = launcher
|
cls.launcher = launcher
|
@ -13,11 +13,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.pyhidra;
|
package ghidra.pyghidra;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
import ghidra.app.plugin.core.osgi.BundleHost;
|
import ghidra.app.plugin.core.osgi.BundleHost;
|
||||||
import ghidra.app.script.GhidraScriptUtil;
|
import ghidra.app.script.GhidraScriptUtil;
|
||||||
@ -28,7 +27,7 @@ import ghidra.test.TestEnv;
|
|||||||
/**
|
/**
|
||||||
* Tests the Python Plugin functionality.
|
* Tests the Python Plugin functionality.
|
||||||
*/
|
*/
|
||||||
public class PyhidraPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
public class PyGhidraPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
|
|
||||||
@ -37,8 +36,8 @@ public class PyhidraPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
env = new TestEnv();
|
env = new TestEnv();
|
||||||
PluginTool tool = env.getTool();
|
PluginTool tool = env.getTool();
|
||||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||||
tool.addPlugin(PyhidraPlugin.class.getName());
|
tool.addPlugin(PyGhidraPlugin.class.getName());
|
||||||
env.getPlugin(PyhidraPlugin.class);
|
env.getPlugin(PyGhidraPlugin.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.pyhidra;
|
package ghidra.pyghidra;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
package ghidra.pyhidra;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import ghidra.pyhidra.PythonFieldExposer.ExposedField;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.Map;;
|
|
||||||
|
|
||||||
public class PythonFieldExposerTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() {
|
|
||||||
Map<String, ExposedField> fields = PythonFieldExposer.getProperties(PyhidraScriptProvider.PyhidraGhidraScript.class);
|
|
||||||
assertTrue(fields.containsKey("currentProgram"));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,240 +0,0 @@
|
|||||||
package ghidra.pyhidra.property;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Repeatable;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.junit.runners.Parameterized.Parameters;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class PropertyUtilsTest {
|
|
||||||
|
|
||||||
@Parameters(name = "{0}")
|
|
||||||
public static List<Object[]> data() {
|
|
||||||
return convertData(PropertyUtilsTest.class.getNestMembers());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Class<?> cls;
|
|
||||||
|
|
||||||
public PropertyUtilsTest(String name, Class<?> cls) {
|
|
||||||
this.cls = cls;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TestResult[] getExpected() {
|
|
||||||
return Arrays.stream(cls.getAnnotationsByType(ExpectedResult.class))
|
|
||||||
.map(TestResult::new)
|
|
||||||
.toArray(TestResult[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() {
|
|
||||||
TestResult[] expected = getExpected();
|
|
||||||
TestResult[] properties = getProperties(cls);
|
|
||||||
assertArrayEquals(expected, properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TestResult[] getProperties(Class<?> cls) {
|
|
||||||
return Arrays.stream(PropertyUtils.getProperties(cls))
|
|
||||||
.map(AbstractJavaProperty.class::cast)
|
|
||||||
.map(TestResult::new)
|
|
||||||
.toArray(TestResult[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Object[]> convertData(Class<?>[] classes) {
|
|
||||||
List<Object[]> result = new ArrayList<>(classes.length);
|
|
||||||
for (Class<?> cls : classes) {
|
|
||||||
if (cls.isRecord() || cls.isAnnotation()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.add(new Object[] { cls.getSimpleName(), cls });
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
@Repeatable(ExpectedResults.class)
|
|
||||||
private static @interface ExpectedResult {
|
|
||||||
String field();
|
|
||||||
|
|
||||||
boolean getter();
|
|
||||||
|
|
||||||
boolean setter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
private static @interface ExpectedResults {
|
|
||||||
ExpectedResult[] value();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static record TestResult(String field, boolean getter, boolean setter) {
|
|
||||||
TestResult(AbstractJavaProperty<?> property) {
|
|
||||||
this(property.field, property.hasGetter(), property.hasValidSetter());
|
|
||||||
}
|
|
||||||
|
|
||||||
TestResult(ExpectedResult result) {
|
|
||||||
this(result.field(), result.getter(), result.setter());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "length", getter = true, setter = false)
|
|
||||||
public static class TestGetter {
|
|
||||||
public int getLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "length", getter = false, setter = true)
|
|
||||||
public static class TestSetter {
|
|
||||||
public void setLength(int i) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "length", getter = true, setter = true)
|
|
||||||
public static class TestProperty {
|
|
||||||
public int getLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(int i) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "length", getter = true, setter = true)
|
|
||||||
public static class TestMultiSetter {
|
|
||||||
public int getLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(int i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(short s) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "length", getter = true, setter = true)
|
|
||||||
public static class TestBoxedMultiSetter {
|
|
||||||
public int getLength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(int i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(Integer i) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestMultiSetterNoGetter {
|
|
||||||
public void setLength(int i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLength(short s) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "valid", getter = true, setter = false)
|
|
||||||
public static class TestIsGetter {
|
|
||||||
public boolean isValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "valid", getter = true, setter = true)
|
|
||||||
public static class TestIsProperty {
|
|
||||||
public boolean isValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValid(boolean valid) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "valid", getter = true, setter = false)
|
|
||||||
public static class TestIsBoxedGetter {
|
|
||||||
public Boolean isValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExpectedResult(field = "valid", getter = true, setter = true)
|
|
||||||
public static class TestIsBoxedProperty {
|
|
||||||
public Boolean isValid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValid(boolean valid) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadIsGetter {
|
|
||||||
public int isValid() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestIsGetterName {
|
|
||||||
public boolean isvalid() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadGetterName {
|
|
||||||
public int getlength() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadSetterName {
|
|
||||||
public void setlength(int i) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadIsTooShortName {
|
|
||||||
public boolean i() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadGetTooShortName {
|
|
||||||
public int ge() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadSetTooShortName {
|
|
||||||
public int se() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadIsNoName {
|
|
||||||
public boolean is() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadGetNoName {
|
|
||||||
public int get() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestBadSetNoName {
|
|
||||||
public int set() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
#----------------------------------------
|
#----------------------------------------
|
||||||
# Pyhidra launch
|
# PyGhidra launch
|
||||||
#----------------------------------------
|
#----------------------------------------
|
||||||
|
|
||||||
# Resolve symbolic link if present and get the directory this script lives in.
|
# Resolve symbolic link if present and get the directory this script lives in.
|
||||||
@ -28,6 +28,6 @@ if [ ! -d "${INSTALL_DIR}/Ghidra" ]; then
|
|||||||
INSTALL_DIR="${SCRIPT_DIR}/../../../.."
|
INSTALL_DIR="${SCRIPT_DIR}/../../../.."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PYHIDRA_LAUNCHER="${INSTALL_DIR}/Ghidra/Features/Pyhidra/pyhidraLauncher.py"
|
PYGHIDRA_LAUNCHER="${INSTALL_DIR}/Ghidra/Features/PyGhidra/pyghidra_launcher.py"
|
||||||
|
|
||||||
python3 "${PYHIDRA_LAUNCHER}" "${INSTALL_DIR}" ${DEV_ARG} ${VMARG_LIST} "$@"
|
python3 "${PYGHIDRA_LAUNCHER}" "${INSTALL_DIR}" ${DEV_ARG} ${VMARG_LIST} "$@"
|
@ -1,4 +1,4 @@
|
|||||||
:: Pyhidra launch
|
:: PyGhidra launch
|
||||||
|
|
||||||
@echo off
|
@echo off
|
||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
@ -32,9 +32,9 @@ if not exist "%INSTALL_DIR%\Ghidra" (
|
|||||||
set "INSTALL_DIR=%SCRIPT_DIR%\..\..\..\.."
|
set "INSTALL_DIR=%SCRIPT_DIR%\..\..\..\.."
|
||||||
)
|
)
|
||||||
|
|
||||||
set "PYHIDRA_LAUNCHER=%INSTALL_DIR%\Ghidra\Features\Pyhidra\pyhidraLauncher.py
|
set "PYGHIDRA_LAUNCHER=%INSTALL_DIR%\Ghidra\Features\PyGhidra\pyghidra_launcher.py
|
||||||
|
|
||||||
%PYTHON% "%PYHIDRA_LAUNCHER%" "%INSTALL_DIR%" %DEV_ARG% %VMARG_LIST% %*
|
%PYTHON% "%PYGHIDRA_LAUNCHER%" "%INSTALL_DIR%" %DEV_ARG% %VMARG_LIST% %*
|
||||||
|
|
||||||
:exit1
|
:exit1
|
||||||
if not %ERRORLEVEL% == 0 (
|
if not %ERRORLEVEL% == 0 (
|
@ -53,8 +53,8 @@ final class PythonTypeStubMethod extends PythonTypeStubElement<ExecutableElement
|
|||||||
Map.entry("java.math.BigDecimal", "decimal.Decimal")));
|
Map.entry("java.math.BigDecimal", "decimal.Decimal")));
|
||||||
|
|
||||||
// FIXME: list and set aren't automatically converted to java.util.List and java.util.Set :(
|
// FIXME: list and set aren't automatically converted to java.util.List and java.util.Set :(
|
||||||
// if wanted they could be setup to be converted automatically by pyhidra
|
// if wanted they could be setup to be converted automatically by PyGhidra
|
||||||
// however, when passed as a parameter and modified, the original underlyng python container
|
// however, when passed as a parameter and modified, the original underlying python container
|
||||||
// wouldn't be modified. To make it work as expected, a python implementation for
|
// wouldn't be modified. To make it work as expected, a python implementation for
|
||||||
// java.util.List and java.util.Set would need to be created using jpype.JImplements,
|
// java.util.List and java.util.Set would need to be created using jpype.JImplements,
|
||||||
// that would wrap the list/set before passing it to Java instead of copying the contents
|
// that would wrap the list/set before passing it to Java instead of copying the contents
|
||||||
|
@ -40,7 +40,7 @@ future releases.
|
|||||||
<li><a href="#RunServer">Ghidra Server</a></li>
|
<li><a href="#RunServer">Ghidra Server</a></li>
|
||||||
<li><a href="#RunHeadless">Headless (Batch) Mode</a></li>
|
<li><a href="#RunHeadless">Headless (Batch) Mode</a></li>
|
||||||
<li><a href="#RunJar">Single Jar Mode</a></li>
|
<li><a href="#RunJar">Single Jar Mode</a></li>
|
||||||
<li><a href="#RunPyhidra">Pyhidra</a></li>
|
<li><a href="#RunPyGhidra">PyGhidra</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Extensions">Extensions</a></li>
|
<li><a href="#Extensions">Extensions</a></li>
|
||||||
<ul>
|
<ul>
|
||||||
@ -102,7 +102,7 @@ Ghidra team if you have a specific need.</p></blockquote>
|
|||||||
<li>Python3 (3.9 to 3.12)</li>
|
<li>Python3 (3.9 to 3.12)</li>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Python 3.7 to 3.12 for <a href="#DebuggerPython">Debugger support</a></li>
|
<li>Python 3.7 to 3.12 for <a href="#DebuggerPython">Debugger support</a></li>
|
||||||
<li>Python 3.9 to 3.12 for <a href="#RunPyhidra">Pyhidra support</a></li>
|
<li>Python 3.9 to 3.12 for <a href="#RunPyGhidra">PyGhidra support</a></li>
|
||||||
<li>This is available from <a href="https://python.org">Python.org</a> or most operating system's
|
<li>This is available from <a href="https://python.org">Python.org</a> or most operating system's
|
||||||
app stores or software repositories. For Linux it is recommended that the system's package
|
app stores or software repositories. For Linux it is recommended that the system's package
|
||||||
repository be used to install a suitable version of Python.</li>
|
repository be used to install a suitable version of Python.</li>
|
||||||
@ -445,8 +445,8 @@ another Java application.</p>
|
|||||||
<p>A single ghidra.jar file can be created using the
|
<p>A single ghidra.jar file can be created using the
|
||||||
<i><GhidraInstallDir></i>/support/buildGhidraJar script.</p>
|
<i><GhidraInstallDir></i>/support/buildGhidraJar script.</p>
|
||||||
|
|
||||||
<h3><a name="RunPyhidra"></a>Pyhidra Mode</h3>
|
<h3><a name="RunPyGhidra"></a>PyGhidra Mode</h3>
|
||||||
<p>Ghidra has integrated the the popular Pyhidra extension to enable native CPython 3 support out of
|
<p>Ghidra has integrated the the popular PyGhidra extension to enable native CPython 3 support out of
|
||||||
the box. To enable this support, Ghidra must be launched from a Python environment using special
|
the box. To enable this support, Ghidra must be launched from a Python environment using special
|
||||||
launch scripts.</p>
|
launch scripts.</p>
|
||||||
<ol>
|
<ol>
|
||||||
@ -454,20 +454,20 @@ launch scripts.</p>
|
|||||||
Navigate to <i><GhidraInstallDir></i>/support/
|
Navigate to <i><GhidraInstallDir></i>/support/
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>Run <i>pyhidraRun.bat</i> (Windows) or <i>pyhidraRun</i> (Linux or macOS)</p>
|
<p>Run <i>pyghidraRun.bat</i> (Windows) or <i>pyghidraRun</i> (Linux or macOS)</p>
|
||||||
<p>If the <b>pyhidra</b> Python module has not yet been installed, the script will offer to
|
<p>If the <b>pyghidra</b> Python module has not yet been installed, the script will offer to
|
||||||
install it for you, along with its dependencies. If you prefer to install it manually, execute:
|
install it for you, along with its dependencies. If you prefer to install it manually, execute:
|
||||||
<pre>python3 -m pip install --no-index -f <i><GhidraInstallDir></i>/Ghidra/Features/Pyhidra/pypkg/dist pyhidra</pre>
|
<pre>python3 -m pip install --no-index -f <i><GhidraInstallDir></i>/Ghidra/Features/PyGhidra/pypkg/dist pyghidra</pre>
|
||||||
<b>NOTE: </b>You may also install and run Pyhidra from within a
|
<b>NOTE: </b>You may also install and run PyGhidra from within a
|
||||||
<a href="https://docs.python.org/3/tutorial/venv.html">virtual environment</a> if you desire.
|
<a href="https://docs.python.org/3/tutorial/venv.html">virtual environment</a> if you desire.
|
||||||
<p>If Ghidra failed to launch, see the <a href="#Troubleshooting">Troubleshooting</a> section.
|
<p>If Ghidra failed to launch, see the <a href="#Troubleshooting">Troubleshooting</a> section.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p>Once Pyhidra has been installed, you are free to use it like any other Python module. You may
|
<p>Once PyGhidra has been installed, you are free to use it like any other Python module. You may
|
||||||
import it from other Python scripts, or launch Pyhidra using the <i>pyhidra</i> or <i>pyhidraw</i>
|
import it from other Python scripts, or launch PyGhidra using the <i>pyghidra</i> or <i>pyghidraw</i>
|
||||||
commands. For more information on using Pyhidra, see the
|
commands. For more information on using PyGhidra, see the
|
||||||
<i><GhidraInstallDir></i>/Ghidra/Features/Pyhidra/Pyhidra_README.html file.</p>
|
<i><GhidraInstallDir></i>/Ghidra/Features/PyGhidra/PyGhidra_README.html file.</p>
|
||||||
|
|
||||||
<p>(<a href="#top">Back to Top</a>)</p>
|
<p>(<a href="#top">Back to Top</a>)</p>
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ ext.deps = [
|
|||||||
name: "setuptools-68.0.0-py3-none-any.whl",
|
name: "setuptools-68.0.0-py3-none-any.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/c7/42/be1c7bbdd83e1bfb160c94b9cafd8e25efc7400346cf7ccdbdb452c467fa/setuptools-68.0.0-py3-none-any.whl",
|
url: "https://files.pythonhosted.org/packages/c7/42/be1c7bbdd83e1bfb160c94b9cafd8e25efc7400346cf7ccdbdb452c467fa/setuptools-68.0.0-py3-none-any.whl",
|
||||||
sha256: "11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f",
|
sha256: "11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f",
|
||||||
destination: [file("${DEPS_DIR}/Debugger-rmi-trace/"), file("${DEPS_DIR}/Pyhidra/")]
|
destination: [file("${DEPS_DIR}/Debugger-rmi-trace/"), file("${DEPS_DIR}/PyGhidra/")]
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "wheel-0.37.1-py2.py3-none-any.whl",
|
name: "wheel-0.37.1-py2.py3-none-any.whl",
|
||||||
@ -218,79 +218,79 @@ ext.deps = [
|
|||||||
name: "JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
name: "JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/5d/cf/7b89469bcede4b2fd69c2db7d1d61e8759393cfeec46f7b0c84f5006a691/JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
url: "https://files.pythonhosted.org/packages/5d/cf/7b89469bcede4b2fd69c2db7d1d61e8759393cfeec46f7b0c84f5006a691/JPype1-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
sha256: "f7aa1469d75f9b310f709b61bb2faa4cef4cbd4d670531ad1d1bb53e29cfda05",
|
sha256: "f7aa1469d75f9b310f709b61bb2faa4cef4cbd4d670531ad1d1bb53e29cfda05",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp39-cp39-win_amd64.whl",
|
name: "JPype1-1.5.0-cp39-cp39-win_amd64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/b9/fd/d38a8e401b089adce04c48021ddcb366891d1932db2f7653054feb470ae6/JPype1-1.5.0-cp39-cp39-win_amd64.whl",
|
url: "https://files.pythonhosted.org/packages/b9/fd/d38a8e401b089adce04c48021ddcb366891d1932db2f7653054feb470ae6/JPype1-1.5.0-cp39-cp39-win_amd64.whl",
|
||||||
sha256: "6bfdc101c56cab0b6b16e974fd8cbb0b3f7f14178286b8b55413c5d82d5f2bea",
|
sha256: "6bfdc101c56cab0b6b16e974fd8cbb0b3f7f14178286b8b55413c5d82d5f2bea",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl",
|
name: "JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/84/9c/80d5edf6d610f82d0658b6402cdf3f8cdd6a7d4f36afb2149da90e0cad47/JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl",
|
url: "https://files.pythonhosted.org/packages/84/9c/80d5edf6d610f82d0658b6402cdf3f8cdd6a7d4f36afb2149da90e0cad47/JPype1-1.5.0-cp310-cp310-macosx_10_9_universal2.whl",
|
||||||
sha256: "7b6b1af3f9e0033080e3532c2686a224cd14706f36c14ef36160a2a1db751a17",
|
sha256: "7b6b1af3f9e0033080e3532c2686a224cd14706f36c14ef36160a2a1db751a17",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
name: "JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/74/98/d6517002355b0585d0e66f7b0283c7f6e2271c898a886e1ebac09836b100/JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
url: "https://files.pythonhosted.org/packages/74/98/d6517002355b0585d0e66f7b0283c7f6e2271c898a886e1ebac09836b100/JPype1-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
sha256: "a02b2f05621c119d35f4acc501b4261eeb48a4af7cc13d9afc2e9eb316c4bd29",
|
sha256: "a02b2f05621c119d35f4acc501b4261eeb48a4af7cc13d9afc2e9eb316c4bd29",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp310-cp310-win_amd64.whl",
|
name: "JPype1-1.5.0-cp310-cp310-win_amd64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/da/5f/253c1c1dba6f7f457b6c3aa2ea9c517287d49764e0ee1042d5818c36e781/JPype1-1.5.0-cp310-cp310-win_amd64.whl",
|
url: "https://files.pythonhosted.org/packages/da/5f/253c1c1dba6f7f457b6c3aa2ea9c517287d49764e0ee1042d5818c36e781/JPype1-1.5.0-cp310-cp310-win_amd64.whl",
|
||||||
sha256: "0b40c76e075d4fed2c83340bb30b7b95bbc396fd370c564c6b608faab00ea4ef",
|
sha256: "0b40c76e075d4fed2c83340bb30b7b95bbc396fd370c564c6b608faab00ea4ef",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",
|
name: "JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/98/37/0049866cbfecb879b46d8e9f9b70944624ab17152a282ad5cf60909054ec/JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",
|
url: "https://files.pythonhosted.org/packages/98/37/0049866cbfecb879b46d8e9f9b70944624ab17152a282ad5cf60909054ec/JPype1-1.5.0-cp311-cp311-macosx_10_9_universal2.whl",
|
||||||
sha256: "85a31b30b482eaf788b21af421e0750aa0be7758307314178143a76632b0ad04",
|
sha256: "85a31b30b482eaf788b21af421e0750aa0be7758307314178143a76632b0ad04",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
name: "JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/17/1e/7728ae8fb41e8fbf3a7309f8936d07b0b1622f2860733df0e7ec30b1ce76/JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
url: "https://files.pythonhosted.org/packages/17/1e/7728ae8fb41e8fbf3a7309f8936d07b0b1622f2860733df0e7ec30b1ce76/JPype1-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
sha256: "5ef976e0f3b2e9604469f449f30bb2031941a159a0637f4c16adb2c5076f3e81",
|
sha256: "5ef976e0f3b2e9604469f449f30bb2031941a159a0637f4c16adb2c5076f3e81",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp311-cp311-win_amd64.whl",
|
name: "JPype1-1.5.0-cp311-cp311-win_amd64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/1f/19/144f3a767b563ba5c6d4aa534ea1f3fad9a5067c3917df4458a6e1afe0ef/JPype1-1.5.0-cp311-cp311-win_amd64.whl",
|
url: "https://files.pythonhosted.org/packages/1f/19/144f3a767b563ba5c6d4aa534ea1f3fad9a5067c3917df4458a6e1afe0ef/JPype1-1.5.0-cp311-cp311-win_amd64.whl",
|
||||||
sha256: "2bc987205ff8d2d8e36dfbef05430e0638e85d4fee1166ba58ebfa6f7a67cdf8",
|
sha256: "2bc987205ff8d2d8e36dfbef05430e0638e85d4fee1166ba58ebfa6f7a67cdf8",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl",
|
name: "JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/30/0d/9ac6f0e59427fc5ebf4547c2fdbb38e347b46c2dc20b430490236d037ed8/JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl",
|
url: "https://files.pythonhosted.org/packages/30/0d/9ac6f0e59427fc5ebf4547c2fdbb38e347b46c2dc20b430490236d037ed8/JPype1-1.5.0-cp312-cp312-macosx_10_9_universal2.whl",
|
||||||
sha256: "8714bfaf09d6877160bc7ac97812016ccb09f6d7ba5ea2a9f519178aefcca93f",
|
sha256: "8714bfaf09d6877160bc7ac97812016ccb09f6d7ba5ea2a9f519178aefcca93f",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
name: "JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/7d/ed/549766039d17550da6e3fa59ed776a021b400324d7766358d3b6e33d8b28/JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
url: "https://files.pythonhosted.org/packages/7d/ed/549766039d17550da6e3fa59ed776a021b400324d7766358d3b6e33d8b28/JPype1-1.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
|
||||||
sha256: "8649b526eccb4047881ad60bdb1974eb71a09cdb7f8bda17c96fdc0f9a3f2d1e",
|
sha256: "8649b526eccb4047881ad60bdb1974eb71a09cdb7f8bda17c96fdc0f9a3f2d1e",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0-cp312-cp312-win_amd64.whl",
|
name: "JPype1-1.5.0-cp312-cp312-win_amd64.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/20/47/9606af72e21703e5fca5e29e5bd5e345506977b6ba492c549648adef47ef/JPype1-1.5.0-cp312-cp312-win_amd64.whl",
|
url: "https://files.pythonhosted.org/packages/20/47/9606af72e21703e5fca5e29e5bd5e345506977b6ba492c549648adef47ef/JPype1-1.5.0-cp312-cp312-win_amd64.whl",
|
||||||
sha256: "9aafc00b00bf8c1b624081e5d4ab87f7752e6c7ee6a141cfc332250b05c6d42f",
|
sha256: "9aafc00b00bf8c1b624081e5d4ab87f7752e6c7ee6a141cfc332250b05c6d42f",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "JPype1-1.5.0.tar.gz",
|
name: "JPype1-1.5.0.tar.gz",
|
||||||
url: "https://files.pythonhosted.org/packages/25/42/8ca50a0e27e3053829545829e7bcba071cbfa4d5d8fd7fc5d1d988f325b1/JPype1-1.5.0.tar.gz",
|
url: "https://files.pythonhosted.org/packages/25/42/8ca50a0e27e3053829545829e7bcba071cbfa4d5d8fd7fc5d1d988f325b1/JPype1-1.5.0.tar.gz",
|
||||||
sha256: "425a6e1966afdd5848b60c2688bcaeb7e40ba504a686f1114589668e0631e878",
|
sha256: "425a6e1966afdd5848b60c2688bcaeb7e40ba504a686f1114589668e0631e878",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
name: "packaging-23.2-py3-none-any.whl",
|
name: "packaging-23.2-py3-none-any.whl",
|
||||||
url: "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl",
|
url: "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl",
|
||||||
sha256: "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7",
|
sha256: "8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7",
|
||||||
destination: file("${DEPS_DIR}/Pyhidra/")
|
destination: file("${DEPS_DIR}/PyGhidra/")
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user