20211221-PWHHUB12月赛-CryptoSecWriteUp

 

ecRNG

考点

  • ecRNG

用椭圆曲线来生成的PRNG伪随机数发生器,但是该曲线是不安全的,可以用smartAttack把私钥r给算出来

十几分钟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
# coding: utf-8
from Crypto.Util.number import *
from hashlib import sha3_512
from Crypto.Cipher import AES
from tqdm import tqdm

_sage_const_512 = Integer(512);
_sage_const_0xA15C4FB663A578D8B2496D3151A946119EE42695E18E13E90600192B1D0ABDBB6F787F90C8D102FF88E284DD4526F5F6B6C980BF88F1D0490714B67E8A2A2B77 = Integer(
0xA15C4FB663A578D8B2496D3151A946119EE42695E18E13E90600192B1D0ABDBB6F787F90C8D102FF88E284DD4526F5F6B6C980BF88F1D0490714B67E8A2A2B77);
_sage_const_0x5E009506FCC7EFF573BC960D88638FE25E76A9B6C7CAEEA072A27DCD1FA46ABB15B7B6210CF90CABA982893EE2779669BAC06E267013486B22FF3E24ABAE2D42 = Integer(
0x5E009506FCC7EFF573BC960D88638FE25E76A9B6C7CAEEA072A27DCD1FA46ABB15B7B6210CF90CABA982893EE2779669BAC06E267013486B22FF3E24ABAE2D42);
_sage_const_0x2CE7D1CA4493B0977F088F6D30D9241F8048FDEA112CC385B793BCE953998CAAE680864A7D3AA437EA3FFD1441CA3FB352B0B710BB3F053E980E503BE9A7FECE = Integer(
0x2CE7D1CA4493B0977F088F6D30D9241F8048FDEA112CC385B793BCE953998CAAE680864A7D3AA437EA3FFD1441CA3FB352B0B710BB3F053E980E503BE9A7FECE);
_sage_const_0x39F15E024D44228FD11C58A71C312FD64167C7D249D5677DA0DFB4B9C3ED0F90701837A5E77B5A2B74433D7FBE027CD0C73B5AA7B300F7384521AF0DC283DC6D = Integer(
0x39F15E024D44228FD11C58A71C312FD64167C7D249D5677DA0DFB4B9C3ED0F90701837A5E77B5A2B74433D7FBE027CD0C73B5AA7B300F7384521AF0DC283DC6D);
_sage_const_0x5F3636A89167A6FBB7B7D1AD97D11C70756835B5F1273E20C06D9E022D74648EC22A3F92C378196D137C3F2027A67381BE79E1C0D65CD9B61211A77A3842C8B2 = Integer(
0x5F3636A89167A6FBB7B7D1AD97D11C70756835B5F1273E20C06D9E022D74648EC22A3F92C378196D137C3F2027A67381BE79E1C0D65CD9B61211A77A3842C8B2);
_sage_const_2 = Integer(2);
_sage_const_210 = Integer(210);
_sage_const_1 = Integer(1);
_sage_const_384 = Integer(384);
_sage_const_0 = Integer(0);
_sage_const_9 = Integer(9)

size = _sage_const_512


def SmartAttack(P, Q, p):
E = P.curve()
Eqp = EllipticCurve(Qp(p, 2), [ZZ(t) + randint(0, p) * p for t in E.a_invariants()])

P_Qps = Eqp.lift_x(ZZ(P.xy()[0]), all=True)
for P_Qp in P_Qps:
if GF(p)(P_Qp.xy()[1]) == P.xy()[1]:
break

Q_Qps = Eqp.lift_x(ZZ(Q.xy()[0]), all=True)
for Q_Qp in Q_Qps:
if GF(p)(Q_Qp.xy()[1]) == Q.xy()[1]:
break

p_times_P = p * P_Qp
p_times_Q = p * Q_Qp

x_P, y_P = p_times_P.xy()
x_Q, y_Q = p_times_Q.xy()

phi_P = -(x_P / y_P)
phi_Q = -(x_Q / y_Q)
k = phi_Q / phi_P
return ZZ(k)


