To1in 的BUU刷题记录——6
12.[BSidesSF2020]decrypto-2
import hashlib import struct import sys class Crypto: def __init__(self, key): if not isinstance(key, bytes): raise TypeError('key must be of type bytes!') self.key = key self._buf = bytes() self._out = open("/dev/stdout", "wb") def _extend_buf(self): self._buf += self.key def get_bytes(self, nbytes): while len(self._buf) < nbytes: self._extend_buf() ret, self._buf = self._buf[:nbytes], self._buf[nbytes:] return ret def encrypt(self, buf): if not isinstance(buf, bytes): raise TypeError('buf must be of type bytes!') stream = self.get_bytes(len(buf)) return bytes(a ^ b for a, b in zip(buf, stream)) def set_outfile(self, fname): self._out = open(fname, "wb") def encrypt_file(self, fname): buf = open(fname, "rb").read() self._out.write(self.encrypt(buf)) class HashCrypto(Crypto): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._blk = self.key self._blkid = 0 def _extend_buf(self): self._blk = hashlib.sha256( self._blk + struct.pack('<I', self._blkid)).digest() self._blkid += 1 self._buf += self._blk def main(argv): if len(argv) not in (3, 4): print("%s <key> <infile> [outfile]" % sys.argv[0]) return argv.pop(0) key = argv.pop(0) inf = argv.pop(0) crypter = HashCrypto(key.encode("utf-8")) if sys.argv: crypter.set_outfile(argv.pop(0)) crypter.encrypt_file(inf) if __name__ == '__main__': main(sys.argv)
和之前的decrypto-1一样,都是异或加密,我们只要获得key就可以找到flag,这次的输出没有给出的固定格式。但是我们观察到输出文件的名字是flag.svg.enc,所以输入的文件应该是svg文件,而svg文件是有固定格式的,于是我们就用svg的固定格式进行异或,然后获得flag。
import hashlib import struct s = b'<?xml version="1.0" encoding="UTF-8" standalone="no"?>' f = open('flag.svg.enc', 'rb').read() x1 = bytes(a ^ b for a, b in zip(s[:32], f[:32])) sha0 = bytes() temp = 0 # range里的数只要够把全部的明文恢复就可以了 for i in range(100): sha0 += x1 temp += 1 x1 = hashlib.sha256(x1 + struct.pack('<I', temp)).digest() flag = bytes(a ^ b for a, b in zip(sha0, f)) print(flag) #reference https://blog.csdn.net/weixin_44110537/article/details/108074791
13.[b01lers2020]fr3sh_h4rv3st
一个脑洞题
Can you xor your way out of this? (Length of key: 4) 1921754512366910363569105a73727c592c5e5701715e571b76304d3625317c1b72744d0d1d354d0d1d73131c2c655e;
题面是一张图片,属性里有上面这串16进制数字。题目描述是xor,key的长度是4,然后这个国外比赛的flag格式是pctf。所以我们猜测key是pctf,于是我们再异或回去,就可以得到flag了。
#Can you xor your way out of this? (Length of key: 4) from Crypto.Util import number c=0x1921754512366910363569105a73727c592c5e5701715e571b76304d3625317c1b72744d0d1d354d0d1d73131c2c655e c = number.long_to_bytes(c) print(c) flag_format = b'pctf' a=b'' for i in range(4): a+=chr(c[i]^flag_format[i]).encode() print(a) m=b'' for i in range(len(c)): m+=chr(c[i]^a[i%4]).encode() print(m)
14.[GKCTF 2021]RRRRsa
from Crypto.Util.number import * from gmpy2 import gcd flag = b'xxxxxxxxxxxxx' p = getPrime(512) q = getPrime(512) m = bytes_to_long(flag) n = p*q e = 65537 c = pow(m,e,n) print('c={}'.format(c)) p1 = getPrime(512) q1 = getPrime(512) n1 = p1*q1 e1 = 65537 assert gcd(e1,(p1-1)*(q1-1)) == 1 c1 = pow(p,e1,n1) print('n1={}'.format(n1)) print('c1={}'.format(c1)) hint1 = pow(2020 * p1 + q1, 202020, n1) hint2 = pow(2021 * p1 + 212121, q1, n1) print('hint1={}'.format(hint1)) print('hint2={}'.format(hint2)) p2 = getPrime(512) q2 = getPrime(512) n2 = p2*q2 e2 = 65537 assert gcd(e1,(p2-1)*(q2-1)) == 1 c2 = pow(q,e2,n2) hint3 = pow(2020 * p2 + 2021 * q2, 202020, n2) hint4 = pow(2021 * p2 + 2020 * q2, 212121, n2) print('n2={}'.format(n2)) print('c2={}'.format(c2)) print('hint3={}'.format(hint3)) print('hint4={}'.format(hint4))
题目给了我们两组hint,一组加密p,一组加密q,所以我们只要把两组hint解决就可以得到flag。
我们先对第二组形式比较简单的hint进行化简。由二项式定理我们可以知道, 展开后,中间项由于含有,直接消去,于是我们可以得到以下式子
为了方便消元,我们把两式的次数补成相同次,我们就可以得到:
然后我们统一前的系数,让两式相减。
可以看到,这个数一定是的倍数,我们让这个式子的值和求最大公约数,就可以求出。然后就可以进行正常的RSA解密。
接下来我们看第一组:
对第一个式子我们同样进行化简:
我们再看到第二个式子,第二个式子的指数是,我们由费马小定理可以得到:
所以
对上式恢复mod ,然后取202020次方
然后统一两式的系数
两式相减,然后和求最大公约数,就可以求出,之后就可以进行正常的RSA解密。
from Crypto.Util.number import * e = 65537 c = 13492392717469817866883431475453770951837476241371989714683737558395769731416522300851917887957945766132864151382877462142018129852703437240533684604508379950293643294877725773675505912622208813435625177696614781601216465807569201380151669942605208425645258372134465547452376467465833013387018542999562042758 n1 = 75003557379080252219517825998990183226659117019770735080523409561757225883651040882547519748107588719498261922816865626714101556207649929655822889945870341168644508079317582220034374613066751916750036253423990673764234066999306874078424803774652754587494762629397701664706287999727238636073466137405374927829 c1 = 68111901092027813007099627893896838517426971082877204047110404787823279211508183783468891474661365139933325981191524511345219830693064573462115529345012970089065201176142417462299650761299758078141504126185921304526414911455395289228444974516503526507906721378965227166653195076209418852399008741560796631569 h1 = 23552090716381769484990784116875558895715552896983313406764042416318710076256166472426553520240265023978449945974218435787929202289208329156594838420190890104226497263852461928474756025539394996288951828172126419569993301524866753797584032740426259804002564701319538183190684075289055345581960776903740881951 h2 = 52723229698530767897979433914470831153268827008372307239630387100752226850798023362444499211944996778363894528759290565718266340188582253307004810850030833752132728256929572703630431232622151200855160886614350000115704689605102500273815157636476901150408355565958834764444192860513855376978491299658773170270 n2 = 114535923043375970380117920548097404729043079895540320742847840364455024050473125998926311644172960176471193602850427607899191810616953021324742137492746159921284982146320175356395325890407704697018412456350862990849606200323084717352630282539156670636025924425865741196506478163922312894384285889848355244489 c2 = 67054203666901691181215262587447180910225473339143260100831118313521471029889304176235434129632237116993910316978096018724911531011857469325115308802162172965564951703583450817489247675458024801774590728726471567407812572210421642171456850352167810755440990035255967091145950569246426544351461548548423025004 h3 = 25590923416756813543880554963887576960707333607377889401033718419301278802157204881039116350321872162118977797069089653428121479486603744700519830597186045931412652681572060953439655868476311798368015878628002547540835719870081007505735499581449077950263721606955524302365518362434928190394924399683131242077 h4 = 104100726926923869566862741238876132366916970864374562947844669556403268955625670105641264367038885706425427864941392601593437305258297198111819227915453081797889565662276003122901139755153002219126366611021736066016741562232998047253335141676203376521742965365133597943669838076210444485458296240951668402513 h34 = (pow(2021, 202020 * 212121, n2) * pow(h3, 212121, n2) - pow(2020, 202020 * 212121, n2) * pow(h4, 202020, n2)) % n2 q2 = GCD(h34, n2) p2 = n2 // q2 d2 = inverse(e, (p2 - 1) * (q2 - 1)) q = pow(c2, d2, n2) h12 = (pow(2020 * (h2 - 212121), 202020, n1) - pow(2021, 202020, n1) * h1) % n1 q1 = GCD(h12, n1) p1 = n1 // q1 d1 = inverse(e, (p1 - 1) * (q1 - 1)) p = pow(c1, d1, n1) d = inverse(e, (p - 1) * (q - 1)) print(long_to_bytes(pow(c, d, p * q)))
15.[羊城杯 2020]Power
from Crypto.Util.number import * import gmpy2 from secret import flag p = getPrime(512) q = getPrime(512) n = p ** 4 * q e = 0x10001 phi = gmpy2.lcm(p - 1, q - 1) d = gmpy2.invert(e, phi) dp = d % (p - 1) m = bytes_to_long(flag) c = pow(m, e, n) print("dp = " + str(dp)) print("c = " + str(c)) y = 449703347709287328982446812318870158230369688625894307953604074502413258045265502496365998383562119915565080518077360839705004058211784369656486678307007348691991136610142919372779782779111507129101110674559235388392082113417306002050124215904803026894400155194275424834577942500150410440057660679460918645357376095613079720172148302097893734034788458122333816759162605888879531594217661921547293164281934920669935417080156833072528358511807757748554348615957977663784762124746554638152693469580761002437793837094101338408017407251986116589240523625340964025531357446706263871843489143068620501020284421781243879675292060268876353250854369189182926055204229002568224846436918153245720514450234433170717311083868591477186061896282790880850797471658321324127334704438430354844770131980049668516350774939625369909869906362174015628078258039638111064842324979997867746404806457329528690722757322373158670827203350590809390932986616805533168714686834174965211242863201076482127152571774960580915318022303418111346406295217571564155573765371519749325922145875128395909112254242027512400564855444101325427710643212690768272048881411988830011985059218048684311349415764441760364762942692722834850287985399559042457470942580456516395188637916303814055777357738894264037988945951468416861647204658893837753361851667573185920779272635885127149348845064478121843462789367112698673780005436144393573832498203659056909233757206537514290993810628872250841862059672570704733990716282248839 g = 2 x = 2019 * p ** 2 + 2020 * p ** 3 + 2021 * p ** 4 c1 = pow(g, x, y) print("c1 = " + str(c1))
题目只给了dp,c,c1。c1应该是提示部分,我们先看到c1的生成过程
这里我们需要求出指数,解出p再进行后面的分析,所以我们用离散对数来解决,使用sagemath里的2discrete_log()。把指数求出来后解方程得到p。
x=discrete_log(c1,mod(2,y)) var('p') solve([2019*p*p+2020*p*p*p+2021*p*p*p*p==x],p)
得到p之后,
通过以上的步骤,我们就可以得到flag。
from Crypto.Util.number import long_to_bytes p = 7234391427703598327916723159145232922047935397302241978344500497098972068808591685717500902909442183573763273395725479516998210374727754578133587007330339 m = pow(c,dp,p) print(long_to_bytes(m))
Comments NOTHING