cyi 源鲁杯2024第三轮wp


没有ak最后一轮misc,遗憾(musc真气人)



Round 3

Web

[Round 3] 404

ctrl+u查看源码,点进js文件(或者从控制台看到)

challenge.yuanloo.com:26187/script.js

访问f12g.php,会跳转,查看历史包,

5Y67Y2EucGhw5YGa5Liq5pWw5a2m6aKY5ZCn

base64解码:去ca.php做个数学题吧

经典数学题,脚本提取并计算

import math
import re
import requests

s = requests.Session()
url = 'http://challenge.yuanloo.com:26187/ca.php'
r = s.get(url)
r.encoding = 'utf-8'  # 修改编码
print(r.text)

pattern = r'\d+\.\d+|\d+'
num = re.findall(pattern, r.text)
# n = 0
# for i in num:
#     print(n, num[n])
#     n += 1
pattern2 = r'[+\-*/]'
operators = re.findall(pattern2, r.text)
# n = 0
# for i in operators:
#     print(n, operators[n])
#     n += 1
temp1 = 0
temp3 = 0
if operators[1] == '+':
    temp1 = (int(num[4]) + int(num[5])) * math.log(int(num[6]))
if operators[1] == '-':
    temp1 = (int(num[4]) - int(num[5])) * math.log(int(num[6]))
if operators[1] == '*':
    temp1 = (int(num[4]) * int(num[5])) * math.log(int(num[6]))
if operators[1] == '/':
    temp1 = (int(num[4]) / int(num[5])) * math.log(int(num[6]))

temp2 = math.sqrt(abs(int(num[8]) - int(num[9]))) + pow(math.sin(int(num[10])), 2)

if operators[5] == '+':
    temp3 = temp1 + (temp2 * math.tan(int(num[15]) / int(num[16])))
if operators[5] == '-':
    temp3 = temp1 - (temp2 * math.tan(int(num[15])) / int(num[16]))
if operators[5] == '*':
    temp3 = temp1 * (temp2 * math.tan(int(num[15])) / int(num[16]))
if operators[5] == '/':
    temp3 = temp1 / (temp2 * math.tan(int(num[15])) / int(num[16]))

temp4 = math.cos(int(num[18])) * math.exp(math.log(int(num[19])))
ans = temp3 + temp4
# print(temp1,temp2,temp3,temp4,ans)

r = s.post(url, data={'user_answer': ans})
print(r.text)  

YLCTF{a5f9d922-72f4-43d6-9d87-3e1e4c2fdeba}

[Round 3] PRead

导出笔记有任意文件读取

读源码

import os
import pickle
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, send_file
from datetime import datetime
from werkzeug.utils import secure_filename

app = Flask(__name__)
app.secret_key = 'MySe3re7K6y'
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max-limit

# 确保上传文件夹存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)


class Note:
    def __init__(self, title, content):
        self.id = datetime.now().strftime('%Y%m%d%H%M%S')
        self.title = title
        self.content = content
        self.created_at = datetime.now()


class NoteManager:
    def __init__(self):
        self.notes = []
        self.file_name = "notes.pkl"
        self.file_path = "./notes/"
        self.file = os.path.join(self.file_path, self.file_name)
        self.load_notes()

    def add_note(self, title, content):
        note = Note(title, content)
        self.notes.append(note)
        self.save_notes()
        return note

    def get_note(self, note_id):
        for note in self.notes:
            if note.id == note_id:
                return note
        return None

    def update_note(self, note_id, title, content):
        note = self.get_note(note_id)
        if note:
            note.title = title
            note.content = content
            self.save_notes()
            return True
        return False

    def delete_note(self, note_id):
        self.notes = [note for note in self.notes if note.id != note_id]
        self.save_notes()

    def save_notes(self):

        with open(self.file, 'wb') as f:
            pickle.dump(self.notes, f)

    def load_notes(self):
        if os.path.exists(self.file):
            with open(self.file, 'rb') as f:
                self.notes = pickle.load(f)

    def import_notes(self, file_path):
        try:
            with open(file_path, 'rb') as f:
                imported_notes = pickle.load(f)
            self.notes.extend(imported_notes)
            self.save_notes()
            return len(imported_notes)
        except Exception as e:
            print(f"Import error: {e}")
            return 0


note_manager = NoteManager()


@app.route('/')
def index():
    return render_template('index.html', notes=note_manager.notes)


@app.route('/add', methods=['GET', 'POST'])
def add_note():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']
        note_manager.add_note(title, content)
        flash('笔记已添加成功', 'success')
        return redirect(url_for('index'))
    return render_template('add_note.html')


@app.route('/edit/<note_id>', methods=['GET', 'POST'])
def edit_note(note_id):
    note = note_manager.get_note(note_id)
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']
        if note_manager.update_note(note_id, title, content):
            flash('笔记已更新成功', 'success')
            return redirect(url_for('index'))
        flash('更新笔记失败', 'error')
    return render_template('edit_note.html', note=note)


