字节码加密(四)jar包解密后直接内存加载

参考使用resource中的jar包资源作为UrlClassloader(二)中第3中方式,通过伪造URL,我们终于得以解决内存byte数组直接用URLClassLoader加载的问题,不必将解密的jar包写入磁盘,造成密码泄露问题

 

package lc2;

import lc3.ResourceClassloader4;

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * https://www.cnblogs.com/silyvin/articles/12182640.html
 * Created by joyce on 2019/10/29.
 */
public class DecJarMemory {
    public static void main(String [] f) throws Exception {

        String sout = "/Users/sunyuming/Documents/tool/jars/MySub-encoded.jar";
        List<URL> urls = MyUrlClassLoader.getURLsDecoded(new String []{sout});
        MyUrlClassLoader myUrlClassLoader = new MyUrlClassLoader(urls.toArray(new URL[urls.size()]));
        Class CA = myUrlClassLoader.loadClass("lc2.C");
        System.out.println("C:--" + CA.getClassLoader());

        // 此句会触发static代码块
        CA.newInstance();
    }

    private static class MyUrlClassLoader extends URLClassLoader{

        private static Coder coder = new Use3DES();

        public static List<URL> getURLsDecoded(String [] resourceJars) throws Exception {

            List<java.net.URL> urls = new ArrayList<>();
            Map<String, byte []> map = new ConcurrentHashMap<>();

            java.net.URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
                public URLStreamHandler createURLStreamHandler(String urlProtocol) {
                    System.out.println("Someone asked for protocol: " + urlProtocol);
                    if ("myjarprotocol".equalsIgnoreCase(urlProtocol)) {
                        return new URLStreamHandler() {
                            @Override
                            protected URLConnection openConnection(URL url) throws IOException {
                                String key = url.toString().split(":")[1];
                                return new URLConnection(url) {
                                    public void connect() throws IOException {}
                                    public InputStream getInputStream() throws IOException {
                                        return new ByteArrayInputStream(map.get(key));
                                    }
                                };
                            }
                        };
                    }
                    return null;
                }
            });

            for(String resourceJar : resourceJars) {
                byte [] jarBytes = coder.decode(resourceJar);
                map.put(resourceJar, jarBytes);
                urls.add(new URL("myjarprotocol:" + resourceJar));
            }

            return urls;
        }

        public MyUrlClassLoader(URL[] urls) {
            super(urls);
        }
    }
}

posted on 2020-01-12 14:30  silyvin  阅读(519)  评论(0)    收藏  举报