DASCTF Sept X 浙江工业大学秋季挑战赛rsa1

这道题其实比较经典,最早应该是出现在2016年的HCTF,出题的思路可以参照这篇博客

2016 HCTF Crypto 出题总结

#! /usr/bin/env python
# -*- coding: utf-8 -*-

# from flag import get_flag
from hashlib import sha512
import random
from Crypto.Util.number import long_to_bytes, getPrime, bytes_to_long
from libnum import invmod, gcd
from pwn import process, context, remote
import itertools
import time


def m_exit(n):
	print ("==============Game Over!=================")
	exit(n)
def isqrt(n):
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    if pow(x, 2) == n:
    	return x
    else:
    	return False
def cal_bit(num):
	num = int(num)
	l = len(bin(num))
	return l-2

def pi_b(x):
	bt = 536380958350616057242691418634880594502192106332317228051967064327642091297687630174183636288378234177476435270519631690543765125295554448698898712393467267006465045949611180821007306678935181142803069337672948471202242891010188677287454504933695082327796243976863378333980923047411230913909715527759877351702062345876337256220760223926254773346698839492268265110546383782370744599490250832085044856878026833181982756791595730336514399767134613980006467147592898197961789187070786602534602178082726728869941829230655559180178594489856595304902790182697751195581218334712892008282605180395912026326384913562290014629187579128041030500771670510157597682826798117937852656884106597180126028398398087318119586692935386069677459788971114075941533740462978961436933215446347246886948166247617422293043364968298176007659058279518552847235689217185712791081965260495815179909242072310545078116020998113413517429654328367707069941427368374644442366092232916196726067387582032505389946398237261580350780769275427857010543262176468343294217258086275244086292475394366278211528621216522312552812343261375050388129743012932727654986046774759567950981007877856194574274373776538888953502272879816420369255752871177234736347325263320696917012616273
	return invmod(x, bt)
def con_fra(a, b):
	r = []
	while True:
		if a == 1:
			break
		tmp = a//b
		if tmp != 0:
			r.append(tmp)
		a, b = b, (a-tmp*b)
	return r

def wiener_attack(e, n):
	cf = con_fra(e, n)
	for x in range(len(cf)):
		k, d = 0, 1
		while x >= 0:
			k, d = d, d*cf[x] + k
			x -= 1
		# print "k: %s\nd: %s\n" %(k, d)
		phi_n = (e*d - 1)//k
		B = n - phi_n + 1
		C = n
		dt = pow(B, 2) - 4*C    # b^2 - 4*a*c
		if dt >= 0 and isqrt(dt) and (B+isqrt(dt)) % 2 == 0:
			print ("phi_n: ", hex(phi_n))
			return phi_n
	print ("wiener attack fail!")