@app.route('/delete/<note_id>')
def delete_note(note_id):
    note_manager.delete_note(note_id)
    flash('笔记已删除成功', 'success')
    return redirect(url_for('index'))


@app.route('/export_notes', methods=['GET'])
def export_notes():
    filename = request.args.get("filename")
    file_path = os.path.join(note_manager.file_path, filename)
    return send_file(file_path, as_attachment=True, download_name="notes_export.pkl")


@app.route('/import_notes', methods=['POST'])
def import_notes():
    if 'file' not in request.files:
        flash('没有文件', 'error')
        return redirect(url_for('index'))

    file = request.files['file']
    if file.filename == '':
        flash('没有选择文件', 'error')
        return redirect(url_for('index'))
    if file:
        filename = secure_filename(file.filename)
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)
        imported_count = note_manager.import_notes(file_path)
        os.remove(file_path)  # 删除临时文件
        if imported_count > 0:
            flash(f'成功导入 {imported_count} 条笔记', 'success')
        else:
            flash('导入失败,请检查文件格式', 'error')
        return redirect(url_for('index'))


if __name__ == '__main__':
    app.run(host='0.0.0.0')

给了secret_key

https://www.cnblogs.com/niyani/p/17074125.html

读了打secret_key的这些文件发现flag(后来学习了一下,发现是用在session伪造,这也没伪造点啊,难道打pickle?等wp了)

tips:前两天的拟态非预期读start.sh,有文件读取的话整点小智慧(doge)

YLCTF{1905541f-d21c-4df6-9515-da7acf5ee7d1}



Pwn

[Round 3] Secret

nc题,太开心了

跟进check_password,发现输入SuperSecretPassword即可

YLCTF{27786369-e80e-4ca6-8188-55917d9d10b5}



Crypto

[Round 3] QWQ

aaencode

decode一下就行了,https://toolwa.com/aaencode/

LFGEGVCGPNUEA5RTL5DHK3S7O4YXI2C7ORUGSNK7M5QW2M27KFLVC7I=

base32转码:YLCTF{h@v3_Fun_w1th_thi5_gam3_QWQ}



Misc

[Round 3] Blackdoor

太原了,https://blog.csdn.net/YueXuan_521/article/details/134125759

html\include\include.php

YLCTF{e2bae51b981c707eb28302fe22d60340}

[Round 3] Tinted

不到hint真的看不出

hint1 : 利用取色器查看RGB数值

040067 FF0065 FF0072 040049 FF3C66 FF004A FF3C6A FF3C42 FF3C52 FF3C5A FF0066 00FF31 FF0052 040067 040062 040074 FF0052 FF004C FF0052 FF0039 FF0054 FF0064 FF004A FF0075 00FF52 040063 040075 040075 00FF53 00FF74 FF0057 00FF75 FF0051 040067 FF004A FF0074 FF0069 FF3C5A FF0057 00FF39 FF0054 FF0067 00FF4A FF3C7A 040054 FF0064 FF0052 FF3C76 040054 FF004C FF0069 FF0075 00FF52 040074 FF3C62 00FF71 00FF70 00FF62 FF0035 040035

https://www.cnblogs.com/LEOGG321/p/14095849.html

跟着文章将后两位提取

with open("C:\\Users\\86139\\Desktop\\040067.txt",'r') as f:
    s = f.read().split('\n')
    for i in s:
        print(i[4:],end='')

得到:(后来发现可以直接cyberchef梭了)67657249664A6A42525A663152676274524C523954644A75526375755374577551674A74695A573954674A7A54645276544C69755274627170623535

十六进制解码:gerIfJjBRZf1RgbtRLR9TdJuRcuuStWuQgJtiZW9TgJzTdRvTLiuRtbqpb55

选择magic模式(cyberchef对可能的形式进行猜测),本次解码原理是base64换表解密

YLCTF{25e1d30c-9141-4784-a3b8-9a99358f4340}

[Round 3] CheckImg

和figure一样,出题人只会对png转来转去(bushi)

(如果zsteg报错,加这个export RUBY_THREAD_VM_STACK_SIZE=500000000)

zsteg -e  b1,r,lsb,xy flag.png > 1.txt

把后面冗余数据删除

搜60 82 ae 42发现

直接winhex开梭,全选--编辑--修改选块--反转字节再十六进制转码,保存为1.png

zsteg 1.png

一眼dna编码

得到

KVEEQRSCI5DVKVSXKZEUQS2FJBKE2WKKGI2EKNCWJFCUQNSKIVAVINBTKVKE2TZUKVHUWRZWGRIVSVSNJZJFIQKNIZLDINKHJQ2FSQKWJVBUSTSIKFLVMSKFKNFEGVZVKVGEMSJWJMZDMVSTJNDUQQSGI5KEYN2LKY2DETKWK5EEQTSCGJDFMU2IJA3ECTKVKVNEWU2CIFGUYVKBIRJEMRSRINKE2TKGKAZU6M2UJVAVAUSLKFDFMRKGJFMDITR5

(也可以cyberchef一把梭)base32:Base32编码解码,Base32在线转换工具 - 千千秀字