def dec(cipher, number):
Inn = sha3_512(str(number).encode()).hexdigest()
Inn = long_to_bytes(int(Inn, 16))
key = Inn[:16]
iv = Inn[32:48]
aes = AES.new(key, AES.MODE_CBC, iv)
m = aes.decrypt(bytes.fromhex(cipher))
return m


p = 0xA15C4FB663A578D8B2496D3151A946119EE42695E18E13E90600192B1D0ABDBB6F787F90C8D102FF88E284DD4526F5F6B6C980BF88F1D0490714B67E8A2A2B77
a = 0x5E009506FCC7EFF573BC960D88638FE25E76A9B6C7CAEEA072A27DCD1FA46ABB15B7B6210CF90CABA982893EE2779669BAC06E267013486B22FF3E24ABAE2D42
b = 0x2CE7D1CA4493B0977F088F6D30D9241F8048FDEA112CC385B793BCE953998CAAE680864A7D3AA437EA3FFD1441CA3FB352B0B710BB3F053E980E503BE9A7FECE

E = EllipticCurve(GF(p), [a, b])
P = E(
1717270988092568699558823338721769193577144381975368211582802328564507675390941376742024016097118883258330768453413278341089979563785352923619162792421720,
4634112377728596645252853727020961671365750881389509274235513279641980340214649262199383894060530855372602832137073858683341979244741310958889147358144641)
Q = E(
3034712809375537908102988750113382444008758539448972750581525810900634243392172703684905257490982543775233630011707375189041302436945106395617312498769005,
4986645098582616415690074082237817624424333339074969364527548107042876175480894132576399611027847402879885574130125050842710052291870268101817275410204850)

# d = SmartAttack(Q, P, p)
# print(d)
# d = 1197516373475505564855340799160714178328749125425344308252840761

new = 32745713477574202442635510163772855149196919427272374656320834804167355888344552445841916692444472764816564099439376659111769006339790502161761321431483387380993247845044928915756568692161000770265985467706760276545480280659321303215736675812511878180644086797137833292877929144343255703623965678401535173
final_Ciphertext = '371a6fadfa7b2acdd3f948b308322c735134a6b706b4564e4816b3f3cab86f4ace5f497aafc1ad3a473c4b38fe394e83'
new = bin(new)[2:].zfill(1024)
next2, next1 = int(new[:512], 2), int(new[512:], 2)

next1 = next1 << 9

