Java Language Evil Java hacks with Reflection


Example

The Reflection API could be used to change values of private and final fields even in the JDK default library. This could be used to manipulate the behaviour of some well known classes as we will see.

What is not possible

Lets start first with the only limitation means the only field we can't change with Reflection. That is the Java SecurityManager. It is declared in java.lang.System as

private static volatile SecurityManager security = null;

But it won't be listed in the System class if we run this code

for(Field f : System.class.getDeclaredFields())
    System.out.println(f);

Thats because of the fieldFilterMap in sun.reflect.Reflection that holds the map itself and the security field in the System.class and protects them against any access with Reflection. So we could not deactivate the SecurityManager.

Crazy Strings

Each Java String is represented by the JVM as an instance of the String class. However, in some situations the JVM saves heap space by using the same instance for Strings that are. This happens for string literals, and also for strings that have been "interned" by calling String.intern(). So if you have "hello" in your code multiple times it is always the same object instance.

Strings are supposed to be immutable, but it is possible to use "evil" reflection to change them. The example below show how we can change the characters in a String by replacing its value field.

public class CrazyStrings {
    static {
        try {
            Field f = String.class.getDeclaredField("value");
            f.setAccessible(true);
            f.set("hello", "you stink!".toCharArray());
        } catch (Exception e) {
        }
    }
    public static void main(String args[])  {
        System.out.println("hello");
    }
}

So this code will print "you stink!"

1 = 42

The same idea could be used with the Integer Class

public class CrazyMath {
    static {
        try {
            Field value = Integer.class.getDeclaredField("value");    
            value.setAccessible(true);          
            value.setInt(Integer.valueOf(1), 42);      
        } catch (Exception e) {
        }
    }
    public static void main(String args[])  {
        System.out.println(Integer.valueOf(1));
    }
}

Everything is true

And according to this stackoverflow post we can use reflection to do something really evil.

public class Evil {    
    static {
        try {
            Field field = Boolean.class.getField("FALSE");
            field.setAccessible(true);
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
            field.set(null, true);
        } catch (Exception e) {
        }
    }
    public static void main(String args[]){
        System.out.format("Everything is %s", false);
    }
}

Note that what we are doing here is going to cause the JVM to behave in inexplicable ways. This is very dangerous.