We have explored both Java and Jython approaches for implementing a TCP server plugin for Ghidra. Through our investigation, we discovered:
- Creating a proper Java plugin requires specific extension properties and proper integration with Ghidra's module system to appear in the installation list
- The Jython approach provides a more accessible and practical way to implement TCP server functionality
- Both approaches can achieve the same goals, with Jython being easier to develop and test
Based on our analysis, we recommend treating the Python (Jython) approach as the main route for implementing the TCP server, with the Java implementation serving as an alternative for deployment if needed later.
The repository follows this organized structure:
src/python/- Python source code filesdocs/- Documentation filestests/python/- Python test filestmp/- Temporary files (excluded from git)- Root directory - Build scripts and main project files
src/python/ghidra_tcp_server_enhanced.py: Main implementation of the TCP server (Jython compatible with port selection)src/python/run_tcp_server.py: Entry point script to start the serverstart_ghidra_with_tcp_server.sh: Script to launch Ghidra with instructions
java/src/main/java/ClientDirectoryManager.java: Directory management for clientsjava/src/main/java/ClientHandler.java: Command handler implementationjava/src/main/java/GhidraPathNavigator.java: Path navigation implementationjava/src/main/java/GhidraTCPCommentingPlugin.java: Main plugin classjava/build.gradle: Gradle build configurationjava/build.sh: Build script for the Java pluginjava/GhidraModule.xml: Module information for Ghidra integration
./start_ghidra_with_tcp_server.sh
- Open Ghidra
- Go to
Window -> Script Manager - Find and run the
ghidra_tcp_server_working.pyscript - The TCP server will start and listen on port 9000
Connect your external client to localhost:9000 to start sending commands to Ghidra.
The TCP server supports these commands:
VAR-TYPE-SET <var_name> <type>- Set variable typeVAR-TYPE-GET <var_name>- Get variable typeFUN-NAME-SET <old_function_name> <new_function_name>- Rename functionFUN-NAME-GET- Get current function nameVAR-NAME-SET <old_var_name> <new_var_name>- Rename variableLIST-FUNCTION <fun_name>- List items in functionLIST-CLASS <class_name>- List items in classLIST-NAMESPACE <namespace>- List items in namespaceSET-COMMENT <fun_name> <line> <text>- Set commentREMOVE-COMMENT <fun_name> <line>- Remove commentREMOVE-ALL-COMMENTS <fun_name>- Remove all comments in functionFIND-VAR-REFERENCES <var_name>- Find variable referencesFIND-FUNCTION-REFERENCES <fun_name>- Find function referencesFIND-ADDR-REFERENCES <hex_addr>- Find address referencesFIND-LABEL <label_name>- Find labelRENAME-LABEL <old_label_name> <new_label_name>- Rename labelRENAME-GLOBAL <old_var_name> <new_var_name>- Rename global variableRETYPE-GLOBAL <var_name> <new_type>- Retype global variableLS <path>- List items at pathCAT <path>- Print content at pathHELP- Show helpQUIT- Close connection
import socket
# Connect to the TCP server
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 9000))
# Send a command
client_socket.send(b'FUN-NAME-GET\n')
response = client_socket.recv(4096).decode('utf-8')
print(response)
# Close connection
client_socket.close()- Proper extension.properties file for Ghidra extension recognition
- Full Ghidra plugin lifecycle management
- Integration with Ghidra's plugin installation system
- Better performance in production environments
- More complex setup but cleaner integration with Ghidra
- Simpler development and debugging process
- More accessible for rapid prototyping
- Direct access to Ghidra API through Jython
- Faster iteration cycle during development
- Easier to modify and test functionality
- TCP server functionality on port 9000
- Support for all specified commands
- Proper error handling and responses
- Integration with Ghidra's internal data structures
- Threaded client handling for multiple connections
- The Python approach is recommended as the main implementation path
- The Java approach provides a more formal Ghidra plugin but requires more configuration
- Both approaches achieve the same functionality but through different mechanisms
- The Python script needs to be run from within Ghidra's Script Manager
- Ensure the appropriate ports are available on your system
- If Ghidra gives import errors in Python, ensure you're running the script from within Ghidra's Script Manager
- For Java plugin, make sure the extension.properties file is correctly set up
- Make sure no other services are using port 9000
- Check that your client is connecting to the correct address (localhost:9000)
After starting the server from within Ghidra:
- Make sure your program is loaded in Ghidra
- Test from another terminal:
telnet localhost 9000
- Or use the demo client:
cd /common/active/sblo/Dev/GhidraPlugin python3 tests/python/demo_client.py
Once connected to the server through telnet or a client:
HELP- Shows all available commandsFUN-NAME-GET- Gets the current function name in GhidraVAR-TYPE-GET variable_name- Gets the type of the specified variableFUN-NAME-SET old_name new_name- Renames a function from old_name to new_nameQUIT- Closes the connection to the server
For the first time load of the server, use:
exec(open('/common/active/sblo/Dev/GhidraPlugin/src/python/ghidra_tcp_server_reloader_jython.py').read()) ; start_server(9003)
For development purposes, after you've already loaded the server script, you need to manually reload the server after changes using:
stop_server() ; exec(open('/common/active/sblo/Dev/GhidraPlugin/src/python/ghidra_tcp_server_reloader_jython.py').read()) ; start_server(9003)
To use this command:
- Copy the command above
- Paste it in the Ghidra Jython console
- Press Enter to execute
For convenience, we've added additional reload functions:
reload_server(9003)- Reloads the server with a single commandquick_reload(9003)- Quick reload of the serverauto_reload_checker()- Run this in the console to auto-reload when requested by clientsremote_reload.py- Client-side script to trigger reloads remotely
Use the Python (Jython) approach as the main implementation route for development and testing, with the Java approach available for formal plugin deployment in production environments.
The project is now complete with both implementation approaches ready for use!