Loading an array of bytes into memory

I am trying to load a jar file directly into memory without dropping it to the hard drive. I tried using ClassLoader, but I am getting an error.

This is my code:

Custom Class Loader

public class CLS_ClassLoader extends ClassLoader { private byte[] bArrData; public CLS_ClassLoader(ClassLoader parent, byte[] bArrData) { super(parent); this.bArrData = bArrData; } public Class<?> loadClass(String name) throws ClassNotFoundException { return defineClass(name, bArrData, 0, bArrData.length); } } 

home

 ClassLoader tParentClsLoader = CLS_ClassLoader.class.getClassLoader(); CLS_ClassLoader tClsLoader = new CLS_ClassLoader(tParentClsLoader, fileToByteArray("D:/App.jar")); Class<?> tClass = null; try { tClass = tClsLoader.loadClass("pkg_main.CLS_Main"); } catch (ClassNotFoundException e) { e.printStackTrace(); } 

Output

 Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1347093252 in class file pkg_main/CLS_Main at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at pkg_main.CLS_ClassLoader.loadClass(CLS_ClassLoader.java:20) at pkg_main.CSL_Main.main(CSL_Main.java:27) 

My idea is to take an encrypted jar file, decrypt it at runtime, and load directly into memory.

Sorry for the typos, I did not speak English well. Thanks in advance!

+6
source share
1 answer

Your main mistake is that defineClass (...) expects class bytes, and you feed it the whole jar file. An actual exception is thrown if class bytes do not start with 0xCAFEBABE, the typical header of a Java class file. So, you need an extra step to sort the classes from the jar file. The following implementation demonstrates the idea:

  class CCLoader extends ClassLoader { private Map<String, byte[]> classes = new HashMap<String, byte[]>(); public CCLoader(InputStream in) { super(CCLoader.class.getClassLoader()); try { JarInputStream jis = new JarInputStream(in); JarEntry je = null; String entryName = null; while ((je = jis.getNextJarEntry()) != null) { entryName = je.getName(); if (je.getName().endsWith(".class")) { byte[] classBytes = readClass(jis); String canonicalName = entryName.replaceAll("/", ".").replaceAll(".class", ""); classes.put(canonicalName, classBytes); } } jis.close(); in.close(); } catch (IOException e) { e.printStackTrace(); } } private byte[] readClass(InputStream stream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); while(true){ int qwe = stream.read(); if(qwe == -1) break; baos.write(qwe); } return baos.toByteArray(); } public Class loadClass(String name) throws ClassNotFoundException { try { return this.getParent().loadClass(name); } catch (ClassNotFoundException e) { return findClass(name); } } public Class findClass(String name) throws ClassNotFoundException { byte[] classBytes = classes.get(name); return defineClass(name, classBytes, 0, classBytes.length); } } 

Following your example, you can try the following:

 ClassLoader tClsLoader = new CCLoader(new FileInputStream("C:/commons-io-2.0.1.jar")); Class<?> tClass = tClsLoader.loadClass("org.apache.commons.io.FileExistsException"); 
+3
source

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


All Articles