To1in的BUU刷题记录6

发布于 2021-07-27  806 次阅读





To1in 的BUU刷题记录6

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))