Merge remote-tracking branch 'origin/patch' into Ghidra_12.1

This commit is contained in:
ghidra1
2026-05-05 15:49:10 -04:00
5 changed files with 110 additions and 45 deletions
@@ -19,7 +19,7 @@ vulnerabilities in networks and systems.
This release includes new features, enhancements, performance improvements, quite a few bug fixes,
and many pull-request contributions. Thanks to all those who have contributed their time, thoughts,
and code. The Ghidra user community thanks you too!
### The not-so-fine print: Please Read!
Ghidra 12.1 is fully backward compatible with project data from previous releases. However, programs
and data type archives which are created or modified in 12.1 will not be usable by an earlier Ghidra
@@ -43,16 +43,6 @@ libraries and operating systems (e.g., CentOS 7.x) may also run into compatibili
launching native executables such as the Decompiler and GNU Demangler which may necessitate a
rebuild of native components.
**NOTE:** Ghidra Server: The Ghidra 12.1 server is compatible with Ghidra 11.3.2 and later Ghidra
clients, although the presence of any newer link-files within a repository may not be handled properly
by client versions prior to 12.0 which lack support for the new storage format. Ghidra 12.1 clients
that introduce new link-files into a project will not be able to add such files into version
control if connected to older Ghidra Server versions.
**NOTE:** Ghidra Server: Due to potential Java version differences, it is
recommended that Ghidra Server installations older than 10.2 be upgraded. Those using 10.2 and newer
should not need a server upgrade unless they need to work with link-files within a shared repository.
**NOTE:** Programs imported with a Ghidra beta version or code built directly from source code
outside of a release tag may not be compatible, and may have flaws that won't be corrected by using
this new release. Any programs analyzed from a beta or other local master source build should be
@@ -64,6 +54,30 @@ process that will provide better results than prior Ghidra versions. You might
fresh import of any program you will continue to reverse engineer to see if the latest Ghidra
provides better results.
**NOTE:** Ghidra Server: The Ghidra 12.1 server is compatible with older Ghidra 11.3.2 clients and
later, although the presence of any newer link-files within a repository may not be handled properly
by client versions prior to 12.0, which lack support for the newer storage format. Ghidra 12.1 clients
require Ghidra Server version 12.1/12.0.5 or newer compatible version.
**NOTE:** Ghidra Server: Due to security fixes made to Ghidra and the Ghidra Server it is highly
recommended that older installation versions be updated to this latest release.
## Security Related Fixes
### RMI Serialization Filter Improvements
RMI Serialization filters for the Ghidra Server have been tightened and similar filters have been
added to Ghidra client applications which may communicate with a Ghidra Server. Please report
any unexpected *InvalidClassException* errors, which may occur, to the Ghidra team. If this does occur,
please check your Ghidra or server application log files for entries which indicate any filter
rejections which would indicate the name of the offending class.
### Ghidra Server - PKI Authentication Vulnerability
For those Ghidra Server deployments which utilize PKI Authentication mode (-a2), a logic bug
within the authentication callback to the server could allow an attacker to authenticate as a
different user without having access to their private key. Prior to completing the forged
authentication callback, the attacker would still need to successfully complete a fully authenticated
TLS connection with the Ghidra Server based on the installed Certificate Authorities (CAs).
## Bitfields
The Decompiler now recovers and displays the names of **bitfield** components in structured
data-types, when analyzing code that manipulates them.
@@ -90,7 +104,7 @@ Where possible, calls to `_objc_msgSend()` and its variations (including `_objc_
have been overridden to reference the actual target method (if discoverable), which results in a
much more user-friendly decompilation.
Additionally, a variety of AARCH64 call fixups have been implemented which further clean up
Additionally, a variety of AARCH64 call-fixups have been implemented which further clean up
decompilation, hiding much of the noise that things like Automatic Reference Counting (ARC) can
generate.
@@ -243,15 +243,15 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
}
@Override
public void checkCompatibility(int minServerInterfaceVersion) throws RemoteException {
if (minServerInterfaceVersion > INTERFACE_VERSION) {
public void checkCompatibility(int clientInterfaceVersion) throws RemoteException {
if (clientInterfaceVersion > SERVER_INTERFACE_VERSION) {
throw new RemoteException(
"Incompatible server interface, a newer Ghidra Server version is required.");
}
else if (minServerInterfaceVersion < MINIMUM_INTERFACE_VERSION) {
else if (clientInterfaceVersion < SERVER_MIN_CLIENT_INTERFACE_VERSION) {
throw new RemoteException(
"Incompatible server interface, the minimum supported Ghidra version is " +
MIN_GHIDRA_VERSION);
ALT_GHIDRA_BIND_VERSION);
}
}
@@ -871,9 +871,20 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
Registry registry = LocateRegistry.createRegistry(
ServerPortFactory.getRMIRegistryPort(), clientSocketFactory, serverSocketFactory);
StringBuilder bindVersions = new StringBuilder(" (");
bindVersions.append(GHIDRA_BIND_VERSION);
registry.bind(BIND_NAME, svr);
log.info("Registered Ghidra Server.");
if (!BIND_NAME.equals(ALT_BIND_NAME)) {
// Include alternate binding in support of older Ghidra client versions
bindVersions.append(", ");
bindVersions.append(ALT_GHIDRA_BIND_VERSION);
registry.bind(ALT_BIND_NAME, svr);
}
bindVersions.append(")");
log.info("Registered Ghidra Server" + bindVersions);
}
catch (Throwable t) {
@@ -199,7 +199,7 @@ public class RepositoryServerAdapter {
lastConnectError = t;
}
Msg.showError(this, null, "Server Error",
"An error occurred on the server (" + serverInfoStr + ").\n" + msg, e);
"An error occurred on the server (" + serverInfoStr + ").\n" + msg);
}
catch (IOException e) {
String err = e.getMessage();
@@ -208,8 +208,8 @@ public class RepositoryServerAdapter {
}
String msg = err != null ? err : e.toString();
Msg.showError(this, null, "Server Error",
"An error occurred while connecting to the server (" + serverInfoStr + ").\n" + msg,
e);
"An error occurred while connecting to the server (" + serverInfoStr + ").\n" +
msg);
}
throw new NotConnectedException("Not connected to repository server", lastConnectError);
}
@@ -175,7 +175,7 @@ class ServerConnectTask extends Task {
gsh = (GhidraServerHandle) reg.lookup(GhidraServerHandle.BIND_NAME);
// Check interface compatibility with the minimum supported version
gsh.checkCompatibility(GhidraServerHandle.MINIMUM_INTERFACE_VERSION);
gsh.checkCompatibility(GhidraServerHandle.MIN_CLIENT_INTERFACE_VERSION);
}
catch (NotBoundException e) {
throw new IOException(e.getMessage());
@@ -420,29 +420,32 @@ class ServerConnectTask extends Task {
}
}
private static void checkServerBindNames(Registry reg) throws RemoteException {
private static void checkServerBindNames(Registry reg) throws IOException {
String requiredVersion = GhidraServerHandle.MIN_GHIDRA_VERSION;
String requiredVersion = GhidraServerHandle.GHIDRA_BIND_VERSION;
if (!Application.getApplicationVersion().startsWith(requiredVersion)) {
requiredVersion = requiredVersion + " - " + Application.getApplicationVersion();
}
requiredVersion += " (or possibly newer)";
String[] regList = reg.list();
RemoteException exc = null;
IOException exc = null;
int badVerCount = 0;
String version = null;
for (String name : regList) {
if (name.equals(GhidraServerHandle.BIND_NAME)) {
return; // found it
}
else if (name.startsWith(GhidraServerHandle.BIND_NAME_PREFIX)) {
String version = name.substring(GhidraServerHandle.BIND_NAME_PREFIX.length());
// NOTE: We only report one version even if server has multiple bindings
version = name.substring(GhidraServerHandle.BIND_NAME_PREFIX.length());
if (version.length() == 0) {
version = "4.3.x (or older)";
}
exc = new RemoteException(
"Incompatible Ghidra Server interface, detected interface version " + version +
",\nthis client requires server version " + requiredVersion);
exc = new IOException(
"Incompatible Ghidra Server - detected interface version " + version +
".\nThis client requires server version " + requiredVersion);
++badVerCount;
}
}
@@ -450,11 +453,11 @@ class ServerConnectTask extends Task {
if (badVerCount == 1) {
throw exc;
}
throw new RemoteException("Incompatible Ghidra Server interface, detected " +
badVerCount + " incompatible server versions" +
",\nthis client requires server version " + requiredVersion);
throw new IOException("Incompatible Ghidra Server - detected " +
badVerCount + " incompatible server versions." +
"\nThis client requires server version " + requiredVersion);
}
throw new RemoteException("Ghidra Server not found.");
throw new IOException("Ghidra Server not found.");
}
}
@@ -52,23 +52,53 @@ public interface GhidraServerHandle extends Remote {
* unchanged allowing 9.1 clients to connect to 9.0 server.
* 12: Revised RepositoryFile serialization to facilitate support for text-data used
* for link-file storage (12.0).
* 13: Client-side serialization filters have been implemented and server-side thrown
* exceptions reduced to be compliant with client-side filters. Server still
* supports older clients back to interface version 11. Server may now BIND
* to the RMI registery with two different names if needed.
*/
/**
* The server interface version that the server will use and is the maximum version that the
* client can operate with.
* The server interface version that the server implements. This corresponds to the maximum
* supported client interface version.
*/
public static final int INTERFACE_VERSION = 12;
public static final int SERVER_INTERFACE_VERSION = 13;
/**
* The minimum server interface version that the client can operate with.
*/
public static final int MINIMUM_INTERFACE_VERSION = 11;
public static final int MIN_CLIENT_INTERFACE_VERSION = 13;
/**
* Minimum version of Ghidra which utilized the current INTERFACE_VERSION
* The minimum interface version that the server will support for older client versions.
* When this version is less than {@link #MIN_CLIENT_INTERFACE_VERSION} it allows the following:
* <ul>
* <li>Older ghidra client versions can continue using the current server version, while</li>
* <li>Current ghidra clients version cannot use an older version server.</li>
* </ul>
* When this version differs from {@link #MIN_CLIENT_INTERFACE_VERSION} the server will bind two
* both {@link #BIND_NAME} and {@value #ALT_BIND_NAME}.
* <p>
* NOTE: It is important that the server authentication interface not be modified between this
* version and {@value #MIN_CLIENT_INTERFACE_VERSION}.
*/
public static final String MIN_GHIDRA_VERSION = "9.0";
public static final int SERVER_MIN_CLIENT_INTERFACE_VERSION = 11;
/**
* The server BIND version which the Ghidra client can communicate with.
* This corresponds to {@value #MIN_CLIENT_INTERFACE_VERSION}.
*/
public static final String GHIDRA_BIND_VERSION = "12.0.5";
/**
* Minimum version of a Ghidra client release which can communicate with the current
* Ghidra Server. This corresponds to {@value #SERVER_MIN_CLIENT_INTERFACE_VERSION}
* and {@link #ALT_BIND_NAME}.
* <p>
* This version is used only by the server only in publishing an alternate BIND name and
* identifies the oldest Ghidra client version that may connect.
*/
public static final String ALT_GHIDRA_BIND_VERSION = "9.0";
/**
* Default RMI base port for Ghidra Server
@@ -81,13 +111,21 @@ public interface GhidraServerHandle extends Remote {
static final String BIND_NAME_PREFIX = "GhidraServer";
/**
* RMI registry binding name for the supported version of the remote GhidraServerHandle object.
* Primary RMI registry binding name for the remote GhidraServerHandle object.
* This BIND name is used by both the server and client.
*/
static final String BIND_NAME = BIND_NAME_PREFIX + MIN_GHIDRA_VERSION;
static final String BIND_NAME = BIND_NAME_PREFIX + GHIDRA_BIND_VERSION;
/**
* Alternate RMI registry binding name for the remote GhidraServerHandle object.
* This alternate BIND name is used only by the server in support of older Ghidra clients
* and corresponds to {@link #SERVER_MIN_CLIENT_INTERFACE_VERSION}.
*/
static final String ALT_BIND_NAME = BIND_NAME_PREFIX + ALT_GHIDRA_BIND_VERSION;
/**
* Returns user authentication proxy object.
* @throws RemoteException
* @throws RemoteException if failure occurs while generating authentication callbacks
* @return authentication callbacks which must be satisfied or null if authentication not
* required.
*/
@@ -107,11 +145,10 @@ public interface GhidraServerHandle extends Remote {
throws FailedLoginException, RemoteException;
/**
* Check server interface compatibility
* @param serverInterfaceVersion client/server interface version
* Check server interface compatibility with the specified client interface version.
* @param clientInterfaceVersion client/server interface version
* @throws RemoteException if requested server interface version not available
* @see #INTERFACE_VERSION
*/
void checkCompatibility(int serverInterfaceVersion) throws RemoteException;
void checkCompatibility(int clientInterfaceVersion) throws RemoteException;
}