Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any level of obfuscation which can "trick" instanceof?

I've been playing with this and so far I haven't been able to find any way to hide or trick instanceof into returning false by hiding its type through layers of obfuscation, but that doesn't mean it's not possible since I'm far from the most knowledgeable person about Java. So I've come to ask the experts.

I've tried the following combinations, and in each case the instanceof operator is able to identify the true/base type of the object.

public class Test {

    public static void main(String[] args) {
        Object o = new TestObject();
        printType("Base Class", o);

        o = (TestSuperObject)(new TestObject());
        printType("Super Class", o);

        o = (TestInterface)(new TestObject());
        printType("Interface", o);

        o = (TestInterface)((TestSuperObject3)(new TestObject3()));
        printType("Interface on Super Class", o);

        o = (TestSuperObject3)((TestInterface)(new TestObject3()));
        printType("Super Class on Interface", o);
    }


    private static void printType(String testCase, Object o) {
        System.out.println(testCase);
        System.out.println("TestObject:" + (o instanceof TestObject));
        System.out.println("TestObject2:" + (o instanceof TestObject2));
        System.out.println("TestObject3:" + (o instanceof TestObject3));
        System.out.println();
    }

}

The classes are defined as...

public class TestObject extends TestSuperObject implements TestInterface
public class TestObject2 extends TestSuperObject implements TestInterface
public interface TestInterface
public class TestSuperObject
public class TestObject3 extends TestSuperObject3
public class TestSuperObject3 implements TestInterface

So basically, is there any way to hide this information or to somehow lose the type information? I don't ask because I have a reason to do it, but rather would like to know and be wary of it in the future if it is possible. Plus, I just find it interesting.

like image 377
asteri Avatar asked Oct 16 '12 13:10

asteri


2 Answers

It is possible to confuse yourself with instanceof but not the JVM.

  • classes with the same name but in different packages are not the same. This means you can do

    // in one class
    ClassA classA = new ClassA(); // package1.ClassA
    another.test(classA);
    
    // calls in another class
    public void test(Object o) {
       if (o instanceof ClassA) // package2.ClassA => false 
    
  • using different class loaders the packages and o.getClass().getName() are the same, but as the class loaders are different instanceof return false.

  • The object is null and null instanceof ClassB is always false, even though null can be assigned to any reference type.
like image 53
Peter Lawrey Avatar answered Sep 29 '22 07:09

Peter Lawrey


So basically, is there any way to hide this information or to somehow lose the type information?

No it is not possible.

Each object has a real type, and Java's strong + static type system makes it impossible to alter the type of an object, or pretend that its actual type is different to what it is.


(It is hypothetically possible to drop into native code and subvert the Java type system, but the consequences of doing this are likely to be really bad ... crash-the-JVM bad.)

like image 23
Stephen C Avatar answered Sep 29 '22 07:09

Stephen C