最后ciphey一把梭

ciphey -t UHHFBGGUVWVIHKEHTMYJ24E4VIEH6JEAT43UTMO4UOKG64QYVMNRTAMFV45GL4YAVMCINHQWVIESJCW5ULFI6K26VSKGHBFGTL7KV42MVWHHNB2FVSHH6AMUUZKSBAMLUADRFFQCTMMFP3O3TMAPRKQFVEFIX4N=

YLCTF{bea5f037-0f60-46fa-9350-c261de6f51e6}



Re

[Round 3] ezmaze

一维迷宫,要满足+和F,上面那几个数字ascll转字符是wasd

from collections import deque

maze_map = ("*****++*********+******+*++******+++*****F"
            "*+*******+*+++*****+***++****+***+*****+***+*+***+++++++************")

directions = {
    'w': (-10, 0),  # 向上
    'a': (-1, 0),  # 向左
    's': (10, 0),  # 向下
    'd': (1, 0)  # 向右
}

maze = []
row_length = 1
for i in range(0, len(maze_map), row_length):
    maze.append(list(maze_map[i:i + row_length]))

start = (5 // row_length, 5 % row_length)  # 起始位置 (5)
goal = (maze_map.index('F') // row_length, maze_map.index('F') % row_length)  # 目标位置 F


def bfs(maze, start, goal):
    row = len(maze)
    col = len(maze[0])

    queue = deque([(start, "")])
    visited = {start}

    while queue:
        (x, y), path_now = queue.popleft()
        # print(f"{x}, {y}, {path_now}")

        if (x, y) == goal:
            return path_now

        for direction, (dx, dy) in directions.items():
            x_n, y_n = x + dx, y + dy
            origin_x, origin_y = x_n, y_n
            while 0 <= x_n < row and 0 <= y_n < col and maze[x_n][y_n] in ['+', 'F']:
                if (x_n, y_n) not in visited:
                    visited.add((x_n, y_n))
                    if maze[x_n][y_n] == 'F':
                        return path_now + direction
                    queue.append(((x_n, y_n), path_now + direction))
                x_n += dx
                y_n += dy
            x_n, y_n = origin_x, origin_y


path = bfs(maze, start, goal)
print(path)
#dsasasdsaw

YLCTF{efac19a75e413ad6680adec92504b654}

[Round 3] CASE

考点:伪随机数

通过获取当前时间戳来作为随机数种子

获得系统时间戳和对应的加密数据

nc challenge.yuanloo.com 25679 & echo "$(date +%s)"

from ctypes import *
c = cdll.LoadLibrary("libc.so.6")
c.srand(1729673028)

r=[]
for i in range(43):
    r.append(c.rand())
print(r)
#[1832493461, 585578708, 2089548833, 578005299, 615532445, 513627915, 1728887083, 1848055492, 1813385881, 1655305840, 283734118, 1748836532, 347059411, 207225596, 30222674, 1464715199, 2131846712, 1111959327, 1619622171, 1869061540, 551853291, 1266831835, 1462910643, 1329122180, 1101406669, 1661912176, 1386875239, 625627464, 774754962, 285087152, 1258985799, 459764775, 870665860, 1201050985, 1037770074, 1486198305, 1714678900, 619173509, 1186770150, 1380581134, 126995701, 1470504268, 981934018]

逆一下

v5 = [1832493461, 585578708, 2089548833, 578005299, 615532445, 513627915, 1728887083, 1848055492, 1813385881, 1655305840, 283734118, 1748836532, 347059411, 207225596, 30222674, 1464715199, 2131846712, 1111959327, 1619622171, 1869061540, 551853291, 1266831835, 1462910643, 1329122180, 1101406669, 1661912176, 1386875239, 625627464, 774754962, 285087152, 1258985799, 459764775, 870665860, 1201050985, 1037770074, 1486198305, 1714678900, 619173509, 1186770150, 1380581134, 126995701, 1470504268, 981934018]
v11 = [0x91,0x4e,0x76,0x35,0xea,0x65,0x6d,0x1e,0x5f,0x2,0xe5,0x9,0x22,0x52,0x67,0x5e,0x40,0xf6,0x48,0x34,0xb9,0xc3,0x4d,0xef,0xfb,0xc8,0x1f,0x3f,0xf6,0xf9,0x46,0x2b,0xd2,0xed,0xa0,0x90,0xc2,0x5b,0xa0,0x9c,0x68,0x51,0xde]

def decrypt(v5, v11):
    decrypted = []
    for i in range(len(v11)):
        random余数 = v5[i] % 255
        original_byte = v11[i] ^ random余数
        decrypted.append(original_byte)
    return decrypted

v12 = decrypt(v5, v11)
decrypted_string = ''.join(chr(i) for i in v12)
print(decrypted_string)
#LYPGS{5nqq5sn7-ro96-4968-nr66-p59105836536}

凯撒直接爆了

posted @ 2024-10-23 21:32  ^cyi^  阅读(54)  评论(0编辑  收藏  举报