赞
踩
这道题其实比较经典,最早应该是出现在2016年的HCTF,出题的思路可以参照这篇博客
- #! /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 的分解,即可得解。
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。