for i in tqdm(range(512)):
rQ0 = next1 + i
# y^2 \equiv x^3 + ax + b mod p
c = (rQ0 ** 3 + a * rQ0 + b) % p
# i_roots = [pow(c, (p + 1) // 4, p), (p - pow(c, (p + 1) // 4, p)) % p]
rQ1 = pow(c, (p + 1) // 4, p)
try:
# maybe not in the curve
rQ = E(rQ0, rQ1)
except:
continue
r = SmartAttack(Q, rQ, p)
assert r * Q == rQ
state = Integer((r * P)[0])
sP = state * P
r = Integer(sP[_sage_const_0])
state = Integer((r * P)[_sage_const_0])
rQ = r * Q
nexti = Integer(rQ[_sage_const_0]) >> _sage_const_9
if nexti == next2:
break


sP = state * P
r = Integer(sP[_sage_const_0])
state = Integer((r * P)[_sage_const_0])
rQ = r * Q
next1 = Integer(rQ[_sage_const_0]) >> _sage_const_9

sP = state * P
r = Integer(sP[_sage_const_0])
state = Integer((r * P)[_sage_const_0])
rQ = r * Q
next2 = Integer(rQ[_sage_const_0]) >> _sage_const_9
number = Integer(bin(next2)[_sage_const_2:].zfill(size) + bin(next1)[_sage_const_2:].zfill(size), _sage_const_2)
print(dec(final_Ciphertext, number))
1
flag{so__Cooool__about__the_backdoor!~}

easy login

考点

  • AES.CBC模式整活
  • MT19937伪随机数的恢复,getrandbits中的潜规则

至于AES的脑洞,出题人还是很严谨的,代码中特意体现出来的东西都用到了,但我对此几乎无感,两步都是尚师傅提示的。全部围绕下面这个东西展开的战斗

1
{name}##{identity}##{sever_certificate}##{hash}

大致绕过方法如下:第二步登录之后需要先使得identity变成admin(默认是guest),这个在token前面加一段$iv\ \oplus\ \ guest\ \oplus admin$就可以成功通过,之后需要恢复死循环外面的一个512位的随机数secret_key从而获得flag;第一步每次注册加密的时候会生成一个256位的随机数sever_certificate,而登录解密的时候,如果identity位置的{}='admin'会输出name位置的{},借用第一步的方法我们可以把前面两个{name}##{identity}##给解成乱码(乱码对.split(b"##")没有任何影响),这样就使得{sever_certificate}位置提前,之后再在密文中{sever_certificate}部分之后,加入类似xor(xor(iv, b'{' + b'A' * 15), b'{admin}##{xxx}##') + token[:16]的一段,就可以把{admin}##{xxx}##给添到{sever_certificate}之后,成功获得sever_certificate。凑足了78个256位($32\times 624=78\times 256$)的sever_certificate就可以通过recover_MT19937恢复secret_key了。

之前的题目是getrandbits(32),经过尚师傅的手工测验后,getrandbits(256)就是32个前者比特串连起来

1
2
3
4
5
6
7
8
9
10
11
12
13
def token_decrypt(Cipher: bytes, iv: bytes, key: bytes):
aes = AES.new(key, AES.MODE_CBC, iv)
try:
Plain = unpad(aes.decrypt(codecs.decode(Cipher, 'hex')), 16).split(b"##")
if (sha256(get_value(Plain[0])).hexdigest().encode() != get_value(Plain[3])):
print("[+] ERROR!")
if (get_value(Plain[1]) == b'admin'):
print("[DEBUG] Wrong hash of", get_value(Plain[0]).decode('latin1'), "!")
return None
except:
print("[!] ERROR!")
return None
return Plain[0], Plain[1], Plain[2]

完整的exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/env python3
# coding: utf-8
from hashlib import sha256
from string import ascii_letters, digits
from pwn import *
from itertools import product
from exploit.recoverMT19937 import *
from random import *
import re

# context.log_level = 'debug'
table = ascii_letters + digits


class Solve:
def __init__(self):
# self.sh = remote('127.0.0.1', 10001)
self.sh = remote('121.40.89.206', 20002)
self.ru = lambda s: self.sh.recvuntil(s)
self.sl = lambda s: self.sh.sendline(s)
self.rl = lambda: self.sh.recvline()
self.sa = lambda r, s: self.sh.sendlineafter(r, s)

def proof_of_work(self):
# [+] sha256(XXXX+if5aJODQwq478imy) == 8d90d5be903797ede85df21b403f33c3bbdc48a7e5c528dbcf0d3eb475145b58
# [+] Plz tell me XXXX:
proof = self.ru(b'[-]')
tail = proof[16:32].decode()
_hash = proof[37:101].decode()
for i in product(table, repeat=4):
head = ''.join(i)
t = sha256((head + tail).encode()).hexdigest()
if t == _hash:
self.sl(head.encode())
break

def i_am_admin(self):
self.ru(b'[-] ')
self.sl(b'1')
self.ru(b'[-] ')
self.sl(b'admin')
self.ru(b'[+] Here is your token and iv:\n[+] ')
token = self.rl()[:-1].decode()
self.ru(b'[+] ')
iv = bytes.fromhex(self.rl()[:-1].decode())
self.ru(b'[-] ')
self.sl(b'2')
guest = b'\x00' * 10 + b'guest' + b'\x00'
admin = b'\x00' * 10 + b'admin' + b'\x00'
payload = xor(xor(iv, guest), admin).hex()
payload += token
self.sl(payload)

def solve_s_c(self):
pass

def recover_MT19937(self, _key):
keys = []
for _ in _key:
i_key = bin(_)[2:].zfill(256)
for j in range(len(i_key) // 32 - 1, -1, -1):
keys.append(int(i_key[j * 32: (j + 1) * 32], 2))
guess = ''
for _ in range(4):
parts = recover_state(keys[:624])
state = backtrace([0] * 4 + parts)[:624]
prng = Random()
prng.setstate((3, tuple(state + [0]), None))
k1, k2, k3, k4 = prng.getrandbits(32), prng.getrandbits(32), prng.getrandbits(32), prng.getrandbits(32)
guess += bin(k4)[2:].zfill(32) + bin(k3)[2:].zfill(32) + bin(k2)[2:].zfill(32) + bin(k1)[2:].zfill(32)
keys = [k4, k3, k2, k1] + keys
print(int(guess, 2))

def solve(self):
self.proof_of_work()
key = []
while len(key) < 78:
self.sa(b'[-] ', b'1')
self.sa(b'[-] ', b'A' * 15)
self.ru(b'[+] Here is your token and iv:\n[+] ')
token = bytes.fromhex(self.rl()[:-1].decode())
self.ru(b'[+] ')
iv = bytes.fromhex(self.rl()[:-1].decode())
self.sa(b'[-] ', b'2')
it_is_my_trick = xor(xor(iv, b'{' + b'A' * 15), b'{admin}##{ji!}##') + token[:16]
payload = xor(iv, b'1' * 16) + xor(b'1' * 12 + b'\x00' * 4, token[:16]) + \
token[16:288] + it_is_my_trick + token[272:288] + token[288:]
self.sl(payload.hex())
self.ru(b'[DEBUG] Wrong hash of')
i_key = self.rl()[:-1].decode()
try:
i_key = int(re.findall(r"\d+", i_key)[0], 2)
key.append(i_key)
except:
continue
self.recover_MT19937(key)
self.i_am_admin()
self.sa(b'[-] ', b'1')
self.ru(b'you are admin:')
self.sh.interactive()


if __name__ == '__main__':
solution = Solve()
solution.solve()

image-20211222210953186

sign_in_rsa

考点

  • RSA泄露$d$分解$N$

  • 算法

    1. 计算$k=ed-1$,并分解成$2^tr$($r$是奇数)
    2. 随机选取$g$,$g\in\mathbb{Z}_N^*$
    3. 令$i$遍历$[0,\ t)$,如果$(g^{2^i\times r}-1, N)>1$,则$p=(g^{2^i\times r}-1, N)$,$q=\frac{N}{p}$,返回$p,\ q$
    4. 否则回到第二步重新选取随机数
  • 原理

    设$k=ed-1=\Delta_1\varphi(N)$,随机数$g\in\mathbb{Z}_N$,则$g^k\equiv g^{\Delta_1\varphi(N)}\equiv g^{\varphi(N)}\equiv1\ (mod\ N)$,即$g^k-1\equiv0(mod\ N)$,即
    $$
    g^k-1=N\Delta_2=pq\Delta_2
    $$
    我们想分解$N$,但是直接从$pq$下手会遇到大整数分解难题,而转换成$g^k-1$上则会有一些突破口;一般来说$(g^k-1,\ N)=N$

    由于$k=ed-1$是偶数可以分解成$2^tr$的形式,其中$r$是奇数,所以$(1)$可以被分解成
    $$
    g^k-1=(g^{\frac{k}{2}}+1)(g^{\frac{k}{2}}-1)=pq\Delta_2\notag
    $$
    同理$(g^{\frac{k}{2}}-1)$能够被继续分解直到$(g^{\frac{k}{2^t}}+1)(g^{\frac{k}{2^t}}-1)$

    结合CRT在QR和square roots中的应用

    $(g^{\frac{k}{2^i}})^2\equiv g^{\frac{k}{2^{i-1}}}\equiv\dots\equiv g^{k}\equiv1\ (mod\ N)$,则

    $\begin{align}g^{\frac{k}{2^i}}&=CRT(<1,\ 1>)\leftrightarrow x_1\notag\\&=CRT(<1,\ -1>)\leftrightarrow x_2\notag\\&=CRT(<-1,\ 1>)\leftrightarrow x_3\notag\\&=CRT(<-1,\ -1>)\leftrightarrow x_4\notag\end{align}$

    只有在$x_2$或$x_3$的情况下,$g^{\frac{k}{2^i}}$才满足($x_3$同理)
    $$
    \begin{cases}
    g^{\frac{k}{2^i}}\equiv 1\ (mod\ p)\\
    g^{\frac{k}{2^i}}\equiv -1\ (mod\ q)
    \end{cases}\notag
    $$
    也就说$p$是$g^{\frac{k}{2^i}}-1$的因子,而$q$不是,这个时候求$(g^{2^i\times r}-1, N)$就是等于$p$(当然你换成$g^{\frac{k}{2^i}}+1$也可以

    最后就是概率的问题,因为每求得一个$g^{\frac{k}{2^i}}$,其实它只对应一个$x_i$,而其是$x_2$或$x_3$的概率正好是$\frac{1}{2}$

    而论文中说在${g\ |\ g\in \mathbb{Z}_N^*}$中,找到符合条件的$g$的概率是$\frac{1}{2}$(没想到为什么,统计出来的就罢了

    image-20220103161009555

    原文Twenty Years of Attacks on the RSA Cryptosystem

  • 脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def divide_pq(e, d, n):
    k = e * d - 1
    t, _k = 0, k
    while _k % 2 == 0:
    t += 1
    _k = _k // 2
    r = k // (2 ** t)
    while 1:
    g = getrandbits(100)
    for i in range(t):
    p = gcd(pow(g, 2 ** i * r, n) - 1, n)
    if p > 1 and p != n:
    q = n // p
    return p, q

最后有点像hash链的加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from Crypto.Util.number import *
from exploit.leakPrivateFracN import d_leak_attack

n, d = 15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 6510060024132448812692374598562478938781873276826121917136087171433612126001066486549172550775880633671688073309060742661536694848138785012316851139079566219427085669995770343650050947604387625705743119055063449704794632066543990637391557798194976737161835401498317792553501071727695913273255675957670000137254200491232988916899437811704442351184491702933366588255664254218916419493613957433723990485119540500734398920034539046985131363424063852960232153505171116298416691316690158260663800875225380729824947022224315510290836013992740531252154869626076244458736535349817731705617890688617614422279803126347527748253
friend_keys = [(15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 107273), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 80021), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 110281), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 125399), (15029760235374231085969639414731714595094502023579580515142415364576906256445975070594748351717296265506796113025536826427911733196972964855469386448087417878697745924349624863909303165292167253527223263941652633363973854290523602860560486258509324353520104509387932968280508674316342236523385959602558170958614970693493378178016898028008319433088550790771390116863660130486812753414200478905354927474330477084174838392457570478397763649784441576899752400739324537777431123697771882670997321209911034933464741353255233083149611904906129535499692359926063803373853328404277847957250932127456840832115242266989310408337, 77641)]
e = 0x10001
cipher = 2621668640772056420471560098924704127784856790481388457844412769822118088860174800889321751481674422274270598394172919656578632970378187564960846030071830293875552723490431731972841568891484366856527528595054839456764493791012121047269761236912586905892771816051261702781783915560998982829509529868080760864895962974173385898354122495270178096361803788632815673814331531474332060419597040425174040815031894440262657639509623993308964349172916870911290368660953787873798343194799625182081014696063160131605363197089825537641567810410348240587342655465209891653946637101421879415183319402455214734741851508514452049810

p, q = d_leak_attack(e, d, n)
assert p * q == n
phi = n - p - q + 1

for _, ei in friend_keys[::-1]:
di = inverse(ei, phi)
cipher = pow(cipher, di, n)
print(long_to_bytes(cipher))
1
flag{3ncrypt_y0ur_s3cr3t_w1th_y0ur_fr1end5_publ1c_k3y}
  • 疑问(或者说方法)

    泄漏$d$攻击的步骤一定是像上面这样吗?

    由$ed-1=k\varphi(n)$可知其实$e$和$k$是同一数量级的,而$e$一般都取65537,所以直接爆破就可以算出$\varphi(n)$岂不美哉

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def get_flag(phi):
    for _, ei in friend_keys[::-1]:
    di = inverse(ei, phi)
    cipher = pow(cipher, di, n)
    return bytes.fromhex(hex(cipher)[2:])


    for k in range(1, e):
    t = (e * d - 1) // k
    if get_flag(t).startswith(b'flag'):
    print(get_flag(t))
    break

    但至于适用性还值得考量

luukaka

考点

  • CopperSimth求小根
  • Paillier同态加密的一般形式

第二个类似祥云杯2021-Guess

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env sage
# coding: utf-8
load('exploit/coppersmithPHighBits.sage')
from Crypto.Util.number import long_to_bytes, isPrime
from gmpy2 import invert, powmod
from math import lcm
n = 14228073730190667444265758569232998545834341711432864414441434537856457554226009751489033431705491278975339077931622009743639467631071474363151300487078680100432725518596365988395929461561533250434031486424245896944629925135857622729999223390971276553928997508637911376545709237354833737994060265750787364825469605787468954601744025244062927831728713075259243916071854001703095748019042346899025896785151209455462423075169662092252456008356019267117214041106983803825784779879133738561202953888980952580302263891778856965344625783352907638953070740712616009213478262015624504889618788466893252102409611427088945902084609824939158090273141699828781599
g = 104756338318355948567384664103742452654286797799572772265848233334512623038814223410545840475708213491580933168492941525415723077772925906306730070567912467752229764629077391411738146979960676773739966985033493353135734679863468554065367379641641877776732166787383073606968314307988023048157536642389004806055502363198290047464507135522056378518722299068757453041609390692043233878813029502849305103895304519202811596850440711557164909395610847550061798126016783826231721060875732764619258276319683759960874598610474526487116193287935726659807081799695149604873036088612391197272153090414815760539467909235655538189612951075972603409435247362402276881345593351325034626085319241822974931255362490361433247117438845892276212349225050480473723922773661650238241659376681125743246319687880452040595990284620390242076959726572663250706701440702801135388505126093218792766996298711732747845811266552028107611595554772334895684283839272384369606543632542613172335294487221561323491737934377355876532240725521412046012357801914284413206938819420564131912564088387486730018108094449689965565218873981804619434009206386324135567769774069088701758230799594812616518042137489600048047478571983854027089251082355287707549749663822654965131297650047047655863594589307878048709000265824696160267631742318727023504
c = 110337660867664870668618596423399170421957516047679509225588623376743804308910177330738477934885576296064264107955132608068039716915229141255177656762910257465732348532323965821043865294553028096906547082618551373641823894294345439394320458729379584778338791447390149190354594056272453424922259417177887790371636260596466767307663828504719149380793176963386400546201890745560501746937761750771953027692686082999321908948997715677766808897936775024313229131624361695754073181908392043158729516103179521695533235615975097099246881718801578279171894214275303379728310998576306972004917364359907184627898803582606166064132907209594129554305783857639940803580780162589238990527574402229360311452329673309294811095686032780187382402401244208403608246186488287045631870185466768772070155917361936402870757098225660585142716834782054689740016959635568917565989361153748200711957665416078406041043067068946260735419003117885045170538814091969325447811589483805740159257095544507862038022099086715866062568327078082077714811272019367066364077835278254199402087714107154020099620284929159828186078676335901409411843708088949544768400190126243155520427016805835963333341089705359758522086506203013124445829394093909811080012839871046714948018821673486671778352056836826280481951815377888832291151086485700501159


def Function(times, a, b):
F = [2,a]
for i in range(times):
F.append( a * F[-1] - b * F[-2])
return F


a = 0b11011101110111110
b = 0x11011101110
s = (Function(77,a,b)[-1])
while 1:
if isPrime(s):
break
else:
s = s >> 1
Fn = Zmod(n)
PR.<x> = PolynomialRing(Fn)
f = (s << 64) + x
roots = f.small_roots(X=2^64, beta=0.4)
p = (s << 64) + int(roots[0])
assert n % p == 0
q = n // p
_lambda = lcm(p - 1, q - 1)
L = lambda x: (x - 1) // n
x = L(powmod(g, _lambda, n*n))
u = invert(x, n)
m = (L(powmod(c, _lambda, n*n))) * u % n
print(long_to_bytes(m))
1
flag{P4ll13r&C0pP3r5m17h_m4y_b3_g00d_Fr13nds~}

Reference

  1. Coinc1dens-RSA 基础知识及攻击方法-d 泄露攻击
  2. ctf wik-d 泄露攻击
  3. Dan Boneh-Twenty Years of Attacks on the RSA Cryptosystem
  4. Why Smart’s attack doesn’t work on this ECDLP?

something else

PWNHUB | 2020密码学专场Writeup

badmonkey -浅析MT19937伪随机数生成算法

ctf wiki-RSA 复杂题目-PRNG Predict

Weak Curves In Elliptic Curve Cryptography