当前位置: 首页 > 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.lryc.cn/news/619455.html

相关文章:

  • AAAI论文速递 | NEST:超图小世界网络让自动驾驶轨迹预测更精准
  • Java面试宝典:G1垃圾收集器下
  • C#面试题及详细答案120道(11-20)-- 面向对象编程(OOP)
  • AI抢饭碗,软件测试该何去何从?
  • TraeCN与Cursor对比分析:双雄争锋下的AI编程工具演进之路
  • Vue3 中 <script setup> 场景下,需要手动导入和不需要手动导入的内容整理
  • 第二十二天:指针与内存
  • TF - IDF算法面试与工作常见问题全解析
  • OpenCV常见问题汇总
  • 音视频处理新纪元:12款AI模型的语音转录和视频理解能力横评
  • 【计算机网络】王道考研笔记整理(4)网络层
  • OpenAI 回应“ChatGPT 用多了会变傻”
  • Debian新一代的APT软件源配置文件格式DEB822详解
  • 【C++详解】用红黑树封装模拟实现mymap、myset
  • 《论文阅读》从特质到移情:人格意识多模态移情反应生成 ACL 2025
  • 2025 环法战车科技对决!维乐 Angel Glide定义舒适新标
  • 用vscode开发和调试golang超简单教程
  • 【debian系统】cuda13和cudnn9.12详细安装步骤
  • Pytest项目_day15(yaml)
  • 肖臻《区块链技术与应用》第十二讲:比特币是匿名的吗?—— 深入解析匿名性、隐私风险与增强技术
  • 《算法导论》第 22 章 - 基本的图算法
  • Linux入门DAY23
  • 【从零开始java学习|第五篇】项目、模块、包、类的概念与联系
  • 解决:Gazebo连接模型数据库失败
  • 制作一款打飞机游戏90:完结
  • JavaSE高级-01
  • BGP 笔记梳理
  • 分布式事务DTP模型
  • Vue3 vs Vue2:全面对比与面试宝典
  • 递归函数与 lambda 函数:用法详解与实践