当前位置: 首页 > news >正文

HNCTF2025 - Misc、Osint、Crypto WriteUp

还是学了非常多的知识的,有待进步与提升

Misc:

芙宁娜的图片

给了文档和图片,图片lsb藏了一个key,随波逐流直接梭出来

文档内容brainfuck得到一个加密后的flag

用key和加密后的flag进行维吉尼亚加密或者一把梭不行

注:为什么知道是维吉尼亚呢,因为看到了又flag{}的雏形了,非常像凯撒密码,但是图片提供了各key,所以很容易想到是维吉尼亚密码辣
好像只能用bugku的维吉尼亚解密

维吉尼亚加密/解密 - Bugku CTF平台
我用千千秀字和其他解密网站不行

星辉骑士

给了一个word文档,一张图片,没有发现什么信息,将其后缀改位zip

解压看到一个flag.zip

解压,发现需要密码

这时就要看看是真加密还是伪加密了

拖入010 editor

是伪加密了

把十个09都改了改为偶数00

 改了之后,保存,解压

解压得到一堆文档,打开可以看到是垃圾邮件隐写

spammimic - decoded

一个一个文档进行解密,还有假flag!

乱成一锅粥了

题目附件是一个流量包

初见端倪

 再往下翻翻

一共有9个zip

 导出字节流都解压

txt文件内容类似base64编码,将其合并一起发现解码出来是乱码,所以想到可能是顺序不对,又注意到,文件命名类似hash值

注:解压发现每个压缩包里都有50个txt文档,而且命名都一样

解密发现是数字,猜测md5解密后的内容在00-50之间,这样就可以按照序号拼接了

用ai帮我们把脚本写出来 

import os
import hashlibdef generate_md5_mapping():"""生成00到50的数字与其MD5值的映射关系"""mapping = {}for i in range(0, 51):  # 包括50,所以是0-50共51个文件# 格式化为两位数字符串:00, 01, ..., 50original_name = f"{i:02d}"# 计算MD5值md5_hash = hashlib.md5(original_name.encode('utf-8')).hexdigest()# 添加到映射表mapping[md5_hash] = original_namereturn mappingdef rename_files(folder_path, mapping):"""根据映射表重命名文件"""for md5_name in os.listdir(folder_path):if md5_name.endswith('.txt'):# 提取MD5部分(不含扩展名)md5_key = os.path.splitext(md5_name)[0]if md5_key in mapping:original_name = mapping[md5_key]new_filename = f"{original_name}.txt"# 构建完整文件路径old_path = os.path.join(folder_path, md5_name)new_path = os.path.join(folder_path, new_filename)# 重命名文件os.rename(old_path, new_path)print(f"成功重命名: {md5_name} -> {new_filename}")else:print(f"警告: 未找到映射 {md5_name} - 可能超出00-50范围")if __name__ == "__main__":# 使用原始字符串避免转义问题folder_path = r"E:\粥\Down"# 生成MD5映射表 (00-50)md5_mapping = generate_md5_mapping()# 执行重命名操作rename_files(folder_path, md5_mapping)print("\n操作完成! 所有文件已恢复为原始数字名称")print(f"共处理文件: {len(md5_mapping)}个 (00-50)")

将文件内容按照01到50合并在一起

import osdef combine_files(folder_path, output_file):"""将01.txt到50.txt的文件内容按顺序合并"""# 确保输出文件路径正确output_path = os.path.join(folder_path, output_file)# 创建01-50的文件名列表file_names = [f"{i:02d}.txt" for i in range(1, 51)]# 按顺序合并文件内容with open(output_path, 'w', encoding='utf-8') as outfile:for filename in file_names:file_path = os.path.join(folder_path, filename)# 检查文件是否存在if not os.path.exists(file_path):print(f"警告: 文件 {filename} 不存在,跳过")continue# 读取并写入内容with open(file_path, 'r', encoding='utf-8') as infile:content = infile.read()outfile.write(content)# 可选:在文件之间添加分隔符# outfile.write("\n\n--- 文件分割线 ---\n\n")print(f"\n合并完成! 所有内容已保存到: {output_path}")print(f"共合并了 {len(file_names)} 个文件 (01.txt - 50.txt)")if __name__ == "__main__":# 配置路径folder_path = r"E:\粥\Down"  # 包含01-50.txt的文件夹output_file = "combined_content.txt"  # 合并后的文件名# 执行合并combine_files(folder_path, output_file)

将其base64解码,发现是一张图片

都转码得到9张图片,将其拼接得到二维码

扫一扫就能得到flag了

谁动了黑线

待定

OSINT

时间图片属性都有

Chasing Freedom 1

可以看到船号是闽平渔65599,而且识图可以知道大概位置

是平潭岛蓝眼泪的位置

搜这个渔船停在那里

