湘岚杯 2025 WP

qiutou 发布于 3 天前 8 次阅读


qiutou 编(复现笔记)

[misc] 别呀啦(签到)

我个人是根据每个文档的修改日期辅助解压,最终得到了flag(当然这道题就是一个简单的解压包

当然在我翻找WP的时候,看到有大佬写的有解压找flag的代码(附在下面

import os
import zipfile
import re
import shutil

# 临时解压目录
TEMP_DIR = "temp_extract"
PROCESSED_FILES = set() # 记录已处理文件
MAX_DEPTH = 100 # 限制最大递归深度

def extract_zip(file_path, extract_to):
  """解压zip文件"""
  with zipfile.ZipFile(file_path, 'r') as zip_ref:
      zip_ref.extractall(extract_to)

def search_flag_in_file(file_path):
  """在文件中搜索flag"""
  with open(file_path, 'r', encoding='utf-8') as f:
      content = f.read()
      match = re.search(r'XLCTF{.*?}', content)
      if match:
          return match.group()
  return None

def process_file(file_path, current_depth=0):
  """递归处理文件"""
  if current_depth > MAX_DEPTH:
      print("已达到最大递归深度,停止处理")
      return None

  # 防止重复处理
  abs_path = os.path.abspath(file_path)
  if abs_path in PROCESSED_FILES:
      return None
  PROCESSED_FILES.add(abs_path)

  # 创建临时目录
  if not os.path.exists(TEMP_DIR):
      os.makedirs(TEMP_DIR)
   
  if zipfile.is_zipfile(file_path):
      print(f"正在解压: {file_path}")
      temp_dir = os.path.join(TEMP_DIR, os.path.basename(file_path))
      os.makedirs(temp_dir, exist_ok=True)
      extract_zip(file_path, temp_dir)
      for root, dirs, files in os.walk(temp_dir):
          for file in files:
              nested_file = os.path.join(root, file)
              flag = process_file(nested_file, current_depth + 1)
              if flag:
                  return flag
  elif file_path.endswith('.txt'):
      print(f"正在搜索flag: {file_path}")
      return search_flag_in_file(file_path)
  return None

def clean_temp():
  """清理临时目录"""
  if os.path.exists(TEMP_DIR):
      shutil.rmtree(TEMP_DIR)

if __name__ == "__main__":
  try:
      input_file = "D:\Download\hhh.zip" # 替换为你的初始压缩包路径
      flag = process_file(input_file)
      if flag:
          print(f"找到flag: {flag}")
      else:
          print("未找到flag")
  finally:
      clean_temp()

作者:vstral
链接:https://juejin.cn/post/7461814810554220571

[misc] base64游戏

这道题,出题人将提供一个平台,将我们输入的字符进行base64编码,所使用的base64表是未知的,因此,我们需要解决的就正是未知的base64表,通过测试反馈然后反推新码表

首先我们需要理解base64的原理:

由于2的六次方==64,6个二进制数字代表一个base64码,然后8个二进制是一个ASCII码,他们所代表的都是一个字符的不同编码方式,但是他们的索引都是一样的,因此我们可以通过索引去知道一个“Z”的base64码应该是什么,然后去反推出码表

五分钟彻底掌握Base64编码哔哩哔哩bilibili:"这个视频讲的很细“

此处采取枚举的方法,将所有base64可以的表达的表示出来,构建码表(附上夏师傅的代码...因为我不会X﹏X

import base64

import itertools

from pwn import *



base64_aiphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"



def text_to_indexes(s):

   encoded_str = base64.b64encode(s.encode()).decode()

   encoded_str = encoded_str.rstrip("=")

   return [base64_aiphabet.index(c) for c in encoded_str]



def build_Aiphabet(encoded_str, idxs):

   Aiphabet = ['?'] * 64

   for i, idx in enumerate(idxs):

       Aiphabet[idx] = encoded_str[i]

   return ''.join(Aiphabet)



def custom_base64_encode(input_bytes, possible_aiphabet):

   binary_str = ''.join(f'{byte:08b}' for byte in input_bytes)

   groups_of_6_bits = [binary_str[i:i+6] for i in range(0, len(binary_str), 6)]

   if len(groups_of_6_bits[-1]) < 6:

       groups_of_6_bits[-1] = groups_of_6_bits[-1].ljust(6, '0')

   encoded_chars = [int(group, 2) for group in groups_of_6_bits]

   encoded_str = ''.join(possible_aiphabet[i] for i in encoded_chars)

   padding = '=' * ((4 - len(encoded_str) % 4) % 4)

   return encoded_str + padding



io = remote("xlctf.huhstsec.top", 33772)



text = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"



io.sendlineafter(b'encode:', text.encode())

io.recvuntil(b'Encode: ')

encoded_str = io.recvline().strip().decode()



print("Encoded_str:", encoded_str)



indexes = text_to_indexes(text)



Aiphabet = build_Aiphabet(encoded_str, indexes)



print(f'Aiphabet: {Aiphabet}')



# with open("output.txt", "a") as file:

#     file.write(Aiphabet + "\n")



io.close()



Aiphabet="/fBawDSFHXLbCygxn9s7imlVYvr21e6GZ+04Tq8RzAhjuKM53dtQIpWEUcJ?PO??" # "def build_Aiphabet(encoded_str, idxs):ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"*50



missing_chars = [char for char in base64_aiphabet if char not in Aiphabet]



print("All cases:")



all_permutations = itertools.permutations(missing_chars)



for perm in all_permutations:

   possible_aiphabet = list(Aiphabet)

   perm_idx = 0



   for i in range(len(possible_aiphabet)):

       if possible_aiphabet[i] == '?':

           possible_aiphabet[i] = perm[perm_idx]

           perm_idx += 1



   possible_aiphabet = ''.join(possible_aiphabet)

   print(possible_aiphabet,end=' | ')



   encoded_data = custom_base64_encode(text.encode(), possible_aiphabet)



   if encoded_data == encoded_str:

       print("Find the Right Aiphabet")
import base64
import itertools
from pwn import *

base64_aiphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

def text_to_indexes(s):
   encoded_str = base64.b64encode(s.encode()).decode()
   encoded_str = encoded_str.rstrip("=")
   return [base64_aiphabet.index(c) for c in encoded_str]

def build_Aiphabet(encoded_str, idxs):
   Aiphabet = ['?'] * 64
   for i, idx in enumerate(idxs):
       Aiphabet[idx] = encoded_str[i]
   return ''.join(Aiphabet)

def custom_base64_encode(input_bytes, possible_aiphabet):
   binary_str = ''.join(f'{byte:08b}' for byte in input_bytes)
   groups_of_6_bits = [binary_str[i:i+6] for i in range(0, len(binary_str), 6)]
   if len(groups_of_6_bits[-1]) < 6:
       groups_of_6_bits[-1] = groups_of_6_bits[-1].ljust(6, '0')
   encoded_chars = [int(group, 2) for group in groups_of_6_bits]
   encoded_str = ''.join(possible_aiphabet[i] for i in encoded_chars)
   padding = '=' * ((4 - len(encoded_str) % 4) % 4)
   return encoded_str + padding

io = remote("xlctf.huhstsec.top", 33772)

text = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

io.sendlineafter(b'encode:', text.encode())
io.recvuntil(b'Encode: ')
encoded_str = io.recvline().strip().decode()

print("Encoded_str:", encoded_str)

indexes = text_to_indexes(text)

Aiphabet = build_Aiphabet(encoded_str, indexes)

print(f'Aiphabet: {Aiphabet}')

# with open("output.txt", "a") as file:
#     file.write(Aiphabet + "\n")

io.close()

Aiphabet="/fBawDSFHXLbCygxn9s7imlVYvr21e6GZ+04Tq8RzAhjuKM53dtQIpWEUcJ?PO??" # "def build_Aiphabet(encoded_str, idxs):ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"*50

missing_chars = [char for char in base64_aiphabet if char not in Aiphabet]

print("All cases:")

all_permutations = itertools.permutations(missing_chars)

for perm in all_permutations:
   possible_aiphabet = list(Aiphabet)
   perm_idx = 0

   for i in range(len(possible_aiphabet)):
       if possible_aiphabet[i] == '?':
           possible_aiphabet[i] = perm[perm_idx]
           perm_idx += 1

   possible_aiphabet = ''.join(possible_aiphabet)
   print(possible_aiphabet,end=' | ')

   encoded_data = custom_base64_encode(text.encode(), possible_aiphabet)

   if encoded_data == encoded_str:
       print("Find the Right Aiphabet")

此处还有另一种解法,就是将原本的码表解码得到索引之后,再去编码构建码表(附上夏师傅代码

import gmpy2

from Crypto.Util.number import long_to_bytes



p_add_q = 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea

x = 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740

c = 0x21bfef2961c512fbb81fd75ca1c38cbc810dee21d04de1e749c9a24cc975447acc1098228108f25a5ab4840212b2c0f305aabb17ee6835599425ffeedb85698ff9edbc70d9e87acd5232526304948f806c0283776d3eb217599e06616a12d899b14723bfeb29becb10e464247760f828463eb4f0536244771c648b6445fab855

e = 0xe6b1bee47bd63f615c7d0a43c529d219



n = x - p_add_q - 1

phi = n - p_add_q + 1



d = gmpy2.invert(e, phi)

m = pow(c, d, n)

print(long_to_bytes(m))



# b'flag{Aurora_CAL}'
import gmpy2
from Crypto.Util.number import long_to_bytes

p_add_q = 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
x = 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
c = 0x21bfef2961c512fbb81fd75ca1c38cbc810dee21d04de1e749c9a24cc975447acc1098228108f25a5ab4840212b2c0f305aabb17ee6835599425ffeedb85698ff9edbc70d9e87acd5232526304948f806c0283776d3eb217599e06616a12d899b14723bfeb29becb10e464247760f828463eb4f0536244771c648b6445fab855
e = 0xe6b1bee47bd63f615c7d0a43c529d219

n = x - p_add_q - 1
phi = n - p_add_q + 1

d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

[MISC]宇宙编史

因为是直接给了压缩包,我打开010看了一下,没什么奇怪的,就直接伪加密了(以前我一直以为很小的文件,才会是伪加密,这是一个误区

打开之后,翻一下就看到了明显的零宽字符

使用这个”Sublime Text“应用非常方便(谢谢师傅推荐

[MISC]银河救援SOS!

打开之后就看到一个图片,下面的字符是:银河字母表(顺带一提,这个绿猫吓到我了

(嗯嗯....我用百度识图和AI都没有认出来,这个算是长见识了)

对照之后得到压缩包密码:superalien

解压后发现又一个加密的压缩包,但含有同样的文件,进行明文攻击即可解密压缩包(口令为n/a)

打开压缩包后发现,有很多图片,分析经纬度,并且采用代码

import os
from PIL import Image
from PIL.ExifTags import TAGS
import matplotlib.pyplot as plt

# 定义一个函数,将度、分、秒格式的坐标转换为十进制格式
def dms_to_decimal(degrees, minutes, seconds):
   return degrees + (minutes / 60) + (seconds / 3600)

# 初始化两个空列表,用于存储转换后的经纬度坐标
x = []
y = []

# 遍历1到80的文件名
for i in range(1, 81):
   file_name = f"{i}.jpg"

   # 检查文件是否存在
   if os.path.exists(file_name):
       print(f"EXIF {file_name}")

       # 打开图像文件
       image = Image.open(file_name)
       # 获取图像的EXIF数据
       exif_data = image._getexif()

       # 检查是否存在EXIF数据
       if exif_data is not None:
           # 遍历EXIF数据中的所有标签
           for tag, value in exif_data.items():
               tag_name = TAGS.get(tag, tag)
               # 检查标签是否为GPS信息
               if 'GPSInfo' in tag_name:
                   print(f"{value}")
                   # 提取经度和纬度的度、分、秒值
                   x_dms_coordinate = (value[2][0], value[2][1], value[2][2])
                   y_dms_coordinate = (value[4][0], value[4][1], value[4][2])

                   # 将度、分、秒格式的坐标转换为十进制格式
                   x_decimal_coordinate = dms_to_decimal(*x_dms_coordinate)
                   y_decimal_coordinate = dms_to_decimal(*y_dms_coordinate)

                   # 将转换后的坐标添加到列表中
                   x.append(x_decimal_coordinate)
                   y.append(y_decimal_coordinate)

                   # 打印转换后的坐标
                   print(f'{x_decimal_coordinate} {y_decimal_coordinate}')

       else:
           print("Have No EXIF Data")

       print("="*100)
   else:
       print(f"{file_name} does not exist")
       print("="*100)

# 打印最终的经纬度列表
print("X list:", x)
print("Y list:", y)

# 使用matplotlib绘制散点图
plt.scatter(y, x , color="blue")
# 在散点图上添加箭头,连接相邻的点
for i in range(len(x) - 1):
   plt.annotate("", xy=(y[i+1], x[i+1]), xytext=(y[i], x[i]),
                arrowprops=dict(arrowstyle="-", color="red", lw=2))
# 设置坐标轴标签
plt.xlabel('X')
plt.ylabel('Y')
# 显示图形
plt.show()

[Crypto]RSA就是数学口牙(签到)

可知RSA的 p+q 和 (p+1)(q+1)

import gmpy2
from Crypto.Util.number import long_to_bytes

x=0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
y=0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
c=0x21bfef2961c512fbb81fd75ca1c38cbc810dee21d04de1e749c9a24cc975447acc1098228108f25a5ab4840212b2c0f305aabb17ee6835599425ffeedb85698ff9edbc70d9e87acd5232526304948f806c0283776d3eb217599e06616a12d899b14723bfeb29becb10e464247760f828463eb4f0536244771c648b6445fab855
e=0xe6b1bee47bd63f615c7d0a43c529d219
n=y-x-1
phi=n-x+1
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

此处解释一下RSA:

##E*D=1(mod z):意思是e乘d模去z==1

[Crypto]你真的懂社会主义核心价值观吗

这道题不知道为什么属于密码(可能是文字编码+base编码,随波逐流一把梭了

flag:XLCTF{HunanFirstNormalUniversityisverybeautiful}

此作者没有提供个人介绍
最后更新于 2025-02-02