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

[idekCTF 2025] diamond ticket

很久没写了。最近的比赛不啥地,或者特别简单或者特别难。难的又找不到WP。

这个idek感觉非常好,但是找不着WP很苦恼。终于找到一个题的,记录一下。

WP: idekCTF 2025 - Connor M

先看看原题:

from Crypto.Util.number import *#Some magic from Willy Wonka
p = 170829625398370252501980763763988409583
a = 164164878498114882034745803752027154293
b = 125172356708896457197207880391835698381def chocolate_generator(m:int) -> int:return (pow(a, m, p) + pow(b, m, p)) % p#The diamond ticket is hiding inside chocolate
diamond_ticket = open("flag.txt", "rb").read()
assert len(diamond_ticket) == 26
assert diamond_ticket[:5] == b"idek{"
assert diamond_ticket[-1:] == b"}"
diamond_ticket = bytes_to_long(diamond_ticket[5:-1])flag_chocolate = chocolate_generator(diamond_ticket)
chocolate_bag = []#Willy Wonka are making chocolates
for i in range(1337):chocolate_bag.append(getRandomRange(1, p))#And he put the golden ticket at the end
chocolate_bag.append(flag_chocolate)#Augustus ate lots of chocolates, but he can't eat all cuz he is full now :D
remain = chocolate_bag[-5:]#Compress all remain chocolates into one
remain_bytes = b"".join([c.to_bytes(p.bit_length()//8, "big") for c in remain])#The last chocolate is too important, so Willy Wonka did magic again
P = getPrime(512)
Q = getPrime(512)
N = P * Q
e = bytes_to_long(b"idek{this_is_a_fake_flag_lolol}")
d = pow(e, -1, (P - 1) * (Q - 1))
c1 = pow(bytes_to_long(remain_bytes), e, N)
c2 = pow(bytes_to_long(remain_bytes), 2, N) # A small gift#How can you get it ?
print(f"{N = }")
print(f"{c1 = }")
print(f"{c2 = }") """
N = 85494791395295332945307239533692379607357839212287019473638934253301452108522067416218735796494842928689545564411909493378925446256067741352255455231566967041733698260315140928382934156213563527493360928094724419798812564716724034316384416100417243844799045176599197680353109658153148874265234750977838548867
c1 = 27062074196834458670191422120857456217979308440332928563784961101978948466368298802765973020349433121726736536899260504828388992133435359919764627760887966221328744451867771955587357887373143789000307996739905387064272569624412963289163997701702446706106089751532607059085577031825157942847678226256408018301
c2 = 30493926769307279620402715377825804330944677680927170388776891152831425786788516825687413453427866619728035923364764078434617853754697076732657422609080720944160407383110441379382589644898380399280520469116924641442283645426172683945640914810778133226061767682464112690072473051344933447823488551784450844649
"""

首先他给出了参数p,a,b并把flag的芯m作了个(a^m+b^m)%p的运算。

第二步取了1337个随机数并把上一步的c放到尾部然后取尾部5个值(显然1337个只用到后4个)连接成字符串再转整,也就是作了个前填充。

第三步作了个RSA,一个是c1=c^e%N,c2=c^2%N,这一步就是共模攻击很容易出

N,c1,c2 = ...
e = bytes_to_long(b"idek{this_is_a_fake_flag_lolol}")_, k1, k2 = xgcd(e, 2)
remain_bytes = long_to_bytes(pow(c1, k1, N) * pow(c2, k2, N) % N)
flag_chocolate = bytes_to_long(remain_bytes[-16:]) # 99584795316725433978492646071734128819

先列方程:c=a^m+b^m mod p 令b=a^k 则c = a^m + (a^m)^k 令X=a^m则有c =X+X^k

拿到这个式子实际上就可以计算了,但在sage上k有亿点大,理论小点的话是可解的。所以(这估计是个论文题,这种方法第一次见)就用到gcd方法。这里引入了一个所有解的公式:

g = pow(x, p, f) - x #g(x) = x^p -x 是所有线性因子的乘积(实际上是所有根)

这两个式子gcd就能得到想要的根(未完)

这里的m解出后实际上是m%p的值

p = 170829625398370252501980763763988409583
a = 164164878498114882034745803752027154293
b = 125172356708896457197207880391835698381c = 99584795316725433978492646071734128819
k = GF(p)(b).log(a)PR.<x> = PolynomialRing(GF(p))
f = x + x**k - c
#g(x) = x^p -x 是所有线性因子的乘积(实际上是所有根)
g = pow(x, p, f) - x
X = [r for r in f.gcd(g).roots()][0][0]
m = GF(p)(X).log(a)
print(f'{m = }') # 4807895356063327854843653048517090061

第三步就是用CVP算法,这里调用了ortools并用了github上的一个模块,用CVP求一个最近平面。

load('./linineq.py')p = 170829625398370252501980763763988409583
o = (p-1)//2
m = 4807895356063327854843653048517090061M = matrix([[256**i for i in reversed(range(20))]])
b = [m]
lb = [30]*20 
ub = [128]*20 for sol in solve_bounded_mod_gen(M, b, lb, ub, o, solver='ortools'):print(bytes(sol))

一道题学到不少东西。好题!

http://www.dtcms.com/a/329571.html

相关文章:

  • C#自定义日期时间选择器
  • 2025 电赛 C 题完整通关攻略:从单目标定到 2 cm 测距精度的全流程实战
  • C++编程学习(第22天)
  • k8s资源管理
  • 集成电路学习:什么是CV计算机视觉
  • 加密界的“瑞士军刀“-----VeraCrypt 加密原理与实操
  • 【数据结构】——栈(Stack)的原理与实现
  • iscc2025决赛wp
  • Redis面试精讲 Day 20:Redis大规模部署性能调优
  • MCP协议更新:从HTTP+SSE到Streamable HTTP,大模型通信的进化之路
  • [Oracle数据库] ORACLE的用户维护和权限操作
  • 多模态RAG赛题实战之策略优化--Datawhale AI夏令营
  • javaswing json格式化工具
  • 何解决PyCharm中pip install安装Python报错ModuleNotFoundError: No module named ‘json’问题
  • Day 39: 图像数据与显存
  • C++ stack and queue
  • Python3:使用venv虚拟环境
  • 猫头虎AI分享:Excel MCP,让AI具备操作Excel表格|创建销售数据表、复制工作表、填充数据、写公式、绘制图表、调节颜色、添加透视表、保存为PDF
  • Oracle数据库空间深度回收:从诊断到优化实战指南
  • Codeforces Round 1042 (Div. 3)
  • 友思特方案 | FPGA 加持,友思特图像采集卡高速预处理助力视觉系统运行提速增效
  • 【记录贴】STM32 I2C 控制 OLED 卡死?根源在 SR1 与 SR2 的读取操作
  • ELK开启安全策略
  • @系统管理 - Ansible 补丁管理方案(Windows Linux)
  • 从零开始:用PyTorch实现线性回归模型
  • MySQL的MVCC多版本并发控制
  • 01数据结构-Prim算法
  • 一场名为“默契”的清洁革命
  • Github学生认证
  • 从钢板内部应力视角,重新认识护栏板矫平机