点开海坛观潮,搜船号

 再高德地图搜索地址,全都试了一遍,最后试了一遍丁鼻垄就对了......

H&NCTF{0503-丁鼻垄}

Chasing Freedom 2

用小红书登app都行识图

输进去不对加一个灯塔就提交成功了

H&NCTF{0504-东庠岛灯塔}

Chasing Freedom 3

直接搜“岚庠渡 码头”

 

一号不对二号三号枚举一下就可以了

H&NCTF{0504-流水码头-岚庠渡3号}

猜猜我在哪儿?

待定

CRYPTO

哈基coke

猫脸

import numpy as np
import cv2def arnold_decode(image, shuffle_times, a, b):""" Arnold inverse shuffle for rgb image """# 确保图像是numpy数组格式if isinstance(image, str):image = cv2.imread(image)# 创建输出图像数组decoded_image = np.zeros_like(image, dtype=np.uint8)h, w = image.shape[0], image.shape[1]N = hfor time in range(shuffle_times):for new_x in range(h):for new_y in range(w):# 逆变换ori_x = ((a*b + 1) * new_x - b * new_y) % Nori_y = (-a * new_x + 1 * new_y) % Ndecoded_image[ori_x, ori_y, :] = image[new_x, new_y, :]image = decoded_image.copy()# 确保图像数据是8位无符号整数decoded_image = np.clip(decoded_image, 0, 255).astype(np.uint8)cv2.imwrite('decoded_flag.png', decoded_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])return decoded_image# 使用示例
if __name__ == "__main__":img_path = 'en_flag.png'  # 替换为加密后的图像路径decoded_img = arnold_decode(img_path, 6, 9, 1)print("解密完成,结果已保存为 decoded_flag.png")

lcgp

