# cdcq

## 【攻防世界】SECCON-CTF-2014 - Decrypt-It-easy

（需要注意一点，Linux上的gcc和Windows上的gcc编译完的程序使用相同种子似乎会得到不同的伪随机数，附件里的可执行文件是Linux平台的，因此爆破脚本也应该跑在Linux上）

  1 from random import randint
2 from Crypto.Util.number import *
3 from gmpy2 import *
4
5
6 def exgcd(a, b):
7     if b == 0:
8         return 1, 0
9     x, y = exgcd(b, a % b)
10     return y, x - a // b * y
11
12
13 def crt(a, m):
14     M = 1
15     for i in m:
16         M = M * i
17
18     ans = 0
19     for i in range(len(a)):
20         x, y = exgcd(M // m[i], m[i])
21         ans = (ans + a[i] * M // m[i] * x) % M
22
23     return (ans + M) % M
24
25
26 def mul_i(a, b, t, p):
27     return [(a[0] * b[0] + a[1] * b[1] * t) % p, (a[0] * b[1] + b[0] * a[1]) % p]
28
29
30 def pow_i(a, b, c, t, p):
31     ans = [1, 0]
32     z = [a, b]
33     while c > 0:
34         if c % 2 == 1:
35             ans = mul_i(ans, z, t, p)
36         z = mul_i(z, z, t, p)
37         c = c // 2
38
39     return ans
40
41
42 def legendre(a, p):
43     return pow(a, (p - 1) // 2, p)
44
45
46 def residue(n, p):
47     t = randint(0, p - 1)
48     while legendre(t ** 2 - n, p) != p - 1:
49         t = randint(0, p - 1)
50
51     a = pow_i(t, 1, (p + 1) // 2, t ** 2 - n, p)
52     # print('residue:', a[0] * a[0] % p == n)
53     return a[0]
54
55
56 def get_string(m):
57     s = ''
58     while m > 0:
59         s = s + chr(m % 256)
60         m = m // 256
61
62     return s[::-1]
63
64
65 def check_visible(s):
66     for i in s:
67         if not 32 <= ord(i) < 128:
68             return 0
69
70     return 1
71
72
73 if __name__ == '__main__':
74     '''
75     n = 0xB8AE199365
76     b = 0xFFEEE
77     c = 0x8D5051562B
78     '''
79     N = [0xB8AE199365, 0xB86E78C811, 0x7BD4071E55]
80     B = [0xFFEEE, 0xFFFEE, 0xFEFEF]
81     C = [0x8D5051562B, 0x5FFA0AC1A2, 0x6008DDF867]
82     t = ''
83     for i in range(len(N)):
84         n = N[i]
85         b = B[i]
86         c = C[i]
87         p = 1
88         for i in range(2, n):
89             if n % i == 0:
90                 p = i
91                 q = n // i
92                 break
93
94         b2 = b * invert(2, p) % p
95         r1 = residue((c + b2 * b2) % p, p)
96         m1 = [(r1 - b2 + p) % p, (p - r1 - b2 + p) % p]
97         b2 = b * invert(2, q) % q
98         r2 = residue((c + b2 * b2) % q, q)
99         m2 = [(r2 - b2 + q) % q, (q - r2 - b2 + q) % q]
100         for temp1 in m1:
101             for temp2 in m2:
102                 m = crt([temp1, temp2], [p, q])
103                 s = get_string(m)
104                 if check_visible(s):
105                     break
106
107         # print('crt1:', m % p == m1)
108         # print('crt2:', m % q == m2)
109
110         # print(s[::-1])
111         t = t + s
112
113     print(t)
View Code

n很小，qp更小，直接在[0,p)和[0,q)枚举m，就能得到m = m1 (mod p)和m = m2 (mod q)

posted on 2020-12-23 18:58  cdcq  阅读(110)  评论(0编辑  收藏