def get_ed(p, q):
	k = cal_bit(q*p)          #length
	phi_n = (p-1)*(q-1)
	r = random.randint(10, 99)
	while True:
		u = getPrime(k//4 - r)
		if gcd(u, phi_n) != 1:
			continue
		t = invmod(u, phi_n)
		e = pi_b(t)
		if gcd(e, phi_n) == 1:
			break
	d = invmod(e, phi_n)
	return (e, d)



# def main():
# 	flag = get_flag()
#
# 	p=getPrime(2048)
# 	q=getPrime(2048)
# 	n = p * q
# 	e, d = get_ed(p, q)
# 	print ("n: ", hex(n))
# 	print ("e: ", hex(e))
#
# 	flag = bytes_to_long(flag)
# 	enc_flag = pow(flag, e, n)
# 	print ("Your flag is: ", hex(enc_flag))
	

# if __name__ == '__main__':
# main()
def divide_pq(ed, n):
	# ed = e*d
	k = ed - 1
	while True:
		g = random.randint(3, n-2)
		t = k
		while True:
			if t % 2 != 0:
				break
			t //= 2
			x = pow(g, t, n)
			if x > 1 and gcd(x-1, n) > 1:
				p = gcd(x-1, n)
				return (p, n//p)
import gmpy2
def main():
	n = 0xd1c2e3f292275f19d32508646e0d688214b9262b902aa17abe3b5083e13aaa82cc571c47dce2131f6a46184388eae0496a259e69c577ab593fe41677dbc22b6620bfc9c8608cf0f95360fe760338d7466dea625a416b6b4bb156d1f7d3afe75af1e9b3d38aca9340455e37a260f29ff5836a89729bc6ddf0d3e8f80733f5ce3c8be1200acad645ce8efa958af0e70008e9db567d5d5c7213466236723c9ea36938de81d6e607391cbc1fcc94dbf08f94c9a67d0ab8f2761d64283dea44ad0a6b6f861e1825a7a0820358fbdf7e4c6bd41ad4ffca4ea74cc9985b3474ba767e2c698edf68963a7c9860b0a76965638c6b936844bf6d6559c41ef2ade450c6eba0b4e11dbbcfb6ade6ac67355a8b744fb65b0db2d50f92719dd32f332ec909acf858f82b98d6df1904d82b436b9496a43f4be8e6975d5952177c620ae0bc4381453be7e267792664b3a6a37e603903ef16295e2c69eb6e1059c225f993c97b881c1dbcc1e0d8ab88699403d089f7500d55ed1de381936475186aa6d7ebd149915a65f24d44c64a3f1d868f12ab262df433abab6b9f49a0eb6ca72bd9df90c6e6a5588c593d1deef609e74d42ebbb3afc6bb38306903bdf3c62f6faf379bdad85ccbdcdca72d2d5ef269ae8a28d9ba80b4cb9ca1dc22023cf324196fefe8f7720b7804db438ba52db3f3489050c689f324abdcd3445609fbe37b17ba253c20939f1
	e = 0x78fed22328c65d24ad7578778c2aae728bf65b88a807e47da31941f9efe04d80cd3377389b45e797a2b84165f9b3b77655f52ed3d787a7c89ad8533e28c418e95c324cdfc3a7b1401ea0e7e9d6f7f16542800069fc5d3da23b39441f6a33ace440c07ab18ae40f334e5b7bf7acb44645bcaccae26d0b8087934d45a29b1ccc6c8ff122ab9c7d736741b1c313b0773f77913cc14f7d381985f1a96477c65e2cc28f8865ff1e9a5171ae41fcbc620332caf95faa4c9e6c4016c4d90613c06e848bdd0e5f1b50d4547ee84e116077b38a48549992764700c9cf29d674c8a50aac9b3729ea58fdf80674bc084d72dc9d0e2a96819e268819ae00682b6089a7a4fa6421a00bf182d823487e0400828c8ecb783844a3f630a0a0bcfa6c50402bbfd6151bdd86337e24953b3b60b68c638454f55dcb8dc3335d9a6155f32336fface5a7c992ab8049b8d776515d57a76e4b3c235ec648e7d7e58a98e362f6bbc26679a1fa3623ae15ce7dd677acf56c2665e28bd2ac42f2f3d3dd2d58cf85b3c07262ed5e14122b900b327fe9be62b00c4c2d23a4ba7ffc68d6ada291c4d8b5b95ee062be0840ee5f00bd2c0c69591d071a1fdda8fadaced1f9c5fa85590e89c0e1b12848103a3e47b20d6b7cc8d0005f246c44cd6345397b6ecd8bdb80c788f811f2c9d0d22c81abd0d076cfafed9c41d192f3e16ae8f9de5da059aa4a84e3ac0277fd
	c = 0x24a78c84f2eb33c076614aea25b77bce5f9acc33fe312a4f59f2a9a7eb582df11a8f57610cda565c76929c0ff08eaaee2b3b68bacd20874d389bb859b1d18cabef8e83c855376ef3b3523bbab27e6e80a7c8e2d2dbfe83fd4d3a1e1a0d212ebef1e93fe9d63d298fcd02d2b832c05febe86163b19bb675560ceafa56858491160c539d6087aca55fc1fa7fd6fc7628f78de906b3ac073242edef23e263573488c3ef359a03f06b649d7def9b2ab01faf78e3008a9de44e56970a99216f51979c2cc0a3e37297d27b1a6a95cf829724479dfea29f1751cce5e3ba2ed35716886415f1dfb11f33a7f9dbbbb4d77f34ccd29f889b8f0381c3c18fbec5d5bfe9785a8c49d0bbe7bfc2754d2a8ca911948b0b7551656d421abcbdcaca7515dd7d851787f068aa1a6e86c3921f0c852483ac19c7a263f0d585824ba8226dacfa6520731de00c0517870e7602a3179600fb580f876b045faf48d107f36c48da5e68a7213e23e78b3e1d526b769e295bfb1d571592e403140303fc55a66b305c44de42084a9600cc17fc1426df7181022b65abfc27076037115a186494858b782f07835171786a0449d0fa9b8b49879a95c555b5bc0639e5fefb85897506b3cccfb4a941f83055b649fdf789203b0cc27f09a5160009638dfe9e515bb2bbc349a6d8bc35ccdd7a8a7e5fe84c59cd13ce1a5ba83e2f57f28cc8bd819219e8ad5348746e4b
	bt = 536380958350616057242691418634880594502192106332317228051967064327642091297687630174183636288378234177476435270519631690543765125295554448698898712393467267006465045949611180821007306678935181142803069337672948471202242891010188677287454504933695082327796243976863378333980923047411230913909715527759877351702062345876337256220760223926254773346698839492268265110546383782370744599490250832085044856878026833181982756791595730336514399767134613980006467147592898197961789187070786602534602178082726728869941829230655559180178594489856595304902790182697751195581218334712892008282605180395912026326384913562290014629187579128041030500771670510157597682826798117937852656884106597180126028398398087318119586692935386069677459788971114075941533740462978961436933215446347246886948166247617422293043364968298176007659058279518552847235689217185712791081965260495815179909242072310545078116020998113413517429654328367707069941427368374644442366092232916196726067387582032505389946398237261580350780769275427857010543262176468343294217258086275244086292475394366278211528621216522312552812343261375050388129743012932727654986046774759567950981007877856194574274373776538888953502272879816420369255752871177234736347325263320696917012616273
	t = pi_b(e)
	print("get t = ", hex(t))
	phi_n = wiener_attack(t, n)
	try:
		u = invmod(t, phi_n)
	except:
		return False
	print("get u = ", hex(u))
	qq, pp = divide_pq(u * t, n)
	print("get p = ", hex(pp))
	print("get q = ", hex(qq))
	d = invmod(e, (qq - 1) * (pp - 1))
	print("get d = ", hex(d))
	flag = pow(c, d, n)
	print("get flag: ", long_to_bytes(flag))
if __name__ == '__main__':
	main()

整个脚本很长,大概流程如下:

1.先通过 e 和 bt 直接求 t

2.再通过 t 和 n 求 phi_n (这里的t符合wiener_attack的条件),wiener_attack其实是个求逆元的函数(上面这个只需要多求一步就能得到u了),在这里得到的就是 u(这里我很不理解,为什么要重新求个pp和qq出来,而不能直接求d,似乎是因为我们用 t 和 n 求出来的phi_n似乎不等同与原来的phi_n,有个大佬就没做这一步,好像是非预期解https://github.com/Hcamael/ctf-library/blob/master/RSA1/rsa_s.py

3.下一步的原理是,u 和 t 是关于 phi_n 的逆元,所以两者包含有n的分解的信息,用 u 和 t 代替 e 和 d 辅助进行 n 的分解,即可得解。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值