常规的 LCG 问题
  • 恢复 LCG 参数 a, b, m(模数、乘数、增量)

  • 反推出初始种子 cc(满足 cc = 2024^flag mod n

  • 求离散对数 flag = log₍₂₀₂₄₎cc mod n

  • 还原原始 flag 字符串

from sage.all import *
from Crypto.Util.number import long_to_bytes, GCD, isPrime# 给定 LCG 输出序列
c = [11250327355112956284720719987943941825496074893551827972877616718074592862130806975889275745497426515405562887727117008818863728803549848574821067056997423443681347885027000632462241968640893471352200125748453396098854283137158609264944692129301617338233670002547470932851350750870478630955328653729176440142198779254117385657086615711880537380965161180532127926250520546846863536247569437, 1289730679860726245234376434590068355673648326448223956572444944595048952808106413165882424967688302988257332835229651422892728384363094065438370663362237241013242843898967355558977974152917458085812489310623200114007728021151551927660975648884448177346441902806386690751359848832912607313329587047853601875294089502467524598036474193845319703759478494109845743765770254308199331552085163360820459311523382612948322756700518669154345145757700392164795583041949318636, 147853940073845086740348793965278392144198492906678575722238097853659884813579087132349845941828785238545905768867483183634111847434793587821166882679621234634787376562998606494582491550592596838027522285263597247798608351871499848571767008878373891341861704004755752362146031951465205665840079918938797056361771851047994530311215961536936283541887169156535180878864233663699607369701462321037824218572445283037132205269900255514050653933970174340553425147148993214797622395988788709572605943994223528210919230924346860415844639247799805670459, 7426988179463569301750073197586782838200202717435911385357661153208197570200804485303362695962843396307030986052311117232622043073376409347836815567322367321085387874196758434280075897513536063432730099103786733447352512984165432175254784494400699821500026196293994318206774720213317148132311223050562359314735977091536842516316149049281012797103790472349557847649282356393682360276814293256129426440381745354969522053841093229320186679875177247919985804406150542514337515002645320320069788390314900121917747534146857716743377658436154645197488134340819076585888700553005062311578963869641978771532330577371974731136, 10389979373355413148376869524987139791217158307590828693700943753512488757973725227850725013905113587408391654379552713436220790487026223039058296951420273907725324214990441639760825661323514381671141482079783647253661594138658677104054180912818864005556386671430082941396497098166887200556959866845325602873713813206312644590812141400536476615405444030140762980665885244721798105034497461675317071497925846844396796854201566038890503298824928152263774446268093725702310124363765630370263370678902342200494544961012407826314577564991676315451785987248633724138137813024481818431889574317602521878974976264742037227074]# 差分构造
t = [c[i] - c[i-1] for i in range(1, len(c))]# 恢复模数 m
m = 0
for i in range(1, len(t)-1):m = GCD(t[i+1] * t[i-1] - t[i]**2, m)print("是否为素数:", isPrime(m))
print("m 位数:", m.bit_length())# 恢复参数 a, b
a = (c[3] - c[2]) * inverse_mod(c[2] - c[1], m) % m
b = (c[2] - a * c[1]) % m# 恢复种子 cc
a_inv = inverse_mod(a, m)
cc = (c[0] - b) * a_inv % m# 离散对数部分
n = 604805773885048132038788501528078428693141138274580426531445179173412328238102786863592612653315029009606622583856638282837864213048342883583286440071990592001905867027978355755042060684149344414810835371740304319571184567860694439564098306766474576403800046937218588251809179787769286393579687694925268985445059
g = Mod(2024, n)
y = Mod(cc, n)flag = discrete_log(y, g)
print("Flag:", long_to_bytes(int(flag)))

数据处理

离散对数 比较喜欢本方法爆破
(sagemath)
from tqdm import tqdm
from itertools import permutations
from Crypto.Util.number import long_to_bytes
from sage.all import *# 1. 模数 Zmod(2^512)
Z = Zmod(2^512)# 2. 目标参数(手动合并换行)
m = Z(5084057673176634704877325918195984684237263100965172410645544705367004138917087081637515846739933954602106965103289595670550636402101057955537123475521383)
c = Z(2989443482952171039348896269189568991072039347099986172010150242445491605115276953489889364577445582220903996856271544149424805812495293211539024953331399)# 3. 恢复出混淆过的 flag
new_flag = str(discrete_log(c, m))# 4. 映射表恢复原始数字
lowercase = '0123456789'  # 正确的数字顺序
uppercase_pattern = '7***4****5'  # 映射前的字符格式# 5. 尝试所有 0123689 的排列来恢复原始 flag
for i in tqdm(permutations("0123689")):up = f"7{''.join(i[:3])}4{''.join(i[3:])}5"table = str.maketrans(up, lowercase)flag = new_flag.translate(table)try:res = long_to_bytes(int(flag)).decode()if res.startswith("H&NCTF"):print("✅ 找到 flag:", res)breakexcept:continue

 

(Python 版本,无需 Sage)

from Crypto.Util.number import *
import sympy
import itertools# 设定大数参数
m = 5084057673176634704877325918195984684237263100965172410645544705367004138917087081637515846739933954602106965103289595670550636402101057955537123475521383
c = 2989443482952171039348896269189568991072039347099986172010150242445491605115276953489889364577445582220903996856271544149424805812495293211539024953331399
n = 2 ** 512# 计算离散对数
flag = sympy.discrete_log(n, c, m)  # 即 c ≡ m^flag mod n
flag_str = str(flag)# 替换映射相关
digits = '0123689'
target_digits = '0123456789'# 枚举可能的密码本并尝试解码
for p in itertools.permutations(digits):up = '7' + ''.join(p[:3]) + '4' + ''.join(p[3:]) + '5'trans_table = str.maketrans(up, target_digits)translated = flag_str.translate(trans_table)try:decoded = long_to_bytes(int(translated))if b'H&NCTF' in decoded:print(f"[+] 找到 flag:{decoded.decode()}")breakexcept Exception:continue

ez-factor

from Crypto.Util.number import long_to_bytes, inverse
from sage.all import PolynomialRing, Zmod, gcd# ===========================
# 已知参数(从题目中整理)
# ===========================N = 155296910351777777627285876776027672037304214686081903889658107735147953235249881743173605221986234177656859035013052546413190754332500394269777193023877978003355429490308124928931570682439681040003000706677272854316717486111569389104048561440718904998206734429111757045421158512642953817797000794436498517023hint = 128897771799394706729823046048701824275008016021807110909858536932196768365642942957519868584739269771824527061163774807292614556912712491005558619713483097387272219068456556103195796986984219731534200739471016634325466080225824620962675943991114643524066815621081841013085256358885072412548162291376467189508ciphertext = 32491252910483344435013657252642812908631157928805388324401451221153787566144288668394161348411375877874802225033713208225889209706188963141818204000519335320453645771183991984871397145401449116355563131852618397832704991151874545202796217273448326885185155844071725702118012339804747838515195046843936285308e = 65537
r_bit_length = 248  # r 是一个 248 位的小素数# ===========================
# Step 1. 使用 Coppersmith’s 方法恢复 r
# ===========================PR.<x> = PolynomialRing(Zmod(N))  # 多项式环 Z_N[x]
f = x - hint                      # f(x) = x - hint# 尝试找到小根 r,使得 f(r) ≡ 0 mod N
roots = f.small_roots(X=2^r_bit_length, beta=0.4, epsilon=0.01)if not roots:print("[-] 未找到满足条件的小根 r,建议调节 beta 或 epsilon 参数后重试")exit()r = int(roots[0])
print("[+] 找到小根 r =", r)# ===========================
# Step 2. 利用 r 分解 N
# ===========================p = gcd(hint - r, N)
if p == 1 or N % p != 0:print("[-] 恢复 p 失败,p 可能不是 N 的因子")exit()q = N // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)# ===========================
# Step 3. 解密密文
# ===========================m = pow(ciphertext, d, N)
flag = long_to_bytes(int(m))
if b'H&NCTF' in flag:print("[+] 可能的flag:", flag)
else:print("[!] 没有找到明显的flag格式,可能需要进一步处理")

three vertical lines

from Crypto.Util.number import long_to_bytes, inverse
from sage.all import *# 1. 把 n 写成一行:
n = Integer(72063558451087451183203801132459543552092564094711815404066471440396765744526854383117910805713050240067432476705168314622044706081669935956972031037827580519320550326077291392722314265758802332280697884744792689996718961355845963752788234205565249205191648439412084543163083032775054018324646541875754706761793307667356964825613429368358849530455220484128264690354330356861777561511117)# 2. 这里改用整数环,构造多项式环
R = PolynomialRing(Integers(n), 'x')
x = R.gen()# 3. 计算 t 满足 t^5 = 4/3 mod n
# 由于 n 不是素数,GF(n) 不适用,改用mod n的整数环中的多项式求解,或者用扩展欧几里得算法求5次根,这里直接计算t:
# 先计算逆元 3^-1 mod n
inv3 = inverse_mod(3, n)
four_thirds = (4 * inv3) % n# 计算四分之三的5次根 t:这里没有现成函数,需要自定义尝试或者用数论方法。  
# 之前用的 GF(n)(4/3).nth_root(5) 在 n 不是素数时不可用# 假设你有 t,下面直接填上:
# 也可以尝试在 Sage 中用 discrete_log 或者其它算法计算
t = pow(four_thirds, inverse_mod(5, (n-1)), n)  # 这是一个尝试的做法,不保证成功# 4. 构造矩阵 M
M = Matrix(ZZ, [[1, t],[0, n]
])# 5. LLL 找到短向量
q, p = M.LLL()[0]
q, p = abs(q), abs(p)print(3 * p**5 + 4 * q**5 == n)# 6. 密文 c,同样合并成一行:
c = Integer(2864901454060087890623075705953001126417241189889895476561381971868301515757296100356013797346138819690091860054965586977737630238293536281745826901578223)e = Integer(65537)
d = inverse(e, (p - 1)*(q - 1))
m = pow(c, d, p*q)
m_int = int(m)  # 转换成普通整数
flag = long_to_bytes(m_int)
print(flag)

ez-factor-pro

待定

为什么出题人的rsa总是ez

待定

http://www.xdnf.cn/news/985843.html

相关文章:

  • 第三讲 基础运算之整数运算
  • 什么是数字化项目风险管理?如何实现项目风险管理数字化?
  • IIS 实现 HTTPS:OpenSSL证书生成与配置完整指南
  • 突然虚拟机磁盘只剩下几十K
  • [特殊字符] React 与 Vue 源码级对比:5大核心差异与实战选择指南
  • # include<heαd.h>和# include″heαd.h″的区别
  • 成都国际数字影像产业园孵化培育模式的探索与突破
  • 人机交互设计知识点总结
  • 驻波比(VSWR)详解
  • 判断字符串子序列
  • OpenAI o3-pro深度解析:87%降价背后的AI战略,AGI发展迈入新阶段!
  • 自动托盘搬运车是什么?它的工作逻辑如何实现物流自动化?
  • Python训练营打卡 Day51
  • 日本滨松R669光电倍增管Hamamatsu直径51 mm 直径端窗型扩展红多碱光阴极面光谱灵敏度特性:300 至 900 nm
  • AI重写工具导致‘文本湍流’特征|如何人工消除算法识别标记
  • 卷积神经网络(一)
  • 基于C++实现(控制台)小学算数自测系统
  • ateⅹⅰt()的用法
  • DD3118完整版参数规格书|DD3118 3.0读卡器控制方案|DD3118高速3.0读卡器芯片
  • 【数据采集+人形机器人】使用 Apple Vision Pro 对宇树(Unitree)G1 和 H1 人形机器人进行全身的遥操作控制
  • RAG 处理流程
  • Linux内核学习资料-deepseek
  • AIGC 基础篇 Python基础 05 元组,集合与字典
  • 45. Jump Game II
  • OPenCV CUDA模块图形变换----构建透视变换映射表函数buildWarpPerspectiveMaps()
  • AUTOSAR实战教程--DoIP_03_ 代码分析与调用栈观测(ISOLAR版)
  • 详解多模态
  • 项目制造型企业如何实现高效管理?从金属工具制造说起
  • 【LeetCode 热题 100】只出现一次的数字 / 多数元素 / 颜色分类 / 寻找重复数
  • 建造者模式(Builder Pattern)