jarvisoj-Crypto

时间:2022-04-27
本文章向大家介绍jarvisoj-Crypto,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

jarvisoj-Crypto

Medium RSA

题目到手后给了一个公钥和一个密文

我们对这个公钥提取信息:

可以得到

N = 0xC2636AE5C3D8E43FFB97AB09028F1AAC6C0BF6CD3D70EBCA281BFFE97FBE30DD

E = 65537

C = 0x6D3EB7DF23EEE1D38710BEBA78A0878E0E9C65BD3D08496DDA64924199110C79

公钥极短,我们可以直接分解N,得到p和q

P = 275127860351348928173285174381581152299

Q = 319576316814478949870590164193048041239

然后容易求出

d = 10866948760844599168252082612378495977388271279679231539839049698621994994673

生成私钥

coding=utf-8
import math
import sys
from Crypto.PublicKey import RSA
keypair = RSA.generate(1024)
keypair.p = 275127860351348928173285174381581152299
keypair.q = 319576316814478949870590164193048041239
keypair.e = 65537
keypair.n = keypair.p * keypair.q
Qn = long((keypair.p-1) * (keypair.q-1))
i = 1
while (True):
    x = (Qn * i ) + 1
    if (x % keypair.e == 0):
        keypair.d = x / keypair.e
        break
    i += 1
private = open('private.pem','w')
private.write(keypair.exportKey())
private.close()
然后解密得到flag:
openssl rsautl -decrypt -in flag.enc -inkey private.pem -out flag.dec
cat flag.dec
PCTF{256b_i5_m3dium}

BrokenPic

发现文件缺少bmp文件头,补上后:

发现图片可以看了

然后可以看到有key,后发现bmp 内的数据变化很规律,可能是块密码,试试 AES,用key 解密一下:

#!/usr/bin/python
# coding=utf-8
from Crypto.Cipher import AES
key = 'PHRACK-BROKENPIC'
aes = AES.new(key)
 
with open('brokenpic.bmp', 'r') as f:
    data = f.read()
    pic = aes.decrypt(data)
 
with open('2.bmp', 'w') as f:
    f.write(pic)

然后可以得到:

扫描后即可得到flag

hard RSA

提取公钥发现e为2,查阅资料找到rabin算法,

可以先分解n,再用对应的脚本解密即可 分解n得到:

p=275127860351348928173285174381581152299 q=319576316814478949870590164193048041239

破解脚本如下

# coding=utf-8
import gmpy2
import string
from Crypto.PublicKey import RSA
with open('pubkey.pem', 'r') as f:
    key = RSA.importKey(f)
    N = key.n
    e = key.e
with open('flag.enc', 'r') as f:
    cipher = f.read().encode('hex')
    cipher = string.atoi(cipher, base=16)
    # print cipher
print "please input p"
p = int(raw_input(), 10)
print 'please input q'
q = int(raw_input(), 10)
inv_p = gmpy2.invert(p, q)
inv_q = gmpy2.invert(q, p)
mp = pow(cipher, (p + 1) / 4, p)
mq = pow(cipher, (q + 1) / 4, q)
a = (inv_p * p * mq + inv_q * q * mp) % N
b = N - int(a)
c = (inv_p * p * mq - inv_q * q * mp) % N
d = N - int(c)
for i in (a, b, c, d):
    s = '%x' % i
    if len(s) % 2 != 0:
        s = '0' + s
print s.decode('hex')

解密后得到:

very hard RSA

根据题目给出的程序容易看出是RSA的共模攻击 破解脚本如下:

# coding=utf-8
import string
import gmpy
def egcd(a, b):
    if a == 0:
        return b, 0, 1
    else:
        g, y, x = egcd(b % a, a)
        return g, x - b // a * y, y
def main():
    with open('flag.enc1', 'r') as f1:
        c1 = f1.read().encode('hex')
        c1 = string.atoi(c1, base=16)
 
    with open('flag.enc2', 'r') as f2:
        c2 = f2.read().encode('hex')
        c2 = string.atoi(c2, base=16)
    n = 0x00b0bee5e3e9e5a7e8d00b493355c618fc8c7d7d03b82e409951c182f398dee3104580e7ba70d383ae5311475656e8a964d380cb157f48c951adfa65db0b122ca40e42fa709189b719a4f0d746e2f6069baf11cebd650f14b93c977352fd13b1eea6d6e1da775502abff89d3a8b3615fd0db49b88a976bc20568489284e181f6f11e270891c8ef80017bad238e363039a458470f1749101bc29949d3a4f4038d463938851579c7525a69984f15b5667f34209b70eb261136947fa123e549dfff00601883afd936fe411e006e4e93d1a00b0fea541bbfc8c5186cb6220503a94b2413110d640c77ea54ba3220fc8f4cc6ce77151e29b3e06578c478bd1bebe04589ef9a197f6f806db8b3ecd826cad24f5324ccdec6e8fead2c2150068602c8dcdc59402ccac9424b790048ccdd9327068095efa010b7f196c74ba8c37b128f9e1411751633f78b7b9e56f71f77a1b4daad3fc54b5e7ef935d9a72fb176759765522b4bbc02e314d5c06b64d5054b7b096c601236e6ccf45b5e611c805d335dbab0c35d226cc208d8ce4736ba39a0354426fae006c7fe52d5267dcfb9c3884f51fddfdf4a9794bcfe0e1557113749e6c8ef421dba263aff68739ce00ed80fd0022ef92d3488f76deb62bdef7bea6026f22a1d25aa2a92d124414a8021fe0c174b9803e6bb5fad75e186a946a17280770f1243f4387446ccceb2222a965cc30b3929L
    e1 = 17
    e2 = 65537
    s = egcd(e1, e2)
    s1 = s[1]
    s2 = s[2]
 
    if s1 < 0:
        s1 = -s1
        c1 = gmpy.invert(c1, n)
    elif s2 < 0:
        s2 = -s2
        c2 = gmpy.invert(c2, n)
 
    m = pow(c1, s1, n) * pow(c2, s2, n) % n
    print '{:x}'.format(int(m)).decode('hex')
 
if __name__ == '__main__':
    main()

解密后可以得到

Extremely hard RSA

拿到题目后分析 得到e =3 推断是RSA的低指数攻击 写脚本如下

#!/usr/bin/python
# coding=utf-8
import gmpy
from Crypto.PublicKey import RSA
def calc(j):
    a, b = gmpy.root(cipher + j * N, 3)
    if b > 0:
        m = a
        print '{:x}'.format(int(m)).decode('hex')
        # pool.terminate()
with open('pubkey.pem', 'r') as f:
    key = RSA.importKey(f)
    N = key.n
    e = key.e
with open('flag.enc', 'r') as f:
    cipher = f.read().encode('hex')
    cipher = int(cipher, 16)
inputs = range(118600000, 118720000)
result = []
map(calc, inputs)
print len(result)

爆破N久后可以得到flag

简单ECC概念

参考链接:http://www.8btc.com/eccmath

大体上的意思是说,给你一个曲线F:y^2=x^3+ax+b

你确定下来a和b,然后找一个在曲线F上的点G(x1,y1)

然后自己随机生成一个k(私钥)

然后生成公钥S=kG

注意,这里的kG可不是k*G这么简单,这是几何意义上的:

S=G+G+G+G+……+G(K个G)

然后把公钥丢出去,私钥留给自己

和RSA差不多啦

重点应该是在于如何求S

G(x1,y1),P(x2,y2)

重点来了:核心公式

x3≡t^2-x1-x2(mod p)

y3≡t(x1-x3)-y1(mod p)

其中

  • 若P=G 则 t=(3x^2+a)/2y1
  • 若P≠G 则 t=(y2-y1)/(x2-x1)

故此可以求出公钥S

于是脚本如下:

# -*- coding:utf8 -*-
a=16546484
p=15424654874903
def egcd(t, b):
    if t == 0:
      return (b, 0, 1)
    else:
      g, y, x = egcd(b % t, t)
      return (g, x - (b // t) * y, y)
def modinv(o, m):
    g, x, y = egcd(o, m)
    if g != 1:
      raise Exception('modular inverse does not exist')
    else:
      return x % m
def ecc_m(x1,y1,x2,y2):
    if ((x1 == x2) & (y1 == y2)):
        fenzi=3*x1*x1+a
        fenmu=2*y1
    else:
        fenzi = y2 - y1
        fenmu = x2 - x1
    m=(abs(fenzi) * modinv(abs(fenmu), p)) % p
    if ((fenzi >= 0 & fenmu >= 0) | (fenzi < 0 & fenmu < 0)):
        return m
    else:
        return p - m
def ecc_x(x1,x2,m):
    result_x = m*m-x1-x2
    if result_x>0:
        return result_x%p
    else:
        p1=p
        if abs(result_x)>p1:
            shang=abs(result_x)/p
            p1=shang*p+p
        return p1+result_x
def ecc_y(x1,result_x,y1,m):
    result_y = m*(x1-result_x)-y1
    if result_y>0:
        return result_y%p
    else:
        p1 = p
        if abs(result_y) > p1:
            shang = abs(result_y) / p
            p1 = shang * p + p
        return p1 + result_y
def ecc_result_x(x1,y1,x2,y2):
    m = ecc_m(x1,y1,x2,y2)
    result_x=ecc_x(x1,x2,m)
    return result_x
def ecc_result_y(x1,y1,x2,y2):
    m = ecc_m(x1,y1,x2,y2)
    result_x = ecc_x(x1, x2, m)
    result_y=ecc_y(x1, result_x, y1, m)
    return result_y
x1=x2=x3=6478678675
y1=y2=5636379357093
n=546767
while(n>0):
    x2=ecc_result_x(x1,y1,x2,y2)
    y2=ecc_result_y(x1,y1,x3,y2)
    x3=x2
    n-=1
print x2,y2
result = x2+y2
flag = "XUSTCTF{%s}"%result
print flag

运行后即可得到flag

神秘的压缩包

拿到题目后发现

立刻想到CRC32的爆破

利用github上的爆破工具:

https://github.com/theonlypwner/crc32

但是长度这里是5位的,而工具只针对6位的

可以在这里学习修改方法:

https://github.com/veritas501/hctf_wp/blob/master/misc_level1_big_zip/misc_level1_big_zip.md

爆破即可得到:

password:f~Z-;lapEwF<0ZkhyAo5

即可解压拿到flag

影之密码

发现只有0 2 4 8,所以猜测是幂数加密,学习链接:

http://baike.baidu.com/link?url=pk_ook24QZMaSO7eHEqHawLWaswbDfgVzHcGGB3YPtSlat-crmZqmKty9bqaWtr-xiTKcbiW1gNt7ldS03A4NK

提示八位大写字母,又发现有7个0,可以分成8段

脚本如下:

#coding=utf-8
 a=["88421","0122","048","02244","04","0142242","0248","0122"]
 # b=["124","01","0118","0118","0212","0114","018","04"]
 flag=""
 for j in range(0,len(a)):
     str = a[j]
     list=[]
     sum=0
     for i in str:
         list.append(i)
     length = len(list)
     for i in range(0,length):
         sum+=int(list[i])
     flag+=chr(64+sum)
     print flag

运行即可得到flag

好多盐

可以看到题目中给出了md5和该md5的盐 剩下的就是强行爆破了 于是脚本如下:

# -*- coding: utf-8 -*-
 import hashlib
 result ="{FLAG:%number}%salt"
 password =["f09ebdb2bb9f5eb4fbd12aad96e1e929.p5Zg6LtD","6cea25448314ddb70d98708553fc0928.ZwbWnG0j","2629906b029983a7c524114c2dd9cc36.1JE25XOn","2e854eb55586dc58e6758cfed62dd865.ICKTxe5j","7b073411ee21fcaf177972c1a644f403.0wdRCo1W","6795d1be7c63f30935273d9eb32c73e3.EuMN5GaH","d10f5340214309e3cfc00bbc7a2fa718.aOrND9AB","8e0dc02301debcc965ee04c7f5b5188b.uQg6JMcx","4fec71840818d02f0603440466a892c9.XY5QnHmU","ee8f46142f3b5d973a01079f7b47e81c.zMVNlHOr","e4d9e1e85f3880aedb7264054acd1896.TqRhn1Yp","0fd046d8ecddefc66203f6539cac486b.AR5lI2He","f6326f02adaa31a66ed06ceab2948d01.Aax2fIPl","720ba10d446a337d79f1da8926835a49.ZAOYDPR2","06af8bcc454229fe5ca09567a9071e62.hvcECKYs","79f58ca7a81ae2775c2c2b73beff8644.TgFacoR3","46aaa5a7fef5e250a2448a8d1257e9cf.GLYu0NO4","2149ac87790dd0fe1b43f40d527e425a.5Xk2O1sG","d15a36d8be574ac8fe64689c728c268e.aZikhUEy","ff7bced91bd9067834e3ad14cc1464cd.E7UROqXn","8cc0437187caf10e5eda345cb6296252.XPin3mVB","5cfcdca4a9cb2985a0b688406617689e.nsGqoafv","5a7dfa8bc7b5dfbb914c0a78ab2760c6.YC1qZUFR","8061d8f222167fcc66569f6261ddd3cc.wNgQi615","3d8a02528c949df7405f0b48afe4a626.CO2NMusb","70651acbc8bd027529bbcccdbf3b0f14.CAXVjFMd","a9dbe70e83596f2d9210970236bdd535.TL6sjEuK","9ed6ef5780f705ade6845b9ef349eb8f.tJ90ibsz","4b46fac0c41b0c6244523612a6c7ac4a.VTjOSNmw","8141e6ecb4f803426d1db8fbeb5686ef.lh75cdNC","df803949fd13f5f7d7dd8457a673104b.V39sEvYX","19052cc5ef69f90094753c2b3bbcd41d.YwoGExpg","cf8591bdccfaa0cdca652f1d31dbd70f.pJCLui49","66e10e3d4a788c335282f42b92c760a1.NQCZoIhj","94c3ae5bcc04c38053106916f9b99bda.vOktelLQ","e67e88646758e465697c15b1ef164a8d.x0hwJGHj","84d3d828e1a0c14b5b095bedc23269fb.2HVWe9fM","264a9e831c3401c38021ba3844479c3f.Cx4og6IW","ed0343dec184d9d2c30a9b9c1c308356.g2rqmPkT","ad5ba8dc801c37037350578630783d80.pFK2JDT5","3f588bedb704da9448e68fe81e42bca6.4ANDOiau","970c9cf3cad3dfa7926f53ccaae89421.R6ML7Qy8","e0a097b7cceaa7a8949fe039884e4a2d.dul2ynqL","7df505218102c64b1fe4fa5981ddb6fa.jPeoyS57","fd4f6043da1f7d5dca993c946ef6cd7c.6p9CwGaY","5fe6d99b9a2824949279187c246c9c30.OGQ2J57y","135b150ad513a961089bb1c05085a3d9.h0dw1Fro","ad6af4fb623b3c51181a371911667fed.HbQT4dRz","c9fa4b0db317d88e2b10060225e92494.ebVnpMzS","d0deab17d115bd6fdce8592bb3667643.bL5zwgvX","006f0cb3a422716692f143f28eb0d187.NHXg1Fof","ddc125de34da1a6ec0cbe401f147bc8f.GDai9Y0n","be5052053c5a806e8f56ed64e0d67821.40alyH3w","aaf18ac446b8c385c4112c10ae87e7dc.ZJQzuIL0","a2db20a4b7386dc2d8c30bf9a05ceef7.QnpOlPWH","8a4fbc32a3251bb51072d51969ba5d33.rtcbipeq","5e35d2c9675ed811880cea01f268e00f.i1Hbne6h","9da23007699e832f4e9344057c5e0bd3.EtbGpMSW","f09233683d05171420f963fc92764e84.fxHoinEe","4feabf309c5872f3cca7295b3577f2a8.KymkJXqA","9b94da2fa9402a3fdb4ff15b9f3ba4d2.G3Tdr1Pg","b3cd8d6b53702d733ba515dec1d770c5.Y71LJWZz","6a5b3b2526bb7e94209c487585034534.rIwb4oxt","e9728ef776144c25ba0155a0faab2526.e1sOXSb8","d41a5e7a98e28d76dbd183df7e3bcb49.36bedvia","81d5ebfea6aff129cf515d4e0e5f8360.dDG4qTjW"]
 n=1000000000
 while(n<10000000000):
     for j in range(0,66):
         salt = password[j][33:]
         md5 = password[j][:32]
         mingwen = "{FLAG:"+str(n)+"}"+password[j][33:]
         miwen = hashlib.md5(mingwen).hexdigest()
         if (miwen == md5) :
             print mingwen
             print password[j]
             n=10000000000
             break
     print n
n+1

这里建议写多线程,我单线程跑了好久,开着爆破,上课回来也就结束了 得到flag是1234567890

Superexpress

题目本质上是一道仿射加密的题目 可以写出脚本

import sys
 encrypted ="805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9"
 # flag = 'TWCTF{*******CENSORED********}'
 list=[]
 def str2num(s):
     return int(s, 16)
 
 for i in range(0,60,2):
     list.append(str2num(encrypted[i:i+2]))
 
 true_a = 0
 true_b = 0
 for a in range(0,255):
     for b in range(0,255):
         c1 = (a*ord("T")+b)%251
         c2 = (a * ord("W") + b) % 251
         c3 = (a * ord("C") + b) % 251
         if((c1==list[0])&(c2==list[1])&(c3==list[2])):
             true_a = a
             true_b = b
             break
     if ((true_a!=0)&(true_b!=0)):
         break
 k=0
 flag=""
 for cishu in range(1,31):
     for mingwen in range(33,127):
         c = (true_a * mingwen + true_b) % 251
         if (c==list[k]):
             k+=1
             flag+=chr(mingwen)
             print flag
             break

运行即可

Vigenere

这是一个具有base64块的Vigenere密码,我们选择使用Kasiski测试来检测密钥长度,并且对每个base64块进行详尽的搜索。后在github上搜到一个能用的脚本,修改后即可运行处flag 脚本如下:

#!/usr/bin/env python3
import functools
import math
import base64
import string
import sys
import logging
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger()
 
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'
assert len(chars) == 64
def shift(char, key, rev = False):
    if not char in chars or key == '?':
        return char
    if rev:
        return chars[(chars.index(char) - chars.index(key)) % len(chars)]
    else:
        return chars[(chars.index(char) + chars.index(key)) % len(chars)]
def decrypt(encrypted, key):
    return base64.b64decode(''.join([shift(c, key[i % len(key)], True) for i, c in enumerate(encrypted)]))
 
with open('encrypted.txt') as fh:
    ciphertext = fh.read().strip()
log.info('encrypted.txt: %s', ciphertext)
 
def kasiski_test(s, l):
    dists = []
    for i in range(len(s) - l):
        word = s[i : i+l]
        j = s[i + l : ].find(word)
        if j != -1:
            dist = (i+l+j) - i
            dists += [ dist ]
    dist = functools.reduce(math.gcd, dists)
    return dist
dist = kasiski_test(ciphertext, 3)
log.info('estimated length: %d', dist)
assert dist == 12
 
isascii = lambda s: all([ c < 128 for c in s ]) # for bytes
chunk = lambda s, l: [s[i:i+l] for i in range(0, len(s), l)]
assert dist % 4 == 0
def is_valid_key_block(key, k, restrict=3):
    key += 'A' * (4 - len(key))
    plaintext = decrypt(ciphertext, key)
    for s in chunk(plaintext, 3)[ k :: dist // 4]:
        if not isascii(s[ : restrict]):
            return False
    return True
for k in range(dist // 4):
    for x in chars:
        for y in chars:
            if not is_valid_key_block(x + y, k, restrict=1):
                continue
            for z in chars:
                if not is_valid_key_block(x + y + z, k, restrict=2):
                    continue
                for w in chars:
                    if is_valid_key_block(x + y + z + w, k):
                        key = x + y + z + w
                        plaintext = decrypt(ciphertext, key)
                        print(k, key, b'  '.join(chunk(plaintext, 3)[ k :: dist // 4]))
 
key = 'shA6I8HUXLFY'
print(key)
print(decrypt(ciphertext, key).decode())

得到flag TWCTF{C14ss1caL CiPhEr iS v3ry fun}

DSA

根据DSA算法,可以知道当使用相同的k的时候,r也相同,那么如果我们知道两个不同的消息利用相同的r的话,就可以进行攻击了。在这道题中,我们发现时m3和m4的r是相同的。 然后我们已知

又有

最后可以写出攻击脚本

from Crypto.Hash import SHA
import gmpy2
y = int("45bb18f60eb051f9d48218df8cd956330a4ff30af5344f6c9540061d5383292d95c4dfc8ac26ca452e170dc79be15cc6159e037bccf564ef361c18c99e8aeb0bc1acf9c0c35d620d60bb7311f1cf08cfbc34ccaa79ef1dad8a7a6facce86659006d4faf057716857ec7ca604ade2c3d731d6d02f933198d390c3efc3f3ff046f", 16)
p = int("00c0596c3b5e933d3378be3626be315ee70ca6b5b11a519b5523d40e5ba74566e22cc88bfec56aad66918b9b30ad281388f0bbc6b8026b7c8026e91184bee0c8ad10ccf296becfe50505383cb4a954b37cb588672f7c0957b6fdf2fa0538fdad83934a45e4f99d38de57c08a24d00d1cc5d5fbdb73291cd10ce7576890b6ba089b", 16)
q = int("00868f78b8c8500bebf67a58e33c1f539d3570d1bd", 16)
g = int("4cd5e6b66a6eb7e92794e3611f4153cb11af5a08d9d4f8a3f250037291ba5fff3c29a8c37bc4ee5f98ec17f418bc7161016c94c84902e4003a7987f0d8cf6a61c13afd5673caa5fb411508cdb3501bdff73e747925f76586f4079fea12098b3450844a2a9e5d0a99bd865e0570d5197df4a1c9b8018fb99cdce9157b98500179", 16)
f3 = open(r"packet3/message3", 'r')
f4 = open(r"packet4/message4", 'r')
data3 = f3.read()
data4 = f4.read()
sha = SHA.new()
sha.update(data3)
m3 = int(sha.hexdigest(), 16)
sha = SHA.new()
sha.update(data4)
m4 = int(sha.hexdigest(), 16)
print m3, m4
s3 = 0x30EB88E6A4BFB1B16728A974210AE4E41B42677D
s4 = 0x5E10DED084203CCBCEC3356A2CA02FF318FD4123
r = 0x5090DA81FEDE048D706D80E0AC47701E5A9EF1CC
ds = s4 - s3
dm = m4 - m3
k = gmpy2.mul(dm, gmpy2.invert(ds, q))
k = gmpy2.f_mod(k, q)
tmp = gmpy2.mul(k, s3) - m3
x = tmp * gmpy2.invert(r, q)
x = gmpy2.f_mod(x, q)
print int(x)

运行即可拿到flag

[61dctf]bbencode

加密脚本的算法只要将加密的密文按着加密脚本重复下去,所以方式就很容易了: 脚本如下:

# assert len(flag) == 32
 def str2num(s):
     return int(s.encode('hex'), 16)
 
 def bbencode(n):
     a = 0
     for i in bin(n)[2:]:
         a = a << 1
         if (int(i)):
             a = a ^ n
         if a >> 256:
             a = a ^ 0x10000000000000000000000000000000000000000000000000000000000000223L
     return a
 
 flag = 61406787709715709430385495960238216763226399960658358000016620560764164045692
 for i in range(10000000):
     flag = bbencode(flag)
     if '666c6167' == str(hex(flag))[2:10]:
         print i
         print hex(flag)[2:-1].decode('hex')

可以得到flag:

[61dctf]rsappend

题目有点小坑,给的数据相当多

但是后面可以发现,还是一道共模攻击的题,于是只需要2组即可,其他都可以删掉

于是可以写出共模攻击的脚本:

#coding=utf-8
import sys
def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, y, x = egcd(b % a, a)
        return (g, x - (b // a) * y, y)
def modinv(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        raise Exception('modular inverse does not exist')
    else:
        return x % m
def main():
    n = 130129008900473203968454456805638875182255844172836031362469765750555629223299054613072677100571707156698316733582683118539756860001556017029333867329591302318262912728008327902112481960175532302595162289611406978353816368008691640641366763939266242207191229240305820321249712345088877729541037319788659353057396178127928848886417880913823432701577855911982710310391664759040416918636673098245499680559140960154217578440590540485803953844560093151975252604098243460784073934982164384904788470380402066708313893480356219937915540825156266934523595689350157227336528136089157698775968997579723271988825396396444999743016035145444220925369592263295741687879468786947998534483539986779457827253891091252408156073413533385415338751818544323853074296042153599429749378847870780593975579477549218822682233583377677693108437331184962345568217859524495625257015837972947971787321584159575618388588687948368216479955807108888453821700067186732627409832722329355336479016104249514839541606562090752437124270651936485389358065775555250883907067083447197860848471728871909151915883316674512739238840179296263390441457949281128267215916340163366686542160467601357340644950755337706786366316621293666173843528346692669268972961669116101104865152273
    e1 = 3493354673
    e2 = 340864687
    c1 = 95302089605615051645253770338205531172677353498946580682786822045513597212422921981567826452072575982096979591435896082106066368909398510427324124083956090397824543655853708684901332136907086372208856759943292176759073194584568350898675282883285945088425893961769183074018286761903249180704401358403273776903672507958464947244563165564687651203497198317095965140433811056890812018746508121991041040929574993486548175817290824525606551459788553765629416110310419007396912225733599205599864440826319234419035248234403040065378375700430311931418759746223148198205862641252459687694589780856855757703678024583642215076094232444641853081607984934672271461513190437757388818064739151861157236855430066735235471068167602037785718403200529481153399754491247323829122718485697100562237822159608309949585990842201041193231738706398444530233533281604482892716292766323711237917277799500317596333142843576977429802405873159965636003943698854699972663575602383960580472190300576561953143218321528070200681456278974433060654128626428761278953024384187213765974659768657721533448706022075747036347982370028705538843276631102928500802573434484354218539824751579164697748967608238067706842975984077663380114254296902060435479795741671231918448537178
    c2 = 105918022590727868761989308441554006325741233318901416621101439141134508212362387984949614887131575960019253866892976283979646611794365370050551871112439674346802340152058463892106629344277362169322187627579360245792142005899616101515519718660483000821415412306495286717542069436530262341500852884860324349096274655178057271529986597578695272732947460673640986877589225588415523871081101162696385279491410034057376225511693022693861779342120101749193614060384925056132593068290214170342896671210026723193650534803792328917982049779674425511275821311773130342656939142955431868128759911406827872932920704284125816103225607727270365652734742083302757644298457617564597237089509337896240249999242834787525341715546373108420197569425092674224333823552432226153066667988737348643469923827028254712179077001007265954488404167147591307425224250970874724864947175449960116685682348915647317191880538777148647712260093008241728509225817352093441924045801257015598517963598799676359095235231066752986688784477694024390356904157694178691411759003004184256950519184836209393583431328640341243629167223114681734264945594931213193459079614652400888215324779908031661350565230685273639666615465296133672907093946148188967451042301308884510424218096
    s = egcd(e1, e2)
    s1 = s[1]
    s2 = s[2]
    if s1<0:
        s1 = - s1
        c1 = modinv(c1, n)
    elif s2<0:
        s2 = - s2
        c2 = modinv(c2, n)
m = (pow(c1,s1,n)*pow(c2,s2,n))%n
print hex(m)
if __name__ == '__main__':
    sys.setrecursionlimit(1000000)
main()

运行可以得到:

0x666c61677b77655f646f5f6374665f746f6765746865725f666f725f66756e7d5c674bef926d37beb619a819f2b21861ebc59a33c396be6d2bc5da331e829827d3e2d518520b9588e60a506f3697e071f7634d4b0952f535e4ccb113131776165273fe16519c322b828220daff8d8303f91f4eb88921b248411679409af9e913071594612e4912c5101610765cc2dafab1a11992121ee7329884c5046c0a73c8acdc9bf61124b8224948cb2c562d7ea545b4e900b0aa0059fadc5547f8c765d43967750f8077e0ef061eb8be88d3815f31b9a5ff3d45694e8016caca4a28e9e10b3bcfccdcc278022770dabd57a499138b2aa0043f8b740ad69a0645019ec99aL

转换后即为flag