文章总结: 本文概述第十九届CISCN初赛WriteUp,包含ECDSA、EzFlag及RSA_NestingDoll三题。作者通过私钥计算、逆向斐波那契生成逻辑及改进Pollardp-1算法分别解出Flag。文章提供了完整的Python解题脚本与核心算法分析,展示了密码学计算与二进制分析技术在CTF实战中的应用,具有较高的技术参考价值。 综合评分: 95 文章分类: CTF,逆向分析
第十九届全国大学生信息安全竞赛(ciscn)暨第三届长城杯网数智安全大赛—初赛WriteUp
Pirater
2025年12月31日 16:01 广东
以下文章来源于Overf1ow ,作者Overf1ow
Overf1ow .
Overf1ow安全团队,不定期更新国内外赛事WP。 官方网站:overf1ow.aristore.top
又一届ciscn,然而这是我们第一次国赛,排在第450名。今年已进入尾声,感谢这一年师傅们对Overf1ow的关注_(•̀ω•́ 」∠)_即将迎来2026,提前祝各位师傅新年快乐!
密码学
ECDSA
题目开头就给私钥了,只需要将代码重新输入计算就行:
from ecdsa import SigningKey, NIST521p
from hashlib import sha512, md5
digest_int = int.from_bytes(sha512(b"Welcome to this challenge!").digest(), "big")
curve_order = NIST521p.order
priv_int = digest_int % curve_order
flag = "flag{" + md5(str(priv_int).encode()).hexdigest() + "}"
print(flag)
flag{581bdf717b780c3cd8282e5a4d50f3a0}
EzFlag
首先放到ida查看程序执行流程:程序首先读取用户输入,并与字符串 “V3ryStr0ngp@ssw0rd” 进行比较,这一步是校验,但Flag的生成逻辑其实在验证通过后的代码块中,
程序初始化变量v11=1。进入一个32次的循环(i从0到31)。每次循环调用函数 f(v11) 获取一个字符。在索引为7,12,17,22的位置插入连字符-。每次循环结束前,更新v11的值v11=v11*8+i+64。
跟进函数f(地址0x1229),分析其逻辑:该函数实现了一个模16的斐波那契数列生成器。它计算斐波那契数列的第v11 项,并在每一步加法后进行&0xF(即模16)操作。最终结果作为索引,从全局字符串K中取值。通过交叉引用或查看数据段,找到全局字符串K的内容为:”012ab9c3478d56ef”。重点就是64位整数溢出截断,还有一个就是如果不手动模拟64位截断,v11会变成一个巨大的数,所以这里也要注意。
exp:
def get_fib_mod16(n):
n = n % 24
if n == 0: return0
if n == 1: return1
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, (a + b) % 16
return b
def solve():
K = "012ab9c3478d56ef"
v11 = 1
flag_content = ""
for i in range(32):
idx = get_fib_mod16(v11)
char = K[idx]
flag_content += char
if i in [7, 12, 17, 22]:
flag_content += "-"
v11 = (v11 * 8 + i + 64) & 0xFFFFFFFFFFFFFFFF
print(f"flag{{{flag_content}}}")
solve()
flag{10632674-1d219-09f29-14769-f60219a24}
RSA_NestingDoll
题目本身并不难理解,n和n1的每个因子满足:p=a*p1+1。其中a是2**20以内随机选取的素数的乘积。 和Pollard p-1很像,可以先了解一下原理:https://www.cnblogs.com/chen-xing-zzu/p/18528441。 对于本题来说,我们可以利用上B的取值范围和n1的值,在原本的分解方法之上再做两件事情:
- 让pows所选取的素数小于
- 再用pows乘上n1,一是依旧满足费马小定理,二是由于大因子的存在,仅仅用pows并不足以分解n
脚本如下:
from Crypto.Util.number import *
from gmpy2 import *
from sympy import prod, primefactors
import random
def prime_powers(B):
sieve_list = list(sieve_base)
whileTrue:
new_sieve = int(next_prime(sieve_list[-1]))
if new_sieve > B:
break
sieve_list.append(new_sieve)
out = []
for p in sieve_list:
pk = p
while pk * p <= B:
pk *= p
out.append(pk)
return out
def Pollard_improve(n, n1, pows, chunk_size):
print(f"factoring...")
factors = []
whileTrue:
x = random.randint(2, n - 1)
for i in range(0, len(pows), chunk_size):
chunk = pows[i : i + chunk_size]
E = int(prod(chunk)) # 将pow乘起来,寻找p可能会更快,但有很大概率找不到
a = x
x = powmod(a, E, n)
y = powmod(x, n1, n)
fac = gcd(y - 1, n)
if1 < fac < n:
factors.append(int(fac))
n //= fac
print(f"find the {len(factors)}-th factor: {fac}")
break
if fac == n:
for p in chunk:
x = pow(a, p, n) # 如果用乘积的方法找不到,就挨个寻找
y = pow(x, n1, n)
fac = gcd(y - 1, n)
if1 < fac < n:
factors.append(int(fac))
n //= fac
print(f"find the {len(factors)}-th factor: {fac}")
break
if is_prime(n):
factors.append(int(n))
print(f"find the {len(factors)}-th factor: {n}")
return factors
n1 = 16141229822582999941795528434053604024130834376743380417543848154510567941426284503974843508505293632858944676904777719167211264225017879544879766461905421764911145115313698529148118556481569662427943129906246669392285465962009760415398277861235401144473728421924300182818519451863668543279964773812681294700932779276119980976088388578080667457572761731749115242478798767995746571783659904107470270861418250270529189065684265364754871076595202944616294213418165898411332609375456093386942710433731450591144173543437880652898520275020008888364820928962186107055633582315448537508963579549702813766809204496344017389879
n = 484831124108275939341366810506193994531550055695853253298115538101629337644848848341479419438032232339003236906071864005366050185096955712484824249228197577223248353640366078747360090084446361275032026781246854700074896711976487694783856878403247312312487197243272330518861346981470353394149785086635163868023866817552387681890963052199983782800993485245670437818180617561464964987316161927118605512017355921555464359512280368738197370963036482455976503266489446554327046948670215814974461717020804892983665655107351050779151227099827044949961517305345415735355361979690945791766389892262659146088374064423340675969505766640604405056526597458482705651442368165084488267428304515239897907407899916127394598273176618290300112450670040922567688605072749116061905175316975711341960774150260004939250949738836358264952590189482518415728072191137713935386026127881564386427069721229262845412925923228235712893710368875996153516581760868562584742909664286792076869106489090142359608727406720798822550560161176676501888507397207863998129261472631954482761264406483807145805232317147769145985955267206369675711834485845321043623959730914679051434102698588945009836642922614296598336035078421463808774940679339890140690147375340294139027290793
c = 657984921229942454933933403447729006306657607710326864301226455143743298424203173231485254106370042482797921667656700155904329772383820736458855765136793243316671212869426397954684784861721375098512569633961083815312918123032774700110069081262242921985864796328969423527821139281310369981972743866271594590344539579191695406770264993187783060116166611986577690957583312376226071223036478908520539670631359415937784254986105845218988574365136837803183282535335170744088822352494742132919629693849729766426397683869482842748401000853783134170305075124230522253670782186531697976487673160305610021244587265868919495629
B = 2**20
e = 65537
prime_power = prime_powers(B)
n_factors = Pollard_improve(n, n1, prime_power, 5000) # 不必一次性用上所有power,给个限定范围能更快
n1_factors = [primefactors(p - 1)[-1] for p in n_factors]
phi = prod([p1 - 1for p1 in n1_factors])
d = inverse(e, phi)
m = pow(c,d,n1)
flag = long_to_bytes(m)
print(flag)
flag{fak3_r5a_0f_euler_ph1_of_RSA_040a2d35}
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:Pirater 《第十九届全国大学生信息安全竞赛(ciscn)暨第三届长城杯网数智安全大赛—初赛WriteUp》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论