📜 ⬆️ ⬇️

Java and Public Morozov pattern

Once it took me to redefine the field marked as private final on a running program. And it was impossible to stop the program, because the server. Well, as a small addition, the type of the variable was defined as an inner class. Of course, also private.

Fortunately, the program allows you to connect modules containing arbitrary code on the go. So - at our disposal all the power of reflection!

I remind you that this is a proof-of-concept, so for a specific task you will at least have to set the necessary type for accessor, and in general, if the code is torn out of context, some blocks may lose their meaning. For example, in the above example, everything will work and without replacing the accessor in general, it will be enough to remove the final. Keep in mind that this will work only for objects. Primitives are usually inlined by the compiler.
')
package main;

class PublicMorozov
{
// , inner
private static final PublicMorozov INSTANCE = new PublicMorozov();
// ,
private static final java.lang. ref .WeakReference<Inner> targetField = new java.lang. ref .WeakReference<Inner>( null );

private class Inner
{}

public PublicMorozov()
{}

public static void makeReplace() throws Exception
{
// ,
java.lang.reflect.Field targetAsField = Class.forName( "main.PublicMorozov" ).getDeclaredField( "targetField" );
// private
targetAsField.setAccessible( true );

//
java.lang.reflect.Field modifiers = Class.forName( "java.lang.reflect.Field" ).getDeclaredField( "modifiers" );
// private
modifiers.setAccessible( true );

// private final, public
modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.PRIVATE);
modifiers.setInt(targetAsField, targetAsField.getModifiers() | java.lang.reflect.Modifier.PUBLIC);

// ... IllegalAccessException
// accessor ,
// overrideFieldAccessor private, fieldAccessor
java.lang.reflect.Field accessorField = Class.forName( "java.lang.reflect.Field" ).getDeclaredField( "overrideFieldAccessor" );
// private
accessorField.setAccessible( true );
// Object ,
java.lang.reflect.Constructor accessorConstructor = Class.forName( "sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl" ).getDeclaredConstructor(java.lang.reflect.Field. class , boolean. class );
// ... ?
accessorConstructor.setAccessible( true );
// - accessor final
accessorField. set (targetAsField, accessorConstructor.newInstance(targetAsField, false ));

// - inner
java.lang.reflect.Constructor innerConstructor = Class.forName( "main.PublicMorozov$Inner" ).getDeclaredConstructor(Class.forName( "main.PublicMorozov" ));
innerConstructor.setAccessible( true );

//
targetAsField. set ( null , new java.lang. ref .WeakReference<Inner>((Inner) innerConstructor.newInstance(INSTANCE)));
}
}


* This source code was highlighted with Source Code Highlighter .

Source: https://habr.com/ru/post/75661/


All Articles