1. 程式人生 > 實用技巧 >【攻防世界】SECCON-CTF-2014 - Decrypt-It-easy

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

附件給了個可執行檔案和一個加密檔案,還給了個readme告訴你加密檔案就是用可執行檔案加密的

可執行檔案逆出來是這樣的:

是的,輸入一個檔案,給每個位元組異或一個隨機數再輸出來……

由於加密的是png,前8位是固定檔案頭,那或許可以破解偽隨機數

很自然的想法是爆破,但是時間戳太大了,列舉時間比較長

不過這裡使用時間戳加密,因此可以靈稽一動,想到從這場比賽舉辦的時間附近開始列舉

比賽在2014年舉辦,那麼從2014/01/01的時間戳開始列舉,結果還真的列舉到了囧

(需要注意一點,Linux上的gcc和Windows上的gcc編譯完的程式使用相同種子似乎會得到不同的偽隨機數,附件裡的可執行檔案是Linux平臺的,因此爆破指令碼也應該跑在Linux上)

解完之後是一張圖片,這個圖片才是真正意義上的密碼學題

加密的柿子很簡單,但是我沒找到什麼優美的辦法,只能直接配方,然後pq拆成兩個柿子,然後二次剩餘,然後再中國剩餘定理拼回來囧

這裡需要注意一點,二次剩餘是有重根的,因此對於解出來的m1和m2,還要分別列舉4種情況,找出最有可能是flag的解密串輸出(一般判斷有沒有不可見字元就行了)

程式碼:

  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