Skip to content

Commit

Permalink
Add support for --objid during guess operation
Browse files Browse the repository at this point in the history
  • Loading branch information
qtc-de committed May 16, 2024
1 parent d080468 commit ef233a7
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Add [plugin template](/plugins/template)
* Add [Quartz Scheduler plugin](/plugins/quartz-scheduler)
* Add [Quartz Scheduler container](/docker/quartz-server)
* Add `--objid` support for guess operation

### Changed

Expand Down
6 changes: 6 additions & 0 deletions src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.io.InvalidClassException;
import java.io.StreamCorruptedException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.UnmarshalException;
Expand Down Expand Up @@ -254,6 +255,11 @@ else if (e instanceof UnmarshalException && e.getMessage().contains("Transport r
throw (UnmarshalException)e;
}

else if (e instanceof UnmarshalException && ExceptionHandler.getCause(e) instanceof StreamCorruptedException)
{
throw (UnmarshalException)e;
}

if( cause instanceof ClassNotFoundException )
{
ExceptionHandler.lookupClassNotFoundException(e, cause.getMessage());
Expand Down
59 changes: 42 additions & 17 deletions src/eu/tneitzel/rmg/operations/Dispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
import eu.tneitzel.rmg.io.WordlistHandler;
import eu.tneitzel.rmg.networking.RMIEndpoint;
import eu.tneitzel.rmg.networking.RMIRegistryEndpoint;
import eu.tneitzel.rmg.utils.IUnknown;
import eu.tneitzel.rmg.utils.RMGUtils;
import eu.tneitzel.rmg.utils.RemoteObjectWrapper;
import eu.tneitzel.rmg.utils.RogueJMX;
import eu.tneitzel.rmg.utils.UnicastWrapper;
import eu.tneitzel.rmg.utils.YsoIntegration;
import javassist.CannotCompileException;
import javassist.NotFoundException;
import sun.rmi.server.UnicastRef;

/**
* The dispatcher class contains all method definitions for the different rmg actions. It obtains a reference
Expand All @@ -46,6 +48,7 @@
*
* @author Tobias Neitzel (@qtc_de)
*/
@SuppressWarnings("restriction")
public class Dispatcher
{
private ArgumentHandler p;
Expand Down Expand Up @@ -86,37 +89,59 @@ private void obtainBoundNames() throws NoSuchObjectException
* The result is stored within an object attribute.
*
* It was observed that using --serial-version-uid option can cause an invalid transport return code
* exception. This seems to be some kind of race condition and cannot be reproduced reliably. The lookup
* operation on the RMI registry does pass only this UnmarshalException to the caller. If this is the case,
* we just retry a few times.
* exception. This seems to be some kind of race condition and cannot be reproduced reliably. It seems
* that RMI / Java does not clear the ObjectInput stream when reading an unknown class from it. The remaining
* bytes are left within the stream. Since RMI uses connection pooling, the next operation encounteres the
* invalid bytes and fails. If this is the case, we just retry a few times.
*
* @throws java.rmi.NoSuchObjectException is thrown when the specified RMI endpoint is not an RMI registry
*/
private void obtainBoundObjects() throws NoSuchObjectException
{
int retryCount = 0;

if (boundNames == null)
if (RMGOption.TARGET_OBJID.notNull())
{
obtainBoundNames();
}
RMIEndpoint ep = getRMIEndpoint();
ObjID objid = RMGUtils.parseObjID(RMGOption.TARGET_OBJID.getValue());

while (retryCount < 5)
{
try
{
remoteObjects = getRegistry().lookupWrappers(boundNames);
return;
UnicastRef ref = ep.getRemoteRef(objid);
remoteObjects = new RemoteObjectWrapper[] { UnicastWrapper.fromRef(ref, IUnknown.class) };
}

catch (java.rmi.UnmarshalException e)
catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e)
{
retryCount += 1;
ExceptionHandler.internalError("obtainBoundObjects", "reflection");
}

catch (Exception e)
}

else
{
int retryCount = 0;

if (boundNames == null)
{
ExceptionHandler.unexpectedException(e, "lookup", "operation", true);
obtainBoundNames();
}

while (retryCount < 5)
{
try
{
remoteObjects = getRegistry().lookupWrappers(boundNames);
return;
}

catch (java.rmi.UnmarshalException e)
{
retryCount += 1;
}

catch (Exception e)
{
ExceptionHandler.unexpectedException(e, "lookup", "operation", true);
}
}
}
}
Expand Down Expand Up @@ -157,7 +182,7 @@ public RMIEndpoint getRMIEndpoint()
int port = RMGOption.TARGET_PORT.require();
String host = RMGOption.TARGET_HOST.require();

this.createMethodCandidate();
createMethodCandidate();
return new RMIEndpoint(host, port);
}

Expand Down
16 changes: 16 additions & 0 deletions src/eu/tneitzel/rmg/utils/IUnknown.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package eu.tneitzel.rmg.utils;

import java.rmi.Remote;

/**
* IUnknown is a dummy interface that is used when performing method guessing with
* a manually specified ObjID. The original implementation required an RemoteObjectWrapper,
* which is basically a wrapper around a remote object. When guessing on ObjID, we only
* have a remote ref. To make a wrapper out of it, we need to specify an interface that
* the ref implements. IUnknown is used for this purpose.
*
* @author Tobias Neitzel (@qtc_de)
*/
public interface IUnknown extends Remote
{
}
4 changes: 3 additions & 1 deletion src/eu/tneitzel/rmg/utils/UnicastWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ public String[] getDuplicateBoundNames()
* the specified interface and uses a RemoteObjectInvocationHandler to forward method invocations to
* the specified RemoteRef.
*
* The boundname property that is part of each UnicastWrapper is set to the ObjID of the remote object.
*
* @param unicastRef UnicastRef to the targeted RemoteObject
* @param intf Interface that is implemented by the RemoteObject
* @return UnicastWrapper created from the specified UnicastRef
Expand All @@ -168,7 +170,7 @@ public static UnicastWrapper fromRef(UnicastRef unicastRef, Class<?> intf) throw
RemoteObjectInvocationHandler remoteObjectInvocationHandler = new RemoteObjectInvocationHandler(unicastRef);
Remote remoteObject = (Remote)Proxy.newProxyInstance(intf.getClassLoader(), new Class[] { intf }, remoteObjectInvocationHandler);

return new UnicastWrapper(remoteObject, null, unicastRef);
return new UnicastWrapper(remoteObject, unicastRef.getLiveRef().getObjID().toString(), unicastRef);
}

/**
Expand Down

0 comments on commit ef233a7

Please sign